Skip to content

Commit

Permalink
Fix RealtimeAPI getRoomSessions (#750)
Browse files Browse the repository at this point in the history
* add wrtc to e2e-test rt-api

* add videoUtils

* add TODO lines

* improve rt-api e2e tests for video

* run only video tests

* add videoUtils to spin off roomSessions in realtime-api e2e tests

* improve e2e tests for realtime-api

* disable cache for some video events

* revert unit test - we have no cache obj now

* changeset

* revert dev change
  • Loading branch information
Edoardo Gallo authored Feb 28, 2023
1 parent 908e158 commit fe3b0e2
Show file tree
Hide file tree
Showing 8 changed files with 685 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-socks-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@signalwire/realtime-api': patch
---

Fix bug between getRoomSessions and nested objects in the Video client.
10 changes: 6 additions & 4 deletions internal/e2e-realtime-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
"test": ""
},
"devDependencies": {
"@types/tap": "^15.0.7",
"dotenv": "^16.0.0",
"esbuild-register": "^3.3.2",
"@types/tap": "^15.0.7"
"esbuild-register": "^3.3.2"
},
"dependencies": {
"ws": "^8.5.0",
"tap": "^16.2.0"
"@mapbox/node-pre-gyp": "^1.0.10",
"tap": "^16.2.0",
"wrtc": "^0.4.7",
"ws": "^8.5.0"
}
}
2 changes: 1 addition & 1 deletion internal/e2e-realtime-api/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const createTestRunner = ({
}
}

const getAuthorization = () => {
export const getAuthorization = () => {
const auth = `${process.env.RELAY_PROJECT}:${process.env.RELAY_TOKEN}`
return 'Basic ' + Buffer.from(auth).toString('base64')
}
Expand Down
76 changes: 67 additions & 9 deletions internal/e2e-realtime-api/src/video.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import tap from 'tap'
import { uuid } from '@signalwire/core'
import { Video } from '@signalwire/realtime-api'
import { createTestRunner } from './utils'
import { Video as JsVideo } from '@signalwire/js'
import { createTestRunner, sleep } from './utils'
import { createRoomSession } from './videoUtils'

const handler = () => {
return new Promise<number>(async (resolve, reject) => {
Expand All @@ -8,36 +12,90 @@ const handler = () => {
host: process.env.RELAY_HOST,
project: process.env.RELAY_PROJECT as string,
token: process.env.RELAY_TOKEN as string,
debug: { logWsTraffic: true },
})

const prefix = uuid()
const roomCount = 3
const findRoomSessionsByPrefix = async () => {
const { roomSessions } = await video.getRoomSessions()
return roomSessions.filter((r) => r.name.startsWith(prefix))
}
const roomSessionCreated = new Map<string, any>()

video.on('room.started', async (roomSession) => {
console.log('Room started', roomSession.id)

roomSession.on('member.updated', async (member) => {
console.log(member)
})
roomSessionCreated.set(roomSession.id, roomSession)
})

video.on('room.ended', async (roomSession) => {
console.log('Room ended', roomSession.id)
})

const { roomSessions } = await video.getRoomSessions()
const roomSessionsAtStart = await findRoomSessionsByPrefix()
tap.equal(roomSessionsAtStart.length, 0, 'roomSessionsAtStart is not zero')

let roomSessionPromises: Promise<JsVideo.RoomSession>[] = []
for (let index = 0; index < roomCount; index++) {
roomSessionPromises.push(
createRoomSession({
roomName: `${prefix}-${index}`,
userName: `${prefix}-member-${index}`,
})
)
}

const jsRoomSessions = await Promise.all(roomSessionPromises)

// Leave time to connect all the room sessions
await sleep(5000)

await new Promise((r) => setTimeout(r, 2000))
// Start Recording on all
await jsRoomSessions[0].startRecording()
await jsRoomSessions[1].startRecording()
await jsRoomSessions[2].startRecording()

if (Array.isArray(roomSessions)) {
return resolve(0)
const playUrl = process.env.PLAYBACK_URL as string
await jsRoomSessions[0].play({ url: playUrl })
await jsRoomSessions[1].play({ url: playUrl })
await jsRoomSessions[2].play({ url: playUrl })

const roomSessionsRunning = await findRoomSessionsByPrefix()

tap.equal(
roomSessionsRunning.filter((r) => r.recording).length,
roomCount,
'Not all rooms are recording'
)

for (let index = 0; index < roomSessionsRunning.length; index++) {
const rs = roomSessionsRunning[index]
const { recordings } = await rs.getRecordings()
await Promise.all(recordings.map((r) => r.stop()))

const { playbacks } = await rs.getPlaybacks()
await Promise.all(playbacks.map((p) => p.stop()))
}

return reject(4)
const roomSessionsAtEnd = await findRoomSessionsByPrefix()
tap.equal(
roomSessionsAtEnd.filter((r) => r.recording).length,
0,
'Some rooms are still recording'
)
tap.equal(roomSessionCreated.size, roomCount, `roomSessionCreated is wrong`)
tap.equal(roomSessionsAtEnd.length, roomCount, 'roomSessionsAtEnd is wrong')

resolve(0)
})
}

async function main() {
const runner = createTestRunner({
name: 'Video E2E',
testHandler: handler,
executionTime: 30_000,
})

await runner.run()
Expand Down
135 changes: 135 additions & 0 deletions internal/e2e-realtime-api/src/videoUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { mediaDevices, RTCPeerConnection, MediaStream } from 'wrtc'
import { CloseEvent } from '@signalwire/core'
import { Video } from '@signalwire/js'
import { WebSocket } from 'ws'
import { request } from 'node:https'
import { getAuthorization } from './utils'

// @ts-expect-error
mediaDevices.enumerateDevices = () => {
return Promise.resolve([])
}

const PERMISSIONS = [
'room.self.audio_mute',
'room.self.audio_unmute',
'room.self.video_mute',
'room.self.video_unmute',
'room.self.deaf',
'room.self.undeaf',
'room.self.set_input_volume',
'room.self.set_output_volume',
'room.self.set_input_sensitivity',
'room.list_available_layouts',
'room.set_layout',
'room.member.video_mute',
'room.member.audio_mute',
'room.member.remove',
'room.recording',
'room.playback',
'room.playback_seek',
]
type CreateVRTParams = {
roomName: string
userName: string
}
const createVRT = (params: CreateVRTParams): Promise<{ token: string }> => {
return new Promise((resolve, reject) => {
const data = JSON.stringify({
room_name: params.roomName,
user_name: params.userName,
auto_create_room: true,
permissions: PERMISSIONS,
})
const options = {
host: process.env.API_HOST,
port: 443,
method: 'POST',
path: '/api/video/room_tokens',
headers: {
Authorization: getAuthorization(),
'Content-Type': 'application/json',
'Content-Length': data.length,
},
}
// console.log('CRT options', options)
const req = request(options, (response) => {
let body = ''
response.on('data', (chunk) => {
body += chunk
})

response.on('end', () => {
resolve(JSON.parse(body))
})
})

req.on('error', reject)

req.write(data)
req.end()
})
}

type CreateRoomSessionParams = CreateVRTParams & {}
export const createRoomSession = (
params: CreateRoomSessionParams
): Promise<Video.RoomSession> => {
return new Promise(async (resolve, reject) => {
try {
const { token } = await createVRT(params)

global.MediaStream = MediaStream
// @ts-expect-error
global.Audio = function () {
console.log('using audio')
}
global.CloseEvent = CloseEvent
global.WebSocket = WebSocket
// @ts-expect-error
global.navigator = {
mediaDevices,
}
// @ts-expect-error
global.window = {
RTCPeerConnection,
}

const roomSession = new Video.RoomSession({
host: process.env.RELAY_HOST || 'relay.signalwire.com',
token: token,
audio: true,
video: true,
// logLevel: 'error',
// debug: {
// logWsTraffic: true,
// },
})

// @ts-expect-error
roomSession._mungeSDP = (sdp: string) => {
console.log('SDP', sdp)
const newLine = '\r\n'
return (
sdp
.split(newLine)
.filter((line) => {
if (line.startsWith('a=candidate')) {
return !line.includes('127.0.0.1')
}
return true
})
.join(newLine) + newLine
)
}

roomSession.join().then((roomSession) => {
// console.log('CreateRoomSession OK', roomSession)
resolve(roomSession)
})
} catch (error) {
console.error('CreateRoomSession Error', error)
reject(error)
}
})
}
Loading

0 comments on commit fe3b0e2

Please sign in to comment.