import { expect, test } from "@playwright/test"; import { randomUUID } from "node:crypto"; for (const width of [390, 1440]) test(`received stock returns to its requirement for explicit count and match at ${width}px`, async ({ page }) => { await page.setViewportSize({ width, height: 900 }); await page.goto("/"); await page.getByLabel("Workspace password").fill("demo-password-please-change"); await page.getByRole("button", { name: "Sign in", exact: true }).click(); await expect(page.getByRole("heading", { name: "Projects", exact: true })).toBeVisible(); const id = `receipt-${randomUUID()}`, revision = `${id}-r1`; const csrf = (await page.context().cookies()).find(cookie => cookie.name === "forge_csrf")!.value; const post = async (path: string, data: object) => { const response = await page.request.post(`/api/v1${path}`, { headers: { "x-csrf-token": csrf, "idempotency-key": randomUUID() }, data }); expect(response.status(), await response.text()).toBeLessThan(300); return response.json(); }; await post("/projects/with-initial-revision", { project: { id, name: `Synthetic receipt project ${width}`, status: "planned", description: "Receipt continuity regression." }, revision: { id: revision, name: "Initial", status: "concept", fabricationRoute: "none" } }); const createdLine = await post(`/project-revisions/${revision}/bom`, { name: "Receipt connectors", requiredQuantity: 4, unit: "each", role: "consumed", optional: false, constraints: {}, alternatives: [] }); const readRequirement = async () => { const response = await page.request.get(`/api/v1/project-revisions/${revision}/bom`); expect(response.ok(), await response.text()).toBe(true); const lines = await response.json(); const line = lines.find((candidate: { id: string }) => candidate.id === createdLine.data.id); expect(line).toBeDefined(); return line; }; await page.goto(`/#/projects/${id}/offers`); await page.reload(); const row = page.locator(".sourcing-requirement"); await expect(row.getByRole("button", { name: "Match owned stock" })).toBeVisible(); await row.getByRole("button", { name: "Record quote for Receipt connectors" }).click(); await row.getByLabel("Supplier", { exact: true }).fill("Synthetic supplier"); await row.getByLabel("Supplier source URL").fill("https://supplier.example/connectors"); await row.getByLabel("Quantity per pack", { exact: true }).fill("10"); await row.getByLabel("Pack price", { exact: true }).fill("2.50"); await row.getByRole("button", { name: "Save quote" }).click(); await row.getByLabel("I checked that this quoted item meets the current requirement").check(); await row.getByRole("button", { name: "Use reviewed quote" }).click(); await row.getByRole("button", { name: "Record received stock" }).click(); const add = page.getByRole("dialog", { name: "Add to inventory", exact: true }); await expect(add.getByRole("region", { name: "Receiving for requirement" })).toContainText("Receipt connectors"); await add.getByRole("combobox", { name: "What are you adding?" }).selectOption("electronic"); await add.getByRole("button", { name: "Continue", exact: true }).click(); const form = page.getByRole("dialog"); await expect(form.getByLabel("Name", { exact: true })).toHaveValue("Receipt connectors"); await expect(form.getByLabel("Quantity received", { exact: true })).toHaveValue(""); await form.getByLabel("Quantity received", { exact: true }).fill("4"); await form.getByRole("button", { name: "Add item", exact: true }).click(); const drawer = page.getByRole("dialog", { name: /^Receipt connectors/u }); await expect(drawer.getByRole("region", { name: "Continue receiving stock" })).toContainText("Confirm its physical count above"); const requirementBeforeCount = await readRequirement(); expect(requirementBeforeCount.itemId ?? null).toBeNull(); await drawer.getByLabel("Counted quantity").fill("4"); await drawer.getByRole("button", { name: "Review physical count", exact: true }).click(); const review = page.getByRole("alertdialog", { name: "Review physical count", exact: true }); await review.getByRole("button", { name: "Confirm physical count", exact: true }).click(); await expect(review).toHaveCount(0); await expect(drawer.getByRole("status", { name: "Physical count saved", exact: true })).toContainText("Confirmed 4 pieces"); expect(await readRequirement()).toEqual(requirementBeforeCount); await expect(drawer.getByRole("region", { name: "Continue receiving stock" })).toContainText("Physical quantity recorded"); await expect(drawer.getByRole("button", { name: "Done", exact: true })).toHaveCount(0); await drawer.getByRole("button", { name: "Return to Receipt connectors", exact: true }).click(); await expect(page).toHaveURL(new RegExp(`/projects/${id}/plan$`, "u")); const edit = page.getByRole("dialog", { name: "Part details", exact: true }); await expect(edit.getByLabel("Requirement name", { exact: true })).toHaveValue("Receipt connectors"); await expect(edit.getByLabel("Required quantity", { exact: true })).toHaveValue("4"); await expect(edit.getByRole("region", { name: "Selected stock candidate", exact: true })).toContainText("Receipt connectors"); await expect(edit.getByRole("region", { name: "Selected stock candidate", exact: true })).toContainText("Selection is a planning choice, not confirmation of fit or usable stock."); await edit.getByRole("button", { name: "Choose another owned item", exact: true }).click(); await expect(edit.getByRole("button", { name: "Clear owned item selection" })).toBeVisible(); expect(await readRequirement()).toEqual(requirementBeforeCount); await edit.getByRole("button", { name: "Save requirement", exact: true }).click(); await expect(edit).toHaveCount(0); expect((await readRequirement()).itemId).toBeTruthy(); await page.getByRole("tab", { name: /^Parts/u }).click(); await expect(page.locator(".bom-row")).toContainText("Ready"); expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true); });