MM-63669 E2E/Playwright: Move "e2e-tests/playwright/test" to "e2e-tests/playwright" folder (#30647)

* move "e2e-tests/playwright/test" to  "e2e-tests/playwright/test" and expose "ensurePluginsLoaded"

* add test setup, and expose ensurePluginsLoaded and ensureServerDeployment to pw
Этот коммит содержится в:
Saturnino Abril
2025-04-07 22:26:29 +08:00
коммит произвёл GitHub
родитель 62753a1481
Коммит a35a6d7a3a
80 изменённых файлов: 165 добавлений и 154 удалений

6
.gitignore поставляемый
Просмотреть файл

@@ -40,9 +40,9 @@ e2e-tests/playwright/playwright-report
e2e-tests/playwright/storage_state
e2e-tests/playwright/test-results
e2e-tests/playwright/results
e2e-tests/playwright/tests/**/*-darwin.png
e2e-tests/playwright/tests/**/*-window.png
e2e-tests/playwright/tests/accessibility/**/*-snapshots
e2e-tests/playwright/specs/**/*-darwin.png
e2e-tests/playwright/specs/**/*-window.png
e2e-tests/playwright/specs/accessibility/**/*-snapshots
e2e-tests/playwright/.eslintcache
# ignore temporary added configuration for pgloader

Просмотреть файл

@@ -41,13 +41,6 @@ ${MME2E_DC_SERVER} exec -i -u "$MME2E_UID" -- playwright bash -c "cd e2e-tests/p
# Collect run results
# Documentation on the results.json file: https://playwright.dev/docs/api/class-testcase#test-case-expected-status
# NB: the following line is needed only for compatibility reasons, to support RollingRelease tests for versions prior to v10.1.0
# It can be removed after releases <=v10.0.x are phased out
mv -v ../playwright/playwright-report/results.json ../playwright/results/reporter/results.json 2>/dev/null || true
# NB: the following line is needed only for compatibility reasons, to support RollingRelease tests for versions prior to v10.6.0
# It can be removed once 10.5 (ESR) is no longer supported
mv -v ../playwright/test/results/ ../playwright/ 2>/dev/null || true
jq -f /dev/stdin ../playwright/results/reporter/results.json > ../playwright/results/summary.json <<EOF
{

Просмотреть файл

Просмотреть файл

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 13 KiB

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 75 KiB

После

Ширина:  |  Высота:  |  Размер: 75 KiB

Просмотреть файл

@@ -4,9 +4,11 @@
import os from 'node:os';
import {expect, test} from '@playwright/test';
import {PluginManifest} from '@mattermost/types/plugins';
import {callsPluginId} from './constant';
import {getAdminClient} from './server/init';
import {testConfig} from './test_config';
export async function shouldHaveCallsEnabled(enabled = true) {
const {adminClient} = await getAdminClient();
@@ -86,3 +88,71 @@ export async function skipIfFeatureFlagNotSet(name: string, value: string | bool
test.skip(cfg.FeatureFlags[name] !== value, `Skipping test - Feature Flag ${name} needs to be set to ${value}`);
}
// ensureServerDeployment is used to ensure server deployment type is as expected.
// If server is not deployed as expected, test will fail.
export async function ensureServerDeployment() {
const {adminClient} = await getAdminClient();
// Based on test config, ensure server is on an HA cluster.
if (testConfig.haClusterEnabled) {
const {haClusterNodeCount, haClusterName} = testConfig;
const {Enable, ClusterName} = (await adminClient.getConfig()).ClusterSettings;
expect(Enable, Enable ? '' : 'Should have cluster enabled').toBe(true);
const sameClusterName = ClusterName === haClusterName;
expect(
sameClusterName,
sameClusterName
? ''
: `Should have cluster name set and as expected. Got "${ClusterName}" but expected "${haClusterName}"`,
).toBe(true);
const clusterInfo = await adminClient.getClusterStatus();
const sameCount = clusterInfo?.length === haClusterNodeCount;
expect(
sameCount,
sameCount
? ''
: `Should match number of nodes in a cluster as expected. Got "${clusterInfo?.length}" but expected "${haClusterNodeCount}"`,
).toBe(true);
clusterInfo.forEach((info) =>
// eslint-disable-next-line no-console
console.log(`hostname: ${info.hostname}, version: ${info.version}, config_hash: ${info.config_hash}`),
);
}
}
// ensurePluginsLoaded is used to ensure all pluginIds including from testConfig.ensurePluginsInstalled are installed and active.
// If any pluginId is not installed, test will fail.
// testConfig.ensurePluginsInstalled is derived from `PW_ENSURE_PLUGINS_INSTALLED` environment variable.
export async function ensurePluginsLoaded(pluginIds: string[] = []) {
const {adminClient} = await getAdminClient();
const pluginStatus = await adminClient.getPluginStatuses();
const plugins = await adminClient.getPlugins();
// Ensure all plugins are installed and active.
testConfig.ensurePluginsInstalled
.concat(pluginIds)
.filter((pluginId) => Boolean(pluginId))
.forEach(async (pluginId) => {
const isInstalled = pluginStatus.some((plugin) => plugin.plugin_id === pluginId);
// If not installed, test will fail.
expect(isInstalled, `${pluginId} is not installed. Related test will fail.`).toBe(true);
const isActive = plugins.active.some((plugin: PluginManifest) => plugin.id === pluginId);
if (!isActive) {
await adminClient.enablePlugin(pluginId);
// eslint-disable-next-line no-console
console.log(`${pluginId} is installed and has been activated.`);
} else {
// eslint-disable-next-line no-console
console.log(`${pluginId} is installed and active.`);
}
});
}

Просмотреть файл

@@ -1,7 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect} from '@playwright/test';
import {Client4} from '@mattermost/client';
import {UserProfile} from '@mattermost/types/users';
import {PluginManifest} from '@mattermost/types/plugins';
@@ -66,14 +65,8 @@ async function sysadminSetup(client: Client4, user: UserProfile | null) {
// Set default preferences
await savePreferences(client, user?.id ?? '');
// Ensure all products as plugin are installed and active.
await ensurePluginsLoaded(client);
// Log plugin details
await printPluginDetails(client);
// Ensure server deployment type is as expected
await ensureServerDeployment(client);
}
async function printLicenseInfo(client: Client4) {
@@ -108,31 +101,6 @@ async function printClientInfo(client: Client4) {
- LogSettings.EnableDiagnostics = ${LogSettings?.EnableDiagnostics}`);
}
export async function ensurePluginsLoaded(client: Client4) {
const pluginStatus = await client.getPluginStatuses();
const plugins = await client.getPlugins();
testConfig.ensurePluginsInstalled.forEach(async (pluginId) => {
const isInstalled = pluginStatus.some((plugin) => plugin.plugin_id === pluginId);
if (!isInstalled) {
// eslint-disable-next-line no-console
console.log(`${pluginId} is not installed. Related visual test will fail.`);
return;
}
const isActive = plugins.active.some((plugin: PluginManifest) => plugin.id === pluginId);
if (!isActive) {
await client.enablePlugin(pluginId);
// eslint-disable-next-line no-console
console.log(`${pluginId} is installed and has been activated.`);
} else {
// eslint-disable-next-line no-console
console.log(`${pluginId} is installed and active.`);
}
});
}
async function printPluginDetails(client: Client4) {
const plugins = await client.getPlugins();
@@ -160,37 +128,6 @@ async function printPluginDetails(client: Client4) {
console.log('');
}
async function ensureServerDeployment(client: Client4) {
if (testConfig.haClusterEnabled) {
const {haClusterNodeCount, haClusterName} = testConfig;
const {Enable, ClusterName} = (await client.getConfig()).ClusterSettings;
expect(Enable, Enable ? '' : 'Should have cluster enabled').toBe(true);
const sameClusterName = ClusterName === haClusterName;
expect(
sameClusterName,
sameClusterName
? ''
: `Should have cluster name set and as expected. Got "${ClusterName}" but expected "${haClusterName}"`,
).toBe(true);
const clusterInfo = await client.getClusterStatus();
const sameCount = clusterInfo?.length === haClusterNodeCount;
expect(
sameCount,
sameCount
? ''
: `Should match number of nodes in a cluster as expected. Got "${clusterInfo?.length}" but expected "${haClusterNodeCount}"`,
).toBe(true);
clusterInfo.forEach((info) =>
// eslint-disable-next-line no-console
console.log(`hostname: ${info.hostname}, version: ${info.version}, config_hash: ${info.config_hash}`),
);
}
}
async function savePreferences(client: Client4, userId: UserProfile['id']) {
try {
if (!userId) {

Просмотреть файл

@@ -8,6 +8,8 @@ import {AxeBuilder} from '@axe-core/playwright';
import {TestBrowser} from './browser_context';
import {
ensureLicense,
ensurePluginsLoaded,
ensureServerDeployment,
shouldHaveCallsEnabled,
shouldHaveFeatureFlag,
shouldRunInLinux,
@@ -63,6 +65,7 @@ export class PlaywrightExtended {
readonly shouldHaveFeatureFlag;
readonly shouldRunInLinux;
readonly ensureLicense;
readonly ensureServerDeployment;
readonly skipIfNoLicense;
readonly skipIfFeatureFlagNotSet;
@@ -71,6 +74,7 @@ export class PlaywrightExtended {
readonly getFileFromAsset;
// ./server
readonly ensurePluginsLoaded;
readonly getAdminClient;
readonly initSetup;
@@ -111,6 +115,7 @@ export class PlaywrightExtended {
this.shouldHaveFeatureFlag = shouldHaveFeatureFlag;
this.shouldRunInLinux = shouldRunInLinux;
this.ensureLicense = ensureLicense;
this.ensureServerDeployment = ensureServerDeployment;
this.skipIfNoLicense = skipIfNoLicense;
this.skipIfFeatureFlagNotSet = skipIfFeatureFlagNotSet;
@@ -119,6 +124,7 @@ export class PlaywrightExtended {
this.getFileFromAsset = getFileFromAsset;
// ./server
this.ensurePluginsLoaded = ensurePluginsLoaded;
this.initSetup = initSetup;
this.getAdminClient = getAdminClient;

71
e2e-tests/playwright/package-lock.json сгенерированный
Просмотреть файл

@@ -7,12 +7,16 @@
"name": "mattermost-playwright",
"hasInstallScript": true,
"workspaces": [
"lib",
"test"
"lib"
],
"dependencies": {
"@mattermost/client": "file:../../webapp/platform/client",
"@mattermost/playwright-lib": "*",
"@mattermost/types": "file:../../webapp/platform/types",
"@playwright/test": "1.51.1",
"dayjs": "1.11.13"
"cross-env": "7.0.3",
"dayjs": "1.11.13",
"zod": "3.24.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "8.29.0",
@@ -226,9 +230,9 @@
}
},
"node_modules/@eslint/config-helpers": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz",
"integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==",
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz",
"integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -317,19 +321,32 @@
}
},
"node_modules/@eslint/plugin-kit": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz",
"integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==",
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
"integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.12.0",
"@eslint/core": "^0.13.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -404,24 +421,20 @@
"resolved": "lib",
"link": true
},
"node_modules/@mattermost/playwright-test": {
"resolved": "test",
"link": true
},
"node_modules/@mattermost/types": {
"resolved": "../../webapp/platform/types",
"link": true
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.7.tgz",
"integrity": "sha512-5yximcFK5FNompXfJFoWanu5l8v1hNGqNHh9du1xETp9HWk/B/PzvchX55WYOPaIeNglG8++68AAiauBAtbnzw==",
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.8.tgz",
"integrity": "sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "^1.3.1",
"@emnapi/runtime": "^1.3.1",
"@emnapi/core": "^1.4.0",
"@emnapi/runtime": "^1.4.0",
"@tybys/wasm-util": "^0.9.0"
}
},
@@ -2087,7 +2100,6 @@
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"cross-spawn": "^7.0.1"
@@ -3541,9 +3553,9 @@
}
},
"node_modules/image-size": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz",
"integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
"integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
"license": "MIT",
"dependencies": {
"queue": "6.0.2"
@@ -5801,19 +5813,6 @@
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"test": {
"name": "@mattermost/playwright-test",
"hasInstallScript": true,
"dependencies": {
"@mattermost/client": "file:../../../webapp/platform/client",
"@mattermost/playwright-lib": "*",
"@mattermost/types": "file:../../../webapp/platform/types",
"zod": "3.24.2"
},
"devDependencies": {
"cross-env": "7.0.3"
}
}
}
}

Просмотреть файл

@@ -1,26 +1,33 @@
{
"name": "mattermost-playwright",
"private": true,
"workspaces": [
"lib",
"test"
],
"workspaces": ["lib"],
"scripts": {
"postinstall": "npm run build",
"build": "npm run build --workspaces --if-present",
"build:watch": "npm run build:watch --workspaces --if-present",
"clean": "rm -rf node_modules package-lock.json logs results test-results && npm run clean --workspaces --if-present",
"tsc": "npm run tsc --workspaces --if-present",
"postinstall": "script/post_install.sh && npm run build",
"build": "npm run build --workspaces",
"build:watch": "npm run build:watch --workspaces",
"tsc": "tsc -b && npm run tsc --workspaces",
"lint": "eslint .",
"prettier": "prettier . --check",
"prettier:fix": "prettier --write .",
"check": "npm run lint && npm run prettier && npm run tsc",
"test": "npm run test --workspace=test",
"test:ci": "npm run test:ci --workspace=test"
"test": "cross-env PW_SNAPSHOT_ENABLE=true playwright test",
"test:ci": "cross-env PW_SNAPSHOT_ENABLE=true playwright test --project=chrome",
"test:update-snapshots": "cross-env PW_SNAPSHOT_ENABLE=true playwright test --update-snapshots",
"test:slomo": "cross-env PW_SNAPSHOT_ENABLE=true PW_SLOWMO=1000 playwright test",
"percy": "cross-env PERCY_TOKEN=$PERCY_TOKEN PW_PERCY_ENABLE=true percy exec -- playwright test --project=chrome --project=ipad",
"codegen": "cross-env playwright codegen $PW_BASE_URL",
"playwright-ui": "cross-env playwright test --ui",
"show-report": "npx playwright show-report results/reporter",
"clean": "rm -rf dist node_modules package-lock.json *.tsbuildinfo logs results storage_state test-results && npm run clean --workspaces"
},
"dependencies": {
"@mattermost/client": "file:../../webapp/platform/client",
"@mattermost/playwright-lib": "*",
"@mattermost/types": "file:../../webapp/platform/types",
"@playwright/test": "1.51.1",
"cross-env": "7.0.3",
"dayjs": "1.11.13",
"@playwright/test": "1.51.1"
"zod": "3.24.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "8.29.0",

Просмотреть файл

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import {defineConfig, devices} from '@playwright/test';
import {duration, testConfig} from '@mattermost/playwright-lib';
export default defineConfig({
@@ -41,6 +42,7 @@ export default defineConfig({
actionTimeout: duration.half_min,
},
projects: [
{name: 'setup', testMatch: /test_setup\.ts/},
{
name: 'ipad',
use: {
@@ -48,6 +50,7 @@ export default defineConfig({
...devices['iPad Pro 11'],
permissions: ['notifications', 'clipboard-read', 'clipboard-write'],
},
dependencies: ['setup'],
},
{
name: 'chrome',
@@ -56,6 +59,7 @@ export default defineConfig({
permissions: ['notifications', 'clipboard-read', 'clipboard-write'],
viewport: {width: 1280, height: 1024},
},
dependencies: ['setup'],
},
{
name: 'firefox',
@@ -64,6 +68,7 @@ export default defineConfig({
permissions: ['notifications'],
viewport: {width: 1280, height: 1024},
},
dependencies: ['setup'],
},
],
reporter: [

Просмотреть файл

Просмотреть файл

@@ -1,9 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test, ChannelsPage} from '@mattermost/playwright-lib';
import {UserProfile} from '@mattermost/types/users';
import {Page} from '@playwright/test';
import {UserProfile} from '@mattermost/types/users';
import {expect, test, ChannelsPage} from '@mattermost/playwright-lib';
test('MM-63451 should be able to navigate the account settings menu with the keyboard after opening it with the mouse', async ({
pw,

Просмотреть файл

@@ -1,13 +1,14 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test, getFileFromAsset, getBlobFromAsset} from '@mattermost/playwright-lib';
import {Client4} from '@mattermost/client';
import {ServerChannel} from '@mattermost/types/channels';
import {FileUploadResponse} from '@mattermost/types/files';
import {Team} from '@mattermost/types/teams';
import {UserProfile} from '@mattermost/types/users';
import {expect, test, getFileFromAsset, getBlobFromAsset} from '@mattermost/playwright-lib';
import {FileUploadResponseSchema} from './schema';
let userClient: Client4;

Просмотреть файл

@@ -1,9 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
import {Page} from '@playwright/test';
import {expect, test} from '@mattermost/playwright-lib';
test('MM-T5654_1 should be able to add attachments while editing a post', async ({pw}) => {
const originalMessage = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit';

Просмотреть файл

@@ -1,9 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import type {Page} from '@playwright/test';
import {expect, PlaywrightExtended, test} from '@mattermost/playwright-lib';
import type {ChannelsPage, ScheduledDraftPage} from '@mattermost/playwright-lib';
import type {Page} from '@playwright/test';
test.skip('MM-T5643_1 should create a scheduled message from a channel', async ({pw}) => {
test.setTimeout(pw.duration.four_min);

Просмотреть файл

@@ -1,9 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {expect, test} from '@mattermost/playwright-lib';
import {Page} from '@playwright/test';
import {expect, test} from '@mattermost/playwright-lib';
// Helper function to intercept API request and modify the response
async function interceptConfigWithLandingPage(page: Page, enabled: boolean) {
const apiUrl = '**/api/v4/config/client?format=old**';

14
e2e-tests/playwright/specs/test_setup.ts Обычный файл
Просмотреть файл

@@ -0,0 +1,14 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {test as setup} from '@mattermost/playwright-lib';
setup('ensure plugins are loaded', async ({pw}) => {
// Ensure all products as plugin are installed and active.
await pw.ensurePluginsLoaded();
});
setup('ensure server deployment', async ({pw}) => {
// Ensure server is on expected deployment type.
await pw.ensureServerDeployment();
});

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 96 KiB

После

Ширина:  |  Высота:  |  Размер: 96 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 172 KiB

После

Ширина:  |  Высота:  |  Размер: 172 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 84 KiB

После

Ширина:  |  Высота:  |  Размер: 84 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 188 KiB

После

Ширина:  |  Высота:  |  Размер: 188 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 186 KiB

После

Ширина:  |  Высота:  |  Размер: 186 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 488 KiB

После

Ширина:  |  Высота:  |  Размер: 488 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 187 KiB

После

Ширина:  |  Высота:  |  Размер: 187 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 490 KiB

После

Ширина:  |  Высота:  |  Размер: 490 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 125 KiB

После

Ширина:  |  Высота:  |  Размер: 125 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 124 KiB

После

Ширина:  |  Высота:  |  Размер: 124 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 499 KiB

После

Ширина:  |  Высота:  |  Размер: 499 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 189 KiB

После

Ширина:  |  Высота:  |  Размер: 189 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 500 KiB

После

Ширина:  |  Высота:  |  Размер: 500 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 120 KiB

После

Ширина:  |  Высота:  |  Размер: 120 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 119 KiB

После

Ширина:  |  Высота:  |  Размер: 119 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 207 KiB

После

Ширина:  |  Высота:  |  Размер: 207 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 212 KiB

После

Ширина:  |  Высота:  |  Размер: 212 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 510 KiB

После

Ширина:  |  Высота:  |  Размер: 510 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 161 KiB

После

Ширина:  |  Высота:  |  Размер: 161 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 509 KiB

После

Ширина:  |  Высота:  |  Размер: 509 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 155 KiB

После

Ширина:  |  Высота:  |  Размер: 155 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 155 KiB

После

Ширина:  |  Высота:  |  Размер: 155 KiB

Просмотреть файл

@@ -1,25 +0,0 @@
{
"name": "@mattermost/playwright-test",
"scripts": {
"test": "cross-env PW_SNAPSHOT_ENABLE=true playwright test",
"test:ci": "cross-env PW_SNAPSHOT_ENABLE=true playwright test --project=chrome",
"test:update-snapshots": "cross-env PW_SNAPSHOT_ENABLE=true playwright test --update-snapshots",
"percy": "cross-env PERCY_TOKEN=$PERCY_TOKEN PW_PERCY_ENABLE=true percy exec -- playwright test --project=chrome --project=ipad",
"tsc": "tsc -b",
"codegen": "cross-env playwright codegen $PW_BASE_URL",
"playwright-ui": "cross-env playwright test --ui",
"test-slomo": "cross-env PW_SNAPSHOT_ENABLE=true PW_SLOWMO=1000 playwright test",
"show-report": "npx playwright show-report",
"postinstall": "script/post_install.sh",
"clean": "rm -rf dist node_modules *.tsbuildinfo logs results storage_state test-results"
},
"dependencies": {
"@mattermost/client": "file:../../../webapp/platform/client",
"@mattermost/playwright-lib": "*",
"@mattermost/types": "file:../../../webapp/platform/types",
"zod": "3.24.2"
},
"devDependencies": {
"cross-env": "7.0.3"
}
}

Просмотреть файл

@@ -17,5 +17,5 @@
"baseUrl": "."
},
"include": ["./**/*"],
"exclude": ["node_modules", "playwright-report"]
"exclude": ["node_modules", "playwright-report", "lib"]
}