- Introduced `.prettierrc.json` to enforce consistent code formatting across the project. - Updated unit and e2e test files to address formatting issues, improve readability, and ensure alignment with the new Prettier configuration.
535 lines
24 KiB
TypeScript
535 lines
24 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");
|
|
});
|
|
});
|