From cfa44a1ca9d9e076bc1d920db1257eab495cb4c9 Mon Sep 17 00:00:00 2001 From: Ammar Ansari Date: Tue, 7 Nov 2023 18:08:16 +0500 Subject: [PATCH] E2E test cases for Call Fabric (#902) * E2E test cases for Call Fabric * call fabric client update * relay application via call fabric * expect the hangup on the relay app * connect relay app via domain app * expect a silence through relay app --- .../e2e-js/tests/callfabric/relayApp.spec.ts | 219 ++++++++++++++++++ internal/e2e-js/tests/callfabric/swml.spec.ts | 50 +++- .../e2e-js/tests/callfabric/videoRoom.spec.ts | 37 ++- internal/e2e-js/utils.ts | 18 +- 4 files changed, 311 insertions(+), 13 deletions(-) create mode 100644 internal/e2e-js/tests/callfabric/relayApp.spec.ts diff --git a/internal/e2e-js/tests/callfabric/relayApp.spec.ts b/internal/e2e-js/tests/callfabric/relayApp.spec.ts new file mode 100644 index 000000000..eaf743091 --- /dev/null +++ b/internal/e2e-js/tests/callfabric/relayApp.spec.ts @@ -0,0 +1,219 @@ +import { Voice } from '@signalwire/realtime-api' +import { + createCFClient, + expectPageReceiveAudio, + getAudioStats, + SERVER_URL, +} from '../../utils' +import { test, expect } from '../../fixtures' + +test.describe('CallFabric Relay Application', () => { + test('should connect to the relay app and expect an audio playback', async ({ + createCustomPage, + }) => { + const client = new Voice.Client({ + host: process.env.RELAY_HOST, + project: process.env.CF_RELAY_PROJECT as string, + token: process.env.CF_RELAY_TOKEN as string, + topics: ['cf-e2e-test-relay'], + debug: { + logWsTraffic: true, + }, + }) + + client.on('call.received', async (call) => { + try { + console.log('Call received', call.id) + + await call.answer() + console.log('Inbound call answered') + + const playback = await call.playAudio({ + url: 'https://cdn.signalwire.com/default-music/welcome.mp3', + }) + await playback.setVolume(10) + } catch (error) { + console.error('Inbound call error', error) + } + }) + + try { + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + await createCFClient(page) + + const resourceName = 'cf-e2e-test-relay' + + await page.evaluate( + async (options) => { + // @ts-expect-error + const client = window._client + + const call = await client.dial({ + to: `/public/${options.resourceName}`, + nodeId: undefined, + }) + + // @ts-expect-error + window._roomObj = call + + await call.start() + }, + { + resourceName, + } + ) + + await expectPageReceiveAudio(page) + + // Hangup the call + await page.evaluate(async () => { + // @ts-expect-error + const call = window._roomObj + + await call.hangup() + }) + + client.disconnect() + } catch (error) { + console.error('CreateRoomSession Error', error) + } + }) + + test('should connect to the relay app and expect a silence', async ({ + createCustomPage, + }) => { + const client = new Voice.Client({ + host: process.env.RELAY_HOST, + project: process.env.CF_RELAY_PROJECT as string, + token: process.env.CF_RELAY_TOKEN as string, + topics: ['cf-e2e-test-relay'], + debug: { + logWsTraffic: true, + }, + }) + + client.on('call.received', async (call) => { + try { + console.log('Call received', call.id) + + await call.answer() + console.log('Inbound call answered') + + const playback = await call.playSilence({ duration: 60 }) + await playback.setVolume(10) + } catch (error) { + console.error('Inbound call error', error) + } + }) + + try { + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + await createCFClient(page) + + const resourceName = 'cf-e2e-test-relay' + + await page.evaluate( + async (options) => { + // @ts-expect-error + const client = window._client + + const call = await client.dial({ + to: `/public/${options.resourceName}`, + nodeId: undefined, + }) + + // @ts-expect-error + window._roomObj = call + + await call.start() + }, + { + resourceName, + } + ) + + const audioStats = await getAudioStats(page) + + expect(audioStats['inbound-rtp']['totalAudioEnergy']).toBeCloseTo(0.1, 0) + + // Hangup the call + await page.evaluate(async () => { + // @ts-expect-error + const call = window._roomObj + + await call.hangup() + }) + + client.disconnect() + } catch (error) { + console.error('CreateRoomSession Error', error) + } + }) + + test('should connect to the relay app and expect a hangup', async ({ + createCustomPage, + }) => { + const client = new Voice.Client({ + host: process.env.RELAY_HOST, + project: process.env.CF_RELAY_PROJECT as string, + token: process.env.CF_RELAY_TOKEN as string, + topics: ['cf-e2e-test-relay'], + debug: { + logWsTraffic: true, + }, + }) + + client.on('call.received', async (call) => { + try { + console.log('Call received', call.id) + + await call.answer() + console.log('Inbound call answered') + + await call.hangup() + } catch (error) { + console.error('Inbound call error', error) + } + }) + + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + const resourceName = 'cf-e2e-test-relay' + + await createCFClient(page) + + // Dial an address and listen a TTS + await page.evaluate( + async ({ resourceName }) => { + // @ts-expect-error + const client = window._client + + const call = await client.dial({ + to: `/public/${resourceName}`, + nodeId: undefined, + }) + + // @ts-expect-error + window._roomObj = call + + await call.start() + }, + { resourceName } + ) + + await page.waitForTimeout(5000) + + const roomSession = await page.evaluate(() => { + // @ts-expect-error + const roomObj = window._roomObj + return roomObj + }) + + expect(roomSession.state).toBe('destroy') + }) +}) diff --git a/internal/e2e-js/tests/callfabric/swml.spec.ts b/internal/e2e-js/tests/callfabric/swml.spec.ts index 2c4cbdc17..f968a4ae0 100644 --- a/internal/e2e-js/tests/callfabric/swml.spec.ts +++ b/internal/e2e-js/tests/callfabric/swml.spec.ts @@ -1,5 +1,5 @@ -import { test } from '../../fixtures' -import { SERVER_URL, createSWClient, expectPageReceiveAudio } from '../../utils' +import { test, expect } from '../../fixtures' +import { SERVER_URL, createCFClient, expectPageReceiveAudio } from '../../utils' test.describe('CallFabric SWML', () => { test('should dial an address and expect a TTS audio', async ({ @@ -10,7 +10,7 @@ test.describe('CallFabric SWML', () => { const resourceName = 'cf-e2e-test-tts' - await createSWClient(page) + await createCFClient(page) // Dial an address and listen a TTS await page.evaluate( @@ -47,4 +47,48 @@ test.describe('CallFabric SWML', () => { await call.hangup() }) }) + + test('should dial an address and expect a hangup', async ({ + createCustomPage, + }) => { + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + const resourceName = 'cf-e2e-test-hangup' + + await createCFClient(page) + + // Dial an address and listen a TTS + await page.evaluate( + async ({ resourceName }) => { + return new Promise(async (resolve, _reject) => { + // @ts-expect-error + const client = window._client + + const call = await client.dial({ + to: `/public/${resourceName}`, + nodeId: undefined, + }) + + // @ts-expect-error + window._roomObj = call + + await call.start() + + resolve(call) + }) + }, + { resourceName } + ) + + await page.waitForTimeout(1000) + + const roomSession = await page.evaluate(() => { + // @ts-expect-error + const roomObj = window._roomObj + return roomObj + }) + + expect(roomSession.state).toBe('destroy') + }) }) diff --git a/internal/e2e-js/tests/callfabric/videoRoom.spec.ts b/internal/e2e-js/tests/callfabric/videoRoom.spec.ts index 8ec0cfb37..cbd83c594 100644 --- a/internal/e2e-js/tests/callfabric/videoRoom.spec.ts +++ b/internal/e2e-js/tests/callfabric/videoRoom.spec.ts @@ -2,7 +2,7 @@ import { Video } from '@signalwire/js' import { test, expect } from '../../fixtures' import { SERVER_URL, - createSWClient, + createCFClient, expectLayoutChanged, expectMCUVisible, setLayoutOnPage, @@ -17,7 +17,7 @@ test.describe('CallFabric VideoRoom', () => { const roomName = 'cf-e2e-test-room' - await createSWClient(page) + await createCFClient(page) // Dial an address and join a video room const roomSession = await page.evaluate( @@ -28,8 +28,6 @@ test.describe('CallFabric VideoRoom', () => { const call = await client.dial({ to: `/public/${roomName}`, - logLevel: 'debug', - debug: { logWsTraffic: true }, nodeId: undefined, }) @@ -199,4 +197,35 @@ test.describe('CallFabric VideoRoom', () => { await setLayoutOnPage(page, layoutName) expect(await layoutChangedPromise).toBe(true) }) + + test('should fail on invalid address', async ({ createCustomPage }) => { + const page = await createCustomPage({ name: '[page]' }) + await page.goto(SERVER_URL) + + await createCFClient(page) + + // Dial an address and join a video room + const roomSession = await page.evaluate(async () => { + try { + // @ts-expect-error + const client = window._client + + const call = await client.dial({ + to: `/public/invalid-address`, + nodeId: undefined, + }) + + // @ts-expect-error + window._roomObj = call + + await call.start() + + return { success: true } + } catch (error) { + return { success: false, error } + } + }) + + expect(roomSession.success).toBe(false) + }) }) diff --git a/internal/e2e-js/utils.ts b/internal/e2e-js/utils.ts index 5e521df2a..3f530632f 100644 --- a/internal/e2e-js/utils.ts +++ b/internal/e2e-js/utils.ts @@ -180,7 +180,7 @@ export const createTestRoomSessionWithJWT = async ( ) } -export const createSWClient = async (page: Page) => { +export const createCFClient = async (page: Page) => { const sat = await createTestSATToken() if (!sat) { console.error('Invalid SAT. Exiting..') @@ -204,7 +204,7 @@ export const createSWClient = async (page: Page) => { return client }, { - RELAY_HOST: process.env.CF_RELAY_HOST, + RELAY_HOST: process.env.RELAY_HOST, API_TOKEN: sat, } ) @@ -436,10 +436,7 @@ export const expectMediaEvent = (page: Page, event: MediaEvent) => { ) } -export const expectTotalAudioEnergyToBeGreaterThan = async ( - page: Page, - value: number -) => { +export const getAudioStats = async (page: Page) => { const audioStats = await page.evaluate(async () => { // @ts-expect-error const roomObj: Video.RoomSession = window._roomObj @@ -488,6 +485,15 @@ export const expectTotalAudioEnergyToBeGreaterThan = async ( }) console.log('audioStats', audioStats) + return audioStats +} + +export const expectTotalAudioEnergyToBeGreaterThan = async ( + page: Page, + value: number +) => { + const audioStats = await getAudioStats(page) + expect(audioStats['inbound-rtp']['totalAudioEnergy']).toBeGreaterThan(value) }