Files
pleno-vue/tests/e2e/assign-draft-order-modal-layout.spec.ts
T

254 lines
8.5 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { API_HOST } from "./support/network.js";
import { isDesktopProject } from "./support/projects";
const json = (body: unknown, status = 200) => ({
status,
contentType: "application/json",
body: JSON.stringify(body),
});
test.describe("Assign draft order modal layout", () => {
test("keeps the close button aligned and footer actions separated", async ({ page }, testInfo) => {
test.skip(!isDesktopProject(testInfo), "Desktop only");
const pageErrors: string[] = [];
const consoleErrors: string[] = [];
page.on("pageerror", (error) => {
pageErrors.push(error.stack || error.message);
});
page.on("console", (message) => {
if (message.type() === "error") {
consoleErrors.push(message.text());
}
});
await page.route(API_HOST, async (route) => {
await route.fulfill(json({ data: [], meta: { pagination: { page: 1, per_page: 100, total: 0 } } }));
});
await page.goto("/tests/e2e/harness/assign-draft-order-customer-modal.html");
const modal = page.getByTestId("draft-order-assign-customer-modal");
await expect(modal).toBeVisible();
const [titleBox, closeBox, cancelBox, submitBox] = await Promise.all([
page.getByTestId("draft-order-assign-title").boundingBox(),
page.getByTestId("draft-order-assign-close").boundingBox(),
page.getByTestId("draft-order-assign-cancel").boundingBox(),
page.getByTestId("draft-order-assign-submit").boundingBox(),
]);
expect(titleBox).not.toBeNull();
expect(closeBox).not.toBeNull();
expect(cancelBox).not.toBeNull();
expect(submitBox).not.toBeNull();
if (!titleBox || !closeBox || !cancelBox || !submitBox) {
throw new Error("Expected modal controls to have measurable layout");
}
expect(Math.abs(closeBox.y - titleBox.y)).toBeLessThanOrEqual(12);
expect(submitBox.x - (cancelBox.x + cancelBox.width)).toBeGreaterThanOrEqual(8);
expect(pageErrors).toEqual([]);
expect(consoleErrors).toEqual([]);
});
test("shows order count and total net amount on invoice collection options", async ({ page }, testInfo) => {
test.skip(!isDesktopProject(testInfo), "Desktop only");
await page.addInitScript(() => {
window.localStorage.setItem("token", "e2e-token");
});
await page.route(API_HOST, async (route) => {
const url = route.request().url();
if (url.includes("/customers")) {
await route.fulfill(
json({
data: [
{
customerNumber: 12345679,
name: "(TEST) Pleno Vognmandsforretning",
city: "Taastrup",
},
],
meta: {
pagination: {
page: 1,
per_page: 100,
total: 1,
},
},
})
);
return;
}
if (url.includes("/collected-invoices")) {
await route.fulfill(
json({
data: [
{
id: 15559,
customer_number: 12345679,
customer_name: "(TEST) Pleno Vognmandsforretning",
created_at: "2026-04-20 11:06:18",
closed_at: null,
total_net_amount: 1562,
orders: [{ id: 1 }, { id: 2 }, { id: 3 }],
},
{
id: 15401,
customer_number: 12345679,
customer_name: "(TEST) Pleno Vognmandsforretning",
created_at: "2026-04-15 12:43:23",
closed_at: null,
total_net_amount: 840,
orders: 2,
},
],
meta: {
pagination: {
page: 1,
per_page: 100,
total: 2,
},
},
})
);
return;
}
await route.fulfill(json({ data: [], meta: { pagination: { page: 1, per_page: 100, total: 0 } } }));
});
await page.goto("/tests/e2e/harness/assign-draft-order-customer-modal.html");
await page.getByTestId("draft-order-assign-customer-search").fill("Pleno");
await page.getByTestId("draft-order-customer-option-12345679").click();
const firstSummary = page.getByTestId("draft-order-invoice-collection-summary-15559");
const secondSummary = page.getByTestId("draft-order-invoice-collection-summary-15401");
const firstMetrics = firstSummary.locator(".draft-order-assign-collection-metric");
const secondMetrics = secondSummary.locator(".draft-order-assign-collection-metric");
await expect(firstSummary).toBeVisible();
await expect(firstMetrics).toHaveCount(2);
await expect(firstMetrics.nth(0)).toContainText(/Ordrer\s*3/);
await expect(firstMetrics.nth(1)).toContainText(/1\.562,00\s*kr\./);
await expect(secondMetrics.nth(0)).toContainText(/Ordrer\s*2/);
await expect(secondMetrics.nth(1)).toContainText(/840,00\s*kr\./);
const [firstOrdersMetricBox, firstTotalMetricBox] = await Promise.all([
firstMetrics.nth(0).boundingBox(),
firstMetrics.nth(1).boundingBox(),
]);
expect(firstOrdersMetricBox).not.toBeNull();
expect(firstTotalMetricBox).not.toBeNull();
if (!firstOrdersMetricBox || !firstTotalMetricBox) {
throw new Error("Expected invoice collection metrics to have measurable layout");
}
expect(Math.abs(firstTotalMetricBox.y - firstOrdersMetricBox.y)).toBeLessThanOrEqual(4);
expect(firstTotalMetricBox.x).toBeGreaterThan(firstOrdersMetricBox.x);
});
test("keeps the modal inside the viewport and scrolls the body when the list is long", async ({ page }, testInfo) => {
test.skip(!isDesktopProject(testInfo), "Desktop only");
await page.setViewportSize({ width: 1280, height: 720 });
await page.addInitScript(() => {
window.localStorage.setItem("token", "e2e-token");
});
await page.route(API_HOST, async (route) => {
const url = route.request().url();
if (url.includes("/customers")) {
await route.fulfill(
json({
data: [
{
customerNumber: 12345679,
name: "(TEST) Pleno Vognmandsforretning",
city: "Taastrup",
},
],
meta: {
pagination: {
page: 1,
per_page: 100,
total: 1,
},
},
})
);
return;
}
if (url.includes("/collected-invoices")) {
await route.fulfill(
json({
data: Array.from({ length: 18 }, (_, index) => ({
id: 16000 - index,
customer_number: 12345679,
customer_name: "(TEST) Pleno Vognmandsforretning",
created_at: `2026-04-${String((index % 9) + 10).padStart(2, "0")} 11:06:18`,
closed_at: null,
total_net_amount: 400 + index * 125,
orders: index + 1,
})),
meta: {
pagination: {
page: 1,
per_page: 100,
total: 18,
},
},
})
);
return;
}
await route.fulfill(json({ data: [], meta: { pagination: { page: 1, per_page: 100, total: 0 } } }));
});
await page.goto("/tests/e2e/harness/assign-draft-order-customer-modal.html");
await page.getByTestId("draft-order-assign-customer-search").fill("Pleno");
await page.getByTestId("draft-order-customer-option-12345679").click();
const modalCard = page.locator(".draft-order-assign-modal");
const modalBody = page.locator(".draft-order-assign-modal .modal-card-body");
const footer = page.locator(".draft-order-assign-footer");
await expect(footer).toBeVisible();
const viewportSize = page.viewportSize();
const modalCardBox = await modalCard.boundingBox();
expect(viewportSize).not.toBeNull();
expect(modalCardBox).not.toBeNull();
if (!viewportSize || !modalCardBox) {
throw new Error("Expected viewport and modal dimensions to be available");
}
expect(modalCardBox.y).toBeGreaterThanOrEqual(0);
expect(modalCardBox.y + modalCardBox.height).toBeLessThanOrEqual(viewportSize.height - 8);
const bodyOverflow = await modalBody.evaluate((element) => ({
clientHeight: element.clientHeight,
scrollHeight: element.scrollHeight,
overflowY: window.getComputedStyle(element).overflowY,
}));
expect(bodyOverflow.overflowY).toBe("auto");
expect(bodyOverflow.scrollHeight).toBeGreaterThan(bodyOverflow.clientHeight);
});
});