181 lines
6.2 KiB
TypeScript
181 lines
6.2 KiB
TypeScript
import { expect, test, type Locator, type Page, type Response } from "@playwright/test";
|
|
import { bookingTestData } from "./fixtures";
|
|
import { mockApi, primeMockSession } from "./support/network.js";
|
|
|
|
const changeInvoiceCollectionActionRegex =
|
|
/Skift fakturasamling|Change invoice collection|Rechnungssammlung|fakturainnsamling|fakturasamling/i;
|
|
|
|
const mobileOrderCardSelector = "[data-testid^='pos-order-list-card-']";
|
|
|
|
async function primePrivilegedSession(page: Page) {
|
|
const token = "superuser-change-invoice-collection-token";
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: ["superuser", "admin", "user"],
|
|
});
|
|
await primeMockSession(page, { token });
|
|
}
|
|
|
|
const waitForOrdersListLayout = async (page: Page): Promise<"table" | "mobile" | null> => {
|
|
const table = page.locator("table");
|
|
const mobileCard = page.locator(mobileOrderCardSelector).first();
|
|
|
|
if (await table.isVisible().catch(() => false)) {
|
|
return "table";
|
|
}
|
|
|
|
if (await mobileCard.isVisible().catch(() => false)) {
|
|
return "mobile";
|
|
}
|
|
|
|
return Promise.any([
|
|
table.waitFor({ state: "visible", timeout: 15000 }).then(() => "table" as const),
|
|
mobileCard.waitFor({ state: "visible", timeout: 15000 }).then(() => "mobile" as const),
|
|
]).catch(() => null);
|
|
};
|
|
|
|
const findDesktopChangeInvoiceCollectionAction = async (page: Page): Promise<Locator | null> => {
|
|
const actionTriggers = page.locator("tbody tr .dropdown-trigger > button");
|
|
const triggerCount = await actionTriggers.count();
|
|
|
|
for (let index = 0; index < triggerCount; index += 1) {
|
|
const trigger = actionTriggers.nth(index);
|
|
|
|
if (!(await trigger.isVisible().catch(() => false))) {
|
|
continue;
|
|
}
|
|
|
|
await trigger.click();
|
|
|
|
const dropdownRoot = trigger.locator("xpath=ancestor::div[contains(@class,'dropdown')][1]");
|
|
const changeInvoiceCollectionAction = dropdownRoot.getByRole("button", {
|
|
name: changeInvoiceCollectionActionRegex,
|
|
});
|
|
|
|
if ((await changeInvoiceCollectionAction.count()) > 0) {
|
|
const visibleAction = changeInvoiceCollectionAction.first();
|
|
if (await visibleAction.isVisible().catch(() => false)) {
|
|
return visibleAction;
|
|
}
|
|
}
|
|
|
|
await page.keyboard.press("Escape");
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
const findMobileChangeInvoiceCollectionAction = async (page: Page): Promise<Locator | null> => {
|
|
const cards = page.locator(mobileOrderCardSelector);
|
|
const cardCount = await cards.count();
|
|
|
|
for (let index = 0; index < cardCount; index += 1) {
|
|
const card = cards.nth(index);
|
|
|
|
if (!(await card.isVisible().catch(() => false))) {
|
|
continue;
|
|
}
|
|
|
|
const testId = await card.getAttribute("data-testid");
|
|
const orderId = testId?.replace("pos-order-list-card-", "");
|
|
|
|
if (!orderId) {
|
|
continue;
|
|
}
|
|
|
|
const actionTrigger = page.getByTestId(`pos-order-list-actions-${orderId}`);
|
|
if (!(await actionTrigger.isVisible().catch(() => false))) {
|
|
continue;
|
|
}
|
|
|
|
await actionTrigger.click();
|
|
|
|
const actionsModal = page.getByTestId("pos-order-actions-modal");
|
|
await expect(actionsModal).toBeVisible();
|
|
|
|
const changeInvoiceCollectionAction = actionsModal.getByRole("button", {
|
|
name: changeInvoiceCollectionActionRegex,
|
|
});
|
|
|
|
if ((await changeInvoiceCollectionAction.count()) > 0) {
|
|
const visibleAction = changeInvoiceCollectionAction.first();
|
|
if (await visibleAction.isVisible().catch(() => false)) {
|
|
return visibleAction;
|
|
}
|
|
}
|
|
|
|
await actionsModal.locator("button.delete").click();
|
|
await expect(actionsModal).toBeHidden();
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
const findChangeInvoiceCollectionAction = async (page: Page, layout: "table" | "mobile") =>
|
|
layout === "mobile" ? findMobileChangeInvoiceCollectionAction(page) : findDesktopChangeInvoiceCollectionAction(page);
|
|
|
|
test.describe("POS order actions", () => {
|
|
test("change invoice collection opens picker and stays on the same page", async ({ page }) => {
|
|
await primePrivilegedSession(page);
|
|
|
|
const departmentId = bookingTestData.departmentId.toString();
|
|
const ordersResponsePromise = page
|
|
.waitForResponse(
|
|
(response: Response) =>
|
|
response.request().method() === "GET" &&
|
|
response.url().includes("/orders?") &&
|
|
response.url().includes("department_id:"),
|
|
{ timeout: 30000 }
|
|
)
|
|
.catch(() => null);
|
|
|
|
await page.goto(`/admin/${departmentId}/modules/pos/orders`);
|
|
await expect(page).toHaveURL(new RegExp(`/admin/${departmentId}/modules/pos/orders`));
|
|
|
|
const ordersResponse = await ordersResponsePromise;
|
|
test.skip(!ordersResponse, "Orders list request did not complete in time for this environment.");
|
|
|
|
const listLayout = await waitForOrdersListLayout(page);
|
|
test.skip(!listLayout, "Orders list did not render in either table or mobile-card layout.");
|
|
|
|
await page.waitForTimeout(500);
|
|
|
|
const changeInvoiceCollectionAction = await findChangeInvoiceCollectionAction(page, listLayout);
|
|
test.skip(
|
|
!changeInvoiceCollectionAction,
|
|
"No order action menu with 'Skift fakturasamling' is available for current test data/permissions."
|
|
);
|
|
if (!changeInvoiceCollectionAction) {
|
|
return;
|
|
}
|
|
|
|
await expect(changeInvoiceCollectionAction).toBeVisible();
|
|
|
|
const beforeUrl = page.url();
|
|
const newTabPromise = page.waitForEvent("popup", { timeout: 2000 }).catch(() => null);
|
|
|
|
await changeInvoiceCollectionAction.click();
|
|
|
|
const popup = await newTabPromise;
|
|
expect(popup).toBeNull();
|
|
await expect(page).toHaveURL(beforeUrl);
|
|
|
|
const pickerModal = page.locator(".swal2-container .modal-card");
|
|
await expect(
|
|
pickerModal,
|
|
"Expected invoice collection picker modal to open after clicking the action."
|
|
).toBeVisible();
|
|
|
|
const selectCheckboxes = pickerModal.locator('[data-testid^="collected-invoice-selector-"] input[type="checkbox"]');
|
|
const selectableCount = await selectCheckboxes.count();
|
|
test.skip(selectableCount === 0, "No invoice collections available for selection in test data.");
|
|
|
|
await selectCheckboxes.first().check();
|
|
|
|
await expect(page).toHaveURL(beforeUrl);
|
|
await expect(page.locator(".swal2-container, .swal2-popup")).toContainText(
|
|
/Faktura samling|fakturasamling|invoice collection/i
|
|
);
|
|
});
|
|
});
|