@signalwire/realtime-api
Version:
SignalWire RealTime SDK for Node.js
517 lines (446 loc) • 15.8 kB
text/typescript
import { actions } from '@signalwire/core'
import { configureFullStack } from '../testUtils'
import { Video } from './Video'
import { RoomSession } from './RoomSession'
import { createClient } from '../client/createClient'
import { RoomSessionRecording } from './RoomSessionRecording'
import { RoomSessionPlayback } from './RoomSessionPlayback'
import { RoomSessionStream } from './RoomSessionStream'
describe('RoomSession Object', () => {
let video: Video
let roomSession: RoomSession
const roomSessionId = 'roomSessionId'
const { store, destroy } = configureFullStack()
const userOptions = {
host: 'example.com',
project: 'example.project',
token: 'example.token',
store,
}
beforeEach(() => {
const swClientMock = {
userOptions,
client: createClient(userOptions),
}
// @ts-expect-error
video = new Video(swClientMock)
// @ts-expect-error
video._client.execute = jest.fn()
// @ts-expect-error
video._client.runWorker = jest.fn()
return new Promise(async (resolve) => {
await video.listen({
onRoomStarted: (room) => {
// @ts-expect-error
room._client.execute = jest.fn()
roomSession = room
resolve(roomSession)
},
})
const eventChannelOne = 'room.<uuid-one>'
const firstRoom = JSON.parse(
`{"jsonrpc":"2.0","id":"uuid1","method":"signalwire.event","params":{"params":{"room":{"recording":false,"room_session_id":"${roomSessionId}","name":"First Room","hide_video_muted":false,"music_on_hold":false,"room_id":"room_id","event_channel":"${eventChannelOne}"},"room_session_id":"${roomSessionId}","room_id":"room_id","room_session":{"recording":false,"name":"First Room","hide_video_muted":false,"id":"${roomSessionId}","music_on_hold":false,"room_id":"room_id","event_channel":"${eventChannelOne}"}},"timestamp":1631692502.1308,"event_type":"video.room.started","event_channel":"video.rooms.4b7ae78a-d02e-4889-a63b-08b156d5916e"}}`
)
// @ts-expect-error
video._client.store.channels.sessionChannel.put(
actions.socketMessageAction(firstRoom)
)
})
})
afterEach(() => {
jest.clearAllMocks()
})
afterAll(() => {
destroy()
})
it('should have all the custom methods defined', () => {
expect(roomSession.videoMute).toBeDefined()
expect(roomSession.videoUnmute).toBeDefined()
expect(roomSession.getMembers).toBeDefined()
expect(roomSession.audioMute).toBeDefined()
expect(roomSession.audioUnmute).toBeDefined()
expect(roomSession.deaf).toBeDefined()
expect(roomSession.undeaf).toBeDefined()
expect(roomSession.setInputVolume).toBeDefined()
expect(roomSession.setOutputVolume).toBeDefined()
expect(roomSession.setMicrophoneVolume).toBeDefined()
expect(roomSession.setSpeakerVolume).toBeDefined()
expect(roomSession.setInputSensitivity).toBeDefined()
expect(roomSession.removeMember).toBeDefined()
expect(roomSession.setHideVideoMuted).toBeDefined()
expect(roomSession.getLayouts).toBeDefined()
expect(roomSession.setLayout).toBeDefined()
expect(roomSession.getRecordings).toBeDefined()
expect(roomSession.startRecording).toBeDefined()
expect(roomSession.getPlaybacks).toBeDefined()
expect(roomSession.play).toBeDefined()
})
describe('Recording APIs', () => {
let mockRecording: RoomSessionRecording
beforeEach(() => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue()
mockRecording = new RoomSessionRecording({
roomSession,
payload: {
room_session_id: roomSessionId,
// @ts-expect-error
recording: {
id: 'recordingId',
state: 'recording',
},
},
})
})
afterEach(() => {
jest.clearAllMocks()
})
it('getRecordings should return an array of recordings', async () => {
const recordingList = [
{
id: '6dfd0d76-b68f-4eef-bdee-08100fe03f4e',
state: 'completed',
started_at: 1663858327.847,
duration: 6.04,
ended_at: 1663858334.343,
},
{
id: 'e69d456b-4191-4dbb-8618-28d477734d65',
state: 'recording',
started_at: 1663858425.548,
},
]
// @ts-expect-error
;(roomSession._client.execute as jest.Mock).mockResolvedValueOnce({
recordings: recordingList,
})
const { recordings } = await roomSession.getRecordings()
recordings.forEach((recording, index) => {
expect(recording.id).toEqual(recordingList[index].id)
expect(recording.roomSessionId).toEqual(roomSessionId)
expect(recording.state).toEqual(recordingList[index].state)
expect(recording.startedAt).toEqual(
new Date(recordingList[index].started_at! * 1000)
)
if (recordingList[index].ended_at) {
expect(recording.endedAt).toEqual(
new Date(recordingList[index].ended_at! * 1000)
)
}
expect(typeof recording.pause).toBe('function')
expect(typeof recording.resume).toBe('function')
expect(typeof recording.stop).toBe('function')
})
})
it('startRecording should return a recording object', async () => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue({})
const recordingPromise = roomSession.startRecording()
// @TODO: Mock server event
roomSession.emit('recording.started', mockRecording)
const recording = await recordingPromise.onStarted()
// @ts-expect-error
recording._client.execute = jest.fn()
await recording.pause()
// @ts-ignore
expect(recording._client.execute).toHaveBeenLastCalledWith({
method: 'video.recording.pause',
params: {
room_session_id: roomSessionId,
recording_id: 'recordingId',
},
})
await recording.resume()
// @ts-ignore
expect(recording._client.execute).toHaveBeenLastCalledWith({
method: 'video.recording.resume',
params: {
room_session_id: roomSessionId,
recording_id: 'recordingId',
},
})
await recording.stop()
// @ts-ignore
expect(recording._client.execute).toHaveBeenLastCalledWith({
method: 'video.recording.stop',
params: {
room_session_id: roomSessionId,
recording_id: 'recordingId',
},
})
})
it('should trigger recording and roomSession listeners', async () => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue()
// Mock the listener
const onStartedMock = jest.fn()
const onUpdatedMock = jest.fn()
const onEndedMock = jest.fn()
const recordingPromise = roomSession.startRecording({
listen: {
onStarted: onStartedMock,
onUpdated: onUpdatedMock,
onEnded: onEndedMock,
},
})
await roomSession.listen({
onRecordingStarted: onStartedMock,
onRecordingUpdated: onUpdatedMock,
onRecordingEnded: onEndedMock,
})
// @TODO: Mock server event
roomSession.emit('recording.started', mockRecording)
roomSession.emit('recording.updated', mockRecording)
roomSession.emit('recording.ended', mockRecording)
await recordingPromise.onStarted()
// Assertions
expect(onStartedMock).toHaveBeenCalledTimes(2)
expect(onUpdatedMock).toHaveBeenCalledTimes(2)
expect(onEndedMock).toHaveBeenCalledTimes(2)
})
})
describe('Playback APIs', () => {
let mockPlayback: RoomSessionPlayback
beforeEach(() => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue()
mockPlayback = new RoomSessionPlayback({
roomSession,
payload: {
room_session_id: roomSessionId,
playback: {
id: 'playbackId',
state: 'playing',
url: 'rtmp://example.com/foo',
volume: 10,
// @ts-expect-error
started_at: 1629460916,
},
},
})
})
afterEach(() => {
jest.clearAllMocks()
})
it('getPlaybacks should return an array of playbacks', async () => {
const playbackList = [
{
id: 'playbackId1',
state: 'completed',
started_at: 1663858327.847,
ended_at: 1663858334.343,
},
{
id: 'playbackId2',
state: 'playing',
started_at: 1663858425.548,
},
]
// @ts-expect-error
;(roomSession._client.execute as jest.Mock).mockResolvedValueOnce({
playbacks: playbackList,
})
const { playbacks } = await roomSession.getPlaybacks()
playbacks.forEach((playback, index) => {
expect(playback.id).toEqual(playbackList[index].id)
expect(playback.roomSessionId).toEqual(roomSessionId)
expect(playback.state).toEqual(playbackList[index].state)
expect(playback.startedAt).toEqual(
new Date(playbackList[index].started_at! * 1000)
)
if (playbackList[index].ended_at) {
expect(playback.endedAt).toEqual(
new Date(playbackList[index].ended_at! * 1000)
)
}
expect(typeof playback.pause).toBe('function')
expect(typeof playback.resume).toBe('function')
expect(typeof playback.stop).toBe('function')
expect(typeof playback.setVolume).toBe('function')
expect(typeof playback.seek).toBe('function')
expect(typeof playback.forward).toBe('function')
expect(typeof playback.rewind).toBe('function')
})
})
it('play should return a playback object', async () => {
const playbackPromise = roomSession.play({
url: 'rtmp://example.com/foo',
volume: 10,
})
// @TODO: Mock server event
roomSession.emit('playback.started', mockPlayback)
const playback = await playbackPromise.onStarted()
// @ts-expect-error
playback._client.execute = jest.fn()
await playback.pause()
// @ts-ignore
expect(playback._client.execute).toHaveBeenLastCalledWith({
method: 'video.playback.pause',
params: {
room_session_id: roomSessionId,
playback_id: 'playbackId',
},
})
await playback.resume()
// @ts-ignore
expect(playback._client.execute).toHaveBeenLastCalledWith({
method: 'video.playback.resume',
params: {
room_session_id: roomSessionId,
playback_id: 'playbackId',
},
})
await playback.setVolume(20)
// @ts-ignore
expect(playback._client.execute).toHaveBeenLastCalledWith({
method: 'video.playback.set_volume',
params: {
room_session_id: roomSessionId,
playback_id: 'playbackId',
volume: 20,
},
})
await playback.stop()
// @ts-ignore
expect(playback._client.execute).toHaveBeenLastCalledWith({
method: 'video.playback.stop',
params: {
room_session_id: roomSessionId,
playback_id: 'playbackId',
},
})
})
it('should trigger playback and roomSession listeners', async () => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue()
// Mock the listener
const onStartedMock = jest.fn()
const onUpdatedMock = jest.fn()
const onEndedMock = jest.fn()
await roomSession.listen({
onPlaybackStarted: onStartedMock,
onPlaybackUpdated: onUpdatedMock,
onPlaybackEnded: onEndedMock,
})
const playbackPromise = roomSession.play({
url: 'rtmp://example.com/foo',
volume: 10,
listen: {
onStarted: onStartedMock,
onUpdated: onUpdatedMock,
onEnded: onEndedMock,
},
})
// @TODO: Mock server event
roomSession.emit('playback.started', mockPlayback)
roomSession.emit('playback.updated', mockPlayback)
roomSession.emit('playback.ended', mockPlayback)
await playbackPromise.onStarted()
// Assertions
expect(onStartedMock).toHaveBeenCalledTimes(2)
expect(onUpdatedMock).toHaveBeenCalledTimes(2)
expect(onEndedMock).toHaveBeenCalledTimes(2)
})
})
describe('Stream APIs', () => {
let mockStream: RoomSessionStream
beforeEach(() => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue()
mockStream = new RoomSessionStream({
roomSession,
payload: {
room_session_id: roomSessionId,
// @ts-expect-error
stream: {
id: 'streamId',
url: 'rtmp://example.com/foo',
room_session_id: roomSessionId,
state: 'streaming',
},
},
})
})
afterEach(() => {
jest.clearAllMocks()
})
it('getStreams should return an array of playbacks', async () => {
const streamList = [
{
id: 'streamId1',
state: 'completed',
started_at: 1663858327.847,
ended_at: 1663858334.343,
},
{
id: 'streamId2',
state: 'streaming',
started_at: 1663858425.548,
},
]
// @ts-expect-error
;(roomSession._client.execute as jest.Mock).mockResolvedValueOnce({
streams: streamList,
})
const { streams } = await roomSession.getStreams()
streams.forEach((stream, index) => {
expect(stream.id).toEqual(streamList[index].id)
expect(stream.roomSessionId).toEqual(roomSessionId)
expect(stream.state).toEqual(streamList[index].state)
expect(stream.startedAt).toEqual(
new Date(streamList[index].started_at! * 1000)
)
if (streamList[index].ended_at) {
expect(stream.endedAt).toEqual(
new Date(streamList[index].ended_at! * 1000)
)
}
expect(typeof stream.stop).toBe('function')
})
})
it('startStream should return a stream object', async () => {
const streamPromise = roomSession.startStream({
url: 'rtmp://example.com/foo',
})
// @TODO: Mock server event
roomSession.emit('stream.started', mockStream)
const stream = await streamPromise.onStarted()
// @ts-expect-error
stream._client.execute = jest.fn()
await stream.stop()
// @ts-ignore
expect(stream._client.execute).toHaveBeenLastCalledWith({
method: 'video.stream.stop',
params: {
room_session_id: roomSessionId,
stream_id: 'streamId',
},
})
})
it('should trigger stream and roomSession listeners', async () => {
// @ts-expect-error
roomSession._client.execute = jest.fn().mockResolvedValue()
// Mock the listener
const onStartedMock = jest.fn()
const onEndedMock = jest.fn()
await roomSession.listen({
onStreamStarted: onStartedMock,
onStreamEnded: onEndedMock,
})
const streamPromise = roomSession.startStream({
url: 'rtmp://example.com/foo',
listen: {
onStarted: onStartedMock,
onEnded: onEndedMock,
},
})
// @TODO: Mock server event
roomSession.emit('stream.started', mockStream)
roomSession.emit('stream.ended', mockStream)
await streamPromise.onStarted()
// Assertions
expect(onStartedMock).toHaveBeenCalledTimes(2)
expect(onEndedMock).toHaveBeenCalledTimes(2)
})
})
})