Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/room/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { describe, expect, it } from 'vitest';
import { splitUtf8, toWebsocketUrl } from './utils';

Check warning on line 2 in src/room/utils.test.ts

View workflow job for this annotation

GitHub Actions / test

'/home/runner/work/client-sdk-js/client-sdk-js/src/room/utils.ts' imported multiple times
import { isSafariSpeakerSelectionSupported, supportsSetSinkId } from './utils';

Check warning on line 3 in src/room/utils.test.ts

View workflow job for this annotation

GitHub Actions / test

'/home/runner/work/client-sdk-js/client-sdk-js/src/room/utils.ts' imported multiple times


describe('toWebsocketUrl', () => {
it('leaves wss urls alone', () => {
Expand Down Expand Up @@ -60,3 +62,74 @@
expect(splitUtf8('', 5)).toEqual([]);
});
});

describe('isSafariSpeakerSelectionSupported', () => {
it('returns true for Safari >= 26', () => {
expect(isSafariSpeakerSelectionSupported({
name: 'Safari',
version: '26.0',
os: 'macOS',
osVersion: '26.0',
})).toBe(true);
expect(isSafariSpeakerSelectionSupported({
name: 'Safari',
version: '27.1',
os: 'macOS',
osVersion: '27.1',
})).toBe(true);
});

it('returns true for iOS Safari >= 26', () => {
expect(isSafariSpeakerSelectionSupported({
name: 'Safari',
version: '26.0',
os: 'iOS',
osVersion: '26.0',
})).toBe(true);
});

it('returns false for Safari < 26', () => {
expect(isSafariSpeakerSelectionSupported({
name: 'Safari',
version: '25.9',
os: 'macOS',
osVersion: '25.9',
})).toBe(false);
});

it('returns false for non-Safari browsers', () => {
expect(isSafariSpeakerSelectionSupported({
name: 'Chrome',
version: '120.0',
os: 'macOS',
osVersion: '14.0',
})).toBe(false);
});
});

describe('supportsSetSinkId', () => {
it('returns true if setSinkId is present', () => {
Object.defineProperty(navigator, 'userAgent', {
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0',
configurable: true,
});
const fakeAudio = { setSinkId: () => {} } as any as HTMLMediaElement;
expect(supportsSetSinkId(fakeAudio)).toBe(true);
});
it('returns true if setSinkId is present', () => {
Object.defineProperty(navigator, 'userAgent', {
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15',
configurable: true,
});
const fakeAudio = { setSinkId: () => {} } as any as HTMLMediaElement;
expect(supportsSetSinkId(fakeAudio)).toBe(true);
});
it('returns false if setSinkId not supported', () => {
Object.defineProperty(navigator, 'userAgent', {
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15',
configurable: true,
});
const fakeAudio = { setSinkId: () => {} } as any as HTMLMediaElement;
expect(supportsSetSinkId(fakeAudio)).toBe(false);
});
});
17 changes: 15 additions & 2 deletions src/room/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ export function isSVCCodec(codec?: string): boolean {
}

export function supportsSetSinkId(elm?: HTMLMediaElement): boolean {
if (!document || isSafariBased()) {
return false;
if (!document || (!isSafariSpeakerSelectionSupported() && isSafariBased())) {
return false
}
if (!elm) {
elm = document.createElement('audio');
Expand Down Expand Up @@ -196,6 +196,19 @@ export function isSafariSvcApi(browser?: BrowserDetails): boolean {
);
}

export function isSafariSpeakerSelectionSupported(browser?: BrowserDetails): boolean {
if (!browser) {
browser = getBrowser();
}
// Safari (macOS or iOS) since version 26
// https://developer.apple.com/documentation/safari-release-notes/safari-26-release-notes#WebRTC
return (
(browser?.name === 'Safari' && compareVersions(browser.version, '26') >= 0) ||
(browser?.os === 'iOS' && !!browser?.osVersion && compareVersions(browser.osVersion, '26') >= 0) ||
(browser?.os === 'macOS' && !!browser?.osVersion && compareVersions(browser.osVersion, '26') >= 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is not connected to checking against Safari, I believe?

);
}

export function isMobile(): boolean {
if (!isWeb()) return false;

Expand Down
Loading