81 lines
No EOL
2.6 KiB
TypeScript
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);
|
|
});
|
|
}); |