snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import type {Page} from '@playwright/test';
|
||||
|
||||
import type {PlaywrightExtended} from '@mattermost/playwright-lib';
|
||||
import {expect, test} from '@mattermost/playwright-lib';
|
||||
|
||||
test.describe('Post dot menu in mobile view', () => {
|
||||
// A narrow width triggers the mobile/responsive layout, where the post
|
||||
// actions ("…") menu is rendered inside a full-screen modal instead of a popover.
|
||||
test.use({viewport: {width: 400, height: 900}});
|
||||
|
||||
/**
|
||||
* @objective Clicking the dimmed area outside the post actions menu dismisses it in mobile view.
|
||||
*/
|
||||
test('closes the post actions menu when clicking outside it', {tag: '@channels'}, async ({pw}) => {
|
||||
const {page, post, copyTextMenuItem} = await openMobilePostActionsMenu(
|
||||
pw,
|
||||
'Message for mobile dot menu outside-click test',
|
||||
);
|
||||
|
||||
// # Click the dimmed area directly above the menu, then reopen and click below it
|
||||
await clickDimmedArea(page, 'above');
|
||||
|
||||
// * The menu is dismissed
|
||||
await expect(copyTextMenuItem).toBeHidden();
|
||||
|
||||
// # Reopen the menu
|
||||
await post.hover();
|
||||
await post.postMenu.openDotMenu();
|
||||
await expect(copyTextMenuItem).toBeVisible();
|
||||
|
||||
// # Click the dimmed area below the menu
|
||||
await clickDimmedArea(page, 'below');
|
||||
|
||||
// * The menu is dismissed again
|
||||
await expect(copyTextMenuItem).toBeHidden();
|
||||
});
|
||||
|
||||
/**
|
||||
* @objective Selecting a menu item still dismisses the menu in mobile view. This guards that the
|
||||
* outside-click fix (which relies on pointer-events) does not break interaction with the items.
|
||||
*/
|
||||
test('closes the post actions menu when a menu item is selected', {tag: '@channels'}, async ({pw}) => {
|
||||
const {copyTextMenuItem} = await openMobilePostActionsMenu(pw, 'Message for mobile dot menu item-click test');
|
||||
|
||||
// # Select a menu item
|
||||
await copyTextMenuItem.click();
|
||||
|
||||
// * The menu is dismissed
|
||||
await expect(copyTextMenuItem).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
// Logs in a fresh user, posts a message, and opens the post actions ("…") menu on it.
|
||||
async function openMobilePostActionsMenu(pw: PlaywrightExtended, message: string) {
|
||||
// # Initialize a user and log in
|
||||
const {user} = await pw.initSetup();
|
||||
const {channelsPage, page} = await pw.testBrowser.login(user);
|
||||
|
||||
// # Post a message in the default channel
|
||||
await channelsPage.goto();
|
||||
await channelsPage.toBeVisible();
|
||||
await channelsPage.postMessage(message);
|
||||
|
||||
// # Open the post actions ("…") menu on the message
|
||||
const post = await channelsPage.getLastPost();
|
||||
await post.toBeVisible();
|
||||
await post.hover();
|
||||
await post.postMenu.toBeVisible();
|
||||
await post.postMenu.openDotMenu();
|
||||
|
||||
// * The menu opens with its items visible
|
||||
const copyTextMenuItem = page.getByRole('menuitem', {name: 'Copy Text'});
|
||||
await expect(copyTextMenuItem).toBeVisible();
|
||||
|
||||
// # Wait for the modal's entrance animation to finish, so the menu has stopped sliding before
|
||||
// # clickDimmedArea() measures where it is
|
||||
await expect(page.locator('.menuModal').locator('..')).toHaveCSS('opacity', '1');
|
||||
|
||||
return {channelsPage, page, post, copyTextMenuItem};
|
||||
}
|
||||
|
||||
// Clicks the dimmed backdrop area of the open menu modal, above or below the menu list. The point is
|
||||
// chosen to fall inside the modal dialog but outside the menu items, which is exactly the region the fix
|
||||
// makes dismissible. It deliberately avoids the outer `.modal` container area beyond the dialog, which
|
||||
// react-bootstrap already dismisses regardless of the fix (so clicking there would not test the fix).
|
||||
async function clickDimmedArea(page: Page, position: 'above' | 'below') {
|
||||
const dialogBox = await page.locator('.menuModal').boundingBox();
|
||||
const listBox = await page.locator('.menuModal .MuiList-root').boundingBox();
|
||||
expect(dialogBox).not.toBeNull();
|
||||
expect(listBox).not.toBeNull();
|
||||
|
||||
// Click just outside the menu list, staying close to it so the point remains within the modal
|
||||
// dialog's dimmed area. The guards assert the point sits inside the dialog bounds but outside the
|
||||
// list, i.e. the region the fix makes dismissible (never the outer `.modal` region beyond the
|
||||
// dialog, which dismisses regardless of the fix).
|
||||
const gap = 25;
|
||||
const x = listBox!.x + listBox!.width / 2;
|
||||
let y: number;
|
||||
if (position === 'above') {
|
||||
y = listBox!.y - gap;
|
||||
expect(y).toBeGreaterThan(dialogBox!.y);
|
||||
expect(y).toBeLessThan(listBox!.y);
|
||||
} else {
|
||||
const listBottom = listBox!.y + listBox!.height;
|
||||
y = listBottom + gap;
|
||||
expect(y).toBeGreaterThan(listBottom);
|
||||
expect(y).toBeLessThan(dialogBox!.y + dialogBox!.height);
|
||||
}
|
||||
|
||||
await page.mouse.click(x, y);
|
||||
}
|
||||
Reference in New Issue
Block a user