Merge remote-tracking branch 'origin/master' into MM-52097
Этот коммит содержится в:
@@ -22,8 +22,6 @@ describe('New Channel modal with Boards enabled', () => {
|
||||
cy.apiLogin(sysadmin);
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
|
||||
cy.shouldHaveFeatureFlag('BoardsProduct', true);
|
||||
});
|
||||
|
||||
it('MM-T5141 New Channel is created with an associated Board', () => {
|
||||
|
||||
@@ -145,4 +145,42 @@ describe('Edit Message', () => {
|
||||
cy.get(postText).should('have.text', `${secondMessage} Another new message Edited`);
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T5416 should discard any changes made after cancelling the edit and opening the edit textbox again should display the original message', () => {
|
||||
const message = 'World!';
|
||||
cy.postMessage(message);
|
||||
|
||||
// * Verify message is sent and not pending
|
||||
cy.getLastPostId().then((postId) => {
|
||||
const postText = `#postMessageText_${postId}`;
|
||||
cy.get(postText).should('have.text', message);
|
||||
|
||||
// # Open edit textbox
|
||||
cy.uiGetPostTextBox().type('{uparrow}');
|
||||
|
||||
// * Edit Post Input should appear, and edit the post
|
||||
cy.get('#edit_textbox').should('be.visible');
|
||||
|
||||
// * Press the escape key to cancel
|
||||
cy.get('#edit_textbox').should('have.text', message).type(' Another new message{esc}');
|
||||
cy.get('#edit_textbox').should('not.exist');
|
||||
|
||||
// * Check that the message wasn't edited
|
||||
cy.get(postText).should('have.text', message);
|
||||
});
|
||||
|
||||
cy.getLastPostId().then((postId) => {
|
||||
const postText = `#postMessageText_${postId}`;
|
||||
cy.get(postText).should('have.text', message);
|
||||
|
||||
// # Open edit textbox again
|
||||
cy.uiGetPostTextBox().type('{uparrow}');
|
||||
|
||||
// * Edit Post Input should appear, and edit the post
|
||||
cy.get('#edit_textbox').should('be.visible');
|
||||
|
||||
// * Opening the edit textbox again after previously cancelling the edit should contain the original message.
|
||||
cy.get('#edit_textbox').should('have.text', message);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@ import {expect} from '@playwright/test';
|
||||
import {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {Client, createRandomTeam, getAdminClient, getDefaultAdminUser, makeClient} from './support/server';
|
||||
import {boardsPluginId, callsPluginId} from './support/constant';
|
||||
import {defaultTeam} from './support/util';
|
||||
import testConfig from './test.config';
|
||||
|
||||
@@ -97,26 +96,15 @@ async function printClientInfo(client: Client) {
|
||||
- BuildHashEnterprise = ${config.BuildHashEnterprise}
|
||||
- BuildEnterpriseReady = ${config.BuildEnterpriseReady}
|
||||
- FeatureFlagAppsEnabled = ${config.FeatureFlagAppsEnabled}
|
||||
- FeatureFlagBoardsProduct = ${config.FeatureFlagBoardsProduct}
|
||||
- FeatureFlagCallsEnabled = ${config.FeatureFlagCallsEnabled}
|
||||
- TelemetryId = ${config.TelemetryId}`);
|
||||
}
|
||||
|
||||
function getProductsAsPlugin() {
|
||||
const productsAsPlugin = [callsPluginId];
|
||||
|
||||
if (!testConfig.boardsProductEnabled) {
|
||||
productsAsPlugin.push(boardsPluginId);
|
||||
}
|
||||
|
||||
return productsAsPlugin;
|
||||
}
|
||||
|
||||
async function ensurePluginsLoaded(client: Client) {
|
||||
const pluginStatus = await client.getPluginStatuses();
|
||||
const plugins = await client.getPlugins();
|
||||
|
||||
getProductsAsPlugin().forEach(async (pluginId) => {
|
||||
testConfig.ensurePluginsInstalled.forEach(async (pluginId) => {
|
||||
const isInstalled = pluginStatus.some((plugin) => plugin.plugin_id === pluginId);
|
||||
if (!isInstalled) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
53
e2e-tests/playwright/package-lock.json
сгенерированный
53
e2e-tests/playwright/package-lock.json
сгенерированный
@@ -8,7 +8,7 @@
|
||||
"dependencies": {
|
||||
"@percy/cli": "1.18.0",
|
||||
"@percy/playwright": "1.0.4",
|
||||
"@playwright/test": "1.30.0",
|
||||
"@playwright/test": "1.32.3",
|
||||
"async-wait-until": "2.0.12",
|
||||
"chalk": "4.1.2",
|
||||
"deepmerge": "4.3.0",
|
||||
@@ -428,18 +428,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.30.0.tgz",
|
||||
"integrity": "sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==",
|
||||
"version": "1.32.3",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.3.tgz",
|
||||
"integrity": "sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.30.0"
|
||||
"playwright-core": "1.32.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
@@ -1396,6 +1399,19 @@
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
@@ -1927,9 +1943,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.30.0.tgz",
|
||||
"integrity": "sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==",
|
||||
"version": "1.32.3",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.32.3.tgz",
|
||||
"integrity": "sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==",
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
@@ -2677,12 +2693,13 @@
|
||||
"integrity": "sha512-4cSkWqpu7uK9zzeVwtMWrgGbP34GUlvZsWdEEt98ep6ZECQA+iGB75pOpIVwcsHKXtkDRE6fgugtxNXs5uHpMg=="
|
||||
},
|
||||
"@playwright/test": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.30.0.tgz",
|
||||
"integrity": "sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==",
|
||||
"version": "1.32.3",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.3.tgz",
|
||||
"integrity": "sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==",
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.30.0"
|
||||
"fsevents": "2.3.2",
|
||||
"playwright-core": "1.32.3"
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
@@ -3366,6 +3383,12 @@
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"optional": true
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
@@ -3747,9 +3770,9 @@
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.30.0.tgz",
|
||||
"integrity": "sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g=="
|
||||
"version": "1.32.3",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.32.3.tgz",
|
||||
"integrity": "sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg=="
|
||||
},
|
||||
"prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@percy/cli": "1.18.0",
|
||||
"@percy/playwright": "1.0.4",
|
||||
"@playwright/test": "1.30.0",
|
||||
"@playwright/test": "1.32.3",
|
||||
"async-wait-until": "2.0.12",
|
||||
"chalk": "4.1.2",
|
||||
"deepmerge": "4.3.0",
|
||||
|
||||
@@ -6,7 +6,7 @@ import {defineConfig, devices} from '@playwright/test';
|
||||
import {duration} from '@e2e-support/util';
|
||||
import testConfig from '@e2e-test.config';
|
||||
|
||||
const defaultOutputFolder = 'playwright-report';
|
||||
const defaultOutputFolder = './playwright-report';
|
||||
|
||||
export default defineConfig({
|
||||
globalSetup: require.resolve('./global_setup'),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export const appsPluginId = 'com.mattermost.apps';
|
||||
export const boardsPluginId = 'focalboard';
|
||||
export const boardsProductId = 'boards';
|
||||
export const callsPluginId = 'com.mattermost.calls';
|
||||
|
||||
@@ -5,22 +5,10 @@ import os from 'node:os';
|
||||
|
||||
import {expect, test} from '@playwright/test';
|
||||
|
||||
import {boardsPluginId, callsPluginId} from './constant';
|
||||
import {callsPluginId} from './constant';
|
||||
import {getAdminClient} from './server/init';
|
||||
import {isSmallScreen} from './util';
|
||||
|
||||
export async function shouldHaveBoardsEnabled(enabled = true) {
|
||||
const {adminClient} = await getAdminClient();
|
||||
const config = await adminClient.getConfig();
|
||||
|
||||
const boardsEnabled =
|
||||
(typeof config.FeatureFlags.BoardsProduct === 'boolean' && config.FeatureFlags.BoardsProduct) ||
|
||||
config.PluginSettings.PluginStates[boardsPluginId].Enable;
|
||||
|
||||
const matched = boardsEnabled === enabled;
|
||||
expect(matched, matched ? '' : `Boards expect "${enabled}" but actual "${boardsEnabled}"`).toBeTruthy();
|
||||
}
|
||||
|
||||
export async function shouldHaveCallsEnabled(enabled = true) {
|
||||
const {adminClient} = await getAdminClient();
|
||||
const config = await adminClient.getConfig();
|
||||
|
||||
@@ -167,8 +167,9 @@ async function makeClient(userRequest?: UserRequest, useCache = true): Promise<C
|
||||
|
||||
const userProfile = await client.login(userRequest.username, userRequest.password);
|
||||
const user = {...userProfile, password: userRequest.password};
|
||||
const config = await client.getClientConfigOld();
|
||||
client.setUseBoardsProduct(config.FeatureFlagBoardsProduct === 'true');
|
||||
|
||||
// Manually do until boards as product is consistent in all the codebase.
|
||||
client.setUseBoardsProduct(true);
|
||||
|
||||
if (useCache) {
|
||||
clients[cacheKey] = {client, user};
|
||||
|
||||
@@ -6,7 +6,6 @@ import merge from 'deepmerge';
|
||||
import {
|
||||
AdminConfig,
|
||||
ExperimentalSettings,
|
||||
FeatureFlags,
|
||||
PasswordSettings,
|
||||
ServiceSettings,
|
||||
TeamSettings,
|
||||
@@ -23,7 +22,6 @@ export function getOnPremServerConfig(): AdminConfig {
|
||||
type TestAdminConfig = {
|
||||
ClusterSettings: Partial<ClusterSettings>;
|
||||
ExperimentalSettings: Partial<ExperimentalSettings>;
|
||||
FeatureFlags: Partial<FeatureFlags>;
|
||||
PasswordSettings: Partial<PasswordSettings>;
|
||||
PluginSettings: Partial<PluginSettings>;
|
||||
ServiceSettings: Partial<ServiceSettings>;
|
||||
@@ -40,9 +38,6 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
ExperimentalSettings: {
|
||||
EnableAppBar: true,
|
||||
},
|
||||
FeatureFlags: {
|
||||
BoardsProduct: testConfig.boardsProductEnabled,
|
||||
},
|
||||
PasswordSettings: {
|
||||
MinimumLength: 5,
|
||||
Lowercase: false,
|
||||
@@ -57,11 +52,6 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
defaultenabled: true,
|
||||
},
|
||||
},
|
||||
PluginStates: {
|
||||
focalboard: {
|
||||
Enable: !testConfig.boardsProductEnabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
ServiceSettings: {
|
||||
SiteURL: testConfig.baseURL,
|
||||
@@ -686,7 +676,6 @@ const defaultServerConfig: AdminConfig = {
|
||||
GraphQL: false,
|
||||
InsightsEnabled: true,
|
||||
CommandPalette: false,
|
||||
BoardsProduct: false,
|
||||
SendWelcomePost: true,
|
||||
WorkTemplate: false,
|
||||
PostPriority: true,
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import {test as base, Browser} from '@playwright/test';
|
||||
|
||||
import {TestBrowser} from './browser_context';
|
||||
import {
|
||||
shouldHaveBoardsEnabled,
|
||||
shouldHaveCallsEnabled,
|
||||
shouldHaveFeatureFlag,
|
||||
shouldSkipInSmallScreen,
|
||||
shouldRunInLinux,
|
||||
} from './flag';
|
||||
import {shouldHaveCallsEnabled, shouldHaveFeatureFlag, shouldSkipInSmallScreen, shouldRunInLinux} from './flag';
|
||||
import {initSetup, getAdminClient} from './server';
|
||||
import {hideDynamicChannelsContent, waitForAnimationEnd, waitUntil} from './test_action';
|
||||
import {pages} from './ui/pages';
|
||||
@@ -36,7 +30,6 @@ class PlaywrightExtended {
|
||||
readonly testBrowser: TestBrowser;
|
||||
|
||||
// ./flag
|
||||
readonly shouldHaveBoardsEnabled;
|
||||
readonly shouldHaveCallsEnabled;
|
||||
readonly shouldHaveFeatureFlag;
|
||||
readonly shouldSkipInSmallScreen;
|
||||
@@ -62,7 +55,6 @@ class PlaywrightExtended {
|
||||
this.testBrowser = new TestBrowser(browser);
|
||||
|
||||
// ./flag
|
||||
this.shouldHaveBoardsEnabled = shouldHaveBoardsEnabled;
|
||||
this.shouldHaveCallsEnabled = shouldHaveCallsEnabled;
|
||||
this.shouldHaveFeatureFlag = shouldHaveFeatureFlag;
|
||||
this.shouldSkipInSmallScreen = shouldSkipInSmallScreen;
|
||||
|
||||
@@ -9,6 +9,7 @@ export default class ChannelsPostCreate {
|
||||
readonly input;
|
||||
readonly attachmentButton;
|
||||
readonly emojiButton;
|
||||
readonly sendButton: Locator;
|
||||
|
||||
constructor(container: Locator) {
|
||||
this.container = container;
|
||||
@@ -16,12 +17,17 @@ export default class ChannelsPostCreate {
|
||||
this.input = container.getByTestId('post_textbox');
|
||||
this.attachmentButton = container.getByLabel('attachment');
|
||||
this.emojiButton = container.getByLabel('select an emoji');
|
||||
this.sendButton = container.getByTestId('SendMessageButton');
|
||||
}
|
||||
|
||||
async postMessage(message: string) {
|
||||
await this.input.fill(message);
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
await this.sendButton.click();
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
await expect(this.container).toBeVisible();
|
||||
await expect(this.input).toBeVisible();
|
||||
|
||||
@@ -49,6 +49,10 @@ export default class ChannelsPage {
|
||||
await this.postCreate.postMessage(message);
|
||||
}
|
||||
|
||||
async sendMessage() {
|
||||
await this.postCreate.sendMessage();
|
||||
}
|
||||
|
||||
async getFirstPost() {
|
||||
await this.page.getByTestId('postView').first().waitFor();
|
||||
const post = await this.page.getByTestId('postView').first();
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
import {Page, ViewportSize} from '@playwright/test';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
import {appsPluginId, callsPluginId} from '@e2e-support/constant';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export type TestArgs = {
|
||||
@@ -17,7 +20,7 @@ export type TestConfig = {
|
||||
adminUsername: string;
|
||||
adminPassword: string;
|
||||
adminEmail: string;
|
||||
boardsProductEnabled: boolean;
|
||||
ensurePluginsInstalled: string[];
|
||||
resetBeforeTest: boolean;
|
||||
haClusterEnabled: boolean;
|
||||
haClusterNodeCount: number;
|
||||
@@ -41,7 +44,10 @@ const config: TestConfig = {
|
||||
adminUsername: process.env.PW_ADMIN_USERNAME || 'sysadmin',
|
||||
adminPassword: process.env.PW_ADMIN_PASSWORD || 'Sys@dmin-sample1',
|
||||
adminEmail: process.env.PW_ADMIN_EMAIL || 'sysadmin@sample.mattermost.com',
|
||||
boardsProductEnabled: parseBool(process.env.PW_BOARDS_PRODUCT_ENABLED, true),
|
||||
ensurePluginsInstalled:
|
||||
typeof process.env?.PW_ENSURE_PLUGINS_INSTALLED === 'string'
|
||||
? process.env.PW_ENSURE_PLUGINS_INSTALLED.split(',')
|
||||
: [appsPluginId, callsPluginId],
|
||||
haClusterEnabled: parseBool(process.env.PW_HA_CLUSTER_ENABLED, false),
|
||||
haClusterNodeCount: parseNumber(process.env.PW_HA_CLUSTER_NODE_COUNT, 2),
|
||||
haClusterName: process.env.PW_HA_CLUSTER_NAME || 'mm_dev_cluster',
|
||||
|
||||
@@ -7,8 +7,6 @@ import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('MM-T4274 Create an Empty Board', async ({pw, pages}) => {
|
||||
await pw.shouldHaveBoardsEnabled();
|
||||
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('Board template', async ({pw, pages, browserName, viewport}, testInfo) => {
|
||||
await pw.shouldHaveBoardsEnabled();
|
||||
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('View untitled board', async ({pw, pages, browserName, viewport}, testInfo) => {
|
||||
await pw.shouldHaveBoardsEnabled();
|
||||
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user