Files
gacha-event-tracker/test/versions.test.ts
T

139 lines
4.6 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { DAY } from "../src/shared/time.ts";
import {
VERSION_DAYS,
VERSIONS,
versionCaption,
versionWindow,
type GameVersion,
} from "../src/shared/versions.ts";
/**
* Version timers: a hand-kept, cited table (spec 2026-10-22). A routine resets
* only at an end the table records; an estimate is shown and never acted on.
*/
const at = (iso: string) => Date.parse(iso);
describe("VERSIONS", () => {
test("each game's versions are in order and meet end to start", () => {
const games = new Set(VERSIONS.map((v) => v.game));
for (const game of games) {
const list = VERSIONS.filter((v) => v.game === game);
list.forEach((v, i) => {
expect(Number.isFinite(at(v.start))).toBe(true);
if (v.end !== undefined) expect(at(v.end)).toBeGreaterThan(at(v.start));
const next = list[i + 1];
if (next !== undefined) {
expect(at(next.start)).toBeGreaterThan(at(v.start));
if (v.end !== undefined) expect(at(v.end)).toBe(at(next.start));
else expect(v.end).toBeDefined(); // only the newest may be open
}
});
}
});
test("every one cites an https page and the day it was read", () => {
for (const v of VERSIONS) {
expect(v.source.startsWith("https://")).toBe(true);
expect(v.checked).toMatch(/^\d{4}-\d{2}-\d{2}$/);
if (v.note?.toLowerCase().includes("in game") === true)
expect(v.note).toMatch(/Confirmed in game, \d{4}-\d{2}-\d{2}\./);
}
});
});
describe("versionWindow", () => {
test("inside 3.7: its number, its key, its recorded end", () => {
expect(versionWindow("wuwa", at("2026-10-22T14:30:00Z"))).toEqual({
number: "3.7",
key: "2026-09-30",
start: at("2026-09-30T03:00:00Z"),
end: at("2026-11-11T10:30:00Z"),
estimate: undefined,
nextNumber: "3.8",
});
});
test("rolls at the recorded instant, not a minute before", () => {
expect(versionWindow("wuwa", at("2026-11-11T10:29:00Z"))?.number).toBe("3.7");
expect(versionWindow("wuwa", at("2026-11-11T10:30:00Z"))).toEqual({
number: "3.8",
key: "2026-11-11",
start: at("2026-11-11T10:30:00Z"),
end: undefined,
estimate: at("2026-11-11T10:30:00Z") + 42 * DAY,
nextNumber: undefined,
});
});
test("never rolls on an estimate: far past it, still 3.8 under the same key", () => {
const w = versionWindow("wuwa", at("2027-02-01T00:00:00Z"));
expect(w?.number).toBe("3.8");
expect(w?.key).toBe("2026-11-11");
});
const open: GameVersion = {
game: "wuwa",
number: "4.0",
start: "2026-12-23T03:00:00Z",
next: "4.1",
source: "https://example.org/",
checked: "2026-10-22",
};
test("a newest entry with no end is open, estimated from its own start", () => {
const w = versionWindow("wuwa", at("2026-12-30T00:00:00Z"), [open]);
expect(w).toEqual({
number: "4.0",
key: "2026-12-23",
start: at(open.start),
end: undefined,
estimate: at(open.start) + 42 * DAY,
nextNumber: "4.1",
});
});
test("no usual length, no estimate", () => {
expect(versionWindow("wuwa", at("2026-12-30T00:00:00Z"), [open], {})?.estimate).toBeUndefined();
});
test("a game with no versions has no window", () => {
expect(versionWindow("genshin", at("2026-10-22T00:00:00Z"))).toBeUndefined();
});
test("WuWa's usual length is six weeks", () => {
expect(VERSION_DAYS.wuwa).toBe(42);
});
});
describe("versionCaption", () => {
const base = { key: "2026-11-11", start: at("2026-11-11T10:30:00Z") };
const estimate = at("2026-12-23T10:30:00Z");
test("a recorded end names the next version and the day", () => {
const w = versionWindow("wuwa", at("2026-10-22T14:30:00Z"))!;
expect(versionCaption(w, at("2026-10-22T14:30:00Z"))).toBe("resets with 3.8 · 11 Nov");
});
test("no recorded end: the next version, if named, and the estimate", () => {
const now = at("2026-11-20T00:00:00Z");
expect(versionCaption({ ...base, number: "3.8", nextNumber: "3.9", estimate }, now)).toBe(
"resets with next version (3.9) · expected ~23 Dec",
);
expect(versionCaption({ ...base, number: "3.8", estimate }, now)).toBe(
"resets with next version · expected ~23 Dec",
);
});
test("past the estimate, it says the end is not yet confirmed", () => {
expect(versionCaption({ ...base, estimate }, at("2027-01-02T00:00:00Z"))).toBe(
"resets with next version · expected ~23 Dec, not yet confirmed",
);
});
test("no estimate at all", () => {
expect(versionCaption(base, at("2026-11-20T00:00:00Z"))).toBe("resets with next version");
});
});