import { describe, expect, it } from 'vitest'; import { buildSeats, commitName, rosterReady, shuffleSeeded, type RosterRow } from './roster'; describe('commitName (keep-last-valid)', () => { it('commits a valid, trimmed name', () => { expect(commitName('Ann', '')).toBe('Ann'); expect(commitName(' Ann ', '')).toBe('Ann'); }); it('keeps the previous valid name when the input goes invalid', () => { expect(commitName('', 'Ann')).toBe('Ann'); expect(commitName(' ', 'Ann')).toBe('Ann'); expect(commitName('a'.repeat(33), 'Ann')).toBe('Ann'); // over the 32-rune cap expect(commitName('_bad', 'Ann')).toBe('Ann'); // leading separator }); it('replaces the committed name with a newer valid one', () => { expect(commitName('Bob', 'Ann')).toBe('Bob'); }); }); describe('rosterReady', () => { const row = (committed: string): RosterRow => ({ name: committed, committed }); it('needs 2-4 rows, each with a committed name', () => { expect(rosterReady([row('A'), row('B')])).toBe(true); expect(rosterReady([row('A'), row('B'), row('C'), row('D')])).toBe(true); }); it('rejects fewer than 2, more than 4, or an empty row', () => { expect(rosterReady([row('A')])).toBe(false); expect(rosterReady([row('A'), row('B'), row('C'), row('D'), row('E')])).toBe(false); expect(rosterReady([row('A'), row('')])).toBe(false); }); }); describe('buildSeats', () => { it('maps committed rows to account-less human seats, carrying the PIN', () => { const lock = { hash: 'h', salt: 's' }; const seats = buildSeats([ { name: 'Ann', committed: 'Ann', pin: lock }, { name: 'x', committed: 'Bob' }, ]); expect(seats).toEqual([ { kind: 'human', name: 'Ann', pin: lock }, { kind: 'human', name: 'Bob', pin: undefined }, ]); expect(seats.every((s) => !('accountId' in s) || s.accountId === undefined)).toBe(true); }); }); describe('shuffleSeeded', () => { it('is deterministic for the same seed', () => { expect(shuffleSeeded([0, 1, 2, 3], 42n)).toEqual(shuffleSeeded([0, 1, 2, 3], 42n)); }); it('keeps every element (a permutation) and does not mutate the input', () => { const input = [0, 1, 2, 3]; const out = shuffleSeeded(input, 7n); expect([...out].sort((a, b) => a - b)).toEqual([0, 1, 2, 3]); expect(input).toEqual([0, 1, 2, 3]); // input untouched }); it('varies the order across seeds (not always the identity)', () => { const orders = new Set([1n, 2n, 3n, 4n, 5n, 6n, 7n, 8n].map((s) => shuffleSeeded([0, 1, 2, 3], s).join(''))); expect(orders.size).toBeGreaterThan(1); }); });