104 lines
3.6 KiB
TypeScript
104 lines
3.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
parseInvalidationEvent,
|
|
toInvalidationEvent,
|
|
} from "./invalidation";
|
|
|
|
describe("invalidation event envelopes", () => {
|
|
it("strips every field except type, opaque id, and version", () => {
|
|
const event = toInvalidationEvent({
|
|
topic: "directory",
|
|
aggregateId: "4afeea7b-6f24-43f3-b747-2db98335e01e",
|
|
eventType: "directory.updated",
|
|
payload: {
|
|
id: "4afeea7b-6f24-43f3-b747-2db98335e01e",
|
|
version: 3,
|
|
title: "private draft title",
|
|
blocks: [{ content: "private" }],
|
|
},
|
|
});
|
|
expect(event).toEqual({
|
|
type: "directory.updated",
|
|
id: "4afeea7b-6f24-43f3-b747-2db98335e01e",
|
|
version: 3,
|
|
});
|
|
});
|
|
|
|
it.each(["catalog.updated", "glossary.updated"])("routes %s through the protected admin topic", (type) => {
|
|
const payload = { id: "test", version: 100 };
|
|
expect(toInvalidationEvent({ topic: "admin", aggregateId: "test", eventType: type, payload }))
|
|
.toEqual({ type, ...payload });
|
|
expect(toInvalidationEvent({ topic: "directory", aggregateId: "test", eventType: type, payload })).toBeNull();
|
|
});
|
|
|
|
it("rejects unknown, malformed, and topic-mismatched messages", () => {
|
|
expect(parseInvalidationEvent("not json")).toBeNull();
|
|
expect(
|
|
parseInvalidationEvent(
|
|
JSON.stringify({ type: "page.content", id: "id", version: 1 }),
|
|
),
|
|
).toBeNull();
|
|
expect(
|
|
toInvalidationEvent({
|
|
topic: "admin",
|
|
aggregateId: "id",
|
|
eventType: "page.updated",
|
|
payload: { id: "id", version: 1 },
|
|
}),
|
|
).toBeNull();
|
|
});
|
|
|
|
it("accepts public Stygian invalidations only on the Stygian topic", () => {
|
|
expect(toInvalidationEvent({
|
|
topic: "stygian",
|
|
aggregateId: "5269001",
|
|
eventType: "stygian.updated",
|
|
payload: { id: "5269001", version: 4 },
|
|
})).toEqual({ type: "stygian.updated", id: "5269001", version: 4 });
|
|
});
|
|
|
|
it("keeps valid scopes only on authenticated admin events", () => {
|
|
const id = "4afeea7b-6f24-43f3-b747-2db98335e01e";
|
|
expect(toInvalidationEvent({
|
|
topic: "admin",
|
|
aggregateId: id,
|
|
eventType: "admin.updated",
|
|
payload: { id, version: 4, scope: "team" },
|
|
})).toEqual({ type: "admin.updated", id, version: 4, scope: "team" });
|
|
expect(parseInvalidationEvent(JSON.stringify({ type: "admin.updated", id, version: 5, scope: `extra:${id}` })))
|
|
.toEqual({ type: "admin.updated", id, version: 5, scope: `extra:${id}` });
|
|
expect(parseInvalidationEvent(JSON.stringify({ type: "page.updated", id, version: 5, scope: "team" })))
|
|
.toBeNull();
|
|
expect(toInvalidationEvent({
|
|
topic: "admin",
|
|
aggregateId: id,
|
|
eventType: "admin.updated",
|
|
payload: { id, version: 6, scope: "unknown" },
|
|
})).toBeNull();
|
|
});
|
|
|
|
it("publishes validated overwrite details only on admin events", () => {
|
|
const id = "4afeea7b-6f24-43f3-b747-2db98335e01e";
|
|
const overwrite = { operation: "overwrite", actorName: "Editor One" };
|
|
expect(toInvalidationEvent({
|
|
topic: "admin",
|
|
aggregateId: id,
|
|
eventType: "admin.updated",
|
|
payload: { id, version: 7, scope: "weapon", ...overwrite },
|
|
})).toEqual({ type: "admin.updated", id, version: 7, scope: "weapon", ...overwrite });
|
|
expect(parseInvalidationEvent(JSON.stringify({
|
|
type: "admin.updated",
|
|
id,
|
|
version: 8,
|
|
operation: "overwrite",
|
|
}))).toBeNull();
|
|
expect(toInvalidationEvent({
|
|
topic: `page:${id}`,
|
|
aggregateId: id,
|
|
eventType: "page.updated",
|
|
payload: { id, version: 7, ...overwrite },
|
|
})).toEqual({ type: "page.updated", id, version: 7 });
|
|
});
|
|
});
|