Files
b6f80ae12e E2E/Playwright: Migrate RFQA browser tests (batch 5, 81-100) (#37417)
* E2E/Playwright: Migrate RFQA browser tests (batch 4, 61-80)

Migrate the fourth batch of Rainforest QA browser tests into Playwright
(migration plan None-core #34-53, keys MM-T480..MM-T1257): 17 new/covered
specs across notifications, search, channel_settings, sidebar_left,
keyboard_shortcuts, and direct_messages_modal, plus 3 duplicate keys folded
into existing tests (MM-T480, MM-T1256, MM-T1257).

POM/infra: add a ChannelMenu page object for the channel header dropdown, an
EditChannelHeaderModal, a header field on the channel-settings info tab, a
channel-wide-mentions checkbox on NotificationsSettings, a getConfirmModal
helper, and a clickNotification browser-API mock helper. Give the channel
header menu and the confirm modal proper accessible names so they can be
targeted semantically. Notification specs run on all browsers now that the
Notification API stub works headless on Chromium and Firefox.

* E2E/Playwright: Migrate RFQA browser tests (batch 5, 81-100)

Migrate the fifth batch of Rainforest QA browser tests into Playwright across
keyboard_shortcuts, search, archived_channels, channel_settings,
plugin_marketplace, messaging, and emoji_picker (keys MM-T1247..MM-T2365),
folding duplicate coverage into existing keyboard-shortcut specs and
documenting skipped cases inline.

POM/infra: add AddPeopleToChannelModal and MarketplaceModal page objects,
manage/add member buttons on the channel members RHS, and an App Marketplace
entry on the global header; target the search "Jump" link through the existing
SearchResultsPanel POM.

Also fix a webapp bug where a post body disappeared when an inline edit was
cancelled mid-animation (found via the up-arrow edit shortcut spec).

* E2E/Playwright: Fail on missing scroll bounding boxes

* E2E/Playwright: Group related batch 5 specs

* E2E/Playwright: Avoid duplicate creator membership

* E2E/Playwright: Group Rainforest batches 1 through 4

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-13 17:14:42 +08:00

166 lines
7.7 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
// The notify-all confirmation modal appears once a channel has more than this many members.
const NOTIFY_ALL_THRESHOLD = 5;
const NOTIFY_ALL_TITLE = 'Confirm sending notifications to entire channel';
/**
* @objective Verify that channel-wide mentions with uppercase letters trigger notifications and are properly highlighted.
*
* @precondition
* - Two users are members of the same team
* - Notification permissions are granted in the browser
*/
test(
'MM-T483 triggers notification with uppercase channel-wide mention and highlights message for all users',
{tag: '@notifications'},
async ({pw}) => {
// # Initialize setup and get the required users and team
const {team, adminUser, user} = await pw.initSetup();
// # Log in as the admin in one browser session and navigate to the "town-square" channel
const {page: adminPage, channelsPage: adminChannelsPage} = await pw.testBrowser.login(adminUser);
await adminChannelsPage.goto(team.name, 'town-square');
await adminChannelsPage.toBeVisible();
// # Stub the Notification in the admin's browser to capture notifications
await pw.stubNotification(adminPage, 'granted');
// # Log in as the regular user in a separate browser and navigate to the "off-topic" channel
const {channelsPage: otherChannelsPage} = await pw.testBrowser.login(user);
await otherChannelsPage.goto(team.name, 'off-topic');
await otherChannelsPage.toBeVisible();
// # Post a channel-wide mention message "@ALL" in uppercase from the user's browser
const message = `@ALL good morning, ${team.name}!`;
await otherChannelsPage.postMessage(message);
// * Verify notification is received in the admin's browser with correct content
const notifications = await pw.waitForNotification(adminPage);
expect(notifications.length).toBe(1);
const notification = notifications[0];
expect(notification.title).toBe('Off-Topic');
expect(notification.body).toBe(`@${user.username}: ${message}`);
// The Notifications API tag must not leak the message body; the app uses the
// opaque post ID as the tag so notifications coalesce per conversation.
const otherLastPost = await otherChannelsPage.getLastPost();
expect(notification.tag).toBe(await otherLastPost.getId());
expect(notification.tag).not.toContain(message);
expect(notification.icon).toContain('.png');
expect(notification.requireInteraction).toBe(false);
expect(notification.silent).toBe(false);
// * Verify the last post as viewed by the regular user in the "off-topic" channel contains the message and is highlighted
await otherLastPost.toContainText(message);
await expect(otherLastPost.container.locator('.mention--highlight')).toBeVisible();
await expect(otherLastPost.container.locator('.mention--highlight').getByText('@ALL')).toBeVisible();
// # Navigate admin to the "off-topic" channel
await adminChannelsPage.goto(team.name, 'off-topic');
// * Verify the message is posted and highlighted correctly for the admin user
const adminLastPost = await adminChannelsPage.getLastPost();
await adminLastPost.toContainText(message);
await expect(adminLastPost.container.locator('.mention--highlight')).toBeVisible();
await expect(adminLastPost.container.locator('.mention--highlight').getByText('@ALL')).toBeVisible();
},
);
/**
* @objective Verify a channel-wide mention typed in mixed case (@channEL) is recognized as a mention,
* prompts the notify-all confirmation, and is posted with its original casing preserved.
*/
test(
'MM-T484 recognizes a mixed-case @channEL channel-wide mention and preserves its casing',
{tag: '@notifications'},
async ({pw}) => {
const {adminClient, team, user} = await pw.initSetup();
// # Add enough members so the channel exceeds the notify-all threshold
for (let i = 0; i < NOTIFY_ALL_THRESHOLD; i++) {
const extraUser = await pw.createNewUserProfile(adminClient, {prefix: 'channel-wide'});
await adminClient.addToTeam(team.id, extraUser.id);
}
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Type a mixed-case channel-wide mention and send it
const message = `@channEL mixed case mention ${pw.random.id()}`;
await channelsPage.centerView.postCreate.writeMessage(message);
await channelsPage.centerView.postCreate.sendMessage();
// * Verify the notify-all confirmation modal appears (mention was recognized despite casing)
const confirmModal = channelsPage.getConfirmModal(NOTIFY_ALL_TITLE);
await confirmModal.toBeVisible();
// # Confirm sending the notification
await confirmModal.confirm();
// * Verify the posted message preserves the mixed-case mention
const lastPost = await channelsPage.getLastPost();
await lastPost.toContainText(message);
},
);
/**
* @objective Verify an @HERE channel-wide mention typed in uppercase is recognized as a mention,
* prompts the notify-all confirmation, and keeps its uppercase casing after switching channels.
*/
test(
'MM-T485 recognizes an uppercase @HERE channel-wide mention and preserves its casing',
{tag: '@notifications'},
async ({pw}) => {
const {adminClient, team, user} = await pw.initSetup();
// # Add enough members so the channel exceeds the notify-all threshold
for (let i = 0; i < NOTIFY_ALL_THRESHOLD; i++) {
const extraUser = await pw.createNewUserProfile(adminClient, {prefix: 'channel-wide'});
await adminClient.addToTeam(team.id, extraUser.id);
}
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'off-topic');
await channelsPage.toBeVisible();
// * Verify the "Channel-wide mentions" keyword is enabled by default in notification settings
const settingsModal = await channelsPage.openSettings();
const notificationSettings = await settingsModal.openNotificationsTab();
await notificationSettings.keywordsTriggerNotificationsEditButton.click();
await expect(notificationSettings.channelWideMentionsCheckbox).toBeChecked();
await settingsModal.close();
// # Type an uppercase channel-wide mention and send it
const message = `@HERE channel-wide mention ${pw.random.id()}`;
await channelsPage.centerView.postCreate.writeMessage(message);
await channelsPage.centerView.postCreate.sendMessage();
// * Verify the notify-all confirmation modal appears (mention was recognized despite uppercase)
const confirmModal = channelsPage.getConfirmModal(NOTIFY_ALL_TITLE);
await confirmModal.toBeVisible();
// # Confirm sending the notification
await confirmModal.confirm();
// * Verify the posted message preserves the uppercase mention
const lastPost = await channelsPage.getLastPost();
await lastPost.toContainText(message);
// # Switch to another channel and back
await channelsPage.sidebarLeft.goToItem('town-square');
await channelsPage.sidebarLeft.goToItem('off-topic');
// * Verify the uppercase mention is still shown after returning to the channel
const postAfterSwitch = await channelsPage.getLastPost();
await postAfterSwitch.toContainText(message);
},
);