Files
PacketStation/frontend/src/screens/clerical/ProjectPage.test.tsx
T
spencermandClaude Fable 5.1 591fe90076
ci / frontend (push) Successful in 30s
ci / server (push) Successful in 4m12s
ci / image (push) Successful in 46s
ci / e2e (push) Successful in 1m24s
Phase 3: VISUAL feed and M-Files drawings in the worker
Migration 0004 (VISUAL and drawing caches, go-live ignored list, resource
map, job tables, order-derived columns with provenance; work order key
includes the operation sequence). The real worker on APScheduler with
settings re-read each fire, pause, run now, advisory locks, job_runs and a
heartbeat. The visual-feed job (five VisualKit reads, COPY and MERGE cache,
suspect-batch guard, the apply in one transaction: drafts, change orders,
retire-moved, work order gone, closed and cancelled observed, projects and
units from order links, auto-release) and the fingerprint. The drawing-lookup
job (queue, budget, download on version change, sha256 into assets, decision
table, staging for rev approval, drawing-origin change orders). Clerical From
VISUAL panel, flags, rev approval, hand uploads, change-order review; Admin
Feed settings and resource map. Synthetic fixture generator and a
fixture-driven worker in CI with a Playwright scenario. Docs updated.

Verified: 3249 server tests and 13 Playwright scenarios on the docker-1 CI
stack, 76 frontend tests, doctor at 0004; one feed and one drawing run
against VISUAL DEV and the vault from the developer machine (counts in the
changelog).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-16 14:45:38 -06:00

65 lines
2.7 KiB
TypeScript

import { fireEvent, screen, within } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import type { OrderRef, VisualOrder } from "../../api/types";
import { DEPARTMENTS, makeMe, renderApp } from "../../test/auth";
import { callsTo, mockFetch } from "../../test/fetchMock";
import { makeProject, makeUnit } from "../../test/packets";
const ORDERS: VisualOrder[] = [
{
cust_order_id: "CO-100",
status: "F",
customer_name: "Test Co",
customer_po_ref: "PO-1",
order_date: "2026-09-01",
desired_ship_date: "2026-12-01",
promise_date: null,
},
{
cust_order_id: "CO-101",
status: "F",
customer_name: "Test Co",
customer_po_ref: "PO-2",
order_date: "2026-09-15",
desired_ship_date: null,
promise_date: "2026-12-20",
},
];
const REF: OrderRef = { ...ORDERS[0]!, via: "project_open", chosen_at: "2026-10-16T08:00:00Z" };
describe("ProjectPage orders", () => {
it("lists the VISUAL orders, marks the one in use, and pins another with a reason", async () => {
const project = makeProject({ units: [makeUnit()], orders: ORDERS, order_ref: REF, order_pin: null });
const fetch = mockFetch({
"/api/auth/me": { body: makeMe() },
"/api/departments": { body: DEPARTMENTS },
"/api/projects/7": { body: project },
"PATCH /api/projects/7": { body: { ...project, order_pin: "CO-101", version: 2 } },
});
renderApp("/clerical/projects/7");
const table = await screen.findByRole("table", { name: "Orders in VISUAL" });
expect(screen.getByText("first open order", { exact: false })).toBeInTheDocument();
expect(within(table).getByText("used by the feed")).toBeInTheDocument();
fireEvent.click(within(table).getByRole("button", { name: "Pin order CO-101" }));
const ask = await screen.findByRole("dialog", { name: "Pin order CO-101" });
fireEvent.change(within(ask).getByLabelText("Reason"), { target: { value: "Second order covers this unit" } });
fireEvent.click(within(ask).getByRole("button", { name: "Pin" }));
expect(await screen.findByText("Order CO-101 pinned")).toBeInTheDocument();
expect(callsTo(fetch, "PATCH", "/api/projects/7")).toEqual([
{ set: { order_pin: "CO-101", order_pin_reason: "Second order covers this unit" }, base: { order_pin: null } },
]);
});
it("shows no orders section for a project without VISUAL orders", async () => {
mockFetch({
"/api/auth/me": { body: makeMe() },
"/api/departments": { body: DEPARTMENTS },
"/api/projects/7": { body: makeProject({ units: [makeUnit()] }) },
});
renderApp("/clerical/projects/7");
await screen.findByRole("heading", { name: "Units" });
expect(screen.queryByRole("heading", { name: "Orders in VISUAL" })).not.toBeInTheDocument();
});
});