2026-09-14 19:11:41 -04:00
|
|
|
import { test } from 'node:test';
|
|
|
|
|
import assert from 'node:assert/strict';
|
|
|
|
|
import type { MatrixClient } from 'matrix-js-sdk';
|
2026-09-14 19:39:40 -04:00
|
|
|
import { AutoDiscovery } from 'matrix-js-sdk';
|
2026-09-14 19:11:41 -04:00
|
|
|
import { CallWidgetDriver } from './CallWidgetDriver';
|
|
|
|
|
|
|
|
|
|
// MSC4515: Element Call (widget mode) asks the host for RTC transports. Without a
|
|
|
|
|
// working answer every call fails with MISSING_MATRIX_RTC_TRANSPORT.
|
|
|
|
|
function fakeClient(opts: {
|
|
|
|
|
serverTransports?: unknown[] | Error;
|
|
|
|
|
wellKnown?: Record<string, unknown>;
|
|
|
|
|
}): MatrixClient {
|
|
|
|
|
return {
|
|
|
|
|
getDeviceId: () => 'DEV',
|
|
|
|
|
getSafeUserId: () => '@me:example.org',
|
|
|
|
|
_unstable_getRTCTransports: async () => {
|
|
|
|
|
if (opts.serverTransports instanceof Error) throw opts.serverTransports;
|
|
|
|
|
return opts.serverTransports ?? [];
|
|
|
|
|
},
|
|
|
|
|
getClientWellKnown: () => opts.wellKnown,
|
2026-09-14 19:39:40 -04:00
|
|
|
getDomain: () => 'example.org',
|
2026-09-14 19:11:41 -04:00
|
|
|
} as unknown as MatrixClient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const focus = { type: 'livekit', livekit_service_url: 'https://matrix.example.org' };
|
|
|
|
|
|
|
|
|
|
test('getRtcTransports prefers the homeserver MSC4143 endpoint', async () => {
|
|
|
|
|
const driver = new CallWidgetDriver(fakeClient({ serverTransports: [focus] }), '!r:x');
|
|
|
|
|
const r = await driver.getRtcTransports();
|
|
|
|
|
assert.deepEqual(r.rtc_transports, [focus]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('getRtcTransports falls back to .well-known rtc_foci when the endpoint 404s', async () => {
|
|
|
|
|
const driver = new CallWidgetDriver(
|
|
|
|
|
fakeClient({
|
|
|
|
|
serverTransports: new Error('404'),
|
|
|
|
|
wellKnown: { 'org.matrix.msc4143.rtc_foci': [focus, { junk: true }, null] },
|
|
|
|
|
}),
|
|
|
|
|
'!r:x',
|
|
|
|
|
);
|
|
|
|
|
const r = await driver.getRtcTransports();
|
|
|
|
|
assert.deepEqual(r.rtc_transports, [focus]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-09-14 19:39:40 -04:00
|
|
|
test('getRtcTransports fetches .well-known itself when the SDK has nothing cached (the live cinny case)', async () => {
|
|
|
|
|
// cinny never sets clientWellKnownPollPeriod, so getClientWellKnown() is undefined
|
|
|
|
|
// at runtime; the driver must resolve it via AutoDiscovery instead.
|
|
|
|
|
const orig = AutoDiscovery.getRawClientConfig;
|
|
|
|
|
let calls = 0;
|
|
|
|
|
AutoDiscovery.getRawClientConfig = async () => {
|
|
|
|
|
calls += 1;
|
|
|
|
|
return { 'org.matrix.msc4143.rtc_foci': [focus] } as never;
|
|
|
|
|
};
|
|
|
|
|
try {
|
|
|
|
|
const driver = new CallWidgetDriver(
|
|
|
|
|
fakeClient({ serverTransports: new Error('404'), wellKnown: undefined }),
|
|
|
|
|
'!r:x',
|
|
|
|
|
);
|
|
|
|
|
const r1 = await driver.getRtcTransports();
|
|
|
|
|
const r2 = await driver.getRtcTransports();
|
|
|
|
|
assert.deepEqual(r1.rtc_transports, [focus]);
|
|
|
|
|
assert.deepEqual(r2.rtc_transports, [focus]);
|
|
|
|
|
assert.equal(calls, 1, 'well-known is fetched once per driver');
|
|
|
|
|
} finally {
|
|
|
|
|
AutoDiscovery.getRawClientConfig = orig;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-09-14 19:11:41 -04:00
|
|
|
test('getRtcTransports returns an empty list when nothing is advertised', async () => {
|
2026-09-14 19:39:40 -04:00
|
|
|
const orig = AutoDiscovery.getRawClientConfig;
|
|
|
|
|
AutoDiscovery.getRawClientConfig = async () => ({ 'm.homeserver': {} }) as never;
|
|
|
|
|
try {
|
|
|
|
|
const driver = new CallWidgetDriver(
|
|
|
|
|
fakeClient({ serverTransports: [], wellKnown: { 'm.homeserver': {} } }),
|
|
|
|
|
'!r:x',
|
|
|
|
|
);
|
|
|
|
|
const r = await driver.getRtcTransports();
|
|
|
|
|
assert.deepEqual(r.rtc_transports, []);
|
|
|
|
|
} finally {
|
|
|
|
|
AutoDiscovery.getRawClientConfig = orig;
|
|
|
|
|
}
|
2026-09-14 19:11:41 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('the MSC4515 capability is granted to the call widget', async () => {
|
|
|
|
|
const driver = new CallWidgetDriver(fakeClient({}), '!r:x');
|
|
|
|
|
const allowed = await driver.validateCapabilities(
|
|
|
|
|
new Set(['org.matrix.msc4515.rtc_transports', 'org.example.not_allowed']),
|
|
|
|
|
);
|
|
|
|
|
assert.deepEqual(Array.from(allowed), ['org.matrix.msc4515.rtc_transports']);
|
|
|
|
|
});
|