diff --git a/.github/workflows/browser-js-production.yml b/.github/workflows/browser-js-production.yml index c88c4531a..a8d7f4a86 100644 --- a/.github/workflows/browser-js-production.yml +++ b/.github/workflows/browser-js-production.yml @@ -30,6 +30,7 @@ jobs: callfabric, renegotiation, videoElement, + performance, v2WebRTC, ] steps: diff --git a/.github/workflows/browser-js-staging.yml b/.github/workflows/browser-js-staging.yml index 4f23353d9..5ced864cc 100644 --- a/.github/workflows/browser-js-staging.yml +++ b/.github/workflows/browser-js-staging.yml @@ -29,6 +29,7 @@ jobs: callfabric, renegotiation, videoElement, + performance, v2WebRTC, ] steps: diff --git a/internal/e2e-js/playwright.config.ts b/internal/e2e-js/playwright.config.ts index 6681df342..1ecb7d7ea 100644 --- a/internal/e2e-js/playwright.config.ts +++ b/internal/e2e-js/playwright.config.ts @@ -61,7 +61,11 @@ const videoElementTests = [ 'buildVideoWithVideoSDK.spec.ts', 'buildVideoWithFabricSDK.spec.ts', ] -const v2WebRTC = ['v2WebrtcFromRest.spec.ts', 'webrtcCalling.spec.ts'] +const performanceTests = [ + 'callStartTime.spec.ts', + 'roomSessionStartTime.spec.ts', +] +const v2WebRTCTests = ['v2WebrtcFromRest.spec.ts', 'webrtcCalling.spec.ts'] const useDesktopChrome: PlaywrightTestConfig['use'] = { ...devices['Desktop Chrome'], @@ -104,7 +108,8 @@ const config: PlaywrightTestConfig = { ...callfabricTests, ...renegotiationTests, ...videoElementTests, - ...v2WebRTC, + ...performanceTests, + ...v2WebRTCTests, ], }, { @@ -152,10 +157,15 @@ const config: PlaywrightTestConfig = { use: useDesktopChrome, testMatch: videoElementTests, }, + { + name: 'performance', + use: useDesktopChrome, + testMatch: performanceTests, + }, { name: 'v2WebRTC', use: useDesktopChrome, - testMatch: v2WebRTC, + testMatch: v2WebRTCTests, }, ], } diff --git a/internal/e2e-js/tests/callfabric/callStartTime.spec.ts b/internal/e2e-js/tests/callfabric/callStartTime.spec.ts new file mode 100644 index 000000000..7bf9faea2 --- /dev/null +++ b/internal/e2e-js/tests/callfabric/callStartTime.spec.ts @@ -0,0 +1,95 @@ +import { uuid } from '@signalwire/core' +import { test, expect } from '../../fixtures' +import { SERVER_URL, createCFClient } from '../../utils' +import { SignalWireContract } from '@signalwire/js' + +export const MAX_CALL_SETUP_TIME_MS = 5000 + +export const logCallStartTime = (ms: number) => { + if (ms < MAX_CALL_SETUP_TIME_MS) { + console.log(`\x1b[1;32m✅ call.start(): ${ms.toFixed(0)} ms\x1b[0m`) + } else { + console.log(`\x1b[1;31m❌ call.start(): ${ms.toFixed(0)} ms\x1b[0m`) + } +} + +test.describe('CallFabric Start Time', () => { + test('should join a video room within 5 seconds', async ({ + createCustomPage, + resource, + }) => { + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + const roomName = `e2e_${uuid()}` + await resource.createVideoRoomResource(roomName) + + await createCFClient(page) + + // Dial an address and join a video room + const ms = await page.evaluate( + async ({ address }) => { + // @ts-expect-error + const client: SignalWireContract = window._client + + const call = await client.dial({ + to: address, + rootElement: document.getElementById('rootElement'), + }) + // @ts-expect-error + window._roomObj = call + + const t0 = performance.now() + await call.start() + + return performance.now() - t0 + }, + { + address: `/public/${roomName}?channel=video`, + } + ) + + logCallStartTime(ms) + + expect(ms).toBeLessThan(MAX_CALL_SETUP_TIME_MS) + }) + + test('should join an audio-only room within 5 seconds', async ({ + createCustomPage, + resource, + }) => { + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + const roomName = `e2e_${uuid()}` + await resource.createVideoRoomResource(roomName) + + await createCFClient(page) + + // Dial an address and join a video room + const ms = await page.evaluate( + async ({ address }) => { + // @ts-expect-error + const client: SignalWireContract = window._client + + const call = await client.dial({ + to: address, + }) + // @ts-expect-error + window._roomObj = call + + const t0 = performance.now() + await call.start() + + return performance.now() - t0 + }, + { + address: `/public/${roomName}?channel=audio`, + } + ) + + logCallStartTime(ms) + + expect(ms).toBeLessThan(MAX_CALL_SETUP_TIME_MS) + }) +}) diff --git a/internal/e2e-js/tests/roomSessionStartTime.spec.ts b/internal/e2e-js/tests/roomSessionStartTime.spec.ts new file mode 100644 index 000000000..f64f32a69 --- /dev/null +++ b/internal/e2e-js/tests/roomSessionStartTime.spec.ts @@ -0,0 +1,55 @@ +import type { Video } from '@signalwire/js' +import { test, expect } from '../fixtures' +import { SERVER_URL, createTestRoomSession, randomizeRoomName } from '../utils' + +export const MAX_CALL_SETUP_TIME_MS = 5000 + +export const logCallStartTime = (ms: number) => { + if (ms < MAX_CALL_SETUP_TIME_MS) { + console.log(`\x1b[1;32m✅ call.start(): ${ms.toFixed(0)} ms\x1b[0m`) + } else { + console.log(`\x1b[1;31m❌ call.start(): ${ms.toFixed(0)} ms\x1b[0m`) + } +} + +test.describe('RoomSession Start Time', () => { + test('should join a room room within 5 seconds', async ({ + createCustomPage, + }) => { + const page = await createCustomPage({ name: 'raise-lower' }) + await page.goto(SERVER_URL) + + const roomName = randomizeRoomName('raise-lower-e2e') + const memberSettings = { + vrt: { + room_name: roomName, + user_name: 'e2e_participant_meta', + auto_create_room: true, + permissions: ['room.prioritize_handraise'], + }, + initialEvents: ['room.updated'], + } + + await createTestRoomSession(page, memberSettings) + + // --------------- Joining the room --------------- + const ms = await page.evaluate(() => { + return new Promise(async (resolve, reject) => { + // @ts-expect-error + const roomObj: Video.RoomSession = window._roomObj + + roomObj.once('room.joined', () => { + console.log('Room joined!') + resolve(performance.now() - t0) + }) + + const t0 = performance.now() + await roomObj.join().catch(reject) + }) + }) + + logCallStartTime(ms) + + expect(ms).toBeLessThan(MAX_CALL_SETUP_TIME_MS) + }) +}) diff --git a/internal/e2e-js/utils.ts b/internal/e2e-js/utils.ts index 9f4e4129c..79f54599b 100644 --- a/internal/e2e-js/utils.ts +++ b/internal/e2e-js/utils.ts @@ -1,3 +1,12 @@ +import express, { Express, Request, Response } from 'express' +import { spawn, ChildProcessWithoutNullStreams } from 'child_process' +import path from 'path' +import { EventEmitter } from 'events' +import { v4 as uuid } from 'uuid' +import { clearInterval } from 'timers' +import { Server } from 'http' +import { createServer } from 'vite' +import { Page } from '@playwright/test' import type { DialParams, FabricRoomSession, @@ -7,16 +16,8 @@ import type { Video, } from '@signalwire/js' import type { MediaEventNames } from '@signalwire/webrtc' -import { createServer } from 'vite' -import path from 'path' import { expect } from './fixtures' -import { Page } from '@playwright/test' -import { v4 as uuid } from 'uuid' -import { clearInterval } from 'timers' -import express, { Express, Request, Response } from 'express' -import { Server } from 'http' -import { spawn, ChildProcessWithoutNullStreams } from 'child_process' -import { EventEmitter } from 'events' + declare global { interface Window { _SWJS: {