- Replaced repetitive department module URL logic with `buildDepartmentModulePath` utility in `DepartmentModulesDisplay.vue`. - Enhanced layouts and responsive behavior across components, including `PosDepartmentStep1MobileTransactionHistory.vue` and `DepartmentDailyReport.vue`. - Removed unused `SuperuserInvoicingLocalStore.vue` and refactored to `SuperuserInvoicingLocalStore.ts`. - Updated media query handling and card layout adjustments in `DepartmentDailyReport.vue`. - Added new Playwright configurations (`playwright.prod.config.ts` and `playwright.live.config.ts`) for e2e release workflows. - Extended e2e and unit test coverage for mobile POS and department modules.
473 lines
23 KiB
TypeScript
473 lines
23 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { mockApi, seedAuthenticatedState } from "./support/network.js";
|
|
|
|
const adminPermissions = [
|
|
"admin",
|
|
"create_department_daily_report_complaints",
|
|
"department_access_1",
|
|
"department_access_2",
|
|
];
|
|
|
|
const json = (body: unknown, status = 200) => ({
|
|
status,
|
|
contentType: "application/json",
|
|
body: JSON.stringify(body),
|
|
});
|
|
|
|
const formatDisplayedDate = (isoDate: string) => {
|
|
const [year, month, day] = isoDate.split("-");
|
|
return `${day}/${month}/${year}`;
|
|
};
|
|
|
|
const buildOverviewPayload = ({
|
|
complaintsState = "ready",
|
|
complaintsValue = 2,
|
|
complaintsMessage = null,
|
|
metrics = {},
|
|
products = [
|
|
{ product_id: 24, slug: "spot-free-lastbil", title: "Spot Free (Lastbil)", state: "ready", value: 3, out_of: 8 },
|
|
{ product_id: 25, slug: "faelg-flex", title: "Fælg flex pr. enhed", state: "ready", value: 2, out_of: 8 },
|
|
{ product_id: 27, slug: "extraordinary-10-min", title: "Ekstraordinær pr. 10 min inkl. kemi", state: "ready", value: 1, out_of: 8 },
|
|
{ product_id: 26, slug: "hoejglans", title: "Højglans - Voksforsegling pr. enhed", state: "ready", value: 4, out_of: 8 },
|
|
{ product_id: 21, slug: "undervognsskyl", title: "Undervognsskyl pr. enhed", state: "ready", value: 2, out_of: 8 },
|
|
{ product_id: 22, slug: "double-duty-kemi", title: "Tillæg for Specialsæbe - DD", state: "ready", value: 5, out_of: 8 },
|
|
],
|
|
...overrides
|
|
}: Record<string, unknown> = {}) => ({
|
|
data: {
|
|
department_ids: [1],
|
|
date: "2026-03-23",
|
|
date_to: "2026-03-23",
|
|
metrics: {
|
|
bookings: { state: "ready", value: 4, out_of: 6, message: null },
|
|
complaints: {
|
|
state: complaintsState,
|
|
value: complaintsState === "ready" ? complaintsValue : null,
|
|
out_of: null,
|
|
message: complaintsMessage,
|
|
},
|
|
night_washes: { state: "ready", value: 1, out_of: null, message: null },
|
|
revenue: { state: "ready", value: 2400, out_of: null, message: null },
|
|
washes: { state: "ready", value: 8, out_of: null, message: null },
|
|
products_sold: { state: "ready", value: 19, out_of: null, message: null },
|
|
transactions: { state: "ready", value: 11, out_of: null, message: null },
|
|
water_usage: { state: "ready", value: 32, out_of: null, message: null },
|
|
overtime: { state: "ready", value: 1.5, out_of: null, message: null },
|
|
...metrics,
|
|
},
|
|
products,
|
|
...overrides,
|
|
},
|
|
});
|
|
|
|
async function mockDailyReportDependencies(
|
|
page,
|
|
input: {
|
|
overviewHandler: (url: URL) => Promise<ReturnType<typeof json>> | ReturnType<typeof json>;
|
|
complaintHandler?: (body: Record<string, unknown>) => Promise<ReturnType<typeof json>> | ReturnType<typeof json>;
|
|
complaintCustomerLookupHandler?: (url: URL) => Promise<ReturnType<typeof json>> | ReturnType<typeof json>;
|
|
permissions?: string[];
|
|
} | ((url: URL) => Promise<ReturnType<typeof json>> | ReturnType<typeof json>)
|
|
) {
|
|
const options = typeof input === "function" ? { overviewHandler: input } : input;
|
|
const complaintHandler = options.complaintHandler || (async (body) => json({
|
|
data: {
|
|
id: 99,
|
|
department_id: body.department_id,
|
|
customer_number: body.customer_number ?? null,
|
|
wash_date: body.wash_date ?? null,
|
|
category: body.category ?? null,
|
|
description: body.description,
|
|
created_by: 1,
|
|
created_at: "2026-04-08 10:00:00",
|
|
},
|
|
}));
|
|
const complaintCustomerLookupHandler = options.complaintCustomerLookupHandler || (async () => json({ data: [] }));
|
|
|
|
await seedAuthenticatedState(page);
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: options.permissions || adminPermissions,
|
|
});
|
|
|
|
await page.route(/\/departments(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(json({
|
|
data: [
|
|
{ id: 1, name: "North" },
|
|
{ id: 2, name: "South" },
|
|
],
|
|
}));
|
|
});
|
|
|
|
await page.route(/\/departments\/weather(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(json({ data: [] }));
|
|
});
|
|
|
|
await page.route(/\/departments\/daily-reports\/get(\?.*)?$/i, async (route) => {
|
|
const url = new URL(route.request().url());
|
|
const date = url.searchParams.get("date") || "2026-03-23";
|
|
await route.fulfill(json({
|
|
data: {
|
|
id: 10,
|
|
department_id: 1,
|
|
water_usage: 32,
|
|
notes: "",
|
|
filled_by: 1,
|
|
created_at: `${date} 00:00:00`,
|
|
},
|
|
}));
|
|
});
|
|
|
|
await page.route(/\/departments\/daily-reports\/complaints$/i, async (route) => {
|
|
const body = route.request().postDataJSON() as Record<string, unknown>;
|
|
const response = await complaintHandler(body);
|
|
await route.fulfill(response);
|
|
});
|
|
|
|
await page.route(/\/departments\/daily-reports\/complaints\/customers(\?.*)?$/i, async (route) => {
|
|
const url = new URL(route.request().url());
|
|
const response = await complaintCustomerLookupHandler(url);
|
|
await route.fulfill(response);
|
|
});
|
|
|
|
await page.route(/\/departments\/daily-reports(?:\/overview)?(\?.*)?$/i, async (route) => {
|
|
const url = new URL(route.request().url());
|
|
if (url.pathname.endsWith("/departments/daily-reports/overview")) {
|
|
const response = await options.overviewHandler(url);
|
|
await route.fulfill(response);
|
|
return;
|
|
}
|
|
|
|
await route.fulfill(json({ data: [] }));
|
|
});
|
|
}
|
|
|
|
async function expandDepartmentFiltersOnMobile(page, testInfo) {
|
|
if (!testInfo.project.use.isMobile) {
|
|
return;
|
|
}
|
|
|
|
if (await page.getByTestId("daily-report-department-controls").count()) {
|
|
return;
|
|
}
|
|
|
|
await page.getByTestId("daily-report-mobile-departments-toggle").click();
|
|
await expect(page.getByTestId("daily-report-department-controls")).toBeVisible();
|
|
}
|
|
|
|
test.describe("Admin daily report", () => {
|
|
test("renders every daily report tile from the overview payload", async ({ page }) => {
|
|
await mockDailyReportDependencies(page, async () => json(buildOverviewPayload()));
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
await expect(page.locator("[data-testid^='daily-report-tile-']")).toHaveCount(17);
|
|
await expect(page.getByTestId("daily-report-tile-bookings")).toContainText("4");
|
|
await expect(page.getByTestId("daily-report-tile-complaints")).toContainText("2");
|
|
await expect(page.getByTestId("daily-report-complaints-add-button")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-tile-night-washes")).toContainText("1");
|
|
await expect(page.getByTestId("daily-report-tile-overtime")).toContainText("1,5");
|
|
await expect(page.getByTestId("daily-report-tile-spot-free-lastbil")).toContainText("Spot Free (Lastbil)");
|
|
await expect(page.getByTestId("daily-report-tile-spot-free-lastbil")).toContainText("3");
|
|
await expect(page.getByTestId("daily-report-tile-faelg-flex")).toContainText("Fælg flex pr. enhed");
|
|
await expect(page.getByTestId("daily-report-tile-extraordinary-10-min")).toContainText("Ekstraordinær pr. 10 min inkl. kemi");
|
|
await expect(page.getByTestId("daily-report-tile-hoejglans")).toContainText("Højglans - Voksforsegling pr. enhed");
|
|
await expect(page.getByTestId("daily-report-tile-undervognsskyl")).toContainText("Undervognsskyl pr. enhed");
|
|
await expect(page.getByTestId("daily-report-tile-double-duty-kemi")).toContainText("Tillæg for Specialsæbe - DD");
|
|
});
|
|
|
|
test("opens and closes the complaints modal, requires wash date/category on multi-day ranges, clears a selected customer, submits without customer number, and refreshes the count", async ({ page }) => {
|
|
const complaintRequests: Array<Record<string, unknown>> = [];
|
|
let complaintCount = 2;
|
|
|
|
await mockDailyReportDependencies(page, {
|
|
overviewHandler: async () => json(buildOverviewPayload({ complaintsValue: complaintCount })),
|
|
complaintHandler: async (body) => {
|
|
complaintRequests.push(body);
|
|
complaintCount = 3;
|
|
return json({
|
|
data: {
|
|
id: 501,
|
|
department_id: body.department_id,
|
|
customer_number: null,
|
|
wash_date: body.wash_date,
|
|
category: body.category,
|
|
description: body.description,
|
|
created_by: 1,
|
|
created_at: "2026-04-08 10:00:00",
|
|
},
|
|
});
|
|
},
|
|
complaintCustomerLookupHandler: async () => json({
|
|
data: [
|
|
{ customer_number: 12345, customer_name: "Acme Transport" },
|
|
],
|
|
}),
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-24");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-tile-complaints")).toContainText("2");
|
|
|
|
const washDateInput = page.getByTestId("daily-report-complaints-wash-date-input");
|
|
await page.getByTestId("daily-report-complaints-add-button").click();
|
|
await expect(page.getByTestId("daily-report-complaints-modal")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-complaints-department-select")).toHaveValue("1");
|
|
await expect(washDateInput).toHaveValue("");
|
|
await expect(page.getByTestId("daily-report-complaints-date-note")).toContainText("konkrete vask");
|
|
|
|
await page.getByTestId("daily-report-complaints-cancel").click();
|
|
await expect(page.getByTestId("daily-report-complaints-modal")).toHaveCount(0);
|
|
|
|
await page.getByTestId("daily-report-complaints-add-button").click();
|
|
await page.getByTestId("daily-report-complaints-customer-search-input").fill("ac");
|
|
await expect(page.getByTestId("daily-report-complaints-customer-option-12345")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-complaints-description-textarea")).toBeVisible();
|
|
await page.getByTestId("daily-report-complaints-customer-option-12345").click();
|
|
await expect(page.getByTestId("daily-report-complaints-customer-selected")).toHaveValue("Acme Transport - 12345");
|
|
await page.getByTestId("daily-report-complaints-customer-clear").click();
|
|
await expect(page.getByTestId("daily-report-complaints-customer-search-input")).toBeVisible();
|
|
await page.getByTestId("daily-report-complaints-submit").click();
|
|
await expect(page.getByTestId("daily-report-complaints-validation-error")).toContainText("Dato for vask");
|
|
await washDateInput.fill("24/03/2026");
|
|
await washDateInput.press("Tab");
|
|
await expect(washDateInput).toHaveValue("24/03/2026");
|
|
await page.getByTestId("daily-report-complaints-submit").click();
|
|
await expect(page.getByTestId("daily-report-complaints-validation-error")).toContainText("Kategori");
|
|
await page.getByTestId("daily-report-complaints-category-select").selectOption("service");
|
|
await page.getByTestId("daily-report-complaints-description-textarea").fill("Delayed service response");
|
|
await page.getByTestId("daily-report-complaints-submit").click();
|
|
|
|
await expect.poll(() => complaintRequests.length).toBe(1);
|
|
expect(complaintRequests[0]).toEqual({
|
|
department_id: 1,
|
|
wash_date: "2026-03-24",
|
|
category: "service",
|
|
description: "Delayed service response",
|
|
});
|
|
await expect(page.getByTestId("daily-report-tile-complaints")).toContainText("3");
|
|
await expect(page.getByTestId("daily-report-complaints-modal")).toHaveCount(0);
|
|
});
|
|
|
|
test("submits complaints with an optional customer selected from search", async ({ page }) => {
|
|
const complaintRequests: Array<Record<string, unknown>> = [];
|
|
const customerLookupQueries: string[] = [];
|
|
|
|
await mockDailyReportDependencies(page, {
|
|
overviewHandler: async () => json(buildOverviewPayload({ complaintsValue: 2 })),
|
|
complaintHandler: async (body) => {
|
|
complaintRequests.push(body);
|
|
return json({
|
|
data: {
|
|
id: 502,
|
|
department_id: body.department_id,
|
|
customer_number: body.customer_number,
|
|
wash_date: body.wash_date,
|
|
category: body.category,
|
|
description: body.description,
|
|
created_by: 1,
|
|
created_at: "2026-04-08 10:10:00",
|
|
},
|
|
});
|
|
},
|
|
complaintCustomerLookupHandler: async (url) => {
|
|
customerLookupQueries.push(url.searchParams.get("search") || "");
|
|
return json({
|
|
data: [
|
|
{ customer_number: 12345, customer_name: "Acme Transport" },
|
|
],
|
|
});
|
|
},
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
|
|
const washDateInput = page.getByTestId("daily-report-complaints-wash-date-input");
|
|
await page.getByTestId("daily-report-complaints-add-button").click();
|
|
await expect(washDateInput).toHaveValue(formatDisplayedDate("2026-03-23"));
|
|
await expect(page.locator('[data-testid="daily-report-complaints-date-note"]')).toHaveCount(0);
|
|
await page.getByTestId("daily-report-complaints-customer-search-input").fill("ac");
|
|
await expect(page.getByTestId("daily-report-complaints-customer-option-12345")).toBeVisible();
|
|
await page.getByTestId("daily-report-complaints-customer-option-12345").click();
|
|
await expect(page.getByTestId("daily-report-complaints-customer-selected")).toHaveValue("Acme Transport - 12345");
|
|
await page.getByTestId("daily-report-complaints-category-select").selectOption("wash_quality");
|
|
await page.getByTestId("daily-report-complaints-description-textarea").fill("Customer-linked complaint");
|
|
await page.getByTestId("daily-report-complaints-submit").click();
|
|
|
|
await expect.poll(() => complaintRequests.length).toBe(1);
|
|
expect(customerLookupQueries).toContain("ac");
|
|
expect(complaintRequests[0]).toEqual({
|
|
department_id: 1,
|
|
customer_number: 12345,
|
|
wash_date: "2026-03-23",
|
|
category: "wash_quality",
|
|
description: "Customer-linked complaint",
|
|
});
|
|
});
|
|
|
|
test("blocks complaint submission when search text is typed without selecting a customer", async ({ page }) => {
|
|
const complaintRequests: Array<Record<string, unknown>> = [];
|
|
|
|
await mockDailyReportDependencies(page, {
|
|
overviewHandler: async () => json(buildOverviewPayload({ complaintsValue: 2 })),
|
|
complaintHandler: async (body) => {
|
|
complaintRequests.push(body);
|
|
return json({ data: body });
|
|
},
|
|
complaintCustomerLookupHandler: async () => json({ data: [] }),
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
|
|
await page.getByTestId("daily-report-complaints-add-button").click();
|
|
await page.getByTestId("daily-report-complaints-customer-search-input").fill("12345");
|
|
await expect(page.getByTestId("daily-report-complaints-customer-no-results")).toBeVisible();
|
|
await page.getByTestId("daily-report-complaints-category-select").selectOption("service");
|
|
await page.getByTestId("daily-report-complaints-description-textarea").fill("Customer lookup not selected");
|
|
await page.getByTestId("daily-report-complaints-submit").click();
|
|
|
|
await expect(page.getByTestId("daily-report-complaints-validation-error")).toContainText("Vaelg en kunde");
|
|
expect(complaintRequests).toHaveLength(0);
|
|
});
|
|
|
|
test("keeps the complaints modal open and shows an API error when submission fails", async ({ page }) => {
|
|
await mockDailyReportDependencies(page, {
|
|
overviewHandler: async () => json(buildOverviewPayload({ complaintsValue: 2 })),
|
|
complaintHandler: async () => json({ message: "Customer not found" }, 400),
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
|
|
await page.getByTestId("daily-report-complaints-add-button").click();
|
|
await page.getByTestId("daily-report-complaints-category-select").selectOption("service");
|
|
await page.getByTestId("daily-report-complaints-description-textarea").fill("Broken mirror");
|
|
await page.getByTestId("daily-report-complaints-submit").click();
|
|
|
|
await expect(page.getByTestId("daily-report-complaints-modal")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-complaints-error")).toContainText("Customer not found");
|
|
});
|
|
|
|
test("hides the complaints plus action without create permission", async ({ page }) => {
|
|
await mockDailyReportDependencies(page, {
|
|
overviewHandler: async () => json(buildOverviewPayload({ complaintsValue: 2 })),
|
|
permissions: adminPermissions.filter((permission) => permission !== "create_department_daily_report_complaints"),
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
await expect(page.locator('[data-testid="daily-report-complaints-add-button"]')).toHaveCount(0);
|
|
});
|
|
|
|
test("falls back to local optional product names when the overview payload omits titles", async ({ page }) => {
|
|
await mockDailyReportDependencies(page, async () => json(buildOverviewPayload({
|
|
products: [
|
|
{ product_id: 24, slug: "spot-free-lastbil", title: "", state: "ready", value: 3, out_of: 8 },
|
|
{ product_id: 25, slug: "faelg-flex", title: null, state: "ready", value: 2, out_of: 8 },
|
|
{ product_id: 27, slug: "extraordinary-10-min", state: "ready", value: 1, out_of: 8 },
|
|
{ product_id: 26, slug: "hoejglans", title: " ", state: "ready", value: 4, out_of: 8 },
|
|
],
|
|
})));
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-tile-spot-free-lastbil")).toContainText("Spot Free (Lastbil)");
|
|
await expect(page.getByTestId("daily-report-tile-faelg-flex")).toContainText("Fælg flex pr. enhed");
|
|
await expect(page.getByTestId("daily-report-tile-extraordinary-10-min")).toContainText("Ekstraordinær pr. 10 min inkl. kemi");
|
|
await expect(page.getByTestId("daily-report-tile-hoejglans")).toContainText("Højglans - Voksforsegling pr. enhed");
|
|
await expect(page.getByTestId("daily-report-tile-undervognsskyl")).toContainText("Undervognsskyl pr. enhed");
|
|
await expect(page.getByTestId("daily-report-tile-double-duty-kemi")).toContainText("Tillæg for Specialsæbe - DD");
|
|
});
|
|
|
|
test("updates departments and date query params with one overview request per UI action", async ({ page }, testInfo) => {
|
|
const overviewRequests: URL[] = [];
|
|
|
|
await mockDailyReportDependencies(page, async (url) => {
|
|
overviewRequests.push(url);
|
|
return json(buildOverviewPayload({
|
|
department_ids: (url.searchParams.get("department_ids") || "1").split(",").map((value) => Number(value)),
|
|
date_to: url.searchParams.get("date_to") || "2026-03-23",
|
|
}));
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
await expect.poll(() => overviewRequests.length).toBe(1);
|
|
await expandDepartmentFiltersOnMobile(page, testInfo);
|
|
|
|
await page.getByTestId("daily-report-department-2").click();
|
|
|
|
await expect.poll(() => overviewRequests.length).toBe(2);
|
|
expect(overviewRequests.at(-1)?.searchParams.get("department_ids")).toBe("1,2");
|
|
await expect(page).toHaveURL(/departmentIds=1%2C2|departmentIds=1,2/);
|
|
|
|
const endDateInput = page.getByTestId("daily-report-date-controls").locator("input[type='date']:visible").nth(1);
|
|
await endDateInput.fill("2026-03-24");
|
|
await endDateInput.blur();
|
|
|
|
await expect.poll(() => overviewRequests.length).toBe(3);
|
|
expect(overviewRequests.at(-1)?.searchParams.get("date_to")).toBe("2026-03-24");
|
|
await expect(page).toHaveURL(/dateTo=2026-03-24/);
|
|
});
|
|
|
|
test("ignores stale overview responses and keeps unavailable overtime fallback visible", async ({ page }) => {
|
|
const overviewRequests: URL[] = [];
|
|
|
|
await mockDailyReportDependencies(page, async (url) => {
|
|
overviewRequests.push(url);
|
|
const dateTo = url.searchParams.get("date_to") || "2026-03-23";
|
|
|
|
if (dateTo === "2026-03-23") {
|
|
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
return json(buildOverviewPayload({
|
|
metrics: {
|
|
bookings: { state: "ready", value: 1, out_of: 2, message: null },
|
|
complaints: { state: "unavailable", value: null, out_of: null, message: "Kundeklager er ikke tilgængelig endnu." },
|
|
night_washes: { state: "ready", value: 0, out_of: null, message: null },
|
|
revenue: { state: "ready", value: 100, out_of: null, message: null },
|
|
washes: { state: "ready", value: 1, out_of: null, message: null },
|
|
products_sold: { state: "ready", value: 2, out_of: null, message: null },
|
|
transactions: { state: "ready", value: 1, out_of: null, message: null },
|
|
water_usage: { state: "ready", value: 3, out_of: null, message: null },
|
|
overtime: { state: "ready", value: 0.25, out_of: null, message: null },
|
|
},
|
|
}));
|
|
}
|
|
|
|
return json(buildOverviewPayload({
|
|
date_to: "2026-03-24",
|
|
metrics: {
|
|
bookings: { state: "ready", value: 6, out_of: 9, message: null },
|
|
complaints: { state: "unavailable", value: null, out_of: null, message: "Kundeklager er ikke tilgængelig endnu." },
|
|
night_washes: { state: "ready", value: 3, out_of: null, message: null },
|
|
revenue: { state: "ready", value: 3200, out_of: null, message: null },
|
|
washes: { state: "ready", value: 10, out_of: null, message: null },
|
|
products_sold: { state: "ready", value: 20, out_of: null, message: null },
|
|
transactions: { state: "ready", value: 9, out_of: null, message: null },
|
|
water_usage: { state: "ready", value: 40, out_of: null, message: null },
|
|
overtime: { state: "unavailable", value: null, out_of: null, message: "Overarbejde kræver Workfeed-kobling." },
|
|
},
|
|
}));
|
|
});
|
|
|
|
await page.goto("/admin/1/modules/daily-report?departmentIds=1&dateFrom=2026-03-23&dateTo=2026-03-23");
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
|
|
const endDateInput = page.getByTestId("daily-report-date-controls").locator("input[type='date']:visible").nth(1);
|
|
await endDateInput.fill("2026-03-24");
|
|
await endDateInput.blur();
|
|
|
|
await expect.poll(() => overviewRequests.length).toBe(2);
|
|
expect(overviewRequests.at(-1)?.searchParams.get("date_to")).toBe("2026-03-24");
|
|
await expect(page).toHaveURL(/dateTo=2026-03-24/);
|
|
await expect(page.getByTestId("daily-report-tile-transactions")).toContainText("9", { timeout: 10000 });
|
|
await expect(page.getByTestId("daily-report-tile-night-washes")).toContainText("3");
|
|
await expect(page.getByTestId("daily-report-tile-overtime")).toContainText("Ikke tilgængelig");
|
|
await expect(page.getByTestId("daily-report-tile-overtime")).toContainText("Workfeed");
|
|
});
|
|
});
|