@@ -340,4 +340,4 @@ onUnmounted(() => {
padding: 1rem; /* Optional padding for content */
}
-
\ No newline at end of file
+
diff --git a/tests/e2e/admin-pos-orders.spec.ts b/tests/e2e/admin-pos-orders.spec.ts
index adfdc203..af96f03d 100644
--- a/tests/e2e/admin-pos-orders.spec.ts
+++ b/tests/e2e/admin-pos-orders.spec.ts
@@ -2349,10 +2349,18 @@ test.describe("Admin POS Orders - desktop action menu layout", () => {
const previewContainer = dropdownContent.getByTestId("action-settings-wheel-attachment-preview");
await expect(attachmentPanel).toBeVisible();
await expect(previewContainer.locator("img, iframe")).toBeVisible();
- await expect(dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-preview-"]')).toBeVisible();
- await expect(dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-download-"]')).toBeVisible();
- await expect(dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-print-"]')).toBeVisible();
- await expect(dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-delete-"]')).toBeVisible();
+ await expect(
+ dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-preview-"]')
+ ).toBeVisible();
+ await expect(
+ dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-download-"]')
+ ).toBeVisible();
+ await expect(
+ dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-print-"]')
+ ).toBeVisible();
+ await expect(
+ dropdownContent.locator('[data-testid^="action-settings-wheel-attachment-action-delete-"]')
+ ).toBeVisible();
const [firstAttachmentRowBox, attachmentPanelBox] = await Promise.all([
firstAttachmentRow.boundingBox(),
diff --git a/tests/e2e/auth.smoke.spec.js b/tests/e2e/auth.smoke.spec.js
index 933c774f..fa369595 100644
--- a/tests/e2e/auth.smoke.spec.js
+++ b/tests/e2e/auth.smoke.spec.js
@@ -17,4 +17,17 @@ test.describe("Auth entry smoke", () => {
await expect(page.getByTestId("login-password")).toBeVisible();
await expect(page.getByTestId("login-submit")).toBeVisible();
});
+
+ test("@smoke qr login route renders without QR bootstrap import errors", async ({ page }) => {
+ const pageErrors = [];
+ page.on("pageerror", (error) => {
+ pageErrors.push(error.message);
+ });
+
+ await mockApi(page, { authenticated: false });
+ await page.goto("/login/qr");
+
+ await expect(page.getByTestId("login-qr-desktop-message")).toBeVisible();
+ expect(pageErrors.join("\n")).not.toContain("does not provide an export named 'default'");
+ });
});
diff --git a/tests/e2e/pos-flow.spec.js b/tests/e2e/pos-flow.spec.js
index 68c82d61..a1e9f9c8 100644
--- a/tests/e2e/pos-flow.spec.js
+++ b/tests/e2e/pos-flow.spec.js
@@ -1126,12 +1126,66 @@ test.describe("POS flow", () => {
await page.locator("#reg_1").fill("AB12345");
await expect(page.getByTestId("pos-step-1").getByText("Pleno Logistics").first()).toBeVisible({ timeout: 10_000 });
+ await expect(page.getByTestId("pos-desktop-vehicle-summary")).toBeVisible({ timeout: 10_000 });
+ await expect(page.getByTestId("pos-desktop-vehicle-summary")).toContainText("Tankvogn med hænger");
- await expect(page.getByText(/Sidste vask/i)).toHaveCount(0);
- await expect(page.getByRole("button", { name: /Kopier sidste vask/i })).toHaveCount(0);
+ await expect(page.getByTestId("pos-desktop-last-wash")).toHaveCount(0);
+ await expect(page.getByTestId("pos-desktop-last-wash-copy")).toHaveCount(0);
});
- test("desktop keeps customer selection mounted only once when an unlinked vehicle card is expanded", async ({
+ test("desktop renders the Sidste vask card when the selected vehicle has a last_order_id", async ({
+ page,
+ }, testInfo) => {
+ test.skip(testInfo.project.name !== "chromium-desktop", "Desktop POS step 1 is validated on chromium-desktop.");
+
+ const fixture = createPosFixture();
+ fixture.vehicles = [
+ {
+ ...fixture.vehicles[0],
+ reg: "AB12345",
+ last_order_id: 9201,
+ },
+ ];
+ fixture.orderItemsByOrderId[9201] = [
+ {
+ id: 92011,
+ order_id: 9201,
+ product_id: fixture.products[0].id,
+ product: fixture.products[0],
+ quantity: 1,
+ notes: "",
+ reference: "",
+ related_item_id: null,
+ price: fixture.products[0].price,
+ },
+ {
+ id: 92012,
+ order_id: 9201,
+ product_id: fixture.products[1].id,
+ product: fixture.products[1],
+ quantity: 1,
+ notes: "",
+ reference: "",
+ related_item_id: 92011,
+ price: fixture.products[1].price,
+ },
+ ];
+
+ await setupDesktopPosPage(page, fixture, { token: "pos-desktop-last-wash-card" });
+
+ await page.locator("#reg_1").fill("AB12345");
+
+ const vehicleSummary = page.getByTestId("pos-desktop-vehicle-summary");
+ const lastWashCard = page.getByTestId("pos-desktop-last-wash");
+
+ await expect(vehicleSummary).toBeVisible({ timeout: 10_000 });
+ await expect(lastWashCard).toBeVisible({ timeout: 10_000 });
+ await expect(lastWashCard).toContainText("Tankvogn med hænger", { timeout: 10_000 });
+ await expect(lastWashCard).toContainText("Dolly", { timeout: 10_000 });
+ await expect(page.getByTestId("pos-desktop-last-wash-copy")).toBeDisabled();
+ });
+
+ test("desktop keeps only one visible customer selector for an unlinked vehicle after the refactor", async ({
page,
}, testInfo) => {
test.skip(testInfo.project.name !== "chromium-desktop", "Desktop POS step 1 is validated on chromium-desktop.");
@@ -1155,18 +1209,14 @@ test.describe("POS flow", () => {
const visibleCustomerSearchInputs = page.locator("#pos_select_customer_input:visible");
const cardPaymentButtons = page.locator("button.customer-quick-action--card");
const visibleCardPaymentButtons = page.locator("button.customer-quick-action--card:visible");
+ const secondaryBlock = page.getByTestId("pos-desktop-secondary-block");
await expect(customerSearchInputs).toHaveCount(1);
await expect(visibleCustomerSearchInputs).toHaveCount(1);
await expect(cardPaymentButtons).toHaveCount(1);
await expect(visibleCardPaymentButtons).toHaveCount(1);
-
- await page.locator(".pos-vehicle-form__expandable .has-text-centered").click();
-
- await expect(customerSearchInputs).toHaveCount(1);
- await expect(visibleCustomerSearchInputs).toHaveCount(1);
- await expect(cardPaymentButtons).toHaveCount(1);
- await expect(visibleCardPaymentButtons).toHaveCount(1);
+ await expect(page.getByTestId("pos-desktop-vehicle-summary")).toBeVisible({ timeout: 10_000 });
+ await expect(secondaryBlock).toHaveCount(0);
});
test("desktop defaults the inline customer picker to customer invoice and keeps the selected action clear", async ({
diff --git a/tests/e2e/pos.visual.spec.js b/tests/e2e/pos.visual.spec.js
index 896f90e0..fa7b58ee 100644
--- a/tests/e2e/pos.visual.spec.js
+++ b/tests/e2e/pos.visual.spec.js
@@ -373,6 +373,11 @@ test.describe("POS visuals", () => {
await expect(page.getByTestId("pos-step-1").locator(".pos-card-tabs > .tabs li.is-active")).toContainText("Kunde");
await expectPosCardTabsDividerSpacing(page.getByTestId("pos-step-1"));
await expectCustomerTabsDividerSpacing(page.getByTestId("pos-step-1"));
+ await expect(page.getByTestId("pos-desktop-vehicle-summary")).toBeVisible();
+ await expect(page.getByTestId("pos-desktop-last-wash")).toBeVisible();
+ await expect(page.getByTestId("pos-desktop-last-wash")).toContainText("Indvendig vask Forvogn");
+ await expect(page.getByTestId("pos-desktop-secondary-block")).toBeVisible();
+ await expect(page.getByTestId("pos-desktop-last-wash-copy")).toBeDisabled();
await expect(page.getByTestId("pos-step-1")).toHaveScreenshot("pos-step-1-customer-desktop.png", {
maxDiffPixels: 2000,
});
diff --git a/tests/e2e/support/network.js b/tests/e2e/support/network.js
index 43cac25f..7dc65332 100644
--- a/tests/e2e/support/network.js
+++ b/tests/e2e/support/network.js
@@ -3320,7 +3320,9 @@ function ensureEdgeGatewayHardwareFixture(edgeGatewayFixture) {
}
function buildEdgeGatewayHardwareBindingsIndex(edgeGatewayFixture, departmentId) {
- const gateways = edgeGatewayFixture.gateways.filter((gateway) => Number(gateway.department_id) === Number(departmentId));
+ const gateways = edgeGatewayFixture.gateways.filter(
+ (gateway) => Number(gateway.department_id) === Number(departmentId)
+ );
const bindingsByRelayId = {};
gateways.forEach((gateway) => {
@@ -3420,8 +3422,7 @@ function buildEdgeGatewayHardwareDepartmentWorkspace(edgeGatewayFixture, departm
required: requiredRelayCount,
bound: boundRelayCount,
missing: Math.max(0, requiredRelayCount - boundRelayCount),
- state:
- requiredRelayCount === 0 ? "NOT_REQUIRED" : boundRelayCount === requiredRelayCount ? "READY" : "MISSING",
+ state: requiredRelayCount === 0 ? "NOT_REQUIRED" : boundRelayCount === requiredRelayCount ? "READY" : "MISSING",
},
links: {
legacy: `/superuser/department/lanes/${lane.id}`,
@@ -3478,7 +3479,10 @@ function buildEdgeGatewayHardwareDepartmentWorkspace(edgeGatewayFixture, departm
const scansByScannerId = {};
(hardware.scans || [])
.filter((scan) => Number(scan.department_id) === Number(departmentId))
- .sort((left, right) => new Date(String(right.created_at || 0)).getTime() - new Date(String(left.created_at || 0)).getTime())
+ .sort(
+ (left, right) =>
+ new Date(String(right.created_at || 0)).getTime() - new Date(String(left.created_at || 0)).getTime()
+ )
.forEach((scan) => {
const scannerId = Number(scan.plate_scanner_id || 0);
if (!scansByScannerId[scannerId]) {
@@ -3514,11 +3518,19 @@ function buildEdgeGatewayHardwareDepartmentWorkspace(edgeGatewayFixture, departm
});
const issues = [];
- const onlineGatewayCount = gatewayPayloads.filter((gateway) => String(gateway?.status || "").toUpperCase() === "ONLINE").length;
- const transportMode = String(gatewayPayloads[0]?.department_transport_mode || gateways[0]?.department_transport_mode || "cloud");
+ const onlineGatewayCount = gatewayPayloads.filter(
+ (gateway) => String(gateway?.status || "").toUpperCase() === "ONLINE"
+ ).length;
+ const transportMode = String(
+ gatewayPayloads[0]?.department_transport_mode || gateways[0]?.department_transport_mode || "cloud"
+ );
if (gatewayPayloads.length === 0) {
- issues.push({ severity: "danger", code: "NO_GATEWAY", message: "No edge gateway has been claimed for this department." });
+ issues.push({
+ severity: "danger",
+ code: "NO_GATEWAY",
+ message: "No edge gateway has been claimed for this department.",
+ });
} else if (transportMode === "gateway" && onlineGatewayCount === 0) {
issues.push({
severity: "danger",
@@ -3663,17 +3675,17 @@ function buildEdgeGatewayHardwareDepartmentWorkspace(edgeGatewayFixture, departm
});
const primaryGateway = gatewayPayloads.find((gateway) => gateway?.is_primary) || gatewayPayloads[0] || null;
- const recentScanAt = scanners
- .map((scanner) => scanner?.recent_scan_at)
- .filter(Boolean)
- .sort((left, right) => new Date(String(right || 0)).getTime() - new Date(String(left || 0)).getTime())[0] || null;
+ const recentScanAt =
+ scanners
+ .map((scanner) => scanner?.recent_scan_at)
+ .filter(Boolean)
+ .sort((left, right) => new Date(String(right || 0)).getTime() - new Date(String(left || 0)).getTime())[0] || null;
- const health =
- issues.some((issue) => issue.severity === "danger")
- ? "AT_RISK"
- : issues.length > 0
- ? "PARTIAL"
- : "READY";
+ const health = issues.some((issue) => issue.severity === "danger")
+ ? "AT_RISK"
+ : issues.length > 0
+ ? "PARTIAL"
+ : "READY";
const summary = {
department_id: department.id,
@@ -3820,7 +3832,9 @@ async function handleEdgeGatewayRoute({ route, request, parsedUrl, pathname, met
if (edgeGatewayWorkspaceDepartmentsPattern.test(pathname) && method === "GET") {
const hardware = ensureEdgeGatewayHardwareFixture(edgeGatewayFixture);
const summaries = (hardware?.departments || [])
- .map((department) => buildEdgeGatewayHardwareDepartmentWorkspace(edgeGatewayFixture, department.id, false)?.summary)
+ .map(
+ (department) => buildEdgeGatewayHardwareDepartmentWorkspace(edgeGatewayFixture, department.id, false)?.summary
+ )
.filter(Boolean)
.sort((left, right) => Number(left?.order_priority || 0) - Number(right?.order_priority || 0));
await route.fulfill(json({ data: summaries }));
@@ -3837,7 +3851,11 @@ async function handleEdgeGatewayRoute({ route, request, parsedUrl, pathname, met
if (numberPlateScannersPattern.test(pathname) && method === "GET") {
const hardware = ensureEdgeGatewayHardwareFixture(edgeGatewayFixture);
const rows = cloneJson(hardware?.scanners || []);
- const paginated = paginateRows(rows, parsedUrl.searchParams.get("page") || 1, parsedUrl.searchParams.get("limit") || 10);
+ const paginated = paginateRows(
+ rows,
+ parsedUrl.searchParams.get("page") || 1,
+ parsedUrl.searchParams.get("limit") || 10
+ );
await route.fulfill(
json({
success: true,
diff --git a/tests/e2e/userBookWash.spec.ts b/tests/e2e/userBookWash.spec.ts
index b5873ad4..a0a236c5 100644
--- a/tests/e2e/userBookWash.spec.ts
+++ b/tests/e2e/userBookWash.spec.ts
@@ -41,7 +41,9 @@ test("[BOOKINGS][User][Creation] should show interior wash products on the inter
await expect(page.getByText("Indvendig vask Forvogn")).toBeVisible();
});
-test("[BOOKINGS][User][Creation] should show desktop loading states while categories and products resolve", async ({ page }, testInfo) => {
+test("[BOOKINGS][User][Creation] should show desktop loading states while categories and products resolve", async ({
+ page,
+}, testInfo) => {
test.skip(!testInfo.project.name.toLowerCase().includes("desktop"), "Desktop only");
await prepareBookingPage(page, {
diff --git a/vite.config.js b/vite.config.js
index db68cc4c..1c211c33 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -222,14 +222,11 @@ export default defineConfig(({ mode }) => {
ignored: ['**/output/playwright/**']
}
},
- optimizeDeps: {
- disabled: 'dev',
- ...(isPlaywrightRuntime
- ? {
- entries: ['index.html']
- }
- : {})
- }
+ optimizeDeps: isPlaywrightRuntime
+ ? {
+ entries: ['index.html']
+ }
+ : undefined
}
})