diff --git a/e2e/global-setup.ts b/e2e/global-setup.ts index 72f6e4163..f746bbe0e 100644 --- a/e2e/global-setup.ts +++ b/e2e/global-setup.ts @@ -1,8 +1,7 @@ import {expect, FullConfig, request} from '@playwright/test'; import {readFile} from 'fs/promises'; -import plugin from '../plugin.json'; -import {adminState, baseURL, channelPrefix, defaultTeam, userPassword, userPrefix} from './constants'; +import {adminState, baseURL, channelPrefix, defaultTeam, pluginID, userPassword, userPrefix} from './constants'; async function globalSetup(config: FullConfig) { const numUsers = config.workers * 3; @@ -189,7 +188,7 @@ async function globalSetup(config: FullConfig) { }); } - await adminContext.post(`/plugins/${plugin.id}/${channel.id}`, { + await adminContext.post(`/plugins/${pluginID}/${channel.id}`, { data: { enabled: true, }, @@ -206,7 +205,7 @@ async function globalSetup(config: FullConfig) { await expect(resp.status()).toEqual(201); } - await adminContext.post(`/api/v4/plugins/${plugin.id}/enable`, { + await adminContext.post(`/api/v4/plugins/${pluginID}/enable`, { headers, }); @@ -214,8 +213,8 @@ async function globalSetup(config: FullConfig) { const serverConfig = await (await adminContext.get('/api/v4/config')).json(); serverConfig.PluginSettings.Plugins = { ...serverConfig.PluginSettings.Plugins, - [`${plugin.id}`]: { - ...serverConfig.PluginSettings.Plugins[plugin.id], + [`${pluginID}`]: { + ...serverConfig.PluginSettings.Plugins[pluginID], defaultenabled: true, enableringing: true, }, diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 1cd14719d..05bb0c68d 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -8,7 +8,8 @@ "@babel/core": "7.20.12", "@babel/eslint-parser": "7.19.1", "@mattermost/types": "6.7.0-0", - "@playwright/test": "1.33.0", + "@playwright/test": "^1.40.1", + "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "5.49.0", "eslint": "8.33.0", "eslint-plugin-import": "2.27.5", @@ -552,22 +553,18 @@ } }, "node_modules/@playwright/test": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.33.0.tgz", - "integrity": "sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", + "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", "dev": true, "dependencies": { - "@types/node": "*", - "playwright-core": "1.33.0" + "playwright": "1.40.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "fsevents": "2.3.2" + "node": ">=16" } }, "node_modules/@types/json-schema": { @@ -583,10 +580,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.51", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.51.tgz", - "integrity": "sha512-LKA7ZhY30I8PiUOzBzhtnIULQTACpiEpPXLiYMWyS+tPAORf+rmXUadHZXB/KFrFyMjeHeKc1GFvLd+3f7LE3w==", - "dev": true + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/semver": { "version": "7.3.13", @@ -2974,16 +2974,34 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/playwright-core": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.33.0.tgz", - "integrity": "sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==", + "node_modules/playwright": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", + "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", "dev": true, + "dependencies": { + "playwright-core": "1.40.1" + }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=14" + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", + "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" } }, "node_modules/prelude-ls": { @@ -3435,6 +3453,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -3964,14 +3988,12 @@ } }, "@playwright/test": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.33.0.tgz", - "integrity": "sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", + "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", "dev": true, "requires": { - "@types/node": "*", - "fsevents": "2.3.2", - "playwright-core": "1.33.0" + "playwright": "1.40.1" } }, "@types/json-schema": { @@ -3987,10 +4009,13 @@ "dev": true }, "@types/node": { - "version": "16.18.51", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.51.tgz", - "integrity": "sha512-LKA7ZhY30I8PiUOzBzhtnIULQTACpiEpPXLiYMWyS+tPAORf+rmXUadHZXB/KFrFyMjeHeKc1GFvLd+3f7LE3w==", - "dev": true + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } }, "@types/semver": { "version": "7.3.13", @@ -5660,10 +5685,20 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "playwright": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", + "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.40.1" + } + }, "playwright-core": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.33.0.tgz", - "integrity": "sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", + "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", "dev": true }, "prelude-ls": { @@ -5964,6 +5999,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", diff --git a/e2e/package.json b/e2e/package.json index 4255ae401..ce84c0bfd 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -9,7 +9,8 @@ "@babel/core": "7.20.12", "@babel/eslint-parser": "7.19.1", "@mattermost/types": "6.7.0-0", - "@playwright/test": "1.33.0", + "@playwright/test": "^1.40.1", + "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "5.49.0", "eslint": "8.33.0", "eslint-plugin-import": "2.27.5", diff --git a/e2e/page.ts b/e2e/page.ts index fa3fc6f59..a79f62300 100644 --- a/e2e/page.ts +++ b/e2e/page.ts @@ -36,23 +36,24 @@ export default class PlaywrightDevPage { async leaveCall() { await this.page.locator('#calls-widget-leave-button').click(); + await this.page.waitForFunction(() => !window.callsClient || window.callsClient.closed); await expect(this.page.locator('#calls-widget')).toBeHidden(); } async startCall() { - const startCallButton = this.page.locator('[aria-label="channel header region"] button:has-text("Start call")'); + const startCallButton = this.page.locator('#calls-join-button'); await expect(startCallButton).toBeVisible(); await startCallButton.click(); + await this.page.waitForFunction(() => window.callsClient && window.callsClient.connected && !window.callsClient.closed); await expect(this.page.locator('#calls-widget')).toBeVisible(); - await expect(this.page.getByTestId('calls-widget-loading-overlay')).toBeHidden(); } async joinCall() { - const joinCallButton = this.page.locator('[aria-label="channel header region"] button:has-text("Join call")'); + const joinCallButton = this.page.locator('#calls-join-button'); await expect(joinCallButton).toBeVisible(); await joinCallButton.click(); + await this.page.waitForFunction(() => window.callsClient && window.callsClient.connected && !window.callsClient.closed); await expect(this.page.locator('#calls-widget')).toBeVisible(); - await expect(this.page.getByTestId('calls-widget-loading-overlay')).toBeHidden(); } async enableCalls() { diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index 8679da8dc..4b17cd3b4 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -4,12 +4,12 @@ const config: PlaywrightTestConfig = { globalSetup: require.resolve('./global-setup'), globalTeardown: require.resolve('./global-teardown'), forbidOnly: Boolean(process.env.CI), - retries: process.env.CI ? 2 : 1, + retries: 1, workers: 4, fullyParallel: true, - timeout: 90 * 1000, + timeout: 120 * 1000, expect: { - timeout: 30 * 1000, + timeout: 60 * 1000, toMatchSnapshot: { maxDiffPixelRatio: 0.05, }, @@ -29,6 +29,10 @@ const config: PlaywrightTestConfig = { '--use-file-for-fake-audio-capture=./assets/sample.wav', ], }, + + // Unfortunately waitForFunction is flaky and randomly returns CSP failures. + // (https://github.com/microsoft/playwright/issues/7395) + bypassCSP: true, }, projects: process.env.CI ? [ { diff --git a/e2e/tests/media.spec.ts b/e2e/tests/media.spec.ts index e5fa123f4..623dccc2d 100644 --- a/e2e/tests/media.spec.ts +++ b/e2e/tests/media.spec.ts @@ -26,12 +26,11 @@ test.describe('screen sharing', () => { await expect(page.locator('#screen-player')).toBeVisible(); await expect(userPage.page.locator('#screen-player')).toBeVisible(); - await devPage.wait(1000); - - const screenStreamID = await userPage.page.evaluate(() => { + const screenStreamID = await (await userPage.page.waitForFunction(() => { + return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; + })).evaluate(() => { return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; }); - expect(screenStreamID).toContain('screen_'); await page.getByTestId('calls-widget-stop-screenshare').click(); @@ -49,8 +48,6 @@ test.describe('screen sharing', () => { const devPage = new PlaywrightDevPage(page); await devPage.joinCall(); - await devPage.wait(1000); - if (process.platform === 'darwin') { await page.keyboard.press('Meta+Shift+E'); } else { @@ -60,12 +57,11 @@ test.describe('screen sharing', () => { await expect(page.locator('#screen-player')).toBeVisible(); await expect(userPage.page.locator('#screen-player')).toBeVisible(); - await devPage.wait(1000); - - const screenTrackID = await userPage.page.evaluate(() => { + const screenTrackID = await (await userPage.page.waitForFunction(() => { + return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; + })).evaluate(() => { return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; }); - expect(screenTrackID).toContain('screen_'); if (process.platform === 'darwin') { @@ -95,10 +91,10 @@ test.describe('screen sharing', () => { await expect(page.locator('#screen-player')).toBeVisible(); await expect(userPage.page.locator('#screen-player')).toBeVisible(); - await devPage.wait(1000); - // verify that on the receiving side the screen track is correctly set - let screenStreamID = await userPage.page.evaluate(() => { + let screenStreamID = await (await userPage.page.waitForFunction(() => { + return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; + })).evaluate(() => { return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; }); expect(screenStreamID).toContain('screen_'); @@ -117,10 +113,10 @@ test.describe('screen sharing', () => { await expect(userPage.page.locator('#screen-player')).toBeVisible(); await expect(devPage.page.locator('#screen-player')).toBeVisible(); - await userPage.wait(1000); - // verify that on the receiving side the screen track is correctly set - screenStreamID = await devPage.page.evaluate(() => { + screenStreamID = await (await devPage.page.waitForFunction(() => { + return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; + })).evaluate(() => { return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id; }); expect(screenStreamID).toContain('screen_'); @@ -141,9 +137,9 @@ test.describe('sending voice', () => { await page.locator('#voice-mute-unmute').click(); - await devPage.wait(1000); - - let voiceTrackID = await userPage.page.evaluate(() => { + let voiceTrackID = await (await userPage.page.waitForFunction(() => { + return window.callsClient.streams[1]?.getAudioTracks()[0]?.id; + })).evaluate(() => { return window.callsClient.streams[1]?.getAudioTracks()[0]?.id; }); @@ -152,9 +148,9 @@ test.describe('sending voice', () => { await userPage.page.locator('#voice-mute-unmute').click(); - await devPage.wait(1000); - - voiceTrackID = await page.evaluate(() => { + voiceTrackID = await (await devPage.page.waitForFunction(() => { + return window.callsClient.streams[1]?.getAudioTracks()[0]?.id; + })).evaluate(() => { return window.callsClient.streams[1]?.getAudioTracks()[0]?.id; }); diff --git a/e2e/tests/notifications.spec.ts b/e2e/tests/notifications.spec.ts index 12b40abed..e71475ad0 100644 --- a/e2e/tests/notifications.spec.ts +++ b/e2e/tests/notifications.spec.ts @@ -19,7 +19,7 @@ const userStorages = getUserStoragesForTest(); const usernames = getUsernamesForTest(); const allUserIDsInTest = getUserIDsForTest(); -test.setTimeout(200 * 1000); +test.setTimeout(240 * 1000); test.beforeEach(async ({page, request}, info) => { // Small optimization to avoid loading an unnecessary channel. @@ -309,7 +309,6 @@ test.describe('notifications', () => { await user1.startCall(); const devPage = new PlaywrightDevPage(page); - await devPage.wait(1000); const user2 = await openGM(userStorages[2], usernames[2]); await user2.startCall(); @@ -338,7 +337,6 @@ test.describe('notifications', () => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await expect(page.locator('#calls-widget')).toBeVisible(); await devPage.hideDocument(true); // Receives two incoming notifications above widget, no notifications on the webapp itself @@ -415,7 +413,6 @@ test.describe('notifications', () => { // The notifications disappear when the calls are ended await user2.leaveCall(); - await devPage.wait(1000); notification = await page.getByTestId('call-incoming-condensed-widget'); await expect(notification).toBeVisible(); @@ -536,9 +533,6 @@ test.describe('notifications', () => { const user1 = await startDMWith(userStorages[1], usernames[0]); await user1.startCall(); - const devPage = new PlaywrightDevPage(page); - await devPage.wait(600); - // received notification let notification = await page.getByTestId('call-incoming'); await expect(notification).toBeVisible(); @@ -549,8 +543,8 @@ test.describe('notifications', () => { await expect(notificationsSoundedAt.length).toEqual(1); // Now start a call + const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await expect(page.locator('#calls-widget')).toBeVisible(); // Original LHS notification should be gone await expect(notification).not.toBeVisible(); @@ -579,13 +573,10 @@ test.describe('notifications', () => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await expect(page.locator('#calls-widget')).toBeVisible(); const user1 = await startDMWith(userStorages[1], usernames[0]); await user1.startCall(); - await devPage.wait(600); - // received notification above widget, not in lhs let notification = await page.getByTestId('call-incoming'); await expect(notification).not.toBeVisible(); diff --git a/e2e/tests/popout.spec.ts b/e2e/tests/popout.spec.ts index 8c636218a..53c6958e4 100644 --- a/e2e/tests/popout.spec.ts +++ b/e2e/tests/popout.spec.ts @@ -275,14 +275,11 @@ test.describe('popout window', () => { await expect(popOut.locator('#sidebar-right [data-testid=call-thread]')).toBeVisible(); - const replyTextbox = popOut.locator('#reply_textbox'); - const msg = '/call leave'; - await replyTextbox.type(msg); - await replyTextbox.press('Enter'); + await popOut.locator('#reply_textbox').fill('/call leave '); + await popOut.getByTestId('SendMessageButton').click(); // Verify we left the call. - await devPage.wait(2000); - await expect(popOut.isClosed()).toEqual(true); await expect(page.locator('#calls-widget')).toBeHidden(); + await expect(popOut.isClosed()).toEqual(true); }); }); diff --git a/e2e/tests/shortcuts.spec.ts b/e2e/tests/shortcuts.spec.ts index 4a031a0ca..983a37239 100644 --- a/e2e/tests/shortcuts.spec.ts +++ b/e2e/tests/shortcuts.spec.ts @@ -39,7 +39,6 @@ test.describe('keyboard shortcuts', () => { test('mute/unmute', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const toggleMute = async () => { if (process.platform === 'darwin') { @@ -75,7 +74,6 @@ test.describe('keyboard shortcuts', () => { test('raise/lower hand', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const toggleHand = async () => { if (process.platform === 'darwin') { @@ -121,7 +119,6 @@ test.describe('keyboard shortcuts', () => { test('participants list toggle', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const toggleParticipants = async () => { if (process.platform === 'darwin') { @@ -147,7 +144,6 @@ test.describe('keyboard shortcuts', () => { test('accessibility conflict', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); // unmute const muteButton = page.locator('#voice-mute-unmute'); diff --git a/e2e/tests/start_call.spec.ts b/e2e/tests/start_call.spec.ts index c7614aab6..efc61a3c8 100644 --- a/e2e/tests/start_call.spec.ts +++ b/e2e/tests/start_call.spec.ts @@ -61,7 +61,6 @@ test.describe('start new call', () => { test('channel header button', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); expect(await page.locator('#calls-widget .calls-widget-bottom-bar').screenshot()).toMatchSnapshot('calls-widget-bottom-bar.png'); await devPage.leaveCall(); }); @@ -80,7 +79,6 @@ test.describe('start new call', () => { const devPage = new PlaywrightDevPage(page); await devPage.gotoDM(usernames[1]); await devPage.startCall(); - await devPage.wait(1000); expect(await page.locator('#calls-widget .calls-widget-bottom-bar').screenshot()).toMatchSnapshot('dm-calls-widget-bottom-bar.png'); await devPage.leaveCall(); }); @@ -130,7 +128,6 @@ test.describe('start new call', () => { test('verify no one is talking…', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); await expect(page.locator('#calls-widget').filter({has: page.getByText('No one is talking…')})).toBeVisible(); @@ -140,7 +137,6 @@ test.describe('start new call', () => { test('ws reconnect', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const reconnected = await page.evaluate(() => { return new Promise((resolve) => { @@ -202,7 +198,6 @@ test.describe('desktop', () => { await page.locator('#calls-widget-toggle-menu-button').click(); await page.locator('#calls-widget-menu-screenshare').click(); await expect(page.locator('#calls-screen-source-modal')).toBeVisible(); - await devPage.wait(1000); expect(await page.locator('#calls-screen-source-modal').screenshot()).toMatchSnapshot('calls-screen-source-modal.png'); await page.locator('#calls-screen-source-modal button:has-text("source_2")').click(); await page.locator('#calls-screen-source-modal button:has-text("Share")').click(); @@ -215,13 +210,17 @@ test.describe('auto join link', () => { test.use({storageState: userStorages[0]}); test('public channel', async ({page, context}) => { + const devPage = new PlaywrightDevPage(page); + await page.locator('#post_textbox').fill('/call link'); await page.getByTestId('SendMessageButton').click(); - const post = page.locator('.post-message__text').last(); - await expect(post).toBeVisible(); + // Make sure we get the ephemeral post and not something else that may + // have been posted by a concurrent test. + const postContent = page.locator('.post__content', {has: page.locator('.post__visibility', {hasText: '(Only visible to you)'})}); + await expect(postContent).toBeVisible(); - const content = await post.textContent(); + const content = await postContent.locator('.post-message__text').textContent(); if (!content) { test.fail(); return; @@ -229,9 +228,10 @@ test.describe('auto join link', () => { const link = content.replace('Call link: ', ''); page.goto(link); - expect(page.locator('#calls-widget .calls-widget-bottom-bar')); - await page.locator('#calls-widget-leave-button').click(); - await expect(page.locator('#calls-widget')).toBeHidden(); + await expect(page.locator('#calls-widget')).toBeVisible(); + await expect(page.getByTestId('calls-widget-loading-overlay')).toBeHidden(); + + await devPage.leaveCall(); }); test('dm channel', async ({page, context}) => { @@ -252,9 +252,10 @@ test.describe('auto join link', () => { const link = content.replace('Call link: ', ''); page.goto(link); - expect(page.locator('#calls-widget .calls-widget-bottom-bar')); - await page.locator('#calls-widget-leave-button').click(); - await expect(page.locator('#calls-widget')).toBeHidden(); + await expect(page.locator('#calls-widget')).toBeVisible(); + await expect(page.getByTestId('calls-widget-loading-overlay')).toBeHidden(); + + await devPage.leaveCall(); }); }); @@ -264,7 +265,6 @@ test.describe('setting audio input device', () => { test('no default', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const currentAudioInputDevice = await page.evaluate(() => { return window.callsClient.currentAudioInputDevice?.deviceId; @@ -280,7 +280,6 @@ test.describe('setting audio input device', () => { test('setting default', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); await page.locator('#calls-widget-toggle-menu-button').click(); await expect(page.locator('#calls-widget-audio-input-button')).toBeVisible(); @@ -309,7 +308,6 @@ test.describe('setting audio input device', () => { await devPage.leaveCall(); await devPage.startCall(); - await devPage.wait(1000); const currentAudioInputDevice2 = await page.evaluate(() => { return window.callsClient.currentAudioInputDevice?.deviceId; @@ -337,7 +335,6 @@ test.describe('setting audio output device', () => { test('no default', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const currentAudioOutputDevice = await page.evaluate(() => { return window.callsClient.currentAudioOutputDevice?.deviceId; @@ -353,7 +350,6 @@ test.describe('setting audio output device', () => { test('setting default', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); await page.locator('#calls-widget-toggle-menu-button').click(); await expect(page.locator('#calls-widget-audio-output-button')).toBeVisible(); @@ -382,7 +378,6 @@ test.describe('setting audio output device', () => { await devPage.leaveCall(); await devPage.startCall(); - await devPage.wait(1000); const currentAudioOutputDevice2 = await page.evaluate(() => { return window.callsClient.currentAudioOutputDevice?.deviceId; @@ -410,7 +405,6 @@ test.describe('switching products', () => { test('playbooks', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); const switchProductsButton = devPage.page.locator('h1', {hasText: 'Channels'}); await expect(switchProductsButton).toBeVisible(); @@ -441,7 +435,6 @@ test.describe('switching views', () => { const devPage = new PlaywrightDevPage(page); devPage.goToChannel(channelName); await devPage.startCall(); - await devPage.wait(1000); // Switch to admin console await devPage.page.locator('#product_switch_menu').click(); @@ -468,7 +461,6 @@ test.describe('ux', () => { test('channel link', async ({page}) => { const devPage = new PlaywrightDevPage(page); await devPage.startCall(); - await devPage.wait(1000); // Check we are on the expected URL await expect(page.url()).toEqual(getChannelURL(getChannelNamesForTest()[0])); diff --git a/webapp/src/actions.ts b/webapp/src/actions.ts index ad0730274..0514387f1 100644 --- a/webapp/src/actions.ts +++ b/webapp/src/actions.ts @@ -373,7 +373,7 @@ export function incomingCallOnChannel(channelID: string, callID: string, callerI export const userLeft = (channelID: string, userID: string, sessionID: string) => { return async (dispatch: DispatchFunc, getState: GetStateFunc) => { // save for later - const callID = calls(getState())[channelID].ID || ''; + const callID = calls(getState())[channelID]?.ID || ''; await dispatch({ type: USER_LEFT,