import { test } from 'node:test'; import assert from 'node:assert/strict'; import { filterThreads, sortThreads, isThreadFilter, isThreadSort, ThreadSnapshot, } from './threadList'; const t = (id: string, latestTs: number, unread = 0, participated = false): ThreadSnapshot => ({ id, latestTs, unread, participated, }); test('filterThreads all returns every thread', () => { const input = [t('a', 1, 0, false), t('b', 2, 3, true)]; assert.deepEqual( filterThreads(input, 'all').map((x) => x.id), ['a', 'b'], ); }); test('filterThreads unread keeps only threads with unread > 0', () => { const input = [t('a', 1, 0), t('b', 2, 2), t('c', 3, 0)]; assert.deepEqual( filterThreads(input, 'unread').map((x) => x.id), ['b'], ); }); test('filterThreads participating keeps only participated threads', () => { const input = [t('a', 1, 0, true), t('b', 2, 0, false), t('c', 3, 0, true)]; assert.deepEqual( filterThreads(input, 'participating').map((x) => x.id), ['a', 'c'], ); }); test('sortThreads recent orders by latestTs descending', () => { const input = [t('a', 100), t('b', 300), t('c', 200)]; assert.deepEqual( sortThreads(input, 'recent').map((x) => x.id), ['b', 'c', 'a'], ); }); test('sortThreads oldest orders by latestTs ascending', () => { const input = [t('a', 100), t('b', 300), t('c', 200)]; assert.deepEqual( sortThreads(input, 'oldest').map((x) => x.id), ['a', 'c', 'b'], ); }); test('sortThreads breaks ties deterministically by id', () => { const input = [t('z', 100), t('a', 100), t('m', 100)]; assert.deepEqual( sortThreads(input, 'recent').map((x) => x.id), ['a', 'm', 'z'], ); assert.deepEqual( sortThreads(input, 'oldest').map((x) => x.id), ['a', 'm', 'z'], ); }); test('filterThreads / sortThreads do not mutate input (all/participating branches)', () => { const input = [t('a', 100, 1, true), t('b', 300, 0, false)]; const before = input.map((x) => x.id); filterThreads(input, 'all'); filterThreads(input, 'participating'); filterThreads(input, 'unread'); sortThreads(input, 'recent'); sortThreads(input, 'oldest'); assert.deepEqual( input.map((x) => x.id), before, ); }); test('filter → sort pipeline composes (unread + recent)', () => { const input = [t('a', 100, 2), t('b', 300, 0), t('c', 200, 1)]; const out = sortThreads(filterThreads(input, 'unread'), 'recent'); assert.deepEqual( out.map((x) => x.id), ['c', 'a'], ); }); test('isThreadFilter / isThreadSort accept valid and reject junk', () => { assert.equal(isThreadFilter('all'), true); assert.equal(isThreadFilter('unread'), true); assert.equal(isThreadFilter('participating'), true); assert.equal(isThreadFilter('bogus'), false); assert.equal(isThreadFilter(undefined), false); assert.equal(isThreadSort('recent'), true); assert.equal(isThreadSort('oldest'), true); assert.equal(isThreadSort('nope'), false); assert.equal(isThreadSort(3), false); });