mirror of
https://github.com/mattermost/mattermost.git
synced 2026-11-02 20:31:01 -06:00
fix(e2e): repair master flakes from the channel intro user limit and tour-tip pulse rings (#38986)
* fix(e2e): repair file_permissions_edge_cases.spec.ts on master MM-T5828 built its permalink from testConfig.internalBaseURL and assumed the server's SiteURL still matched. pw.ensureSiteUrl() restarts the Mattermost container with MM_SERVICESETTINGS_SITEURL pointing at the host-reachable baseURL, and because that is an env override, initSetup()'s patchConfig cannot put it back. On a reused server, every spec that runs after an auth/claim or oidc spec therefore sees a SiteURL the permalink no longer matches, the server emits no permalink embed, and .post-preview never renders. Read SiteURL off the running server instead of assuming it. Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com> * fix(e2e): share permalinkUrl helper across SiteURL-sensitive specs Build /pl/ permalinks from the SiteURL the running server reports, via one helper used by MM-T5828 and the post_list specs that had the same internalBaseURL assumption. Co-authored-by: mattermost-code <matty-code@mattermost.com> * fix(e2e): reject empty SiteURL in permalinkUrl helper Fail fast instead of building a relative /pl/ path when the server reports no SiteURL. Co-authored-by: mattermost-code <matty-code@mattermost.com> * fix(e2e): converge SiteURL for demo_dialog interactive dialogs demo_dialog.spec.ts's two bare-/dialog tests fail on any CI worker that earlier ran a spec calling pw.ensureSiteUrl(). The demo plugin registers its dialog callback as <SiteURL>/plugins/<id>/dialog/1, and App.DoActionRequest only dispatches in-process for relative URLs, so an absolute one is a real outbound POST. Once SiteURL points at the host-mapped baseURL the server cannot reach that address from inside its own container: the submit returns 400, leaving the dialog open, and the cancel posts no notification. Add pw.ensureInternalSiteUrl(), which converges SiteURL back to internalBaseURL and is a no-op on a stack booted with the default, and call it from the two tests whose callback URL is absolute. Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com> * fix(e2e): repair channel_headers.spec.ts MM-T880 on master A channel intro replaces its action buttons -- favorite, "Set header" and notification preferences -- with just the invite button while the server has fewer users than the webapp's usersLimit of 10. On a reused Testcontainers server that count depends on how many specs the worker ran before, so MM-T880's click on the intro's "Set header" button only found it by luck. Add ensureChannelIntroActions(), which tops the server up to that many users, and call it from the test. Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com> * fix(webapp): stop tour-tip pulse rings from swallowing clicks PulsatingDot's ::before/::after rings animate to scale(2.5), 30px across a 12px dot, and were hit-testable. The burn-on-read tour tip puts that dot on top of the burn-on-read button, so for ~77% of every 2s pulse cycle the element at the button's own centre is the dot, not the button. A click whose mousedown and mouseup land on different elements is delivered to their nearest common ancestor, so when a ring crosses the cursor between the two, `click` fires on .BurnOnReadControl and neither the button's toggle nor the tip's open handler runs. That is the intermittent dm_gm_flow.spec.ts "MM-66742_1 BoR toggle is available in DM channel" failure on master: the click reports success and the BURN ON READ label never appears. The rings are decoration; the dot itself stays clickable. https://github.com/mattermost/mattermost/actions/runs/37978315300 Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com> * fix(e2e): drop the permalinkUrl helper now that master resets SiteURL per spec #39091's ensureDefaultServerEnv() restores the default SiteURL before each spec file, so the permalink specs pass with master's own copies (12/12 and 210/210 on a server with a leaked SiteURL). Revert them and remove the helper. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: mattermost-code <matty-code@mattermost.com> Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
This commit is contained in:
5 files changed
+33
-1
No files matched your search
@@ -16,6 +16,7 @@ export {createNewTeam, createRandomTeam} from './team';
|
||||
export {
|
||||
createNewUserProfile,
|
||||
createRandomUser,
|
||||
ensureChannelIntroActions,
|
||||
getDefaultAdminUser,
|
||||
isOutsideRemoteUserHour,
|
||||
setDefaultOnboardingPreferences,
|
||||
|
||||
@@ -43,6 +43,26 @@ export async function createNewUserProfile(
|
||||
return newUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* `usersLimit` in webapp/channels/src/components/post_view/channel_intro_message/index.ts.
|
||||
* Below it, a channel intro shows only the invite button and drops the favorite, "Set header"
|
||||
* and notification preferences buttons.
|
||||
*/
|
||||
const CHANNEL_INTRO_ACTIONS_MIN_USERS = 10;
|
||||
|
||||
/**
|
||||
* Creates throwaway users until the server has enough of them for a channel intro to render its
|
||||
* action buttons. Specs that drive those buttons must call this: on a reused server the user
|
||||
* count depends on how many specs ran before, so the buttons are otherwise there only by luck.
|
||||
*/
|
||||
export async function ensureChannelIntroActions(client: Client4) {
|
||||
const {total_users_count: totalUsers} = await client.getTotalUsersStats();
|
||||
|
||||
for (let i = totalUsers; i < CHANNEL_INTRO_ACTIONS_MIN_USERS; i++) {
|
||||
await client.createUser(await createRandomUser('introfill'), '', '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the tutorial and first-time onboarding task list as already seen for the given
|
||||
* user, so they don't cover the UI on their first visit to a channel. Useful for users
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
elasticsearchServerConfig,
|
||||
enableAIBridgeTestMode,
|
||||
ensureAzurite,
|
||||
ensureChannelIntroActions,
|
||||
ensureDemoPlugin,
|
||||
ensureElasticsearch,
|
||||
ensureFeatureFlag,
|
||||
@@ -200,6 +201,7 @@ export class PlaywrightExtended {
|
||||
readonly getFileFromAsset;
|
||||
|
||||
// ./server
|
||||
readonly ensureChannelIntroActions;
|
||||
readonly ensurePluginsLoaded;
|
||||
readonly getAdminClient;
|
||||
readonly resetConfig;
|
||||
@@ -330,6 +332,7 @@ export class PlaywrightExtended {
|
||||
this.getFileFromAsset = getFileFromAsset;
|
||||
|
||||
// ./server
|
||||
this.ensureChannelIntroActions = ensureChannelIntroActions;
|
||||
this.ensurePluginsLoaded = ensurePluginsLoaded;
|
||||
this.initSetup = initSetup;
|
||||
this.getAdminClient = getAdminClient;
|
||||
|
||||
+5
-1
@@ -57,7 +57,11 @@ test(
|
||||
* that cancelling the modal makes no change, and that the saved header appears in the channel info.
|
||||
*/
|
||||
test('MM-T880 adds a channel header from the intro Set header link', {tag: '@channel_settings'}, async ({pw}) => {
|
||||
const {user, team} = await pw.initSetup();
|
||||
const {adminClient, user, team} = await pw.initSetup();
|
||||
|
||||
// # Make sure the channel intro offers its action buttons instead of only the invite button
|
||||
await pw.ensureChannelIntroActions(adminClient);
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
// The pulse rings grow to 2.5x the dot and are purely decorative. Left hit-testable they
|
||||
// cover whatever the dot is placed over -- e.g. the burn-on-read button it sits on -- and
|
||||
// swallow clicks meant for it.
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
@@ -25,6 +28,7 @@
|
||||
left: 0;
|
||||
display: block;
|
||||
content: "";
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&::after {
|
||||
|
||||
Reference in new issue
Block a user