Resolve direct-order product reconciliation context, preserve valid selections when restricted products are activated, remove the redundant certificate request, and add focused regression coverage.
608 lines
21 KiB
JavaScript
608 lines
21 KiB
JavaScript
import { test, expect } from "@playwright/test";
|
|
import { createPosFixture, mockApi, primeMockSession } from "./support/network.js";
|
|
|
|
const POS_PERMISSIONS = [
|
|
"admin",
|
|
"department_access_12",
|
|
"delete_order",
|
|
"edit_order_items",
|
|
"get_user",
|
|
"list_customer_attributes",
|
|
"get_custom_prices_other",
|
|
];
|
|
const POS_STEP_TIMEOUT = 20_000;
|
|
|
|
function json(body, status = 200) {
|
|
return {
|
|
status,
|
|
contentType: "application/json",
|
|
body: JSON.stringify(body),
|
|
};
|
|
}
|
|
|
|
async function primeOperatorSession(page, token = "pos-customer-rules-token") {
|
|
await primeMockSession(page, { token, bootPath: "/login" });
|
|
}
|
|
|
|
async function openPosAndSelectCustomer(page, customer) {
|
|
await page.goto("/admin/12/modules/pos?step=1");
|
|
await expect(page.getByTestId("pos-step-1")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
|
|
await page.locator("#reg_1").fill("AB12345");
|
|
await page.locator("#pos_select_customer_input").fill(String(customer.customerNumber));
|
|
await expect(page.locator(".customer-drop-down-select").first()).toBeVisible();
|
|
await page.locator(".customer-drop-down-select").first().click();
|
|
await expect(page.locator(".field.has-addons input[disabled]").last()).toHaveValue(customer.name);
|
|
await expect(page.locator(".pos-selected-customer__title").filter({ hasText: customer.name }).first()).toBeVisible();
|
|
}
|
|
|
|
async function expectSameRenderedWidth(left, right, tolerance = 1) {
|
|
await expect(left).toBeVisible();
|
|
await expect(right).toBeVisible();
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
const [leftBox, rightBox] = await Promise.all([left.boundingBox(), right.boundingBox()]);
|
|
if (!leftBox || !rightBox) {
|
|
return Number.POSITIVE_INFINITY;
|
|
}
|
|
|
|
return Math.abs(leftBox.width - rightBox.width);
|
|
})
|
|
.toBeLessThanOrEqual(tolerance);
|
|
}
|
|
|
|
async function expectControlsContained(container, controls, tolerance = 1) {
|
|
await expect(container).toBeVisible();
|
|
await Promise.all(controls.map((control) => expect(control).toBeVisible()));
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
const [containerBox, ...controlBoxes] = await Promise.all([
|
|
container.boundingBox(),
|
|
...controls.map((control) => control.boundingBox()),
|
|
]);
|
|
if (!containerBox || controlBoxes.some((box) => !box)) {
|
|
return Number.POSITIVE_INFINITY;
|
|
}
|
|
|
|
const containerRight = containerBox.x + containerBox.width;
|
|
return Math.max(
|
|
...controlBoxes.flatMap((box) => [containerBox.x - box.x, box.x + box.width - containerRight]),
|
|
0
|
|
);
|
|
})
|
|
.toBeLessThanOrEqual(tolerance);
|
|
}
|
|
|
|
function buildTodayTimestamp(time = "10:00:00.000Z") {
|
|
return `${new Date().toISOString().split("T")[0]}T${time}`;
|
|
}
|
|
|
|
async function commitDesktopReg1ByBlur(page, value = "AB12345") {
|
|
const reg1Input = page.locator("#reg_1");
|
|
await reg1Input.fill(value);
|
|
await reg1Input.evaluate((element) => {
|
|
element.blur();
|
|
});
|
|
}
|
|
|
|
function getSelectedCustomerPhoneValue(page) {
|
|
return page
|
|
.locator(".pos-selected-customer__row")
|
|
.filter({ has: page.locator(".pos-selected-customer__label", { hasText: "Telefon" }) })
|
|
.first()
|
|
.locator(".pos-selected-customer__value");
|
|
}
|
|
|
|
test("rules tab reloads customer attributes when the panel becomes visible", async ({ page }, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const fixture = createPosFixture({
|
|
customerAttributesByNumber: {
|
|
12345679: [
|
|
{ id: 1, customer_number: 12345679, attribute: "invoiceAllOrdersIndividually" },
|
|
{ id: 2, customer_number: 12345679, attribute: "invoiceWithStripe" },
|
|
],
|
|
},
|
|
});
|
|
const customer = fixture.customersByNumber[12345679];
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
await primeOperatorSession(page);
|
|
|
|
await page.goto("/admin/12/modules/pos?step=1");
|
|
await expect(page.getByTestId("pos-step-1")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
|
|
await page.locator("#reg_1").fill("AB12345");
|
|
await page.locator("#pos_select_customer_input").fill(String(customer.customerNumber));
|
|
await expect(page.locator(".customer-drop-down-select").first()).toBeVisible();
|
|
await page.locator(".customer-drop-down-select").first().click();
|
|
await expect(page.locator(".field.has-addons input[disabled]").last()).toHaveValue(customer.name);
|
|
|
|
await expect(page.locator(".pos-selected-customer__title").filter({ hasText: customer.name }).first()).toBeVisible();
|
|
|
|
const rulesTab = page.locator('[data-testid="pos-customer-tab-rules"]:visible').first();
|
|
await expect(rulesTab).toBeVisible();
|
|
|
|
const customerAttributesResponse = page.waitForResponse((response) => {
|
|
return (
|
|
response.request().method() === "GET" &&
|
|
response.url().includes(`/customer/attributes?customer_number=${customer.customerNumber}`)
|
|
);
|
|
});
|
|
|
|
await rulesTab.click();
|
|
await customerAttributesResponse;
|
|
|
|
await expect(page.locator("#invoiceAllOrdersIndividually:visible")).toBeChecked();
|
|
await expect(page.locator("#invoiceWithStripe:visible")).toBeChecked();
|
|
});
|
|
|
|
test("duplicate warning moves below customer rules when rules tab is selected", async ({ page }, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const fixture = createPosFixture({
|
|
ordersById: {
|
|
54520: {
|
|
id: 54520,
|
|
customer_id: 12345679,
|
|
department_id: 12,
|
|
reference: "DUP-RULES-TAB",
|
|
po: "",
|
|
safety_seal: "",
|
|
notes: "",
|
|
reg_1: "AB12345",
|
|
reg_2: "",
|
|
reg_3: "",
|
|
invoice_collection_id: null,
|
|
booking_id: null,
|
|
completed_at: null,
|
|
closed_at: null,
|
|
created_at: buildTodayTimestamp("09:30:00.000Z"),
|
|
include_in_invoice: null,
|
|
},
|
|
},
|
|
});
|
|
const customer = fixture.customersByNumber[12345679];
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
await primeOperatorSession(page, "pos-customer-rules-duplicate-placement-token");
|
|
await openPosAndSelectCustomer(page, customer);
|
|
await commitDesktopReg1ByBlur(page);
|
|
|
|
const actionRail = page.getByTestId("pos-step-1-action-rail");
|
|
const actionRailWarning = actionRail.getByTestId("pos-desktop-duplicate-warning-inline");
|
|
await expect(actionRailWarning).toBeVisible({ timeout: 10_000 });
|
|
|
|
await page.locator('[data-testid="pos-customer-tab-rules"]:visible').first().click();
|
|
|
|
const rulesFooter = page.getByTestId("pos-customer-rules-footer");
|
|
const rulesFooterWarning = rulesFooter.getByTestId("pos-desktop-duplicate-warning-inline");
|
|
const rulesFooterNext = rulesFooter.getByTestId("pos-next-step");
|
|
await expect(rulesFooterWarning).toBeVisible({ timeout: 10_000 });
|
|
await expect(rulesFooterNext).toBeVisible({ timeout: 10_000 });
|
|
await expect(actionRail).toHaveCount(0);
|
|
|
|
const lastRuleRow = page.getByTestId("pos-customer-rule-row").last();
|
|
const lastRuleBox = await lastRuleRow.boundingBox();
|
|
const warningBox = await rulesFooterWarning.boundingBox();
|
|
const footerNextBox = await rulesFooterNext.boundingBox();
|
|
expect(lastRuleBox).not.toBeNull();
|
|
expect(warningBox).not.toBeNull();
|
|
expect(footerNextBox).not.toBeNull();
|
|
expect(warningBox.y).toBeGreaterThanOrEqual(lastRuleBox.y + lastRuleBox.height);
|
|
expect(footerNextBox.y).toBeGreaterThanOrEqual(warningBox.y + warningBox.height);
|
|
|
|
await page.locator('[data-testid="pos-customer-tab-details"]:visible').first().click();
|
|
|
|
await expect(actionRailWarning).toBeVisible({ timeout: 10_000 });
|
|
await expect(actionRail.getByTestId("pos-next-step")).toBeVisible({ timeout: 10_000 });
|
|
await expect(page.getByTestId("pos-customer-rules-footer")).toHaveCount(0);
|
|
});
|
|
|
|
test("customer details renders top-level phone object when economic customer payload is invalid", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const fixture = createPosFixture();
|
|
const customer = fixture.customersByNumber[12345679];
|
|
let usersCustomerInterceptCount = 0;
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
|
|
await page.route(/\/users\/customer(?:\?.*)?$/, async (route) => {
|
|
if (route.request().method() !== "GET") {
|
|
await route.fallback();
|
|
return;
|
|
}
|
|
usersCustomerInterceptCount += 1;
|
|
|
|
await route.fulfill(
|
|
json({
|
|
success: true,
|
|
data: {
|
|
customer_name: customer.name,
|
|
phone: {
|
|
country_code: 45,
|
|
number: 42331128,
|
|
},
|
|
economic_customer: [],
|
|
},
|
|
})
|
|
);
|
|
});
|
|
|
|
await primeOperatorSession(page);
|
|
await page.goto(`/admin/12/modules/pos?customer_id=${customer.customerNumber}&step=1`);
|
|
await expect(page.getByTestId("pos-step-1")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
await expect(page.locator(".pos-selected-customer__title").filter({ hasText: customer.name }).first()).toBeVisible();
|
|
await expect.poll(() => usersCustomerInterceptCount).toBeGreaterThan(0);
|
|
|
|
const phoneValue = getSelectedCustomerPhoneValue(page);
|
|
await expect(phoneValue).toHaveText("42331128");
|
|
await expect(phoneValue).not.toContainText("{");
|
|
await expect(phoneValue).not.toContainText("country_code");
|
|
await expect(phoneValue).not.toContainText("number");
|
|
});
|
|
|
|
test("customer details renders economic customer mobilePhone object as number only", async ({ page }, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const baseFixture = createPosFixture();
|
|
const baseCustomer = baseFixture.customersByNumber[12345679];
|
|
const fixture = createPosFixture({
|
|
customersByNumber: {
|
|
12345679: {
|
|
...baseCustomer,
|
|
mobilePhone: {
|
|
country_code: 45,
|
|
number: 42331128,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
const customer = fixture.customersByNumber[12345679];
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
|
|
await primeOperatorSession(page);
|
|
await openPosAndSelectCustomer(page, customer);
|
|
|
|
const phoneValue = getSelectedCustomerPhoneValue(page);
|
|
await expect(phoneValue).toHaveText("42331128");
|
|
await expect(phoneValue).not.toContainText("{");
|
|
await expect(phoneValue).not.toContainText("country_code");
|
|
await expect(phoneValue).not.toContainText("number");
|
|
});
|
|
|
|
test("only tankcleaning customers can only add tankcleaning products", async ({ page }, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const baseFixture = createPosFixture();
|
|
const tankCleaningProduct = {
|
|
id: 66,
|
|
name: "Tank cleaning 4 spulehoveder",
|
|
description: "Tankcleaning service",
|
|
price: 799,
|
|
subscription_allowed: true,
|
|
category: 5,
|
|
piktogram: "truck",
|
|
apply_category_discount: true,
|
|
requires_note: false,
|
|
is_wash: false,
|
|
display_in_booking_form: true,
|
|
order_priority: 1,
|
|
addons: [],
|
|
};
|
|
const fixture = createPosFixture({
|
|
customerAttributesByNumber: {
|
|
12345679: [
|
|
{
|
|
id: 1,
|
|
customer_number: 12345679,
|
|
attribute: "onlyTankCleaning",
|
|
product_restriction: {
|
|
version: 1,
|
|
disabled_product_ids: [53],
|
|
collections: [{ id: 501, name: "Legacy migration", product_ids: [53] }],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
products: [...baseFixture.products, tankCleaningProduct],
|
|
departmentCategories: [
|
|
...baseFixture.departmentCategories,
|
|
{ id: 13, department_id: 12, category: { id: 5, name: "Tankcleaning", meta: { products: [66] } } },
|
|
],
|
|
});
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
await primeOperatorSession(page, "pos-only-tankcleaning-token");
|
|
|
|
const orderItemPosts = [];
|
|
page.on("request", (request) => {
|
|
if (request.method() === "POST" && new URL(request.url()).pathname.endsWith("/order/items")) {
|
|
orderItemPosts.push(request.postDataJSON());
|
|
}
|
|
});
|
|
|
|
const customer = fixture.customersByNumber[12345679];
|
|
const customerAttributesResponse = page.waitForResponse((response) => {
|
|
return (
|
|
response.request().method() === "GET" &&
|
|
response.url().includes(`/customer/attributes?customer_number=${customer.customerNumber}`)
|
|
);
|
|
});
|
|
await openPosAndSelectCustomer(page, customer);
|
|
await customerAttributesResponse;
|
|
|
|
await page.getByTestId("pos-step-1").getByTestId("pos-next-step").click();
|
|
await expect(page.getByTestId("pos-step-2")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
|
|
const restrictedProductCard = page.getByTestId("pos-product-card-53").first();
|
|
await restrictedProductCard.click();
|
|
await expect(restrictedProductCard).not.toHaveClass(/is-selected/);
|
|
await expect(page.locator(".swal2-popup:visible")).toContainText("Produktet er ikke tilladt for denne kunde");
|
|
await page.locator(".swal2-confirm:visible").click();
|
|
await expect(page.getByTestId("pos-add-to-cart-53")).toHaveCount(0);
|
|
expect(orderItemPosts).toEqual([]);
|
|
|
|
await page.locator(".tabs li").filter({ hasText: "Tankcleaning" }).click();
|
|
await expect(page.getByTestId("pos-product-card-66").first()).toBeVisible();
|
|
await page.getByTestId("pos-product-card-66").first().click();
|
|
await expect(page.getByTestId("pos-add-to-cart-66").first()).toBeEnabled();
|
|
|
|
const addRequest = page.waitForRequest((request) => {
|
|
return request.method() === "POST" && request.url().includes("/order/items");
|
|
});
|
|
await page.getByTestId("pos-add-to-cart-66").first().click();
|
|
const request = await addRequest;
|
|
expect(request.postDataJSON().product_id).toBe(66);
|
|
expect(orderItemPosts).toHaveLength(1);
|
|
});
|
|
|
|
test("exact customer-rule configuration disables desktop add-on controls by option_id without placeholder rows", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const baseFixture = createPosFixture();
|
|
const primaryProduct = {
|
|
...baseFixture.products.find((product) => Number(product.id) === 53),
|
|
};
|
|
const addonProduct = {
|
|
...baseFixture.products.find((product) => Number(product.id) === 63),
|
|
addons: [],
|
|
};
|
|
const allowedLookalikeProduct = {
|
|
...addonProduct,
|
|
id: 64,
|
|
name: "Allowed additional-service lookalike",
|
|
};
|
|
primaryProduct.addons = [
|
|
{
|
|
id: 9001,
|
|
option_id: addonProduct.id,
|
|
name: addonProduct.name,
|
|
price: addonProduct.price,
|
|
product: addonProduct,
|
|
min: 0,
|
|
max: 1,
|
|
},
|
|
{
|
|
id: 9002,
|
|
option_id: allowedLookalikeProduct.id,
|
|
name: allowedLookalikeProduct.name,
|
|
price: allowedLookalikeProduct.price,
|
|
product: allowedLookalikeProduct,
|
|
min: 0,
|
|
max: 1,
|
|
},
|
|
];
|
|
const fixture = createPosFixture({
|
|
customerAttributesByNumber: {
|
|
12345679: [
|
|
{
|
|
id: 1,
|
|
customer_number: 12345679,
|
|
attribute: "restrictAdditionalServices",
|
|
product_restriction: {
|
|
version: 1,
|
|
disabled_product_ids: [addonProduct.id],
|
|
collections: [{ id: 502, name: "Blocked add-ons", product_ids: [addonProduct.id] }],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
products: [
|
|
primaryProduct,
|
|
addonProduct,
|
|
allowedLookalikeProduct,
|
|
...baseFixture.products.filter((product) => ![53, 63, 64].includes(Number(product.id))),
|
|
],
|
|
});
|
|
const customer = fixture.customersByNumber[12345679];
|
|
const orderItemPosts = [];
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
page.on("request", (request) => {
|
|
if (request.method() === "POST" && request.url().includes("/order/items")) {
|
|
orderItemPosts.push(request.postDataJSON());
|
|
}
|
|
});
|
|
await primeOperatorSession(page, "pos-restricted-desktop-addons-token");
|
|
|
|
const customerAttributesResponse = page.waitForResponse(
|
|
(response) =>
|
|
response.request().method() === "GET" &&
|
|
response.url().includes(`/customer/attributes?customer_number=${customer.customerNumber}`)
|
|
);
|
|
await openPosAndSelectCustomer(page, customer);
|
|
await customerAttributesResponse;
|
|
|
|
await page.getByTestId("pos-step-1").getByTestId("pos-next-step").click();
|
|
await expect(page.getByTestId("pos-step-2")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
|
|
await page.getByTestId("pos-product-card-53").first().click();
|
|
const restrictedAddonRow = page.getByTestId("pos-addon-restriction-63");
|
|
const restrictedIncreaseButton = page.getByTestId("pos-addon-63-increase");
|
|
const restrictedAddonButton = page.getByTestId("pos-addon-63-name");
|
|
const restrictedDecreaseButton = page.getByTestId("pos-addon-63-decrease");
|
|
const allowedAddonButton = page.getByTestId("pos-addon-64-name");
|
|
await expect(restrictedAddonRow).toBeVisible();
|
|
await expect(restrictedIncreaseButton).toBeDisabled();
|
|
await expect(restrictedAddonButton).toBeDisabled();
|
|
await expect(restrictedDecreaseButton).toBeDisabled();
|
|
await expect(allowedAddonButton).toBeEnabled();
|
|
await expectSameRenderedWidth(restrictedAddonButton, allowedAddonButton);
|
|
await expectControlsContained(restrictedAddonRow, [
|
|
restrictedIncreaseButton,
|
|
restrictedAddonButton,
|
|
restrictedDecreaseButton,
|
|
]);
|
|
|
|
await page.getByTestId("pos-addon-restriction-tooltip-63").hover();
|
|
await expect(page.locator(".tooltip-content:visible").last()).toContainText(
|
|
"Tilvalg er ikke tilladt for denne kunde"
|
|
);
|
|
|
|
for (const testId of ["pos-addon-63-increase", "pos-addon-63-name", "pos-addon-63-decrease"]) {
|
|
await page.getByTestId(testId).evaluate((button) => button.click());
|
|
}
|
|
expect(orderItemPosts).toEqual([]);
|
|
|
|
await allowedAddonButton.click();
|
|
|
|
await page.getByTestId("pos-add-to-cart-53").first().click();
|
|
await expect.poll(() => orderItemPosts.length, { timeout: 10_000 }).toBe(2);
|
|
expect(orderItemPosts.map((body) => Number(body.product_id))).toEqual([53, 64]);
|
|
expect(Number(orderItemPosts[1].related_item_id)).toBeGreaterThan(0);
|
|
const cartPanel = page.getByTestId("pos-step-2").getByTestId("pos-order-panel-cart");
|
|
await expect(cartPanel).not.toContainText("Ingen data");
|
|
await expect(cartPanel).not.toContainText("0 DKK");
|
|
});
|
|
|
|
test("desktop remains fail-closed when an active product rule has a malformed restriction payload", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const fixture = createPosFixture({
|
|
customerAttributesByNumber: {
|
|
12345679: [{ id: 1, customer_number: 12345679, attribute: "restrictSpotFree" }],
|
|
},
|
|
});
|
|
const customer = fixture.customersByNumber[12345679];
|
|
const orderItemPosts = [];
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
page.on("request", (request) => {
|
|
if (request.method() === "POST" && request.url().includes("/order/items")) {
|
|
orderItemPosts.push(request.postDataJSON());
|
|
}
|
|
});
|
|
await primeOperatorSession(page, "pos-malformed-customer-restrictions-token");
|
|
|
|
await openPosAndSelectCustomer(page, customer);
|
|
await page.getByTestId("pos-step-1").getByTestId("pos-next-step").click();
|
|
await expect(page.getByTestId("pos-step-2")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
await expect(page.getByTestId("pos-customer-restrictions-load-error")).toBeVisible();
|
|
|
|
const blockedProductCard = page.getByTestId("pos-product-card-53").first();
|
|
await blockedProductCard.click();
|
|
await expect(blockedProductCard).not.toHaveClass(/is-selected/);
|
|
await expect(page.locator(".swal2-popup:visible")).toContainText(/Kunderegel|Customer rule/i);
|
|
await page.locator(".swal2-confirm:visible").click();
|
|
await expect(page.locator('[data-testid^="pos-add-to-cart-"]:visible')).toHaveCount(0);
|
|
expect(orderItemPosts).toEqual([]);
|
|
});
|
|
|
|
test("desktop clears pending basket row when customer-rule create is rejected", async ({ page }, testInfo) => {
|
|
test.skip(!testInfo.project.name.includes("desktop"), "Desktop only");
|
|
|
|
const fixture = createPosFixture();
|
|
const customer = fixture.customersByNumber[12345679];
|
|
let rejectedCreateCount = 0;
|
|
|
|
await mockApi(page, {
|
|
authenticated: true,
|
|
permissions: POS_PERMISSIONS,
|
|
edgeGateways: false,
|
|
pos: fixture,
|
|
});
|
|
await page.route(/\/order\/items(?:\?.*)?$/, async (route) => {
|
|
const request = route.request();
|
|
if (request.method() !== "POST") {
|
|
await route.fallback();
|
|
return;
|
|
}
|
|
|
|
rejectedCreateCount += 1;
|
|
await route.fulfill(
|
|
json(
|
|
{
|
|
success: false,
|
|
data: {
|
|
code: "CUSTOMER_RULE_PRODUCT_RESTRICTED",
|
|
message: "This product is not allowed for the selected customer",
|
|
},
|
|
},
|
|
400
|
|
)
|
|
);
|
|
});
|
|
await primeOperatorSession(page, "pos-customer-rule-reject-token");
|
|
|
|
await openPosAndSelectCustomer(page, customer);
|
|
await page.getByTestId("pos-step-1").getByTestId("pos-next-step").click();
|
|
await expect(page.getByTestId("pos-step-2")).toBeVisible({ timeout: POS_STEP_TIMEOUT });
|
|
|
|
await page.getByTestId("pos-product-card-53").first().click();
|
|
await page.getByTestId("pos-add-to-cart-53").first().click();
|
|
|
|
await expect.poll(() => rejectedCreateCount, { timeout: 10_000 }).toBe(1);
|
|
await expect(page.getByText("Produktet blev afvist af kundereglerne og er ikke tilføjet")).toBeVisible({
|
|
timeout: 10_000,
|
|
});
|
|
const cartPanel = page.getByTestId("pos-step-2").getByTestId("pos-order-panel-cart");
|
|
await expect(cartPanel.getByTestId("pos-order-empty-state")).toBeVisible();
|
|
await expect(cartPanel.locator('[data-testid^="pos-order-item-name-"]')).toHaveCount(0);
|
|
});
|