Files
buzz/lib/tierlist-write.test.ts
T
dmgnr 26a4331a08
Build and Deploy Next Preview / build-deploy (push) Successful in 2m52s
fix: keep tierlist saves consistent
2026-10-10 08:10:54 +00:00

125 lines
4.0 KiB
TypeScript

import { describe, expect, spyOn, test } from "bun:test";
import { PgDialect } from "drizzle-orm/pg-core";
import type { tierlistStates } from "./db/schema";
import {
finishTierlistWrite,
lockTierlistList,
normalizeTierlistPlacements,
resolveTierlistStateTarget,
validateTierlistStateInput,
} from "./tierlist-write";
type StateRow = typeof tierlistStates.$inferSelect;
const stateRow = (uuid: string, list: string, ref = "char-1") =>
({ uuid, list, ref }) as StateRow;
describe("tierlist write consistency helpers", () => {
test("validates list, ref, and optional UUID before writing", () => {
expect(
validateTierlistStateInput({
list: "v1",
ref: "char-1",
uuid: undefined,
}),
).toEqual({ list: "v1", ref: "char-1" });
expect(() =>
validateTierlistStateInput({ list: "", ref: "char-1" }),
).toThrow();
expect(() => validateTierlistStateInput({ list: "v1", ref: "" })).toThrow();
expect(() =>
validateTierlistStateInput({ list: "v1", ref: "char-1", uuid: "bad" }),
).toThrow();
});
test("rejects cross-list UUIDs and canonicalizes duplicate refs", () => {
const uuidMatch = stateRow("uuid-1", "v1");
const canonicalRefMatch = stateRow("uuid-0", "v1");
expect(() =>
resolveTierlistStateTarget(stateRow("uuid-2", "v2"), uuidMatch, "v1"),
).toThrow("belongs to another version");
expect(resolveTierlistStateTarget(uuidMatch, undefined, "v1")).toBe(
uuidMatch,
);
expect(resolveTierlistStateTarget(uuidMatch, canonicalRefMatch, "v1")).toBe(
canonicalRefMatch,
);
expect(resolveTierlistStateTarget(undefined, uuidMatch, "v1")).toBe(
uuidMatch,
);
});
test("uses one transaction-scoped advisory lock per list before mutations", async () => {
const order: string[] = [];
const queries: unknown[] = [];
await lockTierlistList(
{
execute: async (query) => {
order.push("lock");
queries.push(query);
},
},
"v1",
);
order.push("write");
const compiled = new PgDialect().sqlToQuery(queries[0] as never);
expect(compiled.sql).toContain("pg_advisory_xact_lock");
expect(compiled.sql).toContain("hashtextextended");
expect(compiled.params).toContain("v1");
expect(order).toEqual(["lock", "write"]);
});
test("normalizes placements without mutating the caller's untiered data", () => {
const placements = { S: ["a"], untiered: ["b"] };
expect(normalizeTierlistPlacements(placements)).toEqual({ S: ["a"] });
expect(placements).toEqual({ S: ["a"], untiered: ["b"] });
});
test("returns persisted success when publication fails after commit", async () => {
const errorLog = spyOn(console, "error").mockImplementation(() => {});
try {
const result = await finishTierlistWrite({
list: "v1",
operation: "state",
data: [{ uuid: "state-1" }],
audit: async () => {},
revalidate: () => {},
publish: async () => {
throw new Error("redis unavailable");
},
});
expect(result).toEqual({
persisted: true,
data: [{ uuid: "state-1" }],
publication: "failed",
});
expect(errorLog).toHaveBeenCalledTimes(1);
} finally {
errorLog.mockRestore();
}
});
test("reports sent when post-commit publication succeeds", async () => {
const result = await finishTierlistWrite({
list: "v1",
operation: "placements",
data: { S: ["char-1"] },
audit: async () => {},
revalidate: () => {},
publish: async () => 1,
});
expect(result).toEqual({
persisted: true,
data: { S: ["char-1"] },
publication: "sent",
});
});
test("does not turn a precommit transaction failure into persisted success", async () => {
const failure = new Error("transaction failed");
await expect(
lockTierlistList({ execute: async () => Promise.reject(failure) }, "v1"),
).rejects.toBe(failure);
});
});