Files
cinny/src/app/state/closedLobbyCategories.test.ts
T
jaredandClaude Opus 4.8 f03c0ef960 test: cover cryptoDiagLog + closedLobbyCategories
Test-coverage batch 2 (2-agent reviewed, both SHIP; isolation verified — Node
runs each test file in its own process, so the console patch can't leak).

- cryptoDiagLog.test.ts: the E2EE KE-cluster diagnostics tool — KE-signature
  capture vs ignore, most-specific-first match order, KE-3/KE-4 rows, Error /
  object / circular-arg serialization (String() fallback never throws), the
  200-entry ring-buffer eviction, getCryptoDiagEntries copy semantics,
  install idempotency, and buildCryptoDiagReport's client metadata + LOCKED
  PII-safe key set (no field can silently leak) + no-client/throwing-getter
  fallbacks. Silences console pass-through so the ring-buffer test stays quiet.
- closedLobbyCategories.test.ts: mirrors closedNavCategories — id join,
  hydrate, PUT/DELETE, idempotent PUT, no-op DELETE, array persistence,
  per-user key namespacing.

Also: mark the EC in-call mobile UI audit done in LOTUS_TODO (stale entry;
shipped as element-call:lotus e36aef8a).

Gates: tsc 0, eslint 0, prettier clean, 911 tests, build ok.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:38:02 -04:00

103 lines
3.8 KiB
TypeScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createStore } from 'jotai';
import { enableMapSet } from 'immer';
import { makeClosedLobbyCategoriesAtom, makeLobbyCategoryId } from './closedLobbyCategories';
// makeClosedLobbyCategoriesAtom(userId) builds a Set<string> atom whose reducer uses
// immer produce (PUT add / DELETE delete) and persists to a per-user localStorage
// key `closedLobbyCategories<userId>`. The reducers produce over a Set, so enable
// immer's Map/Set plugin (the app does this once at startup).
// makeLobbyCategoryId joins args with '|'. (Mirrors closedNavCategories.test.ts.)
enableMapSet();
type Store = Record<string, string>;
const installLocalStorage = (): Store => {
const data: Store = {};
const ls = {
getItem: (k: string) => (k in data ? data[k] : null),
setItem: (k: string, v: string) => {
data[k] = String(v);
},
removeItem: (k: string) => {
delete data[k];
},
};
(globalThis as { localStorage?: unknown }).localStorage = ls;
(globalThis as { window?: unknown }).window = {
addEventListener: () => undefined,
removeEventListener: () => undefined,
};
return data;
};
test('makeLobbyCategoryId joins args with "|"', () => {
assert.equal(makeLobbyCategoryId('space', 'catA'), 'space|catA');
assert.equal(makeLobbyCategoryId('only'), 'only');
assert.equal(makeLobbyCategoryId(), '');
});
test('starts empty when nothing is stored', () => {
installLocalStorage();
const store = createStore();
const lobbyAtom = makeClosedLobbyCategoriesAtom('@u:server');
assert.equal(store.get(lobbyAtom).size, 0);
});
test('hydrates the Set from the per-user localStorage key', () => {
const data = installLocalStorage();
data['closedLobbyCategories@u:server'] = JSON.stringify(['x', 'y']);
const store = createStore();
const lobbyAtom = makeClosedLobbyCategoriesAtom('@u:server');
assert.deepEqual(Array.from(store.get(lobbyAtom)).sort(), ['x', 'y']);
});
test('PUT adds a category and DELETE removes it', () => {
installLocalStorage();
const store = createStore();
const lobbyAtom = makeClosedLobbyCategoriesAtom('@u:server');
store.set(lobbyAtom, { type: 'PUT', categoryId: 'cat1' });
assert.deepEqual(Array.from(store.get(lobbyAtom)), ['cat1']);
store.set(lobbyAtom, { type: 'DELETE', categoryId: 'cat1' });
assert.equal(store.get(lobbyAtom).has('cat1'), false);
});
test('PUT of an existing category is idempotent', () => {
installLocalStorage();
const store = createStore();
const lobbyAtom = makeClosedLobbyCategoriesAtom('@u:server');
store.set(lobbyAtom, { type: 'PUT', categoryId: 'cat1' });
store.set(lobbyAtom, { type: 'PUT', categoryId: 'cat1' });
assert.equal(store.get(lobbyAtom).size, 1);
});
test('DELETE of an absent category is a no-op', () => {
installLocalStorage();
const store = createStore();
const lobbyAtom = makeClosedLobbyCategoriesAtom('@u:server');
store.set(lobbyAtom, { type: 'DELETE', categoryId: 'missing' });
assert.equal(store.get(lobbyAtom).size, 0);
});
test('writes persist to localStorage as an array', () => {
const data = installLocalStorage();
const store = createStore();
const lobbyAtom = makeClosedLobbyCategoriesAtom('@u:server');
store.set(lobbyAtom, { type: 'PUT', categoryId: 'cat1' });
assert.deepEqual(JSON.parse(data['closedLobbyCategories@u:server']), ['cat1']);
});
test('the storage key is namespaced per user', () => {
const data = installLocalStorage();
const store = createStore();
const aAtom = makeClosedLobbyCategoriesAtom('@a:server');
const bAtom = makeClosedLobbyCategoriesAtom('@b:server');
store.set(aAtom, { type: 'PUT', categoryId: 'only-a' });
assert.deepEqual(JSON.parse(data['closedLobbyCategories@a:server']), ['only-a']);
assert.equal(data['closedLobbyCategories@b:server'], undefined);
assert.equal(store.get(bAtom).size, 0);
});