- 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.
166 lines
5.5 KiB
TypeScript
166 lines
5.5 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { mockApi, seedAuthenticatedState } from "./support/network.js";
|
|
|
|
const adminPermissions = [
|
|
"admin",
|
|
"list_bookings",
|
|
"list_department_daily_reports",
|
|
"create_department_daily_report_complaints",
|
|
"department_access_1",
|
|
];
|
|
|
|
const json = (body: unknown, status = 200) => ({
|
|
status,
|
|
contentType: "application/json",
|
|
body: JSON.stringify(body),
|
|
});
|
|
|
|
const buildOverviewPayload = () => ({
|
|
data: {
|
|
department_ids: [1],
|
|
date: "2026-04-09",
|
|
date_to: "2026-04-09",
|
|
metrics: {
|
|
bookings: { state: "ready", value: 4, out_of: 6, message: null },
|
|
complaints: { state: "ready", value: 2, out_of: null, message: null },
|
|
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 },
|
|
},
|
|
products: [],
|
|
},
|
|
});
|
|
|
|
async function mockOverviewPageDependencies(page) {
|
|
await seedAuthenticatedState(page);
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: adminPermissions,
|
|
});
|
|
|
|
await page.route(/\/departments(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(
|
|
json({
|
|
data: [{ id: 1, name: "North" }],
|
|
})
|
|
);
|
|
});
|
|
|
|
await page.route(/\/admin\/bookings\/department\/count(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(
|
|
json({
|
|
data: {
|
|
data: {
|
|
message: 5,
|
|
},
|
|
},
|
|
})
|
|
);
|
|
});
|
|
|
|
await page.route(/\/departments\/self-serve\/enabled(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(
|
|
json({
|
|
data: {
|
|
data: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
})
|
|
);
|
|
});
|
|
|
|
await page.route(/\/departments\/weather(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(json({ data: [] }));
|
|
});
|
|
|
|
await page.route(/\/departments\/daily-reports\/get(\?.*)?$/i, async (route) => {
|
|
await route.fulfill(
|
|
json({
|
|
data: {
|
|
id: 10,
|
|
department_id: 1,
|
|
water_usage: 32,
|
|
notes: "",
|
|
filled_by: 1,
|
|
created_at: "2026-04-09 00:00:00",
|
|
},
|
|
})
|
|
);
|
|
});
|
|
|
|
await page.route(/\/departments\/daily-reports\/complaints$/i, async (route) => {
|
|
await route.fulfill(json({ data: { id: 1 } }));
|
|
});
|
|
|
|
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")) {
|
|
await route.fulfill(json(buildOverviewPayload()));
|
|
return;
|
|
}
|
|
|
|
await route.fulfill(json({ data: [] }));
|
|
});
|
|
}
|
|
|
|
test.describe("Admin overview mobile", () => {
|
|
test("keeps modules first, collapses reports by default, and preserves mobile report actions", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
test.skip(!testInfo.project.use.isMobile, "Mobile-only overview regression");
|
|
|
|
await mockOverviewPageDependencies(page);
|
|
await page.goto("/admin/1");
|
|
|
|
const modules = page.getByTestId("admin-mobile-modules");
|
|
const reportsToggle = page.getByTestId("admin-mobile-reports-toggle");
|
|
|
|
await expect(modules).toBeVisible();
|
|
await expect(reportsToggle).toBeVisible();
|
|
await expect(page.locator("[data-testid='daily-report-page']")).toHaveCount(0);
|
|
|
|
const modulesBox = await modules.boundingBox();
|
|
const reportsBox = await reportsToggle.boundingBox();
|
|
expect(modulesBox?.y ?? 0).toBeLessThan(reportsBox?.y ?? Number.MAX_SAFE_INTEGER);
|
|
expect(await page.evaluate(() => document.documentElement.scrollWidth > document.documentElement.clientWidth)).toBe(
|
|
false
|
|
);
|
|
|
|
await reportsToggle.click();
|
|
await expect(page.getByTestId("daily-report-page")).toBeVisible();
|
|
await expect(page.getByTestId("date-period-mobile-layout")).toBeVisible();
|
|
await expect(page.locator("[data-testid='daily-report-department-controls']")).toHaveCount(0);
|
|
|
|
await page.getByTestId("daily-report-mobile-departments-toggle").click();
|
|
await expect(page.getByTestId("daily-report-department-controls")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-department-all")).toBeVisible();
|
|
expect(await page.evaluate(() => document.documentElement.scrollWidth > document.documentElement.clientWidth)).toBe(
|
|
false
|
|
);
|
|
|
|
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-cancel")).toBeVisible();
|
|
await expect(page.getByTestId("daily-report-complaints-submit")).toBeVisible();
|
|
|
|
const footerFitsViewport = await page.evaluate(() => {
|
|
const footer = document.querySelector(".complaints-modal-footer__actions");
|
|
if (!(footer instanceof HTMLElement)) {
|
|
return false;
|
|
}
|
|
|
|
const rect = footer.getBoundingClientRect();
|
|
return rect.left >= 0 && rect.right <= window.innerWidth;
|
|
});
|
|
expect(footerFitsViewport).toBe(true);
|
|
|
|
await page.getByTestId("daily-report-complaints-cancel").click();
|
|
await expect(page.locator("[data-testid='daily-report-complaints-modal']")).toHaveCount(0);
|
|
});
|
|
});
|