Chores had one global switch and built-ins only a per-game opt-in, so the two answered the same question two different ways. perGame.ts is now the one rule for both: a global answer, then the games that differ. Nothing is migrated. routineGames keeps its meaning as the built-ins' on-list and an absent showRoutines still reads as off, so every reader's answers, and an older cached tab, see what they saw before. The strip stops asking about one game once the reader has answered for all. Co-Authored-By: Claude Opus 5.5 <[email protected]>
90 lines
3.6 KiB
TypeScript
90 lines
3.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { exceptionLine, setFor, shownFor } from "../src/shared/perGame.ts";
|
|
|
|
/**
|
|
* One rule for "the app supplies this for a game": a global answer, and the
|
|
* games that differ from it. Chores and built-in weekly tasks both read it, so
|
|
* a reader's per-game answer means the same thing in both places.
|
|
*/
|
|
describe("shownFor", () => {
|
|
test("with no exceptions, every game takes the global answer", () => {
|
|
expect(shownFor({ all: true }, "genshin")).toBe(true);
|
|
expect(shownFor({ all: false }, "genshin")).toBe(false);
|
|
});
|
|
|
|
test("an exception overrides the global answer for its game only", () => {
|
|
expect(shownFor({ all: false, on: ["zzz"] }, "zzz")).toBe(true);
|
|
expect(shownFor({ all: false, on: ["zzz"] }, "genshin")).toBe(false);
|
|
expect(shownFor({ all: true, off: ["hsr"] }, "hsr")).toBe(false);
|
|
expect(shownFor({ all: true, off: ["hsr"] }, "genshin")).toBe(true);
|
|
});
|
|
|
|
test("an exception survives the global answer flipping", () => {
|
|
// Flipping the switch rewrites nothing else; a game the reader singled out
|
|
// stays singled out.
|
|
expect(shownFor({ all: true, on: ["zzz"] }, "zzz")).toBe(true);
|
|
expect(shownFor({ all: false, off: ["hsr"] }, "hsr")).toBe(false);
|
|
});
|
|
|
|
test("a game in both lists — hand-edited storage — is shown", () => {
|
|
expect(shownFor({ all: false, on: ["zzz"], off: ["zzz"] }, "zzz")).toBe(true);
|
|
expect(shownFor({ all: true, on: ["zzz"], off: ["zzz"] }, "zzz")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("setFor", () => {
|
|
test("an answer that differs from the global one is recorded as an exception", () => {
|
|
expect(setFor({ all: false }, "zzz", true)).toEqual({ on: ["zzz"], off: [] });
|
|
expect(setFor({ all: true }, "hsr", false)).toEqual({ on: [], off: ["hsr"] });
|
|
});
|
|
|
|
test("an answer that matches the global one clears the exception", () => {
|
|
expect(setFor({ all: false, on: ["zzz", "endfield"] }, "zzz", false)).toEqual({
|
|
on: ["endfield"],
|
|
off: [],
|
|
});
|
|
expect(setFor({ all: true, off: ["hsr"] }, "hsr", true)).toEqual({ on: [], off: [] });
|
|
});
|
|
|
|
test("a game never ends up in both lists", () => {
|
|
expect(setFor({ all: true, on: ["zzz"], off: ["zzz"] }, "zzz", false)).toEqual({
|
|
on: [],
|
|
off: ["zzz"],
|
|
});
|
|
});
|
|
|
|
test("other games' exceptions are left where they were", () => {
|
|
expect(setFor({ all: true, off: ["hsr"] }, "genshin", false)).toEqual({
|
|
on: [],
|
|
off: ["hsr", "genshin"],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("exceptionLine", () => {
|
|
const name = (g: string) => ({ genshin: "Genshin Impact", zzz: "Zenless Zone Zero" })[g] ?? g;
|
|
const games = ["genshin", "hsr", "zzz", "endfield"];
|
|
|
|
test("on for everyone, or off for everyone", () => {
|
|
expect(exceptionLine({ all: true }, games, name)).toBe("Every game");
|
|
expect(exceptionLine({ all: false }, games, name)).toBe("No game");
|
|
});
|
|
|
|
test("one exception is named", () => {
|
|
expect(exceptionLine({ all: true, off: ["genshin"] }, games, name)).toBe("All but Genshin Impact");
|
|
expect(exceptionLine({ all: false, on: ["zzz"] }, games, name)).toBe("Only Zenless Zone Zero");
|
|
});
|
|
|
|
test("several are counted", () => {
|
|
expect(exceptionLine({ all: true, off: ["genshin", "hsr", "zzz"] }, games, name)).toBe(
|
|
"All but 3 games",
|
|
);
|
|
expect(exceptionLine({ all: false, on: ["genshin", "zzz"] }, games, name)).toBe("Only 2 games");
|
|
});
|
|
|
|
test("only the games listed count — an exception agreeing with the global answer is none", () => {
|
|
expect(exceptionLine({ all: true, off: ["fgo"] }, games, name)).toBe("Every game");
|
|
expect(exceptionLine({ all: true, on: ["zzz"] }, games, name)).toBe("Every game");
|
|
});
|
|
});
|