pelagia-portal/App/tests/e2e/approvals-edit-highlight.spec.ts

155 lines
5.5 KiB
TypeScript

/**
* User stories covered: Feature 21 — Edit highlight on resubmitted PO
* - When a MANAGER reviews a PO that was resubmitted after edits were requested,
* changed fields are visually highlighted (ring-, border-warning, bg-warning, etc.)
*
* Implementation context (po-detail.tsx):
* - The `resubmitSnapshot` is stored in the SUBMITTED action's metadata when
* a submitter resubmits after EDITS_REQUESTED.
* - po-detail.tsx uses `originalLineItems` and renders a diff label.
* - Changed line items get strikethrough styling (old values) and bold new values.
* - Header fields (vessel, vendor, etc.) use a ring/border highlight when changed.
*
* To drive this flow:
* 1. Tech submits PO
* 2. Manager requests edits (with a note)
* 3. Tech edits the PO and resubmits
* 4. Manager reviews — changed fields should be highlighted
*
* Created: 2026-05-17
*/
import { test, expect, type BrowserContext } from "@playwright/test";
import { fillFirstLineItem, fillPoHeader, login, USERS } from "./helpers/login";
async function driveEditHighlightFlow(
page: import("@playwright/test").Page,
context: BrowserContext,
title: string
): Promise<string> {
// Step 1: Submit as tech
await login(page, USERS.TECH);
await page.goto("/po/new");
await fillPoHeader(page, title);
await fillFirstLineItem(page, {
name: "Original item",
quantity: "2",
unitPrice: "150",
});
await page.getByRole("button", { name: /submit for approval/i }).click();
await expect(page).toHaveURL(/\/po\//, { timeout: 15_000 });
const poUrl = page.url();
const poId = poUrl.split("/po/")[1].replace(/\/$/, "");
// Step 2: Manager requests edits
await context.clearCookies();
await login(page, USERS.MANAGER);
await page.goto(poUrl);
await page.getByRole("button", { name: /request edits/i }).click();
const noteInput = page.getByPlaceholder(/reason|note/i).first();
await noteInput.fill("Please update the quantity");
await page.getByRole("button", { name: /request edits/i }).last().click();
await expect(page.getByText(/edits requested/i)).toBeVisible({ timeout: 10_000 });
// Step 3: Tech edits and resubmits
await context.clearCookies();
await login(page, USERS.TECH);
await page.goto(poUrl);
await page.getByRole("link", { name: /edit/i }).click();
await expect(page).toHaveURL(/\/edit$/, { timeout: 10_000 });
// Change the quantity
const qtyInput = page.getByRole("spinbutton").first();
await qtyInput.click({ clickCount: 3 });
await qtyInput.fill("5");
await page.getByRole("button", { name: /resubmit|update/i }).click();
await expect(page).toHaveURL(/\/po\//, { timeout: 15_000 });
// Step 4: Manager should now see highlighted changes
await context.clearCookies();
await login(page, USERS.MANAGER);
// PO should now be in MGR_REVIEW again — navigate to the approval detail page
return `/approvals/${poId}`;
}
test.describe("Feature 21 — Edit highlights on resubmitted PO", () => {
test("US-21a: manager sees a diff indicator when a PO has been resubmitted after edits", async ({
page,
context,
}: {
page: import("@playwright/test").Page;
context: BrowserContext;
}) => {
let approvalUrl: string;
try {
approvalUrl = await driveEditHighlightFlow(
page,
context,
`E2E_EDITHIGHLIGHT_${Date.now()}`
);
} catch (err) {
test.skip(true, `Could not drive edit highlight flow: ${(err as Error).message}`);
return;
}
await page.goto(approvalUrl);
await page.waitForLoadState("networkidle");
// The approval detail page should display the PO detail with diff information.
// po-detail.tsx shows: "Submitter updated these line items after edits were requested."
// along with strikethrough on old values.
const diffLabel = page.getByText(
/submitter updated|edits were requested|previous values/i
);
const strikethrough = page.locator("s, del, [class*='line-through']");
const hasDiffLabel = await diffLabel.isVisible();
const hasStrikethrough = (await strikethrough.count()) > 0;
expect(hasDiffLabel || hasStrikethrough).toBeTruthy();
console.log(
hasDiffLabel
? "✓ Diff label visible (submitter updated line items after edits)"
: "✓ Strikethrough on changed line items visible"
);
});
test("US-21a: resubmitted PO shows at least one highlight or diff indicator", async ({
page,
context,
}: {
page: import("@playwright/test").Page;
context: BrowserContext;
}) => {
let approvalUrl: string;
try {
approvalUrl = await driveEditHighlightFlow(
page,
context,
`E2E_EDITHI2_${Date.now()}`
);
} catch (err) {
test.skip(true, `Could not drive edit highlight flow: ${(err as Error).message}`);
return;
}
await page.goto(approvalUrl);
await page.waitForLoadState("networkidle");
// Look for any visual highlighting: ring-*, border-warning, bg-warning,
// bg-yellow-*, strikethrough text, or the diff description paragraph
const highlights = page.locator(
"[class*='ring-'], [class*='border-warning'], [class*='bg-warning'], [class*='bg-yellow'], s, del, [class*='line-through']"
);
const diffText = page.getByText(/edits were requested|updated.*line items|previous values/i);
const highlightCount = await highlights.count();
const hasDiffText = await diffText.isVisible();
expect(highlightCount > 0 || hasDiffText).toBeTruthy();
console.log(
`✓ Found ${highlightCount} highlight element(s) and diff text: ${hasDiffText}`
);
});
});