import { test } from 'node:test'; import assert from 'node:assert/strict'; import { MatrixCapabilities } from 'matrix-widget-api'; import { getCallCapabilities } from './utils'; const ROOM = '!room:server'; const USER = '@user:server'; const DEVICE = 'DEVICE1'; test('getCallCapabilities returns a non-empty Set', () => { const caps = getCallCapabilities(ROOM, USER, DEVICE); assert.ok(caps instanceof Set); assert.ok(caps.size > 0); }); test('includes the static MatrixCapabilities', () => { const caps = getCallCapabilities(ROOM, USER, DEVICE); assert.ok(caps.has(MatrixCapabilities.Screenshots)); assert.ok(caps.has(MatrixCapabilities.AlwaysOnScreen)); assert.ok(caps.has(MatrixCapabilities.MSC4039UploadFile)); assert.ok(caps.has(MatrixCapabilities.MSC4039DownloadFile)); assert.ok(caps.has(MatrixCapabilities.MSC3846TurnServers)); assert.ok(caps.has(MatrixCapabilities.MSC4157SendDelayedEvent)); assert.ok(caps.has(MatrixCapabilities.MSC4157UpdateDelayedEvent)); }); test('includes the room-scoped timeline and state capabilities', () => { const caps = getCallCapabilities(ROOM, USER, DEVICE); assert.ok(caps.has(`org.matrix.msc2762.timeline:${ROOM}`)); assert.ok(caps.has(`org.matrix.msc2762.state:${ROOM}`)); }); test('room scoping changes with the roomId', () => { const a = getCallCapabilities('!a:server', USER, DEVICE); const b = getCallCapabilities('!b:server', USER, DEVICE); assert.ok(a.has('org.matrix.msc2762.timeline:!a:server')); assert.ok(!a.has('org.matrix.msc2762.timeline:!b:server')); assert.ok(b.has('org.matrix.msc2762.timeline:!b:server')); }); test('includes send capability for the user-scoped call.member state event', () => { const caps = getCallCapabilities(ROOM, USER, DEVICE); const sendStateMember = [...caps].filter( (c) => c.includes('send') && c.includes('state') && c.includes('org.matrix.msc3401.call.member'), ); // five distinct state-keys are registered for the call.member send capability assert.equal(sendStateMember.length, 5); // the raw user id and the underscore-prefixed device-scoped key both appear const joined = sendStateMember.join('\n'); assert.ok(joined.includes(USER)); assert.ok(joined.includes(`_${USER}_${DEVICE}_m.call`)); }); test('registers both send and receive for each room-event type', () => { const caps = getCallCapabilities(ROOM, USER, DEVICE); [ 'io.element.call.encryption_keys', 'org.matrix.rageshake_request', 'io.element.call.reaction', 'org.matrix.msc4075.rtc.notification', 'org.matrix.msc4310.rtc.decline', ].forEach((type) => { const matches = [...caps].filter((c) => c.includes(type)); // one send + one receive room-event capability each assert.ok(matches.length >= 2, `missing capability for ${type}`); }); }); test('user/device scoping flows into the device-keyed state keys', () => { const caps = getCallCapabilities(ROOM, '@bob:srv', 'DEV2'); const all = [...caps].join('\n'); assert.ok(all.includes('@bob:srv_DEV2')); assert.ok(all.includes('_@bob:srv_DEV2_m.call')); });