-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(device-api): Browser Permissions API (#1184)
Support for querying browser permissions for camera and microphone. ### Breaking changes (React-SDK): - `useHasBrowserPermissions` is not available in the SDK anymore. Please use the appropriate helper hooks: ```typescript const { useMicrophoneState, useCameraState } = useCallStateHooks(); const { hasBrowserPermission: hasMicrophonePermission } = useMicrophoneState(); const { hasBrowserPermission: hasCameraPermission } = useCameraState(); ```
- Loading branch information
Showing
14 changed files
with
254 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
packages/client/src/devices/__tests__/InputMediaDeviceManagerState.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
import { InputMediaDeviceManagerState } from '../InputMediaDeviceManagerState'; | ||
|
||
class TestInputMediaDeviceManagerState extends InputMediaDeviceManagerState { | ||
constructor() { | ||
super('stop-tracks', 'camera' as PermissionName); | ||
} | ||
|
||
getDeviceIdFromStream = vi.fn(); | ||
} | ||
|
||
describe('InputMediaDeviceManagerState', () => { | ||
let state: InputMediaDeviceManagerState; | ||
|
||
beforeEach(() => { | ||
state = new TestInputMediaDeviceManagerState(); | ||
}); | ||
|
||
describe('hasBrowserPermission', () => { | ||
it('should emit true when permission is granted', async () => { | ||
const permissionStatus: Partial<PermissionStatus> = { | ||
state: 'granted', | ||
addEventListener: vi.fn(), | ||
}; | ||
const query = vi.fn(() => Promise.resolve(permissionStatus)); | ||
globalThis.navigator ??= {} as Navigator; | ||
// @ts-ignore - navigator is readonly, but we need to mock it | ||
globalThis.navigator.permissions = { query }; | ||
|
||
const hasPermission = await new Promise((resolve) => { | ||
state.hasBrowserPermission$.subscribe((v) => resolve(v)); | ||
}); | ||
expect(hasPermission).toBe(true); | ||
expect(query).toHaveBeenCalledWith({ name: 'camera' }); | ||
expect(permissionStatus.addEventListener).toHaveBeenCalled(); | ||
}); | ||
|
||
it(' should emit false when permission is denied', async () => { | ||
const permissionStatus: Partial<PermissionStatus> = { | ||
state: 'denied', | ||
addEventListener: vi.fn(), | ||
removeEventListener: vi.fn(), | ||
}; | ||
const query = vi.fn(() => Promise.resolve(permissionStatus)); | ||
globalThis.navigator ??= {} as Navigator; | ||
// @ts-ignore - navigator is readonly, but we need to mock it | ||
globalThis.navigator.permissions = { query }; | ||
|
||
const hasPermission = await new Promise((resolve) => { | ||
state.hasBrowserPermission$.subscribe((v) => resolve(v)); | ||
}); | ||
expect(hasPermission).toBe(false); | ||
expect(query).toHaveBeenCalledWith({ name: 'camera' }); | ||
expect(permissionStatus.addEventListener).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should emit false when prompt is needed', async () => { | ||
const permissionStatus: Partial<PermissionStatus> = { | ||
state: 'prompt', | ||
addEventListener: vi.fn(), | ||
}; | ||
const query = vi.fn(() => Promise.resolve(permissionStatus)); | ||
globalThis.navigator ??= {} as Navigator; | ||
// @ts-ignore - navigator is readonly, but we need to mock it | ||
globalThis.navigator.permissions = { query }; | ||
|
||
const hasPermission = await new Promise((resolve) => { | ||
state.hasBrowserPermission$.subscribe((v) => resolve(v)); | ||
}); | ||
expect(hasPermission).toBe(false); | ||
expect(query).toHaveBeenCalledWith({ name: 'camera' }); | ||
expect(permissionStatus.addEventListener).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should emit true when permissions cannot be queried', async () => { | ||
const query = vi.fn(() => Promise.reject()); | ||
globalThis.navigator ??= {} as Navigator; | ||
// @ts-ignore - navigator is readonly, but we need to mock it | ||
globalThis.navigator.permissions = { query }; | ||
|
||
const hasPermission = await new Promise((resolve) => { | ||
state.hasBrowserPermission$.subscribe((v) => resolve(v)); | ||
}); | ||
expect(hasPermission).toBe(true); | ||
expect(query).toHaveBeenCalledWith({ name: 'camera' }); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
export * from './useDevices'; | ||
export * from './useTrackElementVisibility'; |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.