test: add suites for time, matrix, mimeTypes, and search filters (+47 tests)
Expands pure-logic coverage (harness: tsx + node:test): - utils/time (21): date/time formatters — exact values where timezone-independent, structure/regex where locale/tz-sensitive (written via subagent). - utils/matrix (13): pure id/mxc helpers (isUserId/isRoomId/isRoomAlias/ getMxIdLocalPart/getMxIdServer/isServerName + room-version gates). (subagent) - utils/mimeTypes (7): getBlobSafeMimeType allowlist+remap, safeFile rewrap, mimeTypeToExt, getFileNameExt/WithoutExt edge cases. - message-search filters (6): filterGroupsByMsgType (union, empty-group drop, non-string msgtype) + filterGroupsByPinned (disabled passthrough, pinned-only). All assertions verified against actual runtime behavior. Suite now 74 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { filterGroupsByMsgType, filterGroupsByPinned, ResultGroup } from './useMessageSearch';
|
||||
|
||||
// Minimal ResultGroup/ResultItem fixtures — only the fields the filters read
|
||||
// (event.content.msgtype, event.event_id, group.roomId).
|
||||
const item = (msgtype: string | undefined, eventId: string) => ({
|
||||
rank: 1,
|
||||
event: { event_id: eventId, content: msgtype === undefined ? {} : { msgtype } },
|
||||
context: {},
|
||||
});
|
||||
const mkGroups = (
|
||||
...groups: { roomId: string; items: ReturnType<typeof item>[] }[]
|
||||
): ResultGroup[] => groups as unknown as ResultGroup[];
|
||||
|
||||
test('filterGroupsByMsgType: empty filter returns groups unchanged', () => {
|
||||
const groups = mkGroups({ roomId: '!r1', items: [item('m.text', '$1'), item('m.image', '$2')] });
|
||||
assert.equal(filterGroupsByMsgType(groups, []), groups);
|
||||
});
|
||||
|
||||
test('filterGroupsByMsgType: keeps only matching msgtypes (union)', () => {
|
||||
const groups = mkGroups({
|
||||
roomId: '!r1',
|
||||
items: [item('m.text', '$1'), item('m.image', '$2'), item('m.file', '$3')],
|
||||
});
|
||||
const out = filterGroupsByMsgType(groups, ['m.image', 'm.file']);
|
||||
assert.equal(out.length, 1);
|
||||
assert.deepEqual(
|
||||
out[0].items.map((i) => i.event.event_id),
|
||||
['$2', '$3'],
|
||||
);
|
||||
});
|
||||
|
||||
test('filterGroupsByMsgType: drops groups left empty', () => {
|
||||
const groups = mkGroups(
|
||||
{ roomId: '!r1', items: [item('m.text', '$1')] },
|
||||
{ roomId: '!r2', items: [item('m.image', '$2')] },
|
||||
);
|
||||
const out = filterGroupsByMsgType(groups, ['m.image']);
|
||||
assert.equal(out.length, 1);
|
||||
assert.equal(out[0].roomId, '!r2');
|
||||
});
|
||||
|
||||
test('filterGroupsByMsgType: ignores items with a non-string msgtype', () => {
|
||||
const groups = mkGroups({ roomId: '!r1', items: [item(undefined, '$1'), item('m.video', '$2')] });
|
||||
const out = filterGroupsByMsgType(groups, ['m.video']);
|
||||
assert.equal(out[0].items.length, 1);
|
||||
assert.equal(out[0].items[0].event.event_id, '$2');
|
||||
});
|
||||
|
||||
test('filterGroupsByPinned: disabled returns groups unchanged', () => {
|
||||
const groups = mkGroups({ roomId: '!r1', items: [item('m.text', '$1')] });
|
||||
assert.equal(
|
||||
filterGroupsByPinned(groups, false, () => false),
|
||||
groups,
|
||||
);
|
||||
});
|
||||
|
||||
test('filterGroupsByPinned: keeps pinned items and drops empty groups', () => {
|
||||
const groups = mkGroups(
|
||||
{ roomId: '!r1', items: [item('m.text', '$1'), item('m.text', '$2')] },
|
||||
{ roomId: '!r2', items: [item('m.text', '$3')] },
|
||||
);
|
||||
const pinned = new Set(['!r1/$2']);
|
||||
const out = filterGroupsByPinned(groups, true, (roomId, eventId) =>
|
||||
pinned.has(`${roomId}/${eventId}`),
|
||||
);
|
||||
assert.equal(out.length, 1);
|
||||
assert.equal(out[0].roomId, '!r1');
|
||||
assert.deepEqual(
|
||||
out[0].items.map((i) => i.event.event_id),
|
||||
['$2'],
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user