Files
sudoku-tools/tests/state/gameplayHelpers.test.ts

98 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
digitCompletions,
matchingDigitCells,
matchingDigitCellsAt,
placedDigitAt,
toggledDigitHighlight,
} from "../../src/state/gameplayHelpers";
describe("digit completion helpers", () => {
it.each([4, 6, 9, 12, 16])(
"reports undone, done and overdone digits on a %i by %i grid",
(size) => {
const values = new Array<number>(size * size).fill(0);
values.fill(1, 0, size - 1);
values.fill(2, size, size * 2);
values.fill(3, size * 2, size * 3 + 1);
const progress = digitCompletions(size, values);
expect(progress).toHaveLength(size);
expect(progress[0]).toEqual({
digit: 1,
placed: size - 1,
target: size,
remaining: 1,
excess: 0,
status: "undone",
});
expect(progress[1]).toEqual({
digit: 2,
placed: size,
target: size,
remaining: 0,
excess: 0,
status: "done",
});
expect(progress[2]).toEqual({
digit: 3,
placed: size + 1,
target: size,
remaining: 0,
excess: 1,
status: "overdone",
});
},
);
it("ignores empty, invalid and out-of-grid values without mutating input", () => {
const values = [1, 1, 0, -1, 5, Number.NaN, ...new Array(12).fill(0), 1];
const before = [...values];
expect(digitCompletions(4, values)[0]).toMatchObject({
placed: 2,
remaining: 2,
status: "undone",
});
expect(values).toEqual(before);
});
it.each([0, 3, 17, 4.5, Number.NaN])(
"rejects unsupported puzzle size %s",
(size) => {
expect(() => digitCompletions(size, [])).toThrow(RangeError);
},
);
});
describe("digit match highlighting", () => {
const values = [4, 0, 2, 4, 0, 3, 4, 0, 2, 0, 3, 0, 4, 2, 0, 3];
it("resolves a placed digit and all of its matching cells", () => {
expect(placedDigitAt(4, values, 3)).toBe(4);
expect(matchingDigitCells(4, values, 4)).toEqual([0, 3, 6, 12]);
expect(matchingDigitCellsAt(4, values, 3)).toEqual([0, 3, 6, 12]);
});
it("treats empty, invalid and out-of-grid cells as no match", () => {
expect(placedDigitAt(4, values, 1)).toBeNull();
expect(placedDigitAt(4, values, -1)).toBeNull();
expect(placedDigitAt(4, values, 16)).toBeNull();
expect(matchingDigitCellsAt(4, values, 1)).toEqual([]);
expect(matchingDigitCells(4, values, 0)).toEqual([]);
expect(matchingDigitCells(4, values, 5)).toEqual([]);
});
it("toggles repeated Ctrl/Cmd-style activation and preserves empty clicks", () => {
expect(toggledDigitHighlight(4, values, 0, null)).toBe(4);
expect(toggledDigitHighlight(4, values, 3, 4)).toBeNull();
expect(toggledDigitHighlight(4, values, 2, 4)).toBe(2);
expect(toggledDigitHighlight(4, values, 1, 4)).toBe(4);
});
it("never returns cells beyond the declared grid", () => {
expect(matchingDigitCells(4, [...values, 4, 4], 4)).toEqual([0, 3, 6, 12]);
});
});