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

87 lines
3.9 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
/**
* @objective Verify that clicking a post timestamp in the RHS or center channel highlights the post in the center channel.
*/
test('MM-T176 highlights the center post when its timestamp is clicked', {tag: '@messaging'}, async ({pw}) => {
// # Create and log in as a test user
const {user, team} = await pw.initSetup();
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'town-square');
await channelsPage.toBeVisible();
// # Post a message and open its thread, then reply in the RHS
await channelsPage.postMessage(`timestamp highlight ${pw.random.id()}`);
const rootPost = await channelsPage.getLastPost();
const rootId = await rootPost.getId();
await rootPost.reply();
await channelsPage.sidebarRight.toBeVisible();
await channelsPage.sidebarRight.postMessage('Reply to test timestamp click');
// # Click the root post timestamp in the RHS
await page.locator(`#RHS_ROOT_time_${rootId}`).click();
// * Verify the matching post is highlighted in the center channel
const centerPost = await channelsPage.centerView.getPostById(rootId);
await expect(centerPost.container).toHaveClass(/post--highlight/);
// # Close the RHS and wait for the highlight to fade
await channelsPage.sidebarRight.close();
await expect(centerPost.container).not.toHaveClass(/post--highlight/);
// # Click the same post timestamp in the center channel
await page.locator(`#CENTER_time_${rootId}`).click();
// * Verify the post is highlighted again in the center channel
await expect(centerPost.container).toHaveClass(/post--highlight/);
});
/**
* @objective Verify that following a permalink to the first post in a channel loads the channel start without an endless loading indicator above it.
*/
test('MM-T3308 follows a permalink to the first post without endless loading', {tag: '@messaging'}, async ({pw}) => {
const messageCount = 10;
const base = `permalink-${pw.random.id()}`;
// # Create and log in as a test user, and create a private channel with several posts
const {user, team, adminClient} = await pw.initSetup();
const privateChannel = await adminClient.createPrivateChannel(team.id, 'Permalink First');
await adminClient.addToChannel(user.id, privateChannel.id);
let firstPostId = '';
for (let i = 1; i <= messageCount; i++) {
const created = await adminClient.createPost({channel_id: privateChannel.id, message: `${base}-${i}`});
if (i === 1) {
firstPostId = created.id;
}
}
const {channelsPage, page} = await pw.testBrowser.login(user);
await channelsPage.goto(team.name, 'off-topic');
await channelsPage.toBeVisible();
// # Post a permalink to the first (oldest) post into the public channel
const permalink = `${new URL(page.url()).origin}/${team.name}/pl/${firstPostId}`;
await channelsPage.postMessage(permalink);
await channelsPage.centerView.waitUntilLastPostContains(permalink);
// # Click the permalink in the posted message
const permalinkPost = await channelsPage.getLastPost();
await permalinkPost.body.getByRole('link', {name: permalink}).click();
// * Verify navigation lands in the target private channel
await expect
.poll(() => page.url(), {timeout: pw.duration.ten_sec})
.toContain(`/${team.name}/channels/${privateChannel.name}`);
// * Verify the channel start intro is shown, proving the top loaded without an endless loading indicator
await expect(page.getByText(`This is the start of ${privateChannel.display_name}`)).toBeVisible();
// * Verify the most recent post is the last message that was created
const lastPost = await channelsPage.getLastPost();
await lastPost.toContainText(`${base}-${messageCount}`);
});