From ae1e499f7a251db69af3cdaf683d7e3586994882 Mon Sep 17 00:00:00 2001 From: evujici Date: Thu, 19 Sep 2024 15:01:03 +0200 Subject: [PATCH 1/3] feat: conditionally add device permissions --- src/device/device-management.spec.ts | 50 ++++++++++++++++++++++++++++ src/device/device-management.ts | 14 +++++--- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/device/device-management.spec.ts b/src/device/device-management.spec.ts index 0d0d5e7..bb2d639 100644 --- a/src/device/device-management.spec.ts +++ b/src/device/device-management.spec.ts @@ -12,6 +12,7 @@ import { createDisplayStream, createDisplayStreamWithAudio, createMicrophoneStream, + getDevices, } from './device-management'; jest.mock('../mocks/media-stream-stub'); @@ -254,4 +255,53 @@ describe('Device Management', () => { expect(localDisplayStream.contentHint).toBe('motion'); }); }); + + describe('getDevices', () => { + it('should call ensureDevicePermissions with both audio and video input kinds when no deviceKind is provided', async () => { + expect.hasAssertions(); + const mockDevices = [ + { kind: 'audioinput', deviceId: 'audio1' }, + { kind: 'videoinput', deviceId: 'video1' }, + ] as MediaDeviceInfo[]; + + jest.spyOn(media, 'ensureDevicePermissions').mockResolvedValue(mockDevices); + jest.spyOn(media, 'enumerateDevices').mockResolvedValue(mockDevices); + + const devices = await getDevices(); + expect(media.ensureDevicePermissions).toHaveBeenCalledWith( + [media.DeviceKind.AudioInput, media.DeviceKind.VideoInput], + media.enumerateDevices + ); + expect(devices).toStrictEqual(mockDevices); + }); + + it('should call ensureDevicePermissions with the provided deviceKind', async () => { + expect.hasAssertions(); + const mockDevices = [{ kind: 'audioinput', deviceId: 'audio1' }] as MediaDeviceInfo[]; + + jest.spyOn(media, 'ensureDevicePermissions').mockResolvedValue(mockDevices); + jest.spyOn(media, 'enumerateDevices').mockResolvedValue(mockDevices); + + const devices = await getDevices(media.DeviceKind.AudioInput); + expect(media.ensureDevicePermissions).toHaveBeenCalledWith( + [media.DeviceKind.AudioInput], + media.enumerateDevices + ); + expect(devices).toStrictEqual(mockDevices); + }); + + it('should filter devices based on the provided deviceKind', async () => { + expect.hasAssertions(); + const mockDevices = [ + { kind: 'audioinput', deviceId: 'audio1' }, + { kind: 'videoinput', deviceId: 'video1' }, + ] as MediaDeviceInfo[]; + + jest.spyOn(media, 'ensureDevicePermissions').mockResolvedValue(mockDevices); + jest.spyOn(media, 'enumerateDevices').mockResolvedValue(mockDevices); + + const devices = await getDevices(media.DeviceKind.AudioInput); + expect(devices).toStrictEqual([{ kind: 'audioinput', deviceId: 'audio1' }]); + }); + }); }); diff --git a/src/device/device-management.ts b/src/device/device-management.ts index 804d686..b606d4d 100644 --- a/src/device/device-management.ts +++ b/src/device/device-management.ts @@ -190,11 +190,17 @@ export async function createDisplayStreamWithAudio< */ export async function getDevices(deviceKind?: media.DeviceKind): Promise { let devices: MediaDeviceInfo[]; + const deviceKinds: media.DeviceKind[] = []; + + // If deviceKind is provided, add it to the array. Otherwise, add both audio and video input kinds. + if (deviceKind !== undefined) { + deviceKinds.push(deviceKind); + } else { + deviceKinds.push(media.DeviceKind.AudioInput, media.DeviceKind.VideoInput); + } + try { - devices = await media.ensureDevicePermissions( - [media.DeviceKind.AudioInput, media.DeviceKind.VideoInput], - media.enumerateDevices - ); + devices = await media.ensureDevicePermissions(deviceKinds, media.enumerateDevices); } catch (error) { throw new WebrtcCoreError( WebrtcCoreErrorType.DEVICE_PERMISSION_DENIED, From 244749c2559c053fa9850c73398757dd79503ee7 Mon Sep 17 00:00:00 2001 From: evujici Date: Fri, 20 Sep 2024 09:12:04 +0200 Subject: [PATCH 2/3] chore: use ternary operator --- src/device/device-management.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/device/device-management.ts b/src/device/device-management.ts index b606d4d..e700310 100644 --- a/src/device/device-management.ts +++ b/src/device/device-management.ts @@ -190,14 +190,9 @@ export async function createDisplayStreamWithAudio< */ export async function getDevices(deviceKind?: media.DeviceKind): Promise { let devices: MediaDeviceInfo[]; - const deviceKinds: media.DeviceKind[] = []; - - // If deviceKind is provided, add it to the array. Otherwise, add both audio and video input kinds. - if (deviceKind !== undefined) { - deviceKinds.push(deviceKind); - } else { - deviceKinds.push(media.DeviceKind.AudioInput, media.DeviceKind.VideoInput); - } + const deviceKinds = deviceKind + ? [deviceKind] + : [media.DeviceKind.AudioInput, media.DeviceKind.VideoInput]; try { devices = await media.ensureDevicePermissions(deviceKinds, media.enumerateDevices); From d07eb9bdb1e7a7cee90ef6587076a4cc4fbed382 Mon Sep 17 00:00:00 2001 From: evujici Date: Fri, 20 Sep 2024 10:43:20 +0200 Subject: [PATCH 3/3] test: when permission are denied --- src/device/device-management.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/device/device-management.spec.ts b/src/device/device-management.spec.ts index bb2d639..3d3d344 100644 --- a/src/device/device-management.spec.ts +++ b/src/device/device-management.spec.ts @@ -14,6 +14,7 @@ import { createMicrophoneStream, getDevices, } from './device-management'; +import { WebrtcCoreError, WebrtcCoreErrorType } from '../errors'; jest.mock('../mocks/media-stream-stub'); @@ -303,5 +304,19 @@ describe('Device Management', () => { const devices = await getDevices(media.DeviceKind.AudioInput); expect(devices).toStrictEqual([{ kind: 'audioinput', deviceId: 'audio1' }]); }); + + it('should throw WebrtcCoreError when device permissions are denied', async () => { + expect.hasAssertions(); + jest.spyOn(media, 'ensureDevicePermissions').mockImplementation(() => { + throw new Error(); + }); + + const expectedError = new WebrtcCoreError( + WebrtcCoreErrorType.DEVICE_PERMISSION_DENIED, + 'Failed to ensure device permissions' + ); + + await expect(getDevices()).rejects.toStrictEqual(expectedError); + }); }); });