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]>
65 lines
2.7 KiB
TypeScript
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();
|
|
});
|
|
});
|