From 670d03d5728547dcb124fcc411b22d72d2abae87 Mon Sep 17 00:00:00 2001 From: Codex Review Integration Date: Wed, 19 Aug 2026 14:29:01 -0300 Subject: [PATCH] test(vendors): update the deactivation e2e to the confirmation flow (SH-254) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The browser smoke encoded the behaviour this ticket changes: it asserted the Deactivate button was disabled when work orders were linked. It now asserts the opposite — the work orders are listed as links, "Deactivate anyway" is enabled, and confirming sends confirmOpenWorkOrders=true. Also fixes the mock's DELETE route, whose anchored pattern stopped matching once the request carried a query string. The raced-409 case is unchanged and still preserves the vendor. --- e2e/vendors/vendors.spec.ts | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/e2e/vendors/vendors.spec.ts b/e2e/vendors/vendors.spec.ts index ad1a89e8..181711d6 100644 --- a/e2e/vendors/vendors.spec.ts +++ b/e2e/vendors/vendors.spec.ts @@ -66,6 +66,7 @@ interface MockState { createdBody?: Record; updatedBody?: Record; deletedId?: string; + deleteConfirmedOpenWorkOrders?: boolean; } async function fulfillJson(route: Route, body: unknown, status = 200) { @@ -259,8 +260,9 @@ async function mockVendorApi( }, }), ); - await page.route(/\/api\/vendors\/\d+$/, async (route) => { - const id = route.request().url().split("/").pop() ?? ""; + await page.route(/\/api\/vendors\/\d+(\?.*)?$/, async (route) => { + const requestUrl = new URL(route.request().url()); + const id = requestUrl.pathname.split("/").pop() ?? ""; if (route.request().method() === "PUT") { state.updatedBody = route.request().postDataJSON(); const vendor = vendorRecords.find((item) => String(item.Id) === id); @@ -273,6 +275,8 @@ async function mockVendorApi( return; } if (route.request().method() === "DELETE") { + state.deleteConfirmedOpenWorkOrders = + requestUrl.searchParams.get("confirmOpenWorkOrders") === "true"; if (options.deleteConflict) { await fulfillJson( route, @@ -517,20 +521,28 @@ test.describe("Vendor directory prototype parity", () => { await expect(page.getByRole("button", { name: "Close drawer" })).toHaveCount(0); }); - test("blocks deactivation for linked work orders and preserves the vendor on a raced 409", async ({ + test("confirms deactivation past linked work orders and preserves the vendor on a raced 409", async ({ page, }) => { - const blockedState = await mockVendorApi(page, { deactivationBlocked: true }); + const confirmState = await mockVendorApi(page, { deactivationBlocked: true }); await page.goto("/vendors"); await page.getByRole("button", { name: "Edit vendor Gateway Plumbing" }).click(); await page.getByRole("switch", { name: "Active status" }).click(); - const blockedDialog = page.getByRole("dialog", { name: "Deactivate Vendor" }); - await expect(blockedDialog).toContainText("WO-501 — Emergency boiler repair"); - await expect(blockedDialog.getByRole("button", { name: /^Deactivate$/ })).toBeDisabled(); - expect(blockedState.deletedId).toBeUndefined(); + const dialog = page.getByRole("dialog", { name: "Deactivate this vendor?" }); + await expect(dialog).toContainText("It still has 1 open work order"); + await expect( + dialog.getByRole("link", { name: /WO-501 — Emergency boiler repair/ }), + ).toHaveAttribute("href", "/workorders/501"); + + // SH-254: the open work orders inform the decision, they no longer block it. + const confirm = dialog.getByRole("button", { name: "Deactivate anyway" }); + await expect(confirm).toBeEnabled(); + await confirm.click(); + + await expect.poll(() => confirmState.deletedId).toBe("1"); + expect(confirmState.deleteConfirmedOpenWorkOrders).toBe(true); - await blockedDialog.getByRole("button", { name: "Cancel" }).click(); await page.unrouteAll({ behavior: "wait" }); const racedState = await mockVendorApi(page, { deleteConflict: true }); @@ -538,13 +550,13 @@ test.describe("Vendor directory prototype parity", () => { await page.getByRole("button", { name: "Edit vendor Gateway Plumbing" }).click(); await page.getByRole("switch", { name: "Active status" }).click(); await page - .getByRole("dialog", { name: "Deactivate Vendor" }) + .getByRole("dialog", { name: "Deactivate this vendor?" }) .getByRole("button", { name: /^Deactivate$/, }) .click(); - await expect(page.getByRole("dialog", { name: "Deactivate Vendor" })).toContainText( + await expect(page.getByRole("dialog", { name: "Deactivate this vendor?" })).toContainText( /open work orders|conflict/i, ); expect(racedState.deletedId).toBeUndefined();