test(utils): cover scheduledMessages + lotusDenoiseUtils; fix AudioWorklet detect
- scheduledMessages.test.ts (9): pins the MSC4140 request shape (PUT to the room send endpoint with the org.matrix.msc4140.delay query, POST cancel/restart to /delayed_events with the unstable prefix), the delay-floor math (Math.max(1000, round(sendAt-now)) — "now"/past targets still yield a valid >=1000ms delay), rounding, and url-encoding. - lotusDenoiseUtils.test.ts (9): model-catalog data integrity + isMLDenoiseSupported feature detection across AudioContext/webkit/getUserMedia. - Bug found + fixed: isMLDenoiseSupported used `!!AudioWorkletNode`, a bare global reference that throws ReferenceError (not returns false) on a browser with AudioContext but no AudioWorkletNode binding. Switched to `typeof` so the detection helper reports unsupported instead of throwing. Regression test proven to fail on the old code. Suite now 545 tests (4th real bug caught by the prevention work). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import { test, beforeEach, afterEach } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { Method } from 'matrix-js-sdk';
|
||||
|
||||
import {
|
||||
scheduleMessage,
|
||||
cancelScheduledMessage,
|
||||
restartScheduledMessage,
|
||||
} from './scheduledMessages';
|
||||
|
||||
// Minimal MatrixClient stub: records every authedRequest call and returns a
|
||||
// canned { delay_id } so we can assert the request shape MSC4140 expects.
|
||||
type Call = unknown[];
|
||||
const makeMx = (response: unknown = { delay_id: 'delay-123' }) => {
|
||||
const calls: Call[] = [];
|
||||
const mx = {
|
||||
http: {
|
||||
authedRequest: (...args: unknown[]) => {
|
||||
calls.push(args);
|
||||
return Promise.resolve(response);
|
||||
},
|
||||
},
|
||||
};
|
||||
return { mx: mx as never, calls };
|
||||
};
|
||||
|
||||
const FIXED_NOW = 1_700_000_000_000;
|
||||
let realNow: () => number;
|
||||
beforeEach(() => {
|
||||
realNow = Date.now;
|
||||
Date.now = () => FIXED_NOW;
|
||||
});
|
||||
afterEach(() => {
|
||||
Date.now = realNow;
|
||||
});
|
||||
|
||||
// ── scheduleMessage ─────────────────────────────────────────────────────────
|
||||
|
||||
test('scheduleMessage sends PUT to the room message endpoint with the delay query', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
const content = { msgtype: 'm.text', body: 'later' };
|
||||
const delayId = await scheduleMessage(mx, '!room:lotusguild.org', content, FIXED_NOW + 5000);
|
||||
|
||||
assert.equal(calls.length, 1);
|
||||
const [method, path, query, body] = calls[0];
|
||||
assert.equal(method, Method.Put);
|
||||
// encodeURIComponent leaves '!' untouched but encodes ':'.
|
||||
assert.ok(
|
||||
(path as string).startsWith('/rooms/!room%3Alotusguild.org/send/m.room.message/sched_'),
|
||||
`unexpected path: ${path as string}`,
|
||||
);
|
||||
assert.deepEqual(query, { 'org.matrix.msc4140.delay': 5000 });
|
||||
assert.equal(body, content); // content passed through unchanged
|
||||
assert.equal(delayId, 'delay-123'); // returns server delay_id
|
||||
});
|
||||
|
||||
test('scheduleMessage rounds a fractional delay', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await scheduleMessage(mx, '!r:x', {}, FIXED_NOW + 1500.6);
|
||||
assert.deepEqual(calls[0][2], { 'org.matrix.msc4140.delay': 1501 });
|
||||
});
|
||||
|
||||
test('scheduleMessage floors the delay at 1000ms when target is too soon', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await scheduleMessage(mx, '!r:x', {}, FIXED_NOW + 300);
|
||||
assert.deepEqual(calls[0][2], { 'org.matrix.msc4140.delay': 1000 });
|
||||
});
|
||||
|
||||
test('scheduleMessage floors at 1000ms even for a target in the past', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await scheduleMessage(mx, '!r:x', {}, FIXED_NOW - 60_000);
|
||||
assert.deepEqual(calls[0][2], { 'org.matrix.msc4140.delay': 1000 });
|
||||
});
|
||||
|
||||
test('scheduleMessage uses a unique sched_ transaction id per call', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await scheduleMessage(mx, '!r:x', {}, FIXED_NOW + 2000);
|
||||
await scheduleMessage(mx, '!r:x', {}, FIXED_NOW + 2000);
|
||||
const txn = (p: unknown) => (p as string).split('/').pop() as string;
|
||||
const a = txn(calls[0][1]);
|
||||
const b = txn(calls[1][1]);
|
||||
assert.ok(a.startsWith('sched_'));
|
||||
assert.ok(b.startsWith('sched_'));
|
||||
assert.notEqual(a, b);
|
||||
});
|
||||
|
||||
test('scheduleMessage url-encodes the room id', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await scheduleMessage(mx, '!a/b:c.org', {}, FIXED_NOW + 2000);
|
||||
assert.ok((calls[0][1] as string).startsWith('/rooms/!a%2Fb%3Ac.org/send/'));
|
||||
});
|
||||
|
||||
// ── cancel / restart ────────────────────────────────────────────────────────
|
||||
|
||||
test('cancelScheduledMessage POSTs action:cancel to the delayed_events endpoint', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await cancelScheduledMessage(mx, 'delay-xyz');
|
||||
assert.equal(calls.length, 1);
|
||||
const [method, path, query, body, opts] = calls[0];
|
||||
assert.equal(method, Method.Post);
|
||||
assert.equal(path, '/delayed_events/delay-xyz');
|
||||
assert.equal(query, undefined);
|
||||
assert.deepEqual(body, { action: 'cancel' });
|
||||
assert.deepEqual(opts, { prefix: '/_matrix/client/unstable/org.matrix.msc4140' });
|
||||
});
|
||||
|
||||
test('restartScheduledMessage POSTs action:restart to the delayed_events endpoint', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await restartScheduledMessage(mx, 'delay-xyz');
|
||||
const [method, path, , body, opts] = calls[0];
|
||||
assert.equal(method, Method.Post);
|
||||
assert.equal(path, '/delayed_events/delay-xyz');
|
||||
assert.deepEqual(body, { action: 'restart' });
|
||||
assert.deepEqual(opts, { prefix: '/_matrix/client/unstable/org.matrix.msc4140' });
|
||||
});
|
||||
|
||||
test('cancel/restart url-encode the delay id', async () => {
|
||||
const { mx, calls } = makeMx();
|
||||
await cancelScheduledMessage(mx, 'a/b c');
|
||||
assert.equal(calls[0][1], '/delayed_events/a%2Fb%20c');
|
||||
});
|
||||
Reference in New Issue
Block a user