98 lines
3.0 KiB
TypeScript
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]);
|
|
});
|
|
});
|