mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
* SEC-10179 Integrate test system IO for Playwright and Cypress (#36376) * change retry to 1, fixed and disabled failed tests * add v2 templates for Cypress and Playwright E2E tests with test system io integration * add commenting to pr * identify more playwrights to fix separately * disable deletion-report.spec for separate fix --------- Co-authored-by: Mattermost Build <[email protected]> * fix: permission required by test-system-io actions (#36477) * fix: permission required by e2e test-system-io actions (#36478) Co-authored-by: sabril <[email protected]> * chore(ci): consolidate openldap runner prep into a composite action (#36563) Co-authored-by: sabril <[email protected]> * ci: port test-system-io v2 templates from release-11.9 Bring Playwright/Cypress template-v2 in line with release-11.9 so they include prepare-run/prep-deps caching, runner-prep-openldap, and pinned mattermost-test-system-io action SHAs (1631d8fcea24). Bump Playwright v2 workers to 10 to match 11.8/11.9. Prerequisite for cherry-picking #37570 (testcontainers) onto release-11.7. Co-authored-by: sabril <[email protected]> * E2E/Playwright: Add testcontainers to playwright-lib (#37570) * add testcontainers to playwright-lib * include retry mechanism for transient failures * - Introduced a new command `testcontainers:up` in package.json to run Playwright tests with Testcontainers. - Created a standalone Playwright configuration file `playwright.testcontainers-up.config.ts` for managing Testcontainers. - Added a no-op test `testcontainers_up.spec.ts` to ensure the Testcontainers stack is up during the test run. - Implemented a global setup script `testcontainers_up_global_setup.ts` to start and stop the Testcontainers stack. - Updated dependencies in package.json, including adding `chalk` for logging. * fix package-lock * fix tsc and restore waiting for all migrations to complete --------- Co-authored-by: Mattermost Build <[email protected]> * fix(e2e): remove obsolete CRT intro modal dismiss from uiClickSidebarItem The CRT tutorial modal was removed in MM-66470; dismissing #genericModalLabel races and flakes MM-T4261_3. Co-authored-by: sabril <[email protected]> * fix(e2e): sync Playwright navigations to live testcontainers baseURL After restartMattermostContainer remaps the host port, relative page.goto must follow testConfig.baseURL rather than the worker-start config value. Co-authored-by: sabril <[email protected]> * fix(e2e): restore eslint-disable for axe empty fixture pattern Co-authored-by: sabril <[email protected]> * fix(e2e): ignore webhook assets in eslint; prettier README Co-authored-by: sabril <[email protected]> * fix(e2e): prettier-format testcontainers config helpers Co-authored-by: sabril <[email protected]> * ci(e2e): fully adopt test-system-io and lighten Playwright services Port #37413: drop the dual v1/v2 dispatch path, promote the test-system-io templates to the canonical names, and remove legacy calculate-results / AWS artifact upload plumbing. For Playwright testcontainers on this release, leave optional sidecars (openldap, keycloak, elasticsearch, opensearch, minio, azurite, webhook) off by default and remove the related service-specific specs that are not part of the older suite. Co-authored-by: sabril <[email protected]> * style(e2e): prettier stack.ts after optional webhook change Co-authored-by: sabril <[email protected]> * ci(e2e): grant contents:read to test-system-io workflow callers Reusable Playwright/Cypress templates require contents:read. Without it on the caller job, GitHub Actions fails the workflow at startup. Co-authored-by: sabril <[email protected]> * ci: retrigger enterprise build after transient npm cache failure Co-authored-by: sabril <[email protected]> * test(e2e): align testcontainers feature flags with release docker-compose Mirror MM_FEATUREFLAGS_* from e2e-tests/.ci/server.generate.sh for each release, dropping flags that do not exist in that release's FeatureFlags struct (or were never enabled in the compose stack). Co-authored-by: sabril <[email protected]> * ci: retrigger enterprise after flaky message_export Postgres failure Co-authored-by: sabril <[email protected]> * e2e(playwright): omit unset Testcontainers env keys; align release docs When optional webhook/sidecars are off, .env.testcontainers no longer writes PW_*=undefined. Docs match empty DEFAULT_TESTCONTAINERS_SERVICES. Co-authored-by: sabril <[email protected]> * e2e(playwright): prettier-format lib/README.md table Fixes CI npm run check (prettier) failures from the services table edit. Co-authored-by: sabril <[email protected]> * ci: retrigger E2E after Cypress commit-status race Orchestration reported 1 failed unit before retest; final summary was 100% but commit status stayed failure. Retrigger for a clean green. Co-authored-by: sabril <[email protected]> * e2e(cypress): keep tests/support/env import on release-11.7 #36376 switched message_deletion_spec to @/support/env, but this release has no Cypress webpack @ alias (added later). That caused a Webpack Module not found failure and a stuck failed commit status. Co-authored-by: sabril <[email protected]> --------- Co-authored-by: Mattermost Build <[email protected]> Co-authored-by: sabril <[email protected]> Co-authored-by: yasser khan <[email protected]> Co-authored-by: Hanzo Dev <[email protected]>
270 lines
8.1 KiB
TypeScript
270 lines
8.1 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import {ChainableT} from '../../types';
|
|
|
|
Cypress.Commands.add('uiGetLHS', () => {
|
|
return cy.get('#SidebarContainer').should('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('uiGetLHSHeader', () => {
|
|
return cy.uiGetLHS().
|
|
find('#sidebarTeamMenuButton').
|
|
should('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('uiOpenTeamMenu', (item = '') => {
|
|
// # Click on LHS header
|
|
cy.uiGetLHSHeader().click();
|
|
|
|
if (!item) {
|
|
// # Return the menu if no item is passed
|
|
return cy.uiGetLHSTeamMenu();
|
|
}
|
|
|
|
// # Click on a particular item
|
|
return cy.uiGetLHSTeamMenu().
|
|
findByText(item).
|
|
scrollIntoView().
|
|
should('be.visible').
|
|
click();
|
|
});
|
|
|
|
Cypress.Commands.add('uiGetLHSAddChannelButton', () => {
|
|
return cy.uiGetLHS().findByRole('button', {name: 'Browse or create channels'});
|
|
});
|
|
|
|
Cypress.Commands.add('uiGetLHSTeamMenu', () => {
|
|
return cy.get('#sidebarTeamMenu');
|
|
});
|
|
|
|
function uiOpenSystemConsoleMenu(item = ''): ChainableT<JQuery> {
|
|
// # Click on LHS header button
|
|
cy.uiGetSystemConsoleButton().click();
|
|
|
|
if (!item) {
|
|
// # Return the menu if no item is passed
|
|
return cy.uiGetSystemConsoleMenu();
|
|
}
|
|
|
|
// # Click on a particular item
|
|
return cy.uiGetSystemConsoleMenu().
|
|
findByText(item).
|
|
scrollIntoView().
|
|
should('be.visible').
|
|
click();
|
|
}
|
|
|
|
Cypress.Commands.add('uiOpenSystemConsoleMenu', uiOpenSystemConsoleMenu);
|
|
|
|
function uiGetSystemConsoleButton(): ChainableT<JQuery> {
|
|
return cy.get('.admin-sidebar').
|
|
findByRole('button', {name: 'Menu Icon'});
|
|
}
|
|
|
|
Cypress.Commands.add('uiGetSystemConsoleButton', uiGetSystemConsoleButton);
|
|
|
|
function uiGetSystemConsoleMenu(): ChainableT<JQuery> {
|
|
return cy.get('.admin-sidebar').
|
|
find('.dropdown-menu').
|
|
should('be.visible');
|
|
}
|
|
|
|
Cypress.Commands.add('uiGetSystemConsoleMenu', uiGetSystemConsoleMenu);
|
|
|
|
Cypress.Commands.add('uiGetLhsSection', (section) => {
|
|
if (section === 'UNREADS') {
|
|
return cy.findByText(section).
|
|
parent().
|
|
parent().
|
|
parent();
|
|
}
|
|
|
|
return cy.findAllByRole('button', {name: section}).
|
|
first().
|
|
parent().
|
|
parent().
|
|
parent();
|
|
});
|
|
|
|
Cypress.Commands.add('uiBrowseOrCreateChannel', (menuitem) => {
|
|
cy.uiGetLHSAddChannelButton().should('be.visible').click();
|
|
|
|
cy.get('#browserOrAddChannelMenu').
|
|
should('exist').and('be.visible').
|
|
within(() => {
|
|
if (menuitem) {
|
|
cy.findByText(menuitem).should('exist').click();
|
|
}
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('uiAddDirectMessage', () => {
|
|
return cy.findByRole('button', {name: 'Write a direct message'});
|
|
});
|
|
|
|
Cypress.Commands.add('uiGetFindChannels', () => {
|
|
return cy.get('#lhsNavigator').findByRole('button', {name: 'Find Channels'});
|
|
});
|
|
|
|
Cypress.Commands.add('uiOpenFindChannels', () => {
|
|
cy.uiGetFindChannels().click();
|
|
});
|
|
|
|
function uiGetSidebarThreadsButton(): ChainableT<JQuery> {
|
|
return cy.get('#sidebar-threads-button').should('be.visible');
|
|
}
|
|
Cypress.Commands.add('uiGetSidebarThreadsButton', uiGetSidebarThreadsButton);
|
|
|
|
Cypress.Commands.add('uiGetChannelSidebarMenu', (channelName, isChannelId = false) => {
|
|
cy.uiGetLHS().within(() => {
|
|
if (isChannelId) {
|
|
cy.get(`#sidebarItem_${channelName}`).should('be.visible').find('button').should('exist').click({force: true});
|
|
} else {
|
|
cy.findByText(channelName).should('be.visible').parents('a').find('button').should('exist').click({force: true});
|
|
}
|
|
});
|
|
|
|
return cy.findByRole('menu', {name: 'Edit channel menu'}).should('be.visible');
|
|
});
|
|
|
|
Cypress.Commands.add('uiClickSidebarItem', (name) => {
|
|
cy.uiGetSidebarItem(name).click({force: true});
|
|
|
|
if (name === 'threads') {
|
|
// CRT intro modal was removed in MM-66470; only wait for the threads view to settle.
|
|
cy.get('#tutorial-threads-mobile-header span.Button_label').contains('Followed threads');
|
|
} else {
|
|
cy.findAllByTestId('postView').last().scrollIntoView().should('be.visible');
|
|
}
|
|
});
|
|
|
|
Cypress.Commands.add('uiGetSidebarItem', (channelName) => {
|
|
return cy.get(`#sidebarItem_${channelName}`);
|
|
});
|
|
|
|
declare global {
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
namespace Cypress {
|
|
interface Chainable {
|
|
|
|
/**
|
|
* Get LHS
|
|
*
|
|
* @example
|
|
* cy.uiGetLHS();
|
|
*/
|
|
uiGetLHS(): Chainable;
|
|
|
|
/**
|
|
* Get LHS header
|
|
*
|
|
* @example
|
|
* cy.uiGetLHSHeader().click();
|
|
*/
|
|
uiGetLHSHeader(): Chainable;
|
|
|
|
/**
|
|
* Open team menu
|
|
*
|
|
* @param {string} item - ex. 'Invite People', 'Team Settings', etc.
|
|
*
|
|
* @example
|
|
* cy.uiOpenTeamMenu();
|
|
*/
|
|
uiOpenTeamMenu(item?: string): Chainable;
|
|
|
|
/**
|
|
* Get LHS add channel button
|
|
*
|
|
* @example
|
|
* cy.uiGetLHSAddChannelButton().click();
|
|
*/
|
|
uiGetLHSAddChannelButton(): Chainable;
|
|
|
|
/**
|
|
* Get LHS team menu
|
|
*
|
|
* @example
|
|
* cy.uiGetLHSTeamMenu().should('not.exist);
|
|
*/
|
|
uiGetLHSTeamMenu(): Chainable;
|
|
|
|
/**
|
|
* Get LHS section
|
|
* @param {string} section - section such as UNREADS, CHANNELS, FAVORITES, DIRECT MESSAGES and other custom category
|
|
*
|
|
* @example
|
|
* cy.uiGetLhsSection('CHANNELS');
|
|
*/
|
|
uiGetLhsSection(section: string): Chainable;
|
|
|
|
/**
|
|
* Open menu to browse or create channel
|
|
* @param {string} item - dropdown menu. If set, it will do click action.
|
|
*
|
|
* @example
|
|
* cy.uiBrowseOrCreateChannel('Browse channels');
|
|
*/
|
|
uiBrowseOrCreateChannel(item: string): Chainable;
|
|
|
|
/**
|
|
* Get "+" button to write a direct message
|
|
* @example
|
|
* cy.uiAddDirectMessage();
|
|
*/
|
|
uiAddDirectMessage(): Chainable;
|
|
|
|
/**
|
|
* Get find channels button
|
|
* @example
|
|
* cy.uiGetFindChannels();
|
|
*/
|
|
uiGetFindChannels(): Chainable;
|
|
|
|
/**
|
|
* Open find channels
|
|
* @example
|
|
* cy.uiOpenFindChannels();
|
|
*/
|
|
uiOpenFindChannels(): Chainable;
|
|
|
|
/**
|
|
* Open menu of a channel in the sidebar
|
|
* @param {string} channelName - name of channel, ex. 'town-square'
|
|
* @param {boolean} isChannelId - default false. If true, it will use channel id instead of channel name
|
|
* @example
|
|
* cy.uiGetChannelSidebarMenu('Town Square');
|
|
* cy.uiGetChannelSidebarMenu('user1212__user333', true);
|
|
*/
|
|
uiGetChannelSidebarMenu(channelName: string, isChannelId?: boolean): Chainable;
|
|
|
|
/**
|
|
* Click sidebar item by channel or thread name
|
|
* @param {string} name - channel name for channels, and threads for Global Threads
|
|
*
|
|
* @example
|
|
* cy.uiClickSidebarItem('town-square');
|
|
*/
|
|
uiClickSidebarItem(name: string): Chainable;
|
|
|
|
/**
|
|
* Get sidebar item by channel or thread name
|
|
* @param {string} name - channel name for channels, and threads for Global Threads
|
|
*
|
|
* @example
|
|
* cy.uiGetSidebarItem('town-square').find('.badge').should('be.visible');
|
|
*/
|
|
uiGetSidebarItem(name: string): Chainable;
|
|
|
|
uiOpenSystemConsoleMenu: typeof uiOpenSystemConsoleMenu;
|
|
|
|
uiGetSystemConsoleButton: typeof uiGetSystemConsoleButton;
|
|
|
|
uiGetSystemConsoleMenu: typeof uiGetSystemConsoleMenu;
|
|
|
|
uiGetSidebarThreadsButton: typeof uiGetSidebarThreadsButton;
|
|
}
|
|
}
|
|
}
|