kanban-dev-webapp/tests/integration/activity-log.test.ts

92 lines
No EOL
2.8 KiB
TypeScript

import { describe, it, expect, beforeAll } from "vitest";
import PocketBase from "pocketbase";
import { APP_URL, DEMO, adminPb, requireServices, signIn } from "./helpers";
let admin: PocketBase;
let cookie: string;
let cardId: string;
beforeAll(async () => {
await requireServices();
admin = await adminPb();
cookie = await signIn(DEMO.managerEmail, DEMO.managerPassword);
const project = await admin
.collection("projects")
.getFirstListItem(`slug = "${DEMO.projectSlug}"`);
cardId = (
await admin.collection("cards").getFirstListItem(`project = "${project.id}"`)
).id;
});
async function patch(body: Record<string, unknown>) {
return fetch(`${APP_URL}/api/client/cards/${cardId}`, {
method: "PATCH",
headers: { "content-type": "application/json", cookie },
body: JSON.stringify(body),
});
}
async function activityCount(): Promise<number> {
const rows = await admin
.collection("activity")
.getFullList({ filter: `card = "${cardId}"` });
return rows.length;
}
/** Spec §9 test 5 */
describe("every client-originated change is audited", () => {
it("writes one row with the correct old and new values", async () => {
await admin.collection("cards").update(cardId, { priority: "medium" });
const before = await activityCount();
const response = await patch({ priority: "high" });
expect(response.status).toBe(200);
// Exactly one new row overall — not "at least one", which would pass even
// if the route wrote a row per field it merely looked at.
expect(await activityCount()).toBe(before + 1);
const rows = await admin.collection("activity").getFullList({
filter: `card = "${cardId}" && field = "priority"`,
sort: "-created",
});
expect(rows[0].action).toBe("priority_changed");
expect(rows[0].old_value).toBe("medium");
expect(rows[0].new_value).toBe("high");
expect(rows[0].actor).not.toBe("");
});
it("writes no row when the value is unchanged", async () => {
await admin.collection("cards").update(cardId, { priority: "low" });
const before = await activityCount();
const response = await patch({ priority: "low" });
expect(response.status).toBe(200);
expect(await activityCount()).toBe(before);
});
it("writes one row per field when two change at once", async () => {
await admin
.collection("cards")
.update(cardId, { priority: "medium", target_date: "2026-10-01" });
const before = await activityCount();
const response = await patch({
priority: "critical",
target_date: "2026-12-24",
});
expect(response.status).toBe(200);
expect(await activityCount()).toBe(before + 2);
});
it("returns 400 when the body contains no editable fields", async () => {
const response = await patch({ title: "nope", column: "whatever" });
expect(response.status).toBe(400);
});
});