kanban-dev-webapp/tests/integration/plan-gantt.test.tsx
Dave 14f6c067c2 test(plan): integration test for the new Gantt view
Two tests against the live database and the seeded project:

- loadPlan returns a section containing the seeded project.
- GanttPlanView renders the project name and at least one
  card title to HTML.

vitest integration config now picks up .test.tsx too.
2026-09-21 16:19:52 +02:00

73 lines
2.3 KiB
TypeScript

import { describe, it, expect, beforeAll } from "vitest";
import PocketBase from "pocketbase";
import { renderToStaticMarkup } from "react-dom/server";
import { GanttPlanView } from "@/components/roadmap/gantt-plan-view";
import { buildPlanSections } from "@/lib/roadmap/load";
import type {
CardRecord,
ClientRecord,
ColumnRecord,
ProjectRecord,
SubtaskRecord,
} from "@/lib/pb/types";
import { DEMO, adminPb, requireServices } from "./helpers";
let admin: PocketBase;
beforeAll(async () => {
await requireServices();
admin = await adminPb();
});
async function loadForProject(slug: string) {
const project = await admin
.collection("projects")
.getFirstListItem<ProjectRecord>(`slug = "${slug}"`);
const [clients, columns, cards, subtasks] = await Promise.all([
admin.collection("clients").getFullList<ClientRecord>(),
admin.collection("columns").getFullList<ColumnRecord>({ sort: "position" }),
admin
.collection("cards")
.getFullList<CardRecord>({ filter: `project = "${project.id}" && archived = false` }),
admin
.collection("subtasks")
.getFullList<SubtaskRecord>({
filter: `card.project = "${project.id}"`,
}),
]);
return buildPlanSections({
clients,
projects: [project],
columns,
cards,
subtasks,
});
}
describe("/plan Gantt — seeded project loads", () => {
it("returns at least one section containing the seeded project", async () => {
const sections = await loadForProject(DEMO.projectSlug);
expect(sections.length).toBe(1);
expect(sections[0].project.slug).toBe(DEMO.projectSlug);
expect(sections[0].cards.length).toBeGreaterThan(0);
});
});
describe("/plan Gantt — render", () => {
it("renders the project name and at least one card title", async () => {
const sections = await loadForProject(DEMO.projectSlug);
const html = renderToStaticMarkup(<GanttPlanView sections={sections} />);
expect(html).toContain(sections[0].project.name);
// Pick a card title that contains no characters React will escape
// (the seeded titles use ASCII letters and spaces only).
const safeTitle =
sections[0].cards.find((c) => /^[A-Z0-9 \-]+$/.test(c.title))?.title ??
sections[0].cards[0].title.slice(0, 10);
expect(html).toContain(safeTitle);
});
});