import { test } from 'node:test'; import assert from 'node:assert/strict'; import type { Room } from 'matrix-js-sdk'; import { declinedRing, hasActiveCallMembership, isRingableRoom } from './callRing'; const fakeRoom = (opts: { callRoom?: boolean; joinRule?: string; spaceParent?: boolean }): Room => ({ isCallRoom: () => !!opts.callRoom, getJoinRule: () => opts.joinRule ?? 'invite', getLiveTimeline: () => ({ getState: () => ({ getStateEvents: () => (opts.spaceParent ? [{}] : []) }), }), }) as unknown as Room; test('voice rooms never ring or show "missed call", even as DMs', () => { assert.equal(isRingableRoom(fakeRoom({ callRoom: true }), false), false); assert.equal(isRingableRoom(fakeRoom({ callRoom: true }), true), false); }); test('DMs and invite-only groups outside a space ring', () => { assert.equal(isRingableRoom(fakeRoom({ joinRule: 'public' }), true), true); assert.equal(isRingableRoom(fakeRoom({ joinRule: 'invite' }), false), true); }); test('space channels, public and restricted rooms do not ring', () => { assert.equal(isRingableRoom(fakeRoom({ joinRule: 'invite', spaceParent: true }), false), false); assert.equal(isRingableRoom(fakeRoom({ joinRule: 'public' }), false), false); assert.equal(isRingableRoom(fakeRoom({ joinRule: 'restricted' }), false), false); }); const stateRoom = ( members: Array<{ sender: string; content: Record }>, timeline: unknown[] = [], ): Room => ({ getLiveTimeline: () => ({ getState: () => ({ getStateEvents: () => members.map((m) => ({ getSender: () => m.sender, getStateKey: () => `_${m.sender}_DEV_m.call`, getContent: () => m.content, })), }), getEvents: () => timeline, }), }) as unknown as Room; test('hasActiveCallMembership reads the room state: joined vs left (#312)', () => { const room = stateRoom([ { sender: '@bob:x', content: { application: 'm.call', call_id: '' } }, { sender: '@carol:x', content: {} }, ]); assert.equal(hasActiveCallMembership(room, '@bob:x'), true); assert.equal(hasActiveCallMembership(room, '@carol:x'), false, 'left = empty content'); assert.equal(hasActiveCallMembership(room, '@dave:x'), false); }); test('declinedRing finds our own decline of that ring only (#312)', () => { const decline = (sender: string, rel: string) => ({ getType: () => 'org.matrix.msc4310.rtc.decline', getSender: () => sender, getRelation: () => ({ event_id: rel }), }); const room = stateRoom([], [decline('@me:x', '$ring1'), decline('@bob:x', '$ring2')]); assert.equal(declinedRing(room, '$ring1', '@me:x'), true); assert.equal(declinedRing(room, '$ring2', '@me:x'), false, "someone else's decline"); assert.equal(declinedRing(room, '$ring3', '@me:x'), false); });