150 lines
5.0 KiB
TypeScript
150 lines
5.0 KiB
TypeScript
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",
|
|
);
|
|
});
|
|
});
|