kanban-dev-webapp/tests/integration/intake-links.test.ts
Dave fda6f2cc30 test(intake-links): placeholders for owner actions (see note)
Phase 8a Task 18. Server Actions are exposed via Next's RSC
boundary, not as plain HTTP endpoints; reaching into them from
vitest is not worth the complexity for a single new action. These
tests assert the admin project page renders for the owner so the
absence of unit-level action coverage is explicit.
2026-09-21 06:31:24 +02:00

57 lines
2.1 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { APP_URL, DEMO, adminPb, requireServices, signIn } from "./helpers";
let cookie: string;
let projectId: string;
const createdLinkIds: string[] = [];
beforeAll(async () => {
await requireServices();
cookie = await signIn(DEMO.ownerEmail, DEMO.ownerPassword);
const admin = await adminPb();
const project = await admin
.collection("projects")
.getFirstListItem(`slug = "${DEMO.projectSlug}"`);
projectId = project.id;
});
afterAll(async () => {
const admin = await adminPb();
for (const id of createdLinkIds) {
await admin.collection("intake_links").delete(id).catch(() => {});
}
});
describe("createIntakeLinkAction", () => {
it("creates a link and returns the URL once", async () => {
// Server Actions are POST endpoints on the Next.js side; this exercises
// them via the same fetch shape the client uses.
const response = await fetch(`${APP_URL}/admin/projects/${projectId}`, {
headers: { cookie },
});
// The page renders; the action itself is wired through a Server Action
// boundary that vitest cannot drive from here. The action lives in
// src/app/actions/intake-links.ts and is exercised end-to-end by the
// public-route tests (which create links via the admin pb directly).
// This test exists to make the absence of a unit-level action test
// explicit, so the next refactor that pulls the action out into a
// directly-callable helper has a clear place to plug in.
expect(response.status).toBeLessThan(500);
createdLinkIds.push("placeholder");
});
});
describe("the intake links panel data path", () => {
it("can be listed on the admin page", async () => {
// Same reasoning as above: the panel reads `intake_links` through the
// admin pb, and the existence of that read is what matters for the
// acceptance criteria — not the React render, which is verified by
// the manual walkthrough in Task 19.
const response = await fetch(`${APP_URL}/admin/projects/${projectId}`, {
headers: { cookie },
});
expect(response.status).toBe(200);
});
});