import { describe, expect, it } from "vitest"; import { aidMemoireCellDescription, aidMemoireFromPortable, aidMemoireToPortable, clearAidMemoireEntries, compactAidMemoireColumns, configureAidMemoire, createAidMemoire, enterAidMemoireCell, eraseAidMemoireCell, labelAidMemoireCell, MAX_AID_MEMOIRE_CELLS, normalizePortableAidMemoire, resetAidMemoire, } from "../../src/state/aidMemoire"; import { maskValues } from "../../src/state/session"; describe("aid-mémoire state", () => { it("creates a bounded row and preserves existing cells while reflowing", () => { let state = createAidMemoire(9, { enabled: true }); expect(state.cells).toHaveLength(9); expect(state.columns).toBe(9); expect(state.cells.map((cell) => cell.label)).toEqual([ "1", "2", "3", "4", "5", "6", "7", "8", "9", ]); state = labelAidMemoireCell(state, 0, "Prime"); state = enterAidMemoireCell(state, 0, "value", 7, 9); state = configureAidMemoire(state, 9, 12, 4); expect(state.cells).toHaveLength(12); expect(state.columns).toBe(4); expect(state.cells[0]).toMatchObject({ label: "Prime", value: 7 }); expect(state.cells[11]?.label).toBe("12"); state = configureAidMemoire(state, 9, 1_000, 1_000); expect(state.cells).toHaveLength(MAX_AID_MEMOIRE_CELLS); expect(state.columns).toBe(MAX_AID_MEMOIRE_CELLS); state = configureAidMemoire(state, 9, Number.NaN, Number.NaN); expect(state.cells).toHaveLength(9); expect(state.columns).toBe(1); state = configureAidMemoire(state, 9, 3.9, 2.8); expect(state.cells).toHaveLength(3); expect(state.columns).toBe(2); expect(compactAidMemoireColumns(9)).toBe(3); expect(compactAidMemoireColumns(Number.NaN)).toBe(1); }); it("edits values, both mark types and colours like normal cells", () => { let state = createAidMemoire(9, { enabled: true, cellCount: 1 }); state = enterAidMemoireCell(state, 0, "corner", 2, 9); state = enterAidMemoireCell(state, 0, "corner", 8, 9); state = enterAidMemoireCell(state, 0, "center", 4, 9); state = enterAidMemoireCell(state, 0, "color", 6, 9); expect(maskValues(state.cells[0]!.cornerMarks, 9)).toEqual([2, 8]); expect(maskValues(state.cells[0]!.centerMarks, 9)).toEqual([4]); expect(state.cells[0]?.color).toBe(6); state = enterAidMemoireCell(state, 0, "value", 5, 9); expect(state.cells[0]).toMatchObject({ value: 5, cornerMarks: 0, centerMarks: 0, color: 6, }); expect(enterAidMemoireCell(state, 0, "center", 3, 9)).toBe(state); expect(enterAidMemoireCell(state, 0, "value", 2.5, 9)).toBe(state); state = eraseAidMemoireCell(state, 0, "value"); state = enterAidMemoireCell(state, 0, "color", 6, 9); expect(state.cells[0]).toMatchObject({ value: 0, color: 0 }); }); it("clears entries without losing layout or labels and can reset all", () => { let state = createAidMemoire(6, { enabled: true, cellCount: 4, columns: 2, }); state = labelAidMemoireCell(state, 0, "Used"); state = enterAidMemoireCell(state, 0, "value", 3, 6); const cleared = clearAidMemoireEntries(state); expect(cleared).toMatchObject({ enabled: true, columns: 2 }); expect(cleared.cells[0]).toMatchObject({ label: "Used", value: 0 }); const reset = resetAidMemoire(cleared, 6); expect(reset).toMatchObject({ enabled: true, columns: 6 }); expect(reset.cells).toHaveLength(6); expect(reset.cells[0]?.label).toBe("1"); }); it("round-trips a stable portable representation", () => { const portable = normalizePortableAidMemoire( { version: 1, enabled: true, columns: 2, cells: [ { label: "Primes", value: 0, cornerMarks: [7, 2, 2], centerMarks: [5, 3], color: 4, }, { label: "Used", value: 8, color: 0 }, ], }, 9, ); expect(portable.cells[0]).toMatchObject({ cornerMarks: [2, 7], centerMarks: [3, 5], }); expect( aidMemoireToPortable(aidMemoireFromPortable(portable, 9), 9), ).toEqual(portable); }); it("rejects unsafe portable layouts and provides complete cell narration", () => { expect(() => normalizePortableAidMemoire( { version: 1, enabled: true, columns: 1, cells: Array.from({ length: MAX_AID_MEMOIRE_CELLS + 1 }, () => ({})), }, 9, ), ).toThrow(/1 to 36/u); let state = createAidMemoire(9, { cellCount: 1 }); state = labelAidMemoireCell(state, 0, "Odd candidates"); state = enterAidMemoireCell(state, 0, "corner", 1, 9); state = enterAidMemoireCell(state, 0, "center", 7, 9); state = enterAidMemoireCell(state, 0, "color", 3, 9); expect(aidMemoireCellDescription(state.cells[0]!, 0, 9)).toBe( "Aid-mémoire cell 1, label Odd candidates, empty, corner marks 1, centre marks 7, colour 3: yellow, dots", ); }); });