MM-52642 CLD-6352 MM-54007 Prepare setup for Playwright pipeline (#24647)
* pipeline(playwright): prepare setup for playwright * feedback address * clean up readme * Fix docker-compose command and definition for dashboard * fix the dashboard * ignore dashboard when formatting --------- Co-authored-by: Mattermost Build <build@mattermost.com> Co-authored-by: Mario Vitale <mvitale1989@hotmail.com>
@@ -45,7 +45,7 @@ npm run test
|
||||
Change to root directory, run docker container
|
||||
|
||||
```
|
||||
docker run -it --rm -v "$(pwd):/mattermost/" --ipc=host mcr.microsoft.com/playwright:v1.38.0-jammy /bin/bash
|
||||
docker run -it --rm -v "$(pwd):/mattermost/" --ipc=host mcr.microsoft.com/playwright:v1.38.1-jammy /bin/bash
|
||||
```
|
||||
|
||||
#### 2. Inside the docker container
|
||||
|
||||
46
e2e-tests/playwright/package-lock.json
сгенерированный
@@ -10,7 +10,7 @@
|
||||
"@axe-core/playwright": "4.7.3",
|
||||
"@percy/cli": "1.27.1",
|
||||
"@percy/playwright": "1.0.4",
|
||||
"@playwright/test": "1.38.0",
|
||||
"@playwright/test": "1.38.1",
|
||||
"async-wait-until": "2.0.12",
|
||||
"axe-core": "4.8.1",
|
||||
"chalk": "4.1.2",
|
||||
@@ -488,11 +488,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz",
|
||||
"integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==",
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz",
|
||||
"integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==",
|
||||
"dependencies": {
|
||||
"playwright": "1.38.0"
|
||||
"playwright": "1.38.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -2015,11 +2015,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz",
|
||||
"integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==",
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz",
|
||||
"integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.38.0"
|
||||
"playwright-core": "1.38.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -2032,9 +2032,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz",
|
||||
"integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==",
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz",
|
||||
"integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
@@ -2781,11 +2781,11 @@
|
||||
}
|
||||
},
|
||||
"@playwright/test": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz",
|
||||
"integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==",
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz",
|
||||
"integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==",
|
||||
"requires": {
|
||||
"playwright": "1.38.0"
|
||||
"playwright": "1.38.1"
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
@@ -3846,18 +3846,18 @@
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||
},
|
||||
"playwright": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz",
|
||||
"integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==",
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz",
|
||||
"integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==",
|
||||
"requires": {
|
||||
"fsevents": "2.3.2",
|
||||
"playwright-core": "1.38.0"
|
||||
"playwright-core": "1.38.1"
|
||||
}
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz",
|
||||
"integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g=="
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz",
|
||||
"integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg=="
|
||||
},
|
||||
"prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
{
|
||||
"scripts": {
|
||||
"test": "cross-env PW_SNAPSHOT_ENABLE=true playwright test",
|
||||
"percy": "cross-env PERCY_TOKEN=$PERCY_TOKEN PW_PERCY_ENABLE=true percy exec -- playwright test --project=chrome --project=iphone --project=ipad",
|
||||
"test": "cross-env NODE_OPTIONS='--no-experimental-fetch' PW_SNAPSHOT_ENABLE=true playwright test",
|
||||
"test:update-snapshots": "cross-env NODE_OPTIONS='--no-experimental-fetch' PW_SNAPSHOT_ENABLE=true playwright test --update-snapshots",
|
||||
"percy": "cross-env NODE_OPTIONS='--no-experimental-fetch' PERCY_TOKEN=$PERCY_TOKEN PW_PERCY_ENABLE=true percy exec -- playwright test --project=chrome --project=ipad",
|
||||
"tsc": "tsc -b",
|
||||
"lint": "eslint . --ext .js,.ts",
|
||||
"prettier": "prettier . --check",
|
||||
"prettier:fix": "prettier --write .",
|
||||
"check": "npm run tsc && npm run lint && npm run prettier",
|
||||
"codegen": "cross-env playwright codegen $PW_BASE_URL",
|
||||
"playwright-ui": "playwright test --ui",
|
||||
"test-slomo": "cross-env PW_SNAPSHOT_ENABLE=true PW_SLOWMO=1000 playwright test",
|
||||
"playwright-ui": "cross-env NODE_OPTIONS='--no-experimental-fetch' playwright test --ui",
|
||||
"test-slomo": "cross-env NODE_OPTIONS='--no-experimental-fetch' PW_SNAPSHOT_ENABLE=true PW_SLOWMO=1000 playwright test",
|
||||
"show-report": "npx playwright show-report",
|
||||
"postinstall": "npx playwright install"
|
||||
},
|
||||
@@ -17,7 +18,7 @@
|
||||
"@axe-core/playwright": "4.7.3",
|
||||
"@percy/cli": "1.27.1",
|
||||
"@percy/playwright": "1.0.4",
|
||||
"@playwright/test": "1.38.0",
|
||||
"@playwright/test": "1.38.1",
|
||||
"async-wait-until": "2.0.12",
|
||||
"axe-core": "4.8.1",
|
||||
"chalk": "4.1.2",
|
||||
|
||||
@@ -17,9 +17,10 @@ export default defineConfig({
|
||||
workers: testConfig.workers,
|
||||
expect: {
|
||||
timeout: duration.ten_sec,
|
||||
toMatchSnapshot: {
|
||||
toHaveScreenshot: {
|
||||
threshold: 0.4,
|
||||
maxDiffPixelRatio: 0.0001,
|
||||
animations: 'disabled',
|
||||
},
|
||||
},
|
||||
use: {
|
||||
|
||||
@@ -63,6 +63,7 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
},
|
||||
TeamSettings: {
|
||||
EnableOpenServer: true,
|
||||
MaxUsersPerTeam: 2000,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,14 +11,12 @@ export default class ChannelsCenterView {
|
||||
readonly container: Locator;
|
||||
|
||||
readonly header;
|
||||
readonly headerMobile;
|
||||
readonly postCreate;
|
||||
|
||||
constructor(container: Locator) {
|
||||
this.container = container;
|
||||
|
||||
this.header = new components.ChannelsHeader(this.container.locator('.channel-header'));
|
||||
this.headerMobile = new components.ChannelsHeaderMobile(this.container.locator('.navbar'));
|
||||
this.postCreate = new components.ChannelsPostCreate(container.getByTestId('post-create'));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {expect, Locator} from '@playwright/test';
|
||||
|
||||
export default class ChannelsHeaderMobile {
|
||||
readonly container: Locator;
|
||||
|
||||
constructor(container: Locator) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
await expect(this.container).toBeVisible();
|
||||
}
|
||||
|
||||
async toggleSidebar() {
|
||||
await this.container.getByRole('button', {name: 'Toggle sidebar Menu Icon'}).click();
|
||||
}
|
||||
}
|
||||
|
||||
export {ChannelsHeaderMobile};
|
||||
@@ -2,7 +2,6 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ChannelsHeader} from './channels/header';
|
||||
import {ChannelsHeaderMobile} from './channels/header_mobile';
|
||||
import {ChannelsAppBar} from './channels/app_bar';
|
||||
import {ChannelsPostCreate} from './channels/post_create';
|
||||
import {ChannelsPost} from './channels/post';
|
||||
@@ -27,7 +26,6 @@ const components = {
|
||||
ChannelsSidebarRight,
|
||||
ChannelsAppBar,
|
||||
ChannelsHeader,
|
||||
ChannelsHeaderMobile,
|
||||
ChannelsPostCreate,
|
||||
ChannelsPost,
|
||||
FindChannelsModal,
|
||||
@@ -49,7 +47,6 @@ export {
|
||||
ChannelsSidebarRight,
|
||||
ChannelsAppBar,
|
||||
ChannelsHeader,
|
||||
ChannelsHeaderMobile,
|
||||
ChannelsPostCreate,
|
||||
ChannelsPost,
|
||||
FindChannelsModal,
|
||||
|
||||
@@ -7,11 +7,12 @@ import chalk from 'chalk';
|
||||
import {expect, TestInfo} from '@playwright/test';
|
||||
|
||||
import {illegalRe} from '@e2e-support/util';
|
||||
import testConfig, {TestArgs} from '@e2e-test.config';
|
||||
import testConfig from '@e2e-test.config';
|
||||
import {ScreenshotOptions, TestArgs} from '@e2e-types';
|
||||
|
||||
import snapshotWithPercy from './percy';
|
||||
|
||||
export async function matchSnapshot(testInfo: TestInfo, testArgs: TestArgs) {
|
||||
export async function matchSnapshot(testInfo: TestInfo, testArgs: TestArgs, options: ScreenshotOptions = {}) {
|
||||
if (os.platform() !== 'linux') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
@@ -25,7 +26,7 @@ export async function matchSnapshot(testInfo: TestInfo, testArgs: TestArgs) {
|
||||
if (testConfig.snapshotEnabled) {
|
||||
// Visual test with built-in snapshot
|
||||
const filename = testInfo.title.replace(illegalRe, '').replace(/\s/g, '-').trim().toLowerCase();
|
||||
expect(await testArgs.page.screenshot({fullPage: true})).toMatchSnapshot(`${filename}.png`);
|
||||
await expect(testArgs.page).toHaveScreenshot(`${filename}.png`, {fullPage: true, ...options});
|
||||
}
|
||||
|
||||
if (testConfig.percyEnabled) {
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
import percySnapshot from '@percy/playwright';
|
||||
|
||||
import testConfig, {TestArgs} from '@e2e-test.config';
|
||||
import testConfig from '@e2e-test.config';
|
||||
import {TestArgs} from '@e2e-types';
|
||||
|
||||
export default async function snapshotWithPercy(name: string, testArgs: TestArgs) {
|
||||
if (testArgs.browserName === 'chromium' && testConfig.percyEnabled && testArgs.viewport) {
|
||||
|
||||
@@ -1,40 +1,11 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Page, ViewportSize} from '@playwright/test';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
import {TestConfig} from '@e2e-types';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export type TestArgs = {
|
||||
page: Page;
|
||||
browserName: string;
|
||||
viewport?: ViewportSize | null;
|
||||
};
|
||||
|
||||
export type TestConfig = {
|
||||
// Server
|
||||
baseURL: string;
|
||||
adminUsername: string;
|
||||
adminPassword: string;
|
||||
adminEmail: string;
|
||||
ensurePluginsInstalled: string[];
|
||||
resetBeforeTest: boolean;
|
||||
haClusterEnabled: boolean;
|
||||
haClusterNodeCount: number;
|
||||
haClusterName: string;
|
||||
// CI
|
||||
isCI: boolean;
|
||||
// Playwright
|
||||
headless: boolean;
|
||||
slowMo: number;
|
||||
workers: number;
|
||||
// Visual tests
|
||||
snapshotEnabled: boolean;
|
||||
percyEnabled: boolean;
|
||||
percyToken?: string;
|
||||
};
|
||||
|
||||
// All process.env should be defined here
|
||||
const config: TestConfig = {
|
||||
// Server
|
||||
@@ -44,7 +15,7 @@ const config: TestConfig = {
|
||||
adminEmail: process.env.PW_ADMIN_EMAIL || 'sysadmin@sample.mattermost.com',
|
||||
ensurePluginsInstalled:
|
||||
typeof process.env?.PW_ENSURE_PLUGINS_INSTALLED === 'string'
|
||||
? process.env.PW_ENSURE_PLUGINS_INSTALLED.split(',')
|
||||
? process.env.PW_ENSURE_PLUGINS_INSTALLED.split(',').filter((plugin) => Boolean(plugin))
|
||||
: [],
|
||||
haClusterEnabled: parseBool(process.env.PW_HA_CLUSTER_ENABLED, false),
|
||||
haClusterNodeCount: parseNumber(process.env.PW_HA_CLUSTER_NODE_COUNT, 2),
|
||||
|
||||
@@ -61,19 +61,19 @@ test('/login accessibility tab support', async ({pw, pages, page}) => {
|
||||
await loginPage.footer.termsLink.press('Tab');
|
||||
expect(await loginPage.footer.helpLink).toBeFocused();
|
||||
|
||||
// * Should move focus to header logo after tab
|
||||
await loginPage.footer.helpLink.press('Tab');
|
||||
expect(await loginPage.header.logo).toBeFocused();
|
||||
// # Move focus to login input
|
||||
await loginPage.loginInput.focus();
|
||||
expect(await loginPage.loginInput).toBeFocused();
|
||||
|
||||
// * Should move focus to create account link after tab
|
||||
await loginPage.header.logo.press('Tab');
|
||||
expect(await loginPage.createAccountLink).toBeFocused();
|
||||
|
||||
// * Should move focus to create account link after tab
|
||||
await loginPage.createAccountLink.press('Tab');
|
||||
// * Should move focus to login body after shift+tab
|
||||
await loginPage.loginInput.press('Shift+Tab');
|
||||
expect(await loginPage.bodyCard).toBeFocused();
|
||||
|
||||
// * Then, should move focus to login body after tab
|
||||
await loginPage.bodyCard.press('Tab');
|
||||
expect(await loginPage.loginInput).toBeFocused();
|
||||
// * Should move focus to create account link after shift+tab
|
||||
await loginPage.bodyCard.press('Shift+Tab');
|
||||
expect(await loginPage.createAccountLink).toBeFocused();
|
||||
|
||||
// * Should move focus to login body after tab
|
||||
await loginPage.createAccountLink.press('Shift+Tab');
|
||||
expect(await loginPage.header.logo).toBeFocused();
|
||||
});
|
||||
|
||||
@@ -45,11 +45,11 @@ test('/reset_password accessibility tab support', async ({pages, page}) => {
|
||||
await resetPasswordPage.footer.termsLink.press('Tab');
|
||||
expect(await resetPasswordPage.footer.helpLink).toBeFocused();
|
||||
|
||||
// * Should move focus to header logo after tab
|
||||
await resetPasswordPage.footer.helpLink.press('Tab');
|
||||
expect(await resetPasswordPage.header.backButton).toBeFocused();
|
||||
|
||||
// * Then, should move focus to email input after tab
|
||||
await resetPasswordPage.header.backButton.press('Tab');
|
||||
// # Move focus to email input
|
||||
await resetPasswordPage.emailInput.focus();
|
||||
expect(await resetPasswordPage.emailInput).toBeFocused();
|
||||
|
||||
// * Should move focus to back button after shift+tab
|
||||
await resetPasswordPage.emailInput.press('Shift+Tab');
|
||||
expect(await resetPasswordPage.header.backButton).toBeFocused();
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ test('/signup_user_complete accessibility quick check', async ({pages, page, axe
|
||||
expect(accessibilityScanResults.violations).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('/signup_user_complete accessibility tab support', async ({pages, page}) => {
|
||||
test('/signup_user_complete accessibility tab support', async ({pages, page}, testInfo) => {
|
||||
// # Go to reset password page
|
||||
const signupPage = new pages.SignupPage(page);
|
||||
await signupPage.goto();
|
||||
@@ -71,23 +71,41 @@ test('/signup_user_complete accessibility tab support', async ({pages, page}) =>
|
||||
await signupPage.footer.termsLink.press('Tab');
|
||||
expect(await signupPage.footer.helpLink).toBeFocused();
|
||||
|
||||
// * Should move focus to header logo after tab
|
||||
await signupPage.footer.helpLink.press('Tab');
|
||||
expect(await signupPage.header.logo).toBeFocused();
|
||||
// # Move focus to email input
|
||||
await signupPage.emailInput.focus();
|
||||
expect(await signupPage.emailInput).toBeFocused();
|
||||
|
||||
// * Should move focus to header back button after tab
|
||||
await signupPage.header.logo.press('Tab');
|
||||
expect(await signupPage.header.backButton).toBeFocused();
|
||||
|
||||
// * Should move focus to log in link after tab
|
||||
await signupPage.header.backButton.press('Tab');
|
||||
expect(await signupPage.loginLink).toBeFocused();
|
||||
|
||||
// * Should move focus to sign up body after tab
|
||||
await signupPage.loginLink.press('Tab');
|
||||
// * Should move focus to sign up body after shift+tab
|
||||
await signupPage.emailInput.press('Shift+Tab');
|
||||
expect(await signupPage.bodyCard).toBeFocused();
|
||||
|
||||
// * Then, should move focus to email input after tab
|
||||
await signupPage.bodyCard.press('Tab');
|
||||
expect(await signupPage.emailInput).toBeFocused();
|
||||
// * Should move focus to sign up body after shift+tab
|
||||
await signupPage.emailInput.press('Shift+Tab');
|
||||
expect(await signupPage.bodyCard).toBeFocused();
|
||||
|
||||
if (testInfo.project.name === 'ipad') {
|
||||
// * Should move focus to header back button after shift+tab
|
||||
await signupPage.bodyCard.press('Shift+Tab');
|
||||
expect(await signupPage.header.backButton).toBeFocused();
|
||||
|
||||
// * Should move focus to log in link after shift+tab
|
||||
await signupPage.header.backButton.press('Shift+Tab');
|
||||
expect(await signupPage.loginLink).toBeFocused();
|
||||
|
||||
// * Should move focus to header logo after shift+tab
|
||||
await signupPage.loginLink.press('Shift+Tab');
|
||||
expect(await signupPage.header.logo).toBeFocused();
|
||||
} else {
|
||||
// * Should move focus to log in link after shift+tab
|
||||
await signupPage.bodyCard.press('Shift+Tab');
|
||||
expect(await signupPage.loginLink).toBeFocused();
|
||||
|
||||
// * Should move focus to header back button after shift+tab
|
||||
await signupPage.loginLink.press('Shift+Tab');
|
||||
expect(await signupPage.header.backButton).toBeFocused();
|
||||
|
||||
// * Should move focus to header logo after shift+tab
|
||||
await signupPage.header.backButton.press('Shift+Tab');
|
||||
expect(await signupPage.header.logo).toBeFocused();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -37,7 +37,6 @@ test('MM-T5424 Find channel search returns only 50 results when there are more t
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
// # Click on "Find channel" and type "test_channel"
|
||||
await channelsPage.centerView.headerMobile.toggleSidebar();
|
||||
await channelsPage.sidebarLeft.findChannelButton.click();
|
||||
|
||||
await channelsPage.findChannelsModal.toBeVisible();
|
||||
|
||||
|
До Ширина: | Высота: | Размер: 161 KiB После Ширина: | Высота: | Размер: 68 KiB |
|
До Ширина: | Высота: | Размер: 107 KiB После Ширина: | Высота: | Размер: 107 KiB |
|
До Ширина: | Высота: | Размер: 170 KiB После Ширина: | Высота: | Размер: 170 KiB |
|
До Ширина: | Высота: | Размер: 220 KiB После Ширина: | Высота: | Размер: 93 KiB |
|
До Ширина: | Высота: | Размер: 153 KiB После Ширина: | Высота: | Размер: 150 KiB |
|
До Ширина: | Высота: | Размер: 271 KiB После Ширина: | Высота: | Размер: 271 KiB |
|
До Ширина: | Высота: | Размер: 319 KiB После Ширина: | Высота: | Размер: 136 KiB |
|
До Ширина: | Высота: | Размер: 302 KiB После Ширина: | Высота: | Размер: 131 KiB |
|
До Ширина: | Высота: | Размер: 167 KiB После Ширина: | Высота: | Размер: 167 KiB |
|
До Ширина: | Высота: | Размер: 172 KiB После Ширина: | Высота: | Размер: 172 KiB |
|
До Ширина: | Высота: | Размер: 297 KiB После Ширина: | Высота: | Размер: 296 KiB |
|
До Ширина: | Высота: | Размер: 429 KiB После Ширина: | Высота: | Размер: 175 KiB |
|
До Ширина: | Высота: | Размер: 397 KiB После Ширина: | Высота: | Размер: 168 KiB |
@@ -10,7 +10,8 @@
|
||||
"@mattermost/client/*": ["../../webapp/platform/client/lib/*"],
|
||||
"@mattermost/types/*": ["../../webapp/platform/types/lib/*"],
|
||||
"@e2e-support/*": ["support/*"],
|
||||
"@e2e-test.config": ["test.config.ts"]
|
||||
"@e2e-test.config": ["test.config.ts"],
|
||||
"@e2e-types": ["types.ts"]
|
||||
}
|
||||
},
|
||||
"include": ["./**/*"],
|
||||
|
||||
134
e2e-tests/playwright/types.ts
Обычный файл
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Locator, Page, ViewportSize} from '@playwright/test';
|
||||
|
||||
export type TestArgs = {
|
||||
page: Page;
|
||||
browserName: string;
|
||||
viewport?: ViewportSize | null;
|
||||
};
|
||||
|
||||
export type TestConfig = {
|
||||
// Server
|
||||
baseURL: string;
|
||||
adminUsername: string;
|
||||
adminPassword: string;
|
||||
adminEmail: string;
|
||||
ensurePluginsInstalled: string[];
|
||||
resetBeforeTest: boolean;
|
||||
haClusterEnabled: boolean;
|
||||
haClusterNodeCount: number;
|
||||
haClusterName: string;
|
||||
// CI
|
||||
isCI: boolean;
|
||||
// Playwright
|
||||
headless: boolean;
|
||||
slowMo: number;
|
||||
workers: number;
|
||||
// Visual tests
|
||||
snapshotEnabled: boolean;
|
||||
percyEnabled: boolean;
|
||||
percyToken?: string;
|
||||
};
|
||||
|
||||
// Based on https://github.com/microsoft/playwright/blob/d6ec1ae3994f127e38b866a231a34efc6a4cac0d/packages/playwright/types/test.d.ts#L5692-L5759
|
||||
export type ScreenshotOptions = {
|
||||
/**
|
||||
* When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
|
||||
* treatment depending on their duration:
|
||||
* - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
|
||||
* - infinite animations are canceled to initial state, and then played over after the screenshot.
|
||||
*
|
||||
* Defaults to `"disabled"` that disables animations.
|
||||
*/
|
||||
animations?: 'disabled' | 'allow';
|
||||
|
||||
/**
|
||||
* When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
|
||||
* changed. Defaults to `"hide"`.
|
||||
*/
|
||||
caret?: 'hide' | 'initial';
|
||||
|
||||
/**
|
||||
* An object which specifies clipping of the resulting image.
|
||||
*/
|
||||
clip?: {
|
||||
/**
|
||||
* x-coordinate of top-left corner of clip area
|
||||
*/
|
||||
x: number;
|
||||
|
||||
/**
|
||||
* y-coordinate of top-left corner of clip area
|
||||
*/
|
||||
y: number;
|
||||
|
||||
/**
|
||||
* width of clipping area
|
||||
*/
|
||||
width: number;
|
||||
|
||||
/**
|
||||
* height of clipping area
|
||||
*/
|
||||
height: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to
|
||||
* `false`.
|
||||
*/
|
||||
fullPage?: boolean;
|
||||
|
||||
/**
|
||||
* Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
|
||||
* box `#FF00FF` (customized by `maskColor`) that completely covers its bounding box.
|
||||
*/
|
||||
mask?: Array<Locator>;
|
||||
|
||||
/**
|
||||
* Specify the color of the overlay box for masked elements, in
|
||||
* [CSS color format](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). Default color is pink `#FF00FF`.
|
||||
*/
|
||||
maskColor?: string;
|
||||
|
||||
/**
|
||||
* An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1`. Default is
|
||||
* configurable with `TestConfig.expect`. Unset by default.
|
||||
*/
|
||||
maxDiffPixelRatio?: number;
|
||||
|
||||
/**
|
||||
* An acceptable amount of pixels that could be different. Default is configurable with `TestConfig.expect`. Unset by
|
||||
* default.
|
||||
*/
|
||||
maxDiffPixels?: number;
|
||||
|
||||
/**
|
||||
* Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
omitBackground?: boolean;
|
||||
|
||||
/**
|
||||
* When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
|
||||
* will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
|
||||
* screenshots of high-dpi devices will be twice as large or even larger.
|
||||
*
|
||||
* Defaults to `"css"`.
|
||||
*/
|
||||
scale?: 'css' | 'device';
|
||||
|
||||
/**
|
||||
* An acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the
|
||||
* same pixel in compared images, between zero (strict) and one (lax), default is configurable with
|
||||
* `TestConfig.expect`. Defaults to `0.2`.
|
||||
*/
|
||||
threshold?: number;
|
||||
|
||||
/**
|
||||
* Time to retry the assertion for in milliseconds. Defaults to `timeout` in `TestConfig.expect`.
|
||||
*/
|
||||
timeout?: number;
|
||||
};
|
||||