src/features/reviews/persistence.test.ts
Linked repository file from this build.
import { reviewIdentity, reviewKey, type ReviewIdentity } from "./review-key";
import { describe, expect, spyOn, test } from "bun:test";
import { NotFoundError } from "@/lib/errors";
import { DEMO_REVIEW_NUMBER } from "@/programs/snap-negative/constants";
import { createImportTemplate } from "@/programs/snap-negative/review-template";
import { createDemoReviewTemplate } from "@/programs/snap-negative/review-template";
import { saveCommands, StaleReviewError, type PendingCommand } from "./persistence";
import type { ReviewStore, StoredReview } from "./review-store";
import type { SnapReview } from "@/programs/snap-negative/types";
import { demoActor } from "@/lib/auth/roster";
const examiner = { ...demoActor("examiner"), name: "Test Examiner" };
const pec = { ...demoActor("pec"), name: "Pat Policy" };
class MemoryReviewStore implements ReviewStore {
private byReview = new Map<string, StoredReview>();
private byRequest = new Map<string, StoredReview>();
async load(key: string) {
return this.byReview.get(key);
}
async findBusiness(identity: ReviewIdentity) {
return [...this.byReview.values()].find(
(row) => JSON.stringify(reviewIdentity(row.review)) === JSON.stringify(identity),
);
}
async findRequest(requestId: string) {
return this.byRequest.get(requestId);
}
async append(value: StoredReview, _previous?: SnapReview) {
if (this.byRequest.has(value.requestId)) {
throw new Error("Duplicate request id.");
}
this.byReview.set(reviewKey(value.review), value);
this.byRequest.set(value.requestId, value);
}
async list() {
return [...this.byReview.values()];
}
}
function initialStored(): StoredReview {
return {
review: createImportTemplate(),
version: 0,
requestId: "00000000-0000-4000-8000-000000000001",
actor: examiner,
savedAt: "2026-09-05T12:00:00.000Z",
};
}
function pending(
command: PendingCommand["command"],
requestId = "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
actor: PendingCommand["actor"] = examiner,
): PendingCommand {
return {
id: requestId,
at: "2026-09-05T12:30:00.000Z",
actor,
command,
};
}
async function bootStore() {
const store = new MemoryReviewStore();
await store.append(initialStored());
return store;
}
describe("saveCommands", () => {
test("loads the review once and hands it to append as the previous version", async () => {
const store = await bootStore();
const key = reviewKey(initialStored().review);
const loads = spyOn(store, "load");
const appends = spyOn(store, "append");
const requestId = "22222222-2222-4222-8222-222222222222";
await saveCommands(store, key, 0, requestId, [
pending({ type: "outcome", value: "clean" }, requestId),
]);
expect(loads).toHaveBeenCalledTimes(1);
expect(appends.mock.calls[0]?.[1]).toEqual(initialStored().review);
});
test("an unknown review is a not-found error, not a rule failure", async () => {
const store = new MemoryReviewStore();
const requestId = "33333333-3333-4333-8333-333333333333";
await expect(
saveCommands(store, crypto.randomUUID(), 0, requestId, [
pending({ type: "outcome", value: "clean" }, requestId),
]),
).rejects.toBeInstanceOf(NotFoundError);
});
test("persists command results for reload", async () => {
const store = await bootStore();
const requestId = "11111111-1111-4111-8111-111111111111";
const saved = await saveCommands(store, reviewKey(initialStored().review), 0, requestId, [
pending({ type: "outcome", value: "clean" }, requestId),
]);
const reloaded = await store.load(reviewKey(initialStored().review));
expect(reloaded).toEqual(saved);
expect(reloaded?.review.outcome).toBe("clean");
expect(reloaded?.version).toBe(1);
expect(reloaded?.requestId).toBe(requestId);
});
test("returns the same stored review for repeated request ids", async () => {
const store = await bootStore();
const requestId = "22222222-2222-4222-8222-222222222222";
const commands = [pending({ type: "note", body: "Idempotent note." }, requestId)];
const first = await saveCommands(
store,
reviewKey(initialStored().review),
0,
requestId,
commands,
);
const second = await saveCommands(
store,
reviewKey(initialStored().review),
0,
requestId,
commands,
);
expect(second).toEqual(first);
expect((await store.load(reviewKey(initialStored().review)))?.review.notes).toHaveLength(1);
});
test("throws StaleReviewError when the client version is stale", async () => {
const store = await bootStore();
await saveCommands(
store,
reviewKey(initialStored().review),
0,
"33333333-3333-4333-8333-333333333333",
[pending({ type: "outcome", value: "drop" }, "33333333-3333-4333-8333-333333333333")],
);
await expect(
saveCommands(
store,
reviewKey(initialStored().review),
0,
"44444444-4444-4444-8444-444444444444",
[pending({ type: "note", body: "Too late." }, "44444444-4444-4444-8444-444444444444")],
),
).rejects.toBeInstanceOf(StaleReviewError);
});
test("rejects PEC-led reset requests on the server", async () => {
const store = await bootStore();
await expect(
saveCommands(
store,
reviewKey(initialStored().review),
0,
"55555555-5555-4555-8555-555555555555",
[pending({ type: "reset_demo" }, "55555555-5555-4555-8555-555555555555", pec)],
),
).rejects.toThrow("cannot edit review facts");
});
test("reset restores the frozen fixture while preserving stored identity", async () => {
const store = await bootStore();
const modified = await saveCommands(
store,
reviewKey(initialStored().review),
0,
crypto.randomUUID(),
[pending({ type: "identity", value: { clientName: "Changed Client" } }, crypto.randomUUID())],
);
const reset = await saveCommands(
store,
reviewKey(initialStored().review),
modified.version,
crypto.randomUUID(),
[pending({ type: "reset_demo" }, crypto.randomUUID())],
);
expect(reset.review.clientName).toBe(createDemoReviewTemplate().clientName);
expect(reset.review.id).toBe(modified.review.id);
expect(reset.review.reviewNumber).toBe(DEMO_REVIEW_NUMBER);
});
});
test("a racing request ID collision cannot return another review", async () => {
const current = initialStored();
const other = {
...current,
review: { ...current.review, id: crypto.randomUUID(), reviewNumber: "60099" },
};
let lookup = 0;
const store: ReviewStore = {
async findBusiness() {
return current;
},
async load() {
return current;
},
async findRequest() {
return ++lookup === 1 ? undefined : other;
},
async append() {
throw new Error("Duplicate request id");
},
async list() {
return [];
},
};
await expect(
saveCommands(store, current.review.reviewNumber, 0, "collision", [
pending({ type: "note", body: "My note" }),
]),
).rejects.toThrow("Request belongs to another review");
});
test("an idempotent replay still checks the provisioned actor scope", async () => {
const store = await bootStore();
await expect(
saveCommands(store, reviewKey(initialStored().review), 0, initialStored().requestId, [
pending({ type: "note", body: "My note" }, "scope", {
name: "Other examiner",
role: "examiner",
staffId: "105",
program: "SNAP",
}),
]),
).rejects.toThrow("You do not have access");
});
test("fiscal years isolate edits and request replays for the same review number", async () => {
const store = await bootStore();
const previous = initialStored();
previous.review.id = crypto.randomUUID();
previous.review.sampleMonth = "2025-09";
previous.requestId = "previous-year";
await store.append(previous);
expect(await store.load(DEMO_REVIEW_NUMBER)).toBeUndefined();
const saved = await saveCommands(store, reviewKey(initialStored().review), 0, "this-year-note", [
pending({ type: "note", body: "FFY 2026 only" }),
]);
expect(saved.review.notes.at(-1)?.body).toBe("FFY 2026 only");
expect((await store.load(reviewKey(previous.review)))?.review.notes).toHaveLength(0);
await expect(
saveCommands(store, reviewKey(previous.review), 0, "this-year-note", [
pending({ type: "note", body: "Wrong year" }),
]),
).rejects.toThrow("Request belongs to another review");
await expect(
saveCommands(store, DEMO_REVIEW_NUMBER, 0, "this-year-note", [
pending({ type: "note", body: "Legacy reference" }),
]),
).rejects.toThrow("another review");
});
test("append retries cannot return the same review number from another fiscal year", async () => {
const current = initialStored();
const other = {
...current,
review: { ...current.review, id: crypto.randomUUID(), sampleMonth: "2025-09" },
};
let lookup = 0;
const store: ReviewStore = {
async findBusiness() {
return current;
},
async load() {
return current;
},
async findRequest() {
return ++lookup === 1 ? undefined : other;
},
async append() {
throw new Error("Duplicate request id");
},
async list() {
return [];
},
};
await expect(
saveCommands(store, reviewKey(current.review), 0, "collision", [
pending({ type: "note", body: "My note" }),
]),
).rejects.toThrow("Request belongs to another review");
});
test("editing a sample month cannot move a review to another fiscal year or reset another year's case", async () => {
const store = await bootStore();
await expect(
saveCommands(store, reviewKey(initialStored().review), 0, "move-year", [
pending({ type: "identity", value: { sampleMonth: "2026-10" } }),
]),
).rejects.toThrow("must stay within");
const saved = await saveCommands(store, reviewKey(initialStored().review), 0, "same-year", [
pending({ type: "identity", value: { sampleMonth: "2025-10" } }),
]);
expect(saved.review.sampleMonth).toBe("2025-10");
const previous = initialStored();
previous.review.id = crypto.randomUUID();
previous.review.sampleMonth = "2025-09";
previous.requestId = "previous-year";
await store.append(previous);
await expect(
saveCommands(store, reviewKey(previous.review), 0, "reset-previous", [
pending({ type: "reset_demo" }),
]),
).rejects.toThrow("Reset demo applies only");
await expect(
saveCommands(store, reviewKey(saved.review), saved.version, "restore-year", [
pending({
type: "restore_facts",
identity: { sampleMonth: "2024-10" },
facts: saved.review.facts,
outcome: saved.review.outcome,
}),
]),
).rejects.toThrow("must stay within");
});