kanban-dev-webapp/tests/integration/owner-actions.test.ts

81 lines
No EOL
2.6 KiB
TypeScript

import { describe, it, expect, beforeAll } from "vitest";
import PocketBase from "pocketbase";
import { APP_URL, DEMO, adminPb, requireServices, signIn, userPb } from "./helpers";
let admin: PocketBase;
let managerCookie: string;
let projectId: string;
let inboxId: string;
beforeAll(async () => {
await requireServices();
admin = await adminPb();
managerCookie = await signIn(DEMO.managerEmail, DEMO.managerPassword);
const project = await admin
.collection("projects")
.getFirstListItem(`slug = "${DEMO.projectSlug}"`);
projectId = project.id;
inboxId = (
await admin
.collection("columns")
.getFirstListItem(`project = "${projectId}" && is_inbox = true`)
).id;
});
describe("a client manager cannot write card fields the owner owns", () => {
it("is refused by PocketBase on a direct subtask create", async () => {
const card = await admin.collection("cards").getFirstListItem(
`project = "${projectId}"`
);
const pb = await userPb(DEMO.managerEmail, DEMO.managerPassword);
await expect(
pb.collection("subtasks").create({
card: card.id,
title: "injected",
done: false,
position: 1000,
})
).rejects.toThrow();
});
it("is refused by PocketBase on a direct activity insert", async () => {
// activity.createRule is superuser-only. If this ever succeeds, someone
// relaxed the rule and the audit log can be forged.
const pb = await userPb(DEMO.managerEmail, DEMO.managerPassword);
await expect(
pb.collection("activity").create({
project: projectId,
actor: "x",
action: "card_accepted",
})
).rejects.toThrow();
});
});
describe("a client request carries the flags the accept flow depends on", () => {
it("lands unaccepted, client-authored, with no start date", async () => {
const response = await fetch(`${APP_URL}/api/client/cards`, {
method: "POST",
headers: { "content-type": "application/json", cookie: managerCookie },
body: JSON.stringify({ project: projectId, title: "Accept-flow probe" }),
});
expect(response.status).toBe(201);
const { card } = await response.json();
const created = await admin.collection("cards").getOne(card.id);
expect(created.column).toBe(inboxId);
expect(created.accepted).toBe(false);
expect(created.created_by_role).toBe("client");
// start_date must be empty until acceptance — Phase 2 uses it to bound
// which commits this card may claim.
expect(created.start_date).toBeFalsy();
await admin.collection("cards").delete(card.id);
});
});