50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import { test } from 'node:test';
|
|||
|
|
import assert from 'node:assert/strict';
|
||
|
|
|
||
|
|
import { scheduleMessage } from './scheduledMessages';
|
||
|
|
|
||
|
|
// MSC4140 delayed events are PUT as a plaintext m.room.message, so scheduling
|
||
|
|
// must be refused outright for encrypted rooms — the composer hides the button,
|
||
|
|
// this guard stops any other caller from regressing it.
|
||
|
|
const makeMx = (encrypted: boolean | undefined) => {
|
||
|
|
const calls: unknown[][] = [];
|
||
|
|
const mx = {
|
||
|
|
getRoom: (_roomId: string) =>
|
||
|
|
encrypted === undefined ? null : { hasEncryptionStateEvent: () => encrypted },
|
||
|
|
http: {
|
||
|
|
authedRequest: (...args: unknown[]) => {
|
||
|
|
calls.push(args);
|
||
|
|
return Promise.resolve({ delay_id: 'delay-1' });
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
return { mx: mx as never, calls };
|
||
|
|
};
|
||
|
|
|
||
|
|
test('scheduleMessage throws and sends nothing for an encrypted room', async () => {
|
||
|
|
const { mx, calls } = makeMx(true);
|
||
|
|
await assert.rejects(
|
||
|
|
() => scheduleMessage(mx, '!enc:lotusguild.org', { body: 'secret' }, Date.now() + 60_000),
|
||
|
|
/encrypted rooms/,
|
||
|
|
);
|
||
|
|
assert.equal(calls.length, 0);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('scheduleMessage still sends for an unencrypted room', async () => {
|
||
|
|
const { mx, calls } = makeMx(false);
|
||
|
|
const delayId = await scheduleMessage(
|
||
|
|
mx,
|
||
|
|
'!plain:lotusguild.org',
|
||
|
|
{ body: 'hi' },
|
||
|
|
Date.now() + 60_000,
|
||
|
|
);
|
||
|
|
assert.equal(delayId, 'delay-1');
|
||
|
|
assert.equal(calls.length, 1);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('scheduleMessage sends when the room is unknown to the client', async () => {
|
||
|
|
const { mx, calls } = makeMx(undefined);
|
||
|
|
await scheduleMessage(mx, '!unknown:lotusguild.org', { body: 'hi' }, Date.now() + 60_000);
|
||
|
|
assert.equal(calls.length, 1);
|
||
|
|
});
|