CLD-5948 Playwright/E2E: Update dependencies, server default config and its types, and remove Boards and mobile view tests (#24583)
* update dependencies * update dependencies * remove mobile view * remove boards * update default config and its types * update snapshots * fix formatting * check works and fix styling
@ -6,7 +6,7 @@
|
||||
# Typically run the local server with:
|
||||
cd server && make run
|
||||
|
||||
# Or build and distribute webapp including channels, boards and playbooks
|
||||
# Or build and distribute webapp including channels and playbooks
|
||||
# so that their product URLs do not rely on Webpack dev server.
|
||||
# Especially important when running test inside the Playwright's docker container.
|
||||
cd webapp && make dist
|
||||
@ -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.36.0-focal /bin/bash
|
||||
docker run -it --rm -v "$(pwd):/mattermost/" --ipc=host mcr.microsoft.com/playwright:v1.38.0-jammy /bin/bash
|
||||
```
|
||||
|
||||
#### 2. Inside the docker container
|
||||
|
@ -48,7 +48,7 @@ async function sysadminSetup(client: Client, user: UserProfile | null) {
|
||||
await client.createTeam(createRandomTeam(defaultTeam.name, defaultTeam.displayName, 'O', false));
|
||||
} else if (myDefaultTeam && testConfig.resetBeforeTest) {
|
||||
await Promise.all(
|
||||
myTeams.filter((team) => team.name !== defaultTeam.name).map((team) => client.deleteTeam(team.id))
|
||||
myTeams.filter((team) => team.name !== defaultTeam.name).map((team) => client.deleteTeam(team.id)),
|
||||
);
|
||||
|
||||
const myChannels = await client.getMyChannels(myDefaultTeam.id);
|
||||
@ -61,7 +61,7 @@ async function sysadminSetup(client: Client, user: UserProfile | null) {
|
||||
channel.name !== 'off-topic'
|
||||
);
|
||||
})
|
||||
.map((channel) => client.deleteChannel(channel.id))
|
||||
.map((channel) => client.deleteChannel(channel.id)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ async function ensureServerDeployment(client: Client) {
|
||||
sameClusterName,
|
||||
sameClusterName
|
||||
? ''
|
||||
: `Should have cluster name set and as expected. Got "${ClusterName}" but expected "${haClusterName}"`
|
||||
: `Should have cluster name set and as expected. Got "${ClusterName}" but expected "${haClusterName}"`,
|
||||
).toBe(true);
|
||||
|
||||
const clusterInfo = await client.getClusterStatus();
|
||||
@ -179,12 +179,12 @@ async function ensureServerDeployment(client: Client) {
|
||||
sameCount,
|
||||
sameCount
|
||||
? ''
|
||||
: `Should match number of nodes in a cluster as expected. Got "${clusterInfo?.length}" but expected "${haClusterNodeCount}"`
|
||||
: `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}`)
|
||||
console.log(`hostname: ${info.hostname}, version: ${info.version}, config_hash: ${info.config_hash}`),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
950
e2e-tests/playwright/package-lock.json
generated
@ -4,34 +4,36 @@
|
||||
"percy": "cross-env PERCY_TOKEN=$PERCY_TOKEN PW_PERCY_ENABLE=true percy exec -- playwright test --project=chrome --project=iphone --project=ipad",
|
||||
"tsc": "tsc -b",
|
||||
"lint": "eslint . --ext .js,.ts",
|
||||
"prettier": "prettier --write .",
|
||||
"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",
|
||||
"show-report": "npx playwright show-report"
|
||||
"show-report": "npx playwright show-report",
|
||||
"postinstall": "npx playwright install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@axe-core/playwright": "4.7.3",
|
||||
"@percy/cli": "1.26.2",
|
||||
"@percy/cli": "1.27.1",
|
||||
"@percy/playwright": "1.0.4",
|
||||
"@playwright/test": "1.36.1",
|
||||
"@playwright/test": "1.38.0",
|
||||
"async-wait-until": "2.0.12",
|
||||
"axe-core": "4.7.2",
|
||||
"axe-core": "4.8.1",
|
||||
"chalk": "4.1.2",
|
||||
"deepmerge": "4.3.1",
|
||||
"dotenv": "16.3.1",
|
||||
"form-data": "4.0.0",
|
||||
"isomorphic-unfetch": "4.0.2",
|
||||
"uuid": "9.0.0"
|
||||
"uuid": "9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/uuid": "9.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "6.1.0",
|
||||
"@typescript-eslint/parser": "6.1.0",
|
||||
"@types/uuid": "9.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.0",
|
||||
"@typescript-eslint/parser": "6.7.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "8.45.0",
|
||||
"prettier": "2.8.7",
|
||||
"typescript": "5.0.4"
|
||||
"eslint": "8.49.0",
|
||||
"prettier": "3.0.3",
|
||||
"typescript": "5.2.2"
|
||||
}
|
||||
}
|
||||
|
@ -52,13 +52,6 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'iphone',
|
||||
use: {
|
||||
browserName: 'chromium',
|
||||
...devices['iPhone 13 Pro'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ipad',
|
||||
use: {
|
||||
|
@ -16,41 +16,38 @@
|
||||
# 5. PW_ADMIN_EMAIL
|
||||
# - Default to "sysadmin@sample.mattermost.com" if not set.
|
||||
|
||||
# 6. PW_BOARDS_PRODUCT_ENABLED
|
||||
# - Default to "true" if not set. Used to correctly set server config.
|
||||
|
||||
# 7. PW_HA_CLUSTER_ENABLED
|
||||
# 6. PW_HA_CLUSTER_ENABLED
|
||||
# - Default to "false" if not set. Set to true if the test server is with HA enabled.
|
||||
|
||||
# 8. PW_HA_CLUSTER_NODE_COUNT
|
||||
# 7. PW_HA_CLUSTER_NODE_COUNT
|
||||
# - Default to "2" if not set.
|
||||
|
||||
# 9. PW_HA_CLUSTER_NAME
|
||||
# 8. PW_HA_CLUSTER_NAME
|
||||
# - Default to "mm_dev_cluster" if not set.
|
||||
|
||||
# 10. PW_RESET_BEFORE_TEST
|
||||
# 9. PW_RESET_BEFORE_TEST
|
||||
# - Default to "false" if not set. If true, the setup deletes all teams and channels other than the default team which is "ad-1".
|
||||
|
||||
# 11. CI
|
||||
# 10. CI
|
||||
# - Default to "false" if not set.
|
||||
|
||||
# 12. PW_HEADLESS
|
||||
# 11. PW_HEADLESS
|
||||
# - Default to "false" or headless mode if not set. Set to true to run test in headed mode.
|
||||
|
||||
# 13. PW_SLOWMO
|
||||
# 12. PW_SLOWMO
|
||||
# - Default to "0" if not set which means normal test speed run. Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on.
|
||||
|
||||
# 14. PW_WORKERS
|
||||
# 13. PW_WORKERS
|
||||
# - Default to "1" if not set. The maximum number of concurrent worker processes to use for parallelizing tests.
|
||||
|
||||
# 15. PW_SNAPSHOT_ENABLE
|
||||
# 14. PW_SNAPSHOT_ENABLE
|
||||
# - Default to "false" if not set. Set to true to enable snapshot testing.
|
||||
# Note that, snapshot testing should be done in Playwright docker image only.
|
||||
# This is to ensure that, there's a common base platform for all contributors
|
||||
# regardless of each local development platform.
|
||||
|
||||
# 16. PW_PERCY_ENABLE
|
||||
# 15. PW_PERCY_ENABLE
|
||||
# - Default to "false" if not set. Use to save and compare results via https://percy.io/.
|
||||
|
||||
# 17. PERCY_TOKEN
|
||||
# 16. PERCY_TOKEN
|
||||
# - A token required by https://percy.io/.
|
||||
|
@ -2,6 +2,5 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export const appsPluginId = 'com.mattermost.apps';
|
||||
export const boardsPluginId = 'focalboard';
|
||||
export const callsPluginId = 'com.mattermost.calls';
|
||||
export const playbooksPluginId = 'playbooks';
|
||||
|
@ -3,11 +3,10 @@
|
||||
|
||||
import os from 'node:os';
|
||||
|
||||
import {expect, test} from '@playwright/test';
|
||||
import {expect} from '@playwright/test';
|
||||
|
||||
import {callsPluginId} from './constant';
|
||||
import {getAdminClient} from './server/init';
|
||||
import {isSmallScreen} from './util';
|
||||
|
||||
export async function shouldHaveCallsEnabled(enabled = true) {
|
||||
const {adminClient} = await getAdminClient();
|
||||
@ -26,14 +25,10 @@ export async function shouldHaveFeatureFlag(name: string, value: string | boolea
|
||||
const matched = config.FeatureFlags[name] === value;
|
||||
expect(
|
||||
matched,
|
||||
matched ? '' : `FeatureFlags["${name}'] expect "${value}" but actual "${config.FeatureFlags[name]}"`
|
||||
matched ? '' : `FeatureFlags["${name}'] expect "${value}" but actual "${config.FeatureFlags[name]}"`,
|
||||
).toBeTruthy();
|
||||
}
|
||||
|
||||
export function shouldSkipInSmallScreen() {
|
||||
test.skip(({viewport}) => isSmallScreen(viewport), 'Not applicable to mobile device');
|
||||
}
|
||||
|
||||
export async function shouldRunInLinux() {
|
||||
const platform = os.platform();
|
||||
await expect(platform, 'Run in Linux or Playwright docker image only').toBe('linux');
|
||||
|
@ -35,9 +35,6 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
Enable: testConfig.haClusterEnabled,
|
||||
ClusterName: testConfig.haClusterName,
|
||||
},
|
||||
ExperimentalSettings: {
|
||||
DisableAppBar: false,
|
||||
},
|
||||
PasswordSettings: {
|
||||
MinimumLength: 5,
|
||||
Lowercase: false,
|
||||
@ -48,9 +45,15 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
},
|
||||
PluginSettings: {
|
||||
EnableUploads: true,
|
||||
Plugins: {
|
||||
PluginStates: {
|
||||
'com.mattermost.calls': {
|
||||
defaultenabled: true,
|
||||
Enable: false,
|
||||
},
|
||||
'com.mattermost.nps': {
|
||||
Enable: false,
|
||||
},
|
||||
playbooks: {
|
||||
Enable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -65,7 +68,7 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
};
|
||||
|
||||
// Should be based only from the generated default config from ./server via "make config-reset"
|
||||
// Based on v7.10 server
|
||||
// Based on v9.1 server
|
||||
const defaultServerConfig: AdminConfig = {
|
||||
ServiceSettings: {
|
||||
SiteURL: '',
|
||||
@ -157,6 +160,11 @@ const defaultServerConfig: AdminConfig = {
|
||||
EnableLatex: false,
|
||||
EnableInlineLatex: true,
|
||||
PostPriority: true,
|
||||
AllowPersistentNotifications: true,
|
||||
AllowPersistentNotificationsForGuests: false,
|
||||
PersistentNotificationIntervalMinutes: 5,
|
||||
PersistentNotificationMaxCount: 6,
|
||||
PersistentNotificationMaxRecipients: 5,
|
||||
EnableAPIChannelDeletion: false,
|
||||
EnableLocalMode: false,
|
||||
LocalModeSocketLocation: '/var/tmp/mattermost_local.socket',
|
||||
@ -170,15 +178,11 @@ const defaultServerConfig: AdminConfig = {
|
||||
EnableCustomGroups: true,
|
||||
SelfHostedPurchase: true,
|
||||
AllowSyncedDrafts: true,
|
||||
AllowPersistentNotifications: true,
|
||||
PersistentNotificationMaxCount: 6,
|
||||
PersistentNotificationMaxRecipients: 5,
|
||||
PersistentNotificationIntervalMinutes: 5,
|
||||
AllowPersistentNotificationsForGuests: false,
|
||||
},
|
||||
TeamSettings: {
|
||||
SiteName: 'Mattermost',
|
||||
MaxUsersPerTeam: 50,
|
||||
EnableJoinLeaveMessageByDefault: true,
|
||||
EnableUserCreation: true,
|
||||
EnableOpenServer: false,
|
||||
EnableUserDeactivation: false,
|
||||
@ -222,6 +226,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
DisableDatabaseSearch: false,
|
||||
MigrationsStatementTimeoutSeconds: 100000,
|
||||
ReplicaLagSettings: [],
|
||||
ReplicaMonitorIntervalSeconds: 5,
|
||||
},
|
||||
LogSettings: {
|
||||
EnableConsole: true,
|
||||
@ -236,6 +241,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
EnableDiagnostics: true,
|
||||
VerboseDiagnostics: false,
|
||||
EnableSentry: true,
|
||||
AdvancedLoggingJSON: {},
|
||||
AdvancedLoggingConfig: '',
|
||||
},
|
||||
ExperimentalAuditSettings: {
|
||||
@ -246,6 +252,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
FileMaxBackups: 0,
|
||||
FileCompress: false,
|
||||
FileMaxQueueSize: 1000,
|
||||
AdvancedLoggingJSON: {},
|
||||
AdvancedLoggingConfig: '',
|
||||
},
|
||||
NotificationLogSettings: {
|
||||
@ -257,6 +264,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
FileLevel: 'INFO',
|
||||
FileJson: true,
|
||||
FileLocation: '',
|
||||
AdvancedLoggingJSON: {},
|
||||
AdvancedLoggingConfig: '',
|
||||
},
|
||||
PasswordSettings: {
|
||||
@ -292,6 +300,21 @@ const defaultServerConfig: AdminConfig = {
|
||||
AmazonS3SSE: false,
|
||||
AmazonS3Trace: false,
|
||||
AmazonS3RequestTimeoutMilliseconds: 30000,
|
||||
DedicatedExportStore: false,
|
||||
ExportDriverName: 'local',
|
||||
ExportDirectory: './data/',
|
||||
ExportAmazonS3AccessKeyId: '',
|
||||
ExportAmazonS3SecretAccessKey: '',
|
||||
ExportAmazonS3Bucket: '',
|
||||
ExportAmazonS3PathPrefix: '',
|
||||
ExportAmazonS3Region: '',
|
||||
ExportAmazonS3Endpoint: 's3.amazonaws.com',
|
||||
ExportAmazonS3SSL: true,
|
||||
ExportAmazonS3SignV2: false,
|
||||
ExportAmazonS3SSE: false,
|
||||
ExportAmazonS3Trace: false,
|
||||
ExportAmazonS3RequestTimeoutMilliseconds: 30000,
|
||||
ExportAmazonS3PresignExpiresSeconds: 21600,
|
||||
},
|
||||
EmailSettings: {
|
||||
EnableSignUpWithEmail: true,
|
||||
@ -343,7 +366,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
SupportSettings: {
|
||||
TermsOfServiceLink: 'https://mattermost.com/pl/terms-of-use/',
|
||||
PrivacyPolicyLink: 'https://mattermost.com/pl/privacy-policy/',
|
||||
AboutLink: 'https://docs.mattermost.com/pl/about-mattermost',
|
||||
AboutLink: 'https://mattermost.com/pl/about-mattermost',
|
||||
HelpLink: 'https://mattermost.com/pl/help/',
|
||||
ReportAProblemLink: 'https://mattermost.com/pl/report-a-bug',
|
||||
ForgotPasswordLink: '',
|
||||
@ -538,7 +561,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
UseNewSAMLLibrary: false,
|
||||
EnableSharedChannels: false,
|
||||
EnableRemoteClusterService: false,
|
||||
DisableAppBar: true,
|
||||
DisableAppBar: false,
|
||||
DisableRefetchingOnBrowserFocus: false,
|
||||
DelayChannelAutocomplete: false,
|
||||
},
|
||||
@ -582,10 +605,14 @@ const defaultServerConfig: AdminConfig = {
|
||||
DataRetentionSettings: {
|
||||
EnableMessageDeletion: false,
|
||||
EnableFileDeletion: false,
|
||||
EnableBoardsDeletion: false,
|
||||
MessageRetentionDays: 365,
|
||||
FileRetentionDays: 365,
|
||||
BoardsRetentionDays: 365,
|
||||
DeletionJobStartTime: '02:00',
|
||||
BatchSize: 3000,
|
||||
TimeBetweenBatchesMilliseconds: 100,
|
||||
RetentionIdsBatchSize: 100,
|
||||
},
|
||||
MessageExportSettings: {
|
||||
EnableExport: false,
|
||||
@ -624,6 +651,9 @@ const defaultServerConfig: AdminConfig = {
|
||||
'com.mattermost.nps': {
|
||||
Enable: true,
|
||||
},
|
||||
playbooks: {
|
||||
Enable: true,
|
||||
},
|
||||
},
|
||||
EnableMarketplace: true,
|
||||
EnableRemoteMarketplace: true,
|
||||
@ -635,6 +665,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
},
|
||||
DisplaySettings: {
|
||||
CustomURLSchemes: [],
|
||||
MaxMarkdownNodes: 0,
|
||||
ExperimentalTimezone: true,
|
||||
},
|
||||
GuestAccountsSettings: {
|
||||
@ -653,30 +684,24 @@ const defaultServerConfig: AdminConfig = {
|
||||
CloudSettings: {
|
||||
CWSURL: 'https://customers.mattermost.com',
|
||||
CWSAPIURL: 'https://portal.internal.prod.cloud.mattermost.com',
|
||||
CWSMock: false,
|
||||
},
|
||||
FeatureFlags: {
|
||||
TestFeature: 'off',
|
||||
TestBoolFeature: false,
|
||||
EnableRemoteClusterService: false,
|
||||
AppsEnabled: true,
|
||||
PluginPlaybooks: '',
|
||||
PluginApps: '',
|
||||
PluginFocalboard: '',
|
||||
PluginCalls: '',
|
||||
PermalinkPreviews: true,
|
||||
PermalinkPreviews: false,
|
||||
CallsEnabled: true,
|
||||
BoardsFeatureFlags: '',
|
||||
NormalizeLdapDNs: false,
|
||||
GraphQL: false,
|
||||
CommandPalette: false,
|
||||
SendWelcomePost: true,
|
||||
PostPriority: true,
|
||||
PostPriority: false,
|
||||
WysiwygEditor: false,
|
||||
ThreadsEverywhere: false,
|
||||
OnboardingTourTips: true,
|
||||
DeprecateCloudFree: false,
|
||||
CloudReverseTrial: false,
|
||||
StreamlinedMarketplace: true
|
||||
EnableExportDirectDownload: false,
|
||||
StreamlinedMarketplace: true,
|
||||
},
|
||||
ImportSettings: {
|
||||
Directory: './import',
|
||||
|
@ -24,7 +24,7 @@ export async function initSetup({
|
||||
const {adminClient, adminUser} = await getAdminClient();
|
||||
if (!adminClient) {
|
||||
throw new Error(
|
||||
"Failed to setup admin: Check that you're able to access the server using the same admin credential."
|
||||
"Failed to setup admin: Check that you're able to access the server using the same admin credential.",
|
||||
);
|
||||
}
|
||||
|
||||
@ -83,8 +83,8 @@ export async function initSetup({
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
chalk.green(
|
||||
`This failed due to the experimental fetch support in Node.js starting v18.0.0.\nYou may set environment variable: "export NODE_OPTIONS='--no-experimental-fetch'", then try again.'`
|
||||
)
|
||||
`This failed due to the experimental fetch support in Node.js starting v18.0.0.\nYou may set environment variable: "export NODE_OPTIONS='--no-experimental-fetch'", then try again.'`,
|
||||
),
|
||||
);
|
||||
}
|
||||
expect(err, 'Should not throw an error').toBeFalsy();
|
||||
|
@ -16,6 +16,6 @@ export async function hideDynamicChannelsContent(page: Page) {
|
||||
|
||||
export async function waitForAnimationEnd(locator: Locator) {
|
||||
return locator.evaluate((element) =>
|
||||
Promise.all(element.getAnimations({subtree: true}).map((animation) => animation.finished))
|
||||
Promise.all(element.getAnimations({subtree: true}).map((animation) => animation.finished)),
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
import {test as base, Browser, Page, ViewportSize} from '@playwright/test';
|
||||
import {test as base, Browser, Page} from '@playwright/test';
|
||||
import {AxeResults} from 'axe-core';
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
|
||||
import {TestBrowser} from './browser_context';
|
||||
import {shouldHaveCallsEnabled, shouldHaveFeatureFlag, shouldSkipInSmallScreen, shouldRunInLinux} from './flag';
|
||||
import {shouldHaveCallsEnabled, shouldHaveFeatureFlag, shouldRunInLinux} from './flag';
|
||||
import {initSetup, getAdminClient} from './server';
|
||||
import {isSmallScreen} from './util';
|
||||
import {hideDynamicChannelsContent, waitForAnimationEnd, waitUntil} from './test_action';
|
||||
import {pages} from './ui/pages';
|
||||
import {matchSnapshot} from './visual';
|
||||
@ -29,8 +28,8 @@ export const test = base.extend<ExtendedFixtures>({
|
||||
const ab = new AxeBuilderExtended();
|
||||
await use(ab);
|
||||
},
|
||||
pw: async ({browser, viewport}, use) => {
|
||||
const pw = new PlaywrightExtended(browser, viewport);
|
||||
pw: async ({browser}, use) => {
|
||||
const pw = new PlaywrightExtended(browser);
|
||||
await use(pw);
|
||||
await pw.testBrowser.close();
|
||||
},
|
||||
@ -47,7 +46,6 @@ class PlaywrightExtended {
|
||||
// ./flag
|
||||
readonly shouldHaveCallsEnabled;
|
||||
readonly shouldHaveFeatureFlag;
|
||||
readonly shouldSkipInSmallScreen;
|
||||
readonly shouldRunInLinux;
|
||||
|
||||
// ./server
|
||||
@ -62,20 +60,16 @@ class PlaywrightExtended {
|
||||
// ./ui/pages
|
||||
readonly pages;
|
||||
|
||||
// ./util
|
||||
readonly isSmallScreen;
|
||||
|
||||
// ./visual
|
||||
readonly matchSnapshot;
|
||||
|
||||
constructor(browser: Browser, viewport: ViewportSize | null) {
|
||||
constructor(browser: Browser) {
|
||||
// ./browser_context
|
||||
this.testBrowser = new TestBrowser(browser);
|
||||
|
||||
// ./flag
|
||||
this.shouldHaveCallsEnabled = shouldHaveCallsEnabled;
|
||||
this.shouldHaveFeatureFlag = shouldHaveFeatureFlag;
|
||||
this.shouldSkipInSmallScreen = shouldSkipInSmallScreen;
|
||||
this.shouldRunInLinux = shouldRunInLinux;
|
||||
|
||||
// ./server
|
||||
@ -90,9 +84,6 @@ class PlaywrightExtended {
|
||||
// ./ui/pages
|
||||
this.pages = pages;
|
||||
|
||||
// ./util
|
||||
this.isSmallScreen = () => isSmallScreen(viewport);
|
||||
|
||||
// ./visual
|
||||
this.matchSnapshot = matchSnapshot;
|
||||
}
|
||||
|
@ -1,27 +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 BoardsCreateModal {
|
||||
readonly container: Locator;
|
||||
|
||||
readonly productSwitchMenu;
|
||||
|
||||
constructor(container: Locator) {
|
||||
this.container = container;
|
||||
|
||||
this.productSwitchMenu = container.getByRole('button', {name: 'Product switch menu'});
|
||||
}
|
||||
|
||||
async switchProduct(name: string) {
|
||||
await this.productSwitchMenu.click();
|
||||
await this.container.getByRole('link', {name: ` ${name}`}).click();
|
||||
}
|
||||
|
||||
async toBeVisible(name: string) {
|
||||
await expect(this.container.getByRole('heading', {name})).toBeVisible();
|
||||
}
|
||||
}
|
||||
|
||||
export {BoardsCreateModal};
|
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Locator} from '@playwright/test';
|
||||
|
||||
export default class BoardsSidebar {
|
||||
readonly container: Locator;
|
||||
|
||||
readonly plusButton;
|
||||
readonly createNewBoardMenuItem;
|
||||
readonly createNewCategoryMenuItem;
|
||||
readonly titles;
|
||||
|
||||
constructor(container: Locator) {
|
||||
this.container = container;
|
||||
|
||||
this.plusButton = container.locator('.add-board-icon');
|
||||
this.createNewBoardMenuItem = container.getByRole('button', {name: 'Create new board'});
|
||||
this.createNewCategoryMenuItem = container.getByRole('button', {name: 'Create New Category'});
|
||||
this.titles = container.locator('.SidebarBoardItem > .octo-sidebar-title');
|
||||
}
|
||||
|
||||
async waitForTitle(name: string) {
|
||||
await this.container.getByRole('button', {name: ` ${name}`}).waitFor({state: 'visible'});
|
||||
}
|
||||
}
|
||||
|
||||
export {BoardsSidebar};
|
@ -47,8 +47,8 @@ export default class ChannelsCenterView {
|
||||
|
||||
/**
|
||||
* Return the Nth post in the Center from the top
|
||||
* @param index
|
||||
* @returns
|
||||
* @param index
|
||||
* @returns
|
||||
*/
|
||||
async getNthPost(index: number) {
|
||||
const nthPost = this.container.getByTestId('postView').nth(index);
|
||||
@ -73,7 +73,7 @@ export default class ChannelsCenterView {
|
||||
const content = await post.container.textContent();
|
||||
return content?.includes(text);
|
||||
},
|
||||
{timeout}
|
||||
{timeout},
|
||||
);
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ export default class ChannelsCenterView {
|
||||
|
||||
return content?.includes(text);
|
||||
},
|
||||
{timeout}
|
||||
{timeout},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export default class EmojiGifPicker {
|
||||
|
||||
this.gifTab = container.getByText('GIFs');
|
||||
this.gifSearchInput = container.getByPlaceholder('Search GIPHY');
|
||||
this.gifPickerItems = container.locator('.gif-picker__items')
|
||||
this.gifPickerItems = container.locator('.gif-picker__items');
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
@ -24,7 +24,7 @@ export default class EmojiGifPicker {
|
||||
|
||||
async openGifTab() {
|
||||
await expect(this.gifTab).toBeVisible();
|
||||
|
||||
|
||||
await this.gifTab.click({force: true});
|
||||
|
||||
await expect(this.gifSearchInput).toBeVisible();
|
||||
@ -41,7 +41,7 @@ export default class EmojiGifPicker {
|
||||
|
||||
await this.gifPickerItems.locator('img').nth(n).waitFor();
|
||||
const nthGif = this.gifPickerItems.locator('img').nth(n);
|
||||
await expect(nthGif).toBeVisible()
|
||||
await expect(nthGif).toBeVisible();
|
||||
|
||||
const nthGifSrc = await nthGif.getAttribute('src');
|
||||
const nthGifAlt = await nthGif.getAttribute('alt');
|
||||
|
@ -1,13 +1,12 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {BoardsSidebar} from './boards/sidebar';
|
||||
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';
|
||||
import {ChannelsCenterView} from './channels/center_view'
|
||||
import {ChannelsCenterView} from './channels/center_view';
|
||||
import {ChannelsSidebarLeft} from './channels/sidebar_left';
|
||||
import {ChannelsSidebarRight} from './channels/sidebar_right';
|
||||
import {DeletePostModal} from './channels/delete_post_modal';
|
||||
@ -22,7 +21,6 @@ import {ThreadFooter} from './channels/thread_footer';
|
||||
import {EmojiGifPicker} from './channels/emoji_gif_picker';
|
||||
|
||||
const components = {
|
||||
BoardsSidebar,
|
||||
GlobalHeader,
|
||||
ChannelsCenterView,
|
||||
ChannelsSidebarLeft,
|
||||
@ -45,7 +43,6 @@ const components = {
|
||||
|
||||
export {
|
||||
components,
|
||||
BoardsSidebar,
|
||||
GlobalHeader,
|
||||
ChannelsCenterView,
|
||||
ChannelsSidebarLeft,
|
||||
|
@ -1,47 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {expect, Page} from '@playwright/test';
|
||||
|
||||
import {components} from '@e2e-support/ui/components';
|
||||
|
||||
export default class BoardsCreatePage {
|
||||
readonly boards = 'Boards';
|
||||
readonly page: Page;
|
||||
|
||||
readonly globalHeader;
|
||||
|
||||
readonly createBoardHeading;
|
||||
readonly createEmptyBoardButton;
|
||||
readonly useTemplateButton;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.globalHeader = new components.GlobalHeader(this.page.locator('#global-header'));
|
||||
this.createBoardHeading = page.getByRole('heading', {name: 'Create a board'});
|
||||
this.createEmptyBoardButton = page.getByRole('button', {name: ' Create an empty board'});
|
||||
this.useTemplateButton = page.getByRole('button', {name: 'Use this template'});
|
||||
}
|
||||
|
||||
async goto(teamId = '') {
|
||||
let boardsUrl = '/boards';
|
||||
if (teamId) {
|
||||
boardsUrl += `/team/${teamId}`;
|
||||
}
|
||||
|
||||
await this.page.goto(boardsUrl);
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
await this.globalHeader.toBeVisible(this.boards);
|
||||
await expect(this.createEmptyBoardButton).toBeVisible();
|
||||
await expect(this.useTemplateButton).toBeVisible();
|
||||
await expect(this.createBoardHeading).toBeVisible();
|
||||
}
|
||||
|
||||
async createEmptyBoard() {
|
||||
await this.createEmptyBoardButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
export {BoardsCreatePage};
|
@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {expect, Page} from '@playwright/test';
|
||||
|
||||
import {components} from '@e2e-support/ui/components';
|
||||
|
||||
export default class BoardsViewPage {
|
||||
readonly boards = 'Boards';
|
||||
readonly page: Page;
|
||||
|
||||
readonly sidebar;
|
||||
readonly globalHeader;
|
||||
|
||||
readonly topHead;
|
||||
readonly editableTitle;
|
||||
readonly shareButton;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.sidebar = new components.BoardsSidebar(page.locator('.octo-sidebar'));
|
||||
this.globalHeader = new components.GlobalHeader(this.page.locator('#global-header'));
|
||||
this.topHead = page.locator('.top-head');
|
||||
this.editableTitle = this.topHead.getByPlaceholder('Untitled board');
|
||||
this.shareButton = page.getByRole('button', {name: ' Share'});
|
||||
}
|
||||
|
||||
async goto(teamId = '', boardId = '', viewId = '', cardId = '') {
|
||||
let boardsUrl = '/boards';
|
||||
if (teamId) {
|
||||
boardsUrl += `/team/${teamId}`;
|
||||
if (boardId) {
|
||||
boardsUrl += `/${boardId}`;
|
||||
if (viewId) {
|
||||
boardsUrl += `/${viewId}`;
|
||||
if (cardId) {
|
||||
boardsUrl += `/${cardId}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.page.goto(boardsUrl);
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
await this.page.waitForLoadState('networkidle');
|
||||
await this.globalHeader.toBeVisible(this.boards);
|
||||
await expect(this.shareButton).toBeVisible();
|
||||
await expect(this.topHead).toBeVisible();
|
||||
}
|
||||
|
||||
async shouldHaveUntitledBoard() {
|
||||
await this.editableTitle.isVisible();
|
||||
expect(await this.editableTitle.getAttribute('value')).toBe('');
|
||||
await expect(this.page.getByTitle('(Untitled Board)')).toBeVisible();
|
||||
}
|
||||
}
|
||||
|
||||
export {BoardsViewPage};
|
@ -4,7 +4,6 @@
|
||||
import {Page} from '@playwright/test';
|
||||
|
||||
import {components} from '@e2e-support/ui/components';
|
||||
import {isSmallScreen} from '@e2e-support/util';
|
||||
|
||||
export default class ChannelsPage {
|
||||
readonly channels = 'Channels';
|
||||
@ -19,7 +18,7 @@ export default class ChannelsPage {
|
||||
|
||||
readonly findChannelsModal;
|
||||
readonly deletePostModal;
|
||||
|
||||
|
||||
readonly postDotMenu;
|
||||
readonly postReminderMenu;
|
||||
|
||||
@ -35,7 +34,7 @@ export default class ChannelsPage {
|
||||
this.sidebarRight = new components.ChannelsSidebarRight(page.locator('#sidebar-right'));
|
||||
this.appBar = new components.ChannelsAppBar(page.locator('.app-bar'));
|
||||
|
||||
// Modals
|
||||
// Modals
|
||||
this.findChannelsModal = new components.FindChannelsModal(page.getByRole('dialog', {name: 'Find Channels'}));
|
||||
this.deletePostModal = new components.DeletePostModal(page.locator('#deletePostModal'));
|
||||
|
||||
@ -48,10 +47,6 @@ export default class ChannelsPage {
|
||||
}
|
||||
|
||||
async toBeVisible() {
|
||||
if (!isSmallScreen(this.page.viewportSize())) {
|
||||
await this.globalHeader.toBeVisible(this.channels);
|
||||
}
|
||||
|
||||
await this.centerView.toBeVisible();
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {BoardsCreatePage} from './boards_create';
|
||||
import {BoardsViewPage} from './boards_view';
|
||||
import {ChannelsPage} from './channels';
|
||||
import {LandingLoginPage} from './landing_login';
|
||||
import {LoginPage} from './login';
|
||||
@ -10,8 +8,6 @@ import {ResetPasswordPage} from './reset_password';
|
||||
import {SignupPage} from './signup';
|
||||
|
||||
const pages = {
|
||||
BoardsCreatePage,
|
||||
BoardsViewPage,
|
||||
ChannelsPage,
|
||||
LandingLoginPage,
|
||||
LoginPage,
|
||||
@ -19,4 +15,4 @@ const pages = {
|
||||
SignupPage,
|
||||
};
|
||||
|
||||
export {pages, BoardsCreatePage, BoardsViewPage, ChannelsPage, LandingLoginPage, LoginPage, SignupPage};
|
||||
export {pages, ChannelsPage, LandingLoginPage, LoginPage, SignupPage};
|
||||
|
@ -44,7 +44,7 @@ export default class SignupPage {
|
||||
this.createAccountButton = page.locator('button:has-text("Create Account")');
|
||||
this.emailError = page.locator('text=Please enter a valid email address');
|
||||
this.usernameError = page.locator(
|
||||
'text=Usernames have to begin with a lowercase letter and be 3-22 characters long. You can use lowercase letters, numbers, periods, dashes, and underscores.'
|
||||
'text=Usernames have to begin with a lowercase letter and be 3-22 characters long. You can use lowercase letters, numbers, periods, dashes, and underscores.',
|
||||
);
|
||||
this.passwordError = page.locator('text=Must be 5-64 characters long.');
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {ViewportSize} from '@playwright/test';
|
||||
|
||||
const second = 1000;
|
||||
const minute = 60 * 1000;
|
||||
@ -46,7 +45,3 @@ export function getRandomId(length = 7): string {
|
||||
export const defaultTeam = {name: 'ad-1', displayName: 'eligendi', type: 'O'};
|
||||
|
||||
export const illegalRe = /[/?<>\\:*|":&();]/g;
|
||||
|
||||
export function isSmallScreen(viewport?: ViewportSize | {width: number; height: number} | null) {
|
||||
return viewport?.width ? Boolean(viewport?.width <= 390) : true;
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ export async function matchSnapshot(testInfo: TestInfo, testArgs: TestArgs) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
`^ Warning: No visual test performed. Run in Linux or Playwright docker image to match snapshot.`
|
||||
)
|
||||
`^ Warning: No visual test performed. Run in Linux or Playwright docker image to match snapshot.`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
import {Page, ViewportSize} from '@playwright/test';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
import {callsPluginId} from '@e2e-support/constant';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export type TestArgs = {
|
||||
@ -47,7 +45,7 @@ const config: TestConfig = {
|
||||
ensurePluginsInstalled:
|
||||
typeof process.env?.PW_ENSURE_PLUGINS_INSTALLED === 'string'
|
||||
? process.env.PW_ENSURE_PLUGINS_INSTALLED.split(',')
|
||||
: [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',
|
||||
|
@ -1,44 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {expect, test} from '@e2e-support/test_fixture';
|
||||
import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('MM-T4274 Create an Empty Board', async ({pw, pages}) => {
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
// Log in a user in new browser context
|
||||
const {page} = await pw.testBrowser.login(user);
|
||||
|
||||
// Visit a default channel page
|
||||
const channelsPage = new pages.ChannelsPage(page);
|
||||
await channelsPage.goto();
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
// Switch to Boards page
|
||||
await channelsPage.globalHeader.switchProduct('Boards');
|
||||
|
||||
// Should have redirected to boards create page
|
||||
const boardsCreatePage = new pages.BoardsCreatePage(page);
|
||||
await boardsCreatePage.toBeVisible();
|
||||
|
||||
// Create empty board
|
||||
await boardsCreatePage.createEmptyBoard();
|
||||
|
||||
// Should have redirected to boards view page
|
||||
const boardsViewPage = new pages.BoardsViewPage(page);
|
||||
await boardsViewPage.toBeVisible();
|
||||
await boardsViewPage.shouldHaveUntitledBoard();
|
||||
|
||||
// Type new title and hit enter
|
||||
const title = 'Testing';
|
||||
await boardsViewPage.editableTitle.fill(title);
|
||||
await boardsViewPage.editableTitle.press('Enter');
|
||||
|
||||
// Should update the title in heading and in sidebar
|
||||
expect(await boardsViewPage.editableTitle.getAttribute('value')).toBe(title);
|
||||
await boardsViewPage.sidebar.waitForTitle(title);
|
||||
});
|
@ -22,7 +22,7 @@ test('MM-T5435_1 Global Drafts link in sidebar should be hidden when another use
|
||||
createRandomPost({
|
||||
channel_id: channel.id,
|
||||
user_id: adminUser.id,
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// # Log in as user in new browser context
|
||||
|
@ -28,7 +28,8 @@ test('MM-T5445 Should search, select and post correct Gif when Gif picker is ope
|
||||
await channelPage.emojiGifPickerPopup.searchGif('hello');
|
||||
|
||||
// # Select the first gif
|
||||
const {img: firstSearchGifResult, alt: altOfFirstSearchGifResult} = await channelPage.emojiGifPickerPopup.getNthGif(0);
|
||||
const {img: firstSearchGifResult, alt: altOfFirstSearchGifResult} =
|
||||
await channelPage.emojiGifPickerPopup.getNthGif(0);
|
||||
await firstSearchGifResult.click();
|
||||
|
||||
// # Send the selected gif as a message
|
||||
@ -82,7 +83,8 @@ test('MM-T5446 Should search, select and post correct Gif when Gif picker is ope
|
||||
await channelPage.emojiGifPickerPopup.searchGif('hello');
|
||||
|
||||
// # Select the first gif
|
||||
const {img: firstSearchGifResult, alt: altOfFirstSearchGifResult} = await channelPage.emojiGifPickerPopup.getNthGif(0);
|
||||
const {img: firstSearchGifResult, alt: altOfFirstSearchGifResult} =
|
||||
await channelPage.emojiGifPickerPopup.getNthGif(0);
|
||||
await firstSearchGifResult.click();
|
||||
|
||||
// # Send the selected gif as a message in the thread
|
||||
|
@ -37,9 +37,7 @@ 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"
|
||||
if (pw.isSmallScreen()) {
|
||||
await channelsPage.centerView.headerMobile.toggleSidebar();
|
||||
}
|
||||
await channelsPage.centerView.headerMobile.toggleSidebar();
|
||||
await channelsPage.sidebarLeft.findChannelButton.click();
|
||||
|
||||
await channelsPage.findChannelsModal.toBeVisible();
|
||||
|
@ -1,24 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {test} from '@e2e-support/test_fixture';
|
||||
import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('Board template', async ({pw, pages, browserName, viewport}, testInfo) => {
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
// Log in a user in new browser context
|
||||
const {page} = await pw.testBrowser.login(user);
|
||||
|
||||
// Should have redirected to boards create page
|
||||
const boardsCreatePage = new pages.BoardsCreatePage(page);
|
||||
await boardsCreatePage.goto();
|
||||
await boardsCreatePage.toBeVisible();
|
||||
|
||||
// Match snapshot of create board page
|
||||
const testArgs = {page, browserName, viewport};
|
||||
await pw.matchSnapshot(testInfo, testArgs);
|
||||
});
|
Before Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 182 KiB |
Before Width: | Height: | Size: 238 KiB |
@ -1,32 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {test} from '@e2e-support/test_fixture';
|
||||
import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('View untitled board', async ({pw, pages, browserName, viewport}, testInfo) => {
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
// Log in a user in new browser context
|
||||
const {page} = await pw.testBrowser.login(user);
|
||||
|
||||
// Should have redirected to boards create page
|
||||
const boardsCreatePage = new pages.BoardsCreatePage(page);
|
||||
await boardsCreatePage.goto();
|
||||
await boardsCreatePage.toBeVisible();
|
||||
|
||||
// Create empty board
|
||||
await boardsCreatePage.createEmptyBoard();
|
||||
|
||||
// Should have redirected to boards view page
|
||||
const boardsViewPage = new pages.BoardsViewPage(page);
|
||||
await boardsViewPage.toBeVisible();
|
||||
await boardsViewPage.shouldHaveUntitledBoard();
|
||||
|
||||
// Match snapshot of create board page
|
||||
const testArgs = {page, browserName, viewport};
|
||||
await pw.matchSnapshot(testInfo, testArgs);
|
||||
});
|
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 84 KiB |
@ -15,16 +15,8 @@ test('Intro to channel as regular user', async ({pw, pages, browserName, viewpor
|
||||
await channelsPage.goto();
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
// Wait for Boards' bot image to be loaded
|
||||
// await pw.shouldHaveFeatureFlag('OnboardingAutoShowLinkedBoard', true);
|
||||
// const boardsWelcomePost = await channelsPage.getFirstPost();
|
||||
// await expect(await boardsWelcomePost.getProfileImage('boards')).toBeVisible();
|
||||
// await wait(duration.one_sec);
|
||||
|
||||
// Wait for Playbooks icon to be loaded in App bar, except in iphone
|
||||
if (!pw.isSmallScreen()) {
|
||||
await expect(channelsPage.appBar.playbooksIcon).toBeVisible();
|
||||
}
|
||||
await expect(channelsPage.appBar.playbooksIcon).toBeVisible();
|
||||
|
||||
// Hide dynamic elements of Channels page
|
||||
await pw.hideDynamicChannelsContent(page);
|
||||
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 170 KiB |
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 220 KiB |
Before Width: | Height: | Size: 156 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
Before Width: | Height: | Size: 312 KiB After Width: | Height: | Size: 319 KiB |
Before Width: | Height: | Size: 241 KiB |
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 278 KiB |
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 302 KiB |
Before Width: | Height: | Size: 230 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 167 KiB |
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 296 KiB After Width: | Height: | Size: 297 KiB |
Before Width: | Height: | Size: 411 KiB After Width: | Height: | Size: 429 KiB |
Before Width: | Height: | Size: 355 KiB |
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 291 KiB |
Before Width: | Height: | Size: 393 KiB After Width: | Height: | Size: 397 KiB |
Before Width: | Height: | Size: 266 KiB |
@ -405,6 +405,7 @@ export type TeamSettings = {
|
||||
ExperimentalPrimaryTeam: string;
|
||||
ExperimentalDefaultChannels: string[];
|
||||
EnableLastActiveTime: boolean;
|
||||
EnableJoinLeaveMessageByDefault: boolean;
|
||||
};
|
||||
|
||||
export type ClientRequirements = {
|
||||
@ -429,6 +430,7 @@ export type SqlSettings = {
|
||||
DisableDatabaseSearch: boolean;
|
||||
MigrationsStatementTimeoutSeconds: number;
|
||||
ReplicaLagSettings: ReplicaLagSetting[];
|
||||
ReplicaMonitorIntervalSeconds: number;
|
||||
};
|
||||
|
||||
export type LogSettings = {
|
||||
@ -445,6 +447,7 @@ export type LogSettings = {
|
||||
VerboseDiagnostics: boolean;
|
||||
EnableSentry: boolean;
|
||||
AdvancedLoggingConfig: string;
|
||||
AdvancedLoggingJSON: Record<string, any>;
|
||||
};
|
||||
|
||||
export type ExperimentalAuditSettings = {
|
||||
@ -456,6 +459,7 @@ export type ExperimentalAuditSettings = {
|
||||
FileCompress: boolean;
|
||||
FileMaxQueueSize: number;
|
||||
AdvancedLoggingConfig: string;
|
||||
AdvancedLoggingJSON: Record<string, any>;
|
||||
};
|
||||
|
||||
export type NotificationLogSettings = {
|
||||
@ -468,6 +472,7 @@ export type NotificationLogSettings = {
|
||||
FileJson: boolean;
|
||||
FileLocation: string;
|
||||
AdvancedLoggingConfig: string;
|
||||
AdvancedLoggingJSON: Record<string, any>;
|
||||
};
|
||||
|
||||
export type PasswordSettings = {
|
||||
@ -504,6 +509,21 @@ export type FileSettings = {
|
||||
AmazonS3SSE: boolean;
|
||||
AmazonS3Trace: boolean;
|
||||
AmazonS3RequestTimeoutMilliseconds: number;
|
||||
DedicatedExportStore: boolean;
|
||||
ExportDriverName: string;
|
||||
ExportDirectory: string;
|
||||
ExportAmazonS3AccessKeyId: string;
|
||||
ExportAmazonS3SecretAccessKey: string;
|
||||
ExportAmazonS3Bucket: string;
|
||||
ExportAmazonS3PathPrefix: string;
|
||||
ExportAmazonS3Region: string;
|
||||
ExportAmazonS3Endpoint: string;
|
||||
ExportAmazonS3SSL: boolean;
|
||||
ExportAmazonS3SignV2: boolean;
|
||||
ExportAmazonS3SSE: boolean;
|
||||
ExportAmazonS3Trace: boolean;
|
||||
ExportAmazonS3RequestTimeoutMilliseconds: number;
|
||||
ExportAmazonS3PresignExpiresSeconds: number;
|
||||
};
|
||||
|
||||
export type EmailSettings = {
|
||||
@ -793,6 +813,10 @@ export type DataRetentionSettings = {
|
||||
FileRetentionDays: number;
|
||||
DeletionJobStartTime: string;
|
||||
BatchSize: number;
|
||||
EnableBoardsDeletion: boolean,
|
||||
BoardsRetentionDays: number;
|
||||
TimeBetweenBatchesMilliseconds: number;
|
||||
RetentionIdsBatchSize: number;
|
||||
};
|
||||
|
||||
export type MessageExportSettings = {
|
||||
@ -842,6 +866,7 @@ export type PluginSettings = {
|
||||
export type DisplaySettings = {
|
||||
CustomURLSchemes: string[];
|
||||
ExperimentalTimezone: boolean;
|
||||
MaxMarkdownNodes: number;
|
||||
};
|
||||
|
||||
export type GuestAccountsSettings = {
|
||||
@ -862,6 +887,7 @@ export type ImageProxySettings = {
|
||||
export type CloudSettings = {
|
||||
CWSURL: string;
|
||||
CWSAPIURL: string;
|
||||
CWSMock: boolean;
|
||||
};
|
||||
|
||||
export type FeatureFlags = Record<string, string | boolean>;
|
||||
|