Skip to content

Commit

Permalink
Recordings e2e (#345)
Browse files Browse the repository at this point in the history
* Recordings e2e

* Fix crash

* Bump timeout

* CRT support

* Media e2e (#347)

* Basic media testing

* Add sample audio file

* Ease parallelization

* Full parallelism
  • Loading branch information
streamer45 committed Mar 3, 2023
1 parent 5a25ba6 commit cb53b09
Show file tree
Hide file tree
Showing 18 changed files with 277 additions and 52 deletions.
Binary file added e2e/assets/sample.wav
Binary file not shown.
3 changes: 2 additions & 1 deletion e2e/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export default class PlaywrightDevPage {
}

async leaveCall() {
await expect(this.page.locator('#calls-widget-leave-button')).toBeVisible();
await this.page.locator('#calls-widget-leave-button').click();
await expect(this.page.locator('#calls-widget')).toBeHidden();
}
Expand All @@ -30,13 +29,15 @@ export default class PlaywrightDevPage {
await expect(startCallButton).toBeVisible();
await startCallButton.click();
await expect(this.page.locator('#calls-widget')).toBeVisible();
await expect(this.page.locator('#calls-widget-loading-overlay')).toBeHidden();
}

async joinCall() {
const joinCallButton = this.page.locator('[aria-label="channel header region"] button:has-text("Join Call")');
await expect(joinCallButton).toBeVisible();
await joinCallButton.click();
await expect(this.page.locator('#calls-widget')).toBeVisible();
await expect(this.page.locator('#calls-widget-loading-overlay')).toBeHidden();
}

async enableCalls() {
Expand Down
7 changes: 5 additions & 2 deletions e2e/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ const config: PlaywrightTestConfig = {
forbidOnly: Boolean(process.env.CI),
retries: process.env.CI ? 2 : 1,
workers: 4,
timeout: 30 * 1000,
fullyParallel: true,
timeout: 60 * 1000,
expect: {
timeout: 20 * 1000,
timeout: 30 * 1000,
toMatchSnapshot: {
maxDiffPixelRatio: 0.05,
},
Expand All @@ -24,6 +25,8 @@ const config: PlaywrightTestConfig = {
args: [
'--use-fake-device-for-media-stream',
'--use-fake-ui-for-media-stream',
'--auto-select-desktop-capture-source="Entire screen"',
'--use-file-for-fake-audio-capture=./assets/sample.wav',
],
},
},
Expand Down
4 changes: 2 additions & 2 deletions e2e/tests/global_widget.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {test, expect, chromium} from '@playwright/test';

import {userState, baseURL, defaultTeam, pluginID} from '../constants';

import {getChannelNameForTest} from '../utils';
import {getChannelNameForTest, getUserIdxForTest} from '../utils';

test.describe('global widget', () => {
test.use({storageState: userState.users[6].storageStatePath});
test.use({storageState: userState.users[getUserIdxForTest()].storageStatePath});

test('start call', async ({page, request}) => {
const channelName = getChannelNameForTest();
Expand Down
28 changes: 10 additions & 18 deletions e2e/tests/join_call.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,32 @@ import {test, expect, chromium} from '@playwright/test';

import PlaywrightDevPage from '../page';
import {userState} from '../constants';
import {startCall, getUserIdxForTest} from '../utils';

const userIdx = getUserIdxForTest();

test.beforeEach(async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
await devPage.goto();
});

test.describe('join call', () => {
test.use({storageState: userState.users[2].storageStatePath});

const startCall = async () => {
const browser = await chromium.launch();
const context = await browser.newContext({storageState: userState.users[3].storageStatePath});
const userPage = new PlaywrightDevPage(await context.newPage());
await userPage.goto();
await userPage.startCall();
return () => {
userPage.leaveCall();
};
};
test.use({storageState: userState.users[userIdx].storageStatePath});

test('channel header button', async ({page}) => {
// start a call
const leaveCall = await startCall();
const userPage = await startCall(userState.users[userIdx + 1].storageStatePath);

const devPage = new PlaywrightDevPage(page);
await devPage.joinCall();
await devPage.leaveCall();

await leaveCall();
await userPage.leaveCall();
});

test('channel toast', async ({page}) => {
// start a call
const leaveCall = await startCall();
const userPage = await startCall(userState.users[userIdx + 1].storageStatePath);

await page.locator('.post__body').last().scrollIntoViewIfNeeded();

Expand All @@ -48,12 +40,12 @@ test.describe('join call', () => {
const devPage = new PlaywrightDevPage(page);
await devPage.leaveCall();

await leaveCall();
await userPage.leaveCall();
});

test('call thread', async ({page}) => {
// start a call
const leaveCall = await startCall();
const userPage = await startCall(userState.users[userIdx + 1].storageStatePath);

const joinCallButton = page.locator('.post__body').last().locator('button:has-text("Join call")');
await expect(joinCallButton).toBeVisible();
Expand All @@ -72,6 +64,6 @@ test.describe('join call', () => {
await leaveCallButton.click();
await expect(page.locator('#calls-widget')).toBeHidden();

await leaveCall();
await userPage.leaveCall();
});
});
121 changes: 121 additions & 0 deletions e2e/tests/media.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import {test, expect, chromium} from '@playwright/test';

import {userState, baseURL, defaultTeam, pluginID} from '../constants';

import {getChannelNameForTest, getUserIdxForTest, startCall} from '../utils';

import PlaywrightDevPage from '../page';

const userIdx = getUserIdxForTest();

test.beforeEach(async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
await devPage.goto();
});

test.describe('screen sharing', () => {
test.use({storageState: userState.users[userIdx].storageStatePath});

test('share screen button', async ({page}) => {
const userPage = await startCall(userState.users[userIdx + 1].storageStatePath);

const devPage = new PlaywrightDevPage(page);
await devPage.joinCall();

await page.locator('#calls-widget-toggle-menu-button').click();
await page.locator('#calls-widget-menu-screenshare').click();

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(() => {
return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id;
});

expect(screenStreamID).toContain('screen_');

await page.getByTestId('calls-widget-stop-screenshare').click();

await expect(page.locator('#screen-player')).toBeHidden();
await expect(userPage.page.locator('#screen-player')).toBeHidden();

await devPage.leaveCall();
await userPage.leaveCall();
});

test('share screen keyboard shortcut', async ({page}) => {
const userPage = await startCall(userState.users[userIdx + 1].storageStatePath);

const devPage = new PlaywrightDevPage(page);
await devPage.joinCall();

await devPage.wait(1000);

if (process.platform === 'darwin') {
await page.keyboard.press('Meta+Shift+E');
} else {
await page.keyboard.press('Control+Shift+E');
}

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(() => {
return window.callsClient.getRemoteScreenStream()?.getVideoTracks()[0]?.id;
});

expect(screenTrackID).toContain('screen_');

if (process.platform === 'darwin') {
await page.keyboard.press('Meta+Shift+E');
} else {
await page.keyboard.press('Control+Shift+E');
}

await expect(page.locator('#screen-player')).toBeHidden();
await expect(userPage.page.locator('#screen-player')).toBeHidden();

await devPage.leaveCall();
await userPage.leaveCall();
});
});

test.describe('sending voice', () => {
test.use({storageState: userState.users[userIdx].storageStatePath});

test('unmuting', async ({page}) => {
const userPage = await startCall(userState.users[userIdx + 1].storageStatePath);

const devPage = new PlaywrightDevPage(page);
await devPage.joinCall();

await page.locator('#voice-mute-unmute').click();

await devPage.wait(1000);

let voiceTrackID = await userPage.page.evaluate(() => {
return window.callsClient.streams[1]?.getAudioTracks()[0]?.id;
});

await expect(userPage.page.getByTestId(voiceTrackID)).toBeHidden();
await expect(userPage.page.getByTestId(voiceTrackID)).toHaveAttribute('autoplay', '');

await userPage.page.locator('#voice-mute-unmute').click();

await devPage.wait(1000);

voiceTrackID = await page.evaluate(() => {
return window.callsClient.streams[1]?.getAudioTracks()[0]?.id;
});

await expect(page.getByTestId(voiceTrackID)).toBeHidden();
await expect(page.getByTestId(voiceTrackID)).toHaveAttribute('autoplay', '');

await devPage.leaveCall();
await userPage.leaveCall();
});
});
10 changes: 6 additions & 4 deletions e2e/tests/popout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import {test, expect} from '@playwright/test';

import PlaywrightDevPage from '../page';
import {userState} from '../constants';
import {getChannelNameForTest} from '../utils';
import {getChannelNameForTest, getUserIdxForTest} from '../utils';

const userIdx = getUserIdxForTest();

test.describe('popout window', () => {
test.use({storageState: userState.users[4].storageStatePath});
test.use({storageState: userState.users[userIdx].storageStatePath});

test('popout opens muted', async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
Expand All @@ -27,7 +29,7 @@ test.describe('popout window', () => {

test('popout opens in a DM channel', async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
await devPage.gotoDM(userState.users[0].username);
await devPage.gotoDM(userState.users[userIdx + 1].username);
await devPage.startCall();

const [popOut, _] = await Promise.all([
Expand Down Expand Up @@ -83,7 +85,7 @@ test.describe('popout window', () => {

test('supports chat in a DM channel', async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
await devPage.gotoDM(userState.users[0].username);
await devPage.gotoDM(userState.users[userIdx + 1].username);
await devPage.startCall();

const [popOut, _] = await Promise.all([
Expand Down
60 changes: 60 additions & 0 deletions e2e/tests/recordings.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {test, expect, chromium} from '@playwright/test';

import {userState, baseURL, defaultTeam, pluginID} from '../constants';

import {getChannelNameForTest} from '../utils';

import PlaywrightDevPage from '../page';

test.beforeEach(async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
await devPage.goto();
});

test.describe('call recordings', () => {
test.use({storageState: userState.users[6].storageStatePath});

test('recording - slash command', async ({page}) => {
const channelName = getChannelNameForTest();

// start call
const devPage = new PlaywrightDevPage(page);
await devPage.startCall();

// start recording
await page.locator('#post_textbox').fill('/call recording start');
await page.locator('[data-testid=SendMessageButton]').click();

// verify recording badge renders correctly
await expect(page.getByTestId('calls-recording-badge')).toBeVisible();
await expect(page.getByTestId('calls-recording-badge')).toContainText('REC');

// very recording start prompt renders correctly
await expect(page.getByTestId('calls-widget-banner-recording')).toBeVisible();
await expect(page.getByTestId('calls-widget-banner-recording')).toContainText('You are recording');

// close prompt
await page.getByTestId('calls-widget-banner-recording').locator('.icon-close').click();
await expect(page.getByTestId('calls-widget-banner-recording')).toBeHidden();

// Give it a few of seconds to produce a decent recording
await devPage.wait(4000);

// stop recording
await page.locator('#post_textbox').fill('/call recording stop');
await page.locator('[data-testid=SendMessageButton]').click();

// very recording ended prompt renders correctly
await expect(page.getByTestId('calls-widget-banner-recording')).toBeVisible();
await expect(page.getByTestId('calls-widget-banner-recording')).toContainText('Recording has stopped. Processing...');

// verify recording file has been posted by the bot (assumes CRT enabled)
await page.locator('.post__body').last().locator('.ThreadFooter button.ReplyButton').click();
await expect(page.locator('.ThreadViewer').locator('.post__header').last()).toContainText('calls');
await expect(page.locator('.ThreadViewer').locator('.post__header').last()).toContainText('BOT');
await expect(page.locator('.ThreadViewer').locator('.post__body').last().filter({has: page.getByTestId('fileAttachmentList')})).toBeVisible();

// leave call
await devPage.leaveCall();
});
});
5 changes: 4 additions & 1 deletion e2e/tests/shortcuts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import {test, expect, chromium} from '@playwright/test';

import PlaywrightDevPage from '../page';
import {userState} from '../constants';
import {getUserIdxForTest} from '../utils';

const userIdx = getUserIdxForTest();

test.beforeEach(async ({page, context}) => {
const devPage = new PlaywrightDevPage(page);
await devPage.goto();
});

test.describe('keyboard shortcuts', () => {
test.use({storageState: userState.users[0].storageStatePath});
test.use({storageState: userState.users[userIdx].storageStatePath});

test('join/leave call', async ({page}) => {
const devPage = new PlaywrightDevPage(page);
Expand Down

0 comments on commit cb53b09

Please sign in to comment.