Files
pleno-vue/tests/unit/customer-rule-tooltip.spec.js
T

220 lines
6.8 KiB
JavaScript

// @vitest-environment jsdom
import { flushPromises, mount } from "@vue/test-utils";
import { afterEach, describe, expect, it, vi } from "vitest";
const loadCatalogMock = vi.hoisted(() => vi.fn());
vi.mock("@/features/customer/customerRuleProductCatalog.js", () => ({
loadCustomerRuleProductCatalog: loadCatalogMock,
}));
import CustomerRuleTooltip from "@/features/customer/CustomerRuleTooltip.vue";
import { createTestI18n } from "./helpers/mountWithApp.js";
const BTooltipStub = {
name: "BTooltip",
props: {
active: {
type: Boolean,
default: false,
},
contentClass: {
type: String,
default: "",
},
},
template: `
<span class="b-tooltip-stub" :data-active="active ? 'true' : 'false'">
<slot />
<span class="b-tooltip-stub__content" :class="contentClass" v-show="active"><slot name="content" /></span>
</span>
`,
};
const messages = {
en: {
customer_rules: {
attributes: {
onlyTankCleaning: {
description: "Allows only tank cleaning services.",
},
restrictAdditionalServices: {
description: "Blocks additional services.",
},
restrictSpotFree: {
description: "Blocks spot-free rinse services.",
},
},
tooltip: {
available_if_enabled: "Would remain available if enabled",
available_while_enabled: "Available while active",
blocked_if_enabled: "Would be blocked if enabled",
blocked_now: "Blocked while active",
changes: "Changes",
groups: {
primary_products: "Primary products",
related_addons: "Related add-ons",
standalone_additional_services: "Standalone additional services",
},
load_failed: "Could not load affected products.",
loading_products: "Loading affected products...",
no_affected_products: "No affected products found in the current product catalog.",
},
},
},
};
function mountTooltip(props = {}) {
return mount(CustomerRuleTooltip, {
props: {
testId: "rule-tooltip",
...props,
},
slots: {
default: "<span>Rule label</span>",
},
global: {
plugins: [createTestI18n(messages)],
stubs: {
BTooltip: BTooltipStub,
},
},
});
}
afterEach(() => {
loadCatalogMock.mockReset();
vi.useRealTimers();
});
describe("CustomerRuleTooltip", () => {
it("renders the rule change and exact additional-service product groups", () => {
const wrapper = mountTooltip({
active: true,
attribute: "restrictAdditionalServices",
products: [
{
id: 10,
category: 4,
name: "Truck wash",
addons: [
{
option_id: 62,
name: "Interior add-on",
product: { id: 62, category: 4, name: "Interior add-on" },
},
],
},
{ id: 91, category: 8, name: "Extra detergent" },
],
});
const content = wrapper.get('[data-testid="rule-tooltip-content"]');
expect(content.text()).toContain("Changes");
expect(content.text()).toContain("Blocks additional services.");
expect(content.text()).toContain("Blocked while active");
expect(content.text()).not.toContain("Truck wash");
expect(wrapper.get('[data-testid="rule-tooltip-blocked-relatedAddons"]').text()).toContain("Interior add-on");
expect(
wrapper.get('[data-testid="rule-tooltip-blocked-relatedAddons"] .customer-rule-tooltip__blocked-prefix').text()
).toBe("-");
expect(wrapper.get('[data-testid="rule-tooltip-blocked-relatedAddons"] li').classes()).toContain(
"customer-rule-tooltip__blocked-product"
);
expect(wrapper.get('[data-testid="rule-tooltip-blocked-standaloneAdditionalServices"]').text()).toContain(
"Extra detergent"
);
});
it("renders both blocked and available products for only-tank-cleaning rules", () => {
const wrapper = mountTooltip({
active: false,
attribute: "onlyTankCleaning",
products: [
{ id: 10, category: 4, name: "Truck wash" },
{ id: 20, category: 5, name: "Tank cleaning 4 spulehoveder" },
],
});
expect(wrapper.get('[data-testid="rule-tooltip-blocked-primaryProducts"]').text()).toContain("Truck wash");
expect(
wrapper.get('[data-testid="rule-tooltip-blocked-primaryProducts"] .customer-rule-tooltip__blocked-prefix').text()
).toBe("-");
expect(wrapper.get('[data-testid="rule-tooltip-available-primaryProducts"]').text()).toContain(
"Tank cleaning 4 spulehoveder"
);
expect(
wrapper
.find('[data-testid="rule-tooltip-available-primaryProducts"] .customer-rule-tooltip__blocked-prefix')
.exists()
).toBe(false);
});
it("lazy-loads catalog products on hover when no products are provided", async () => {
loadCatalogMock.mockResolvedValueOnce([
{ id: 23, category: 4, name: "Spot free rinse" },
{ id: 88, category: 4, name: "Standard wash" },
]);
const wrapper = mountTooltip({
active: false,
attribute: "restrictSpotFree",
customerNumber: 12345679,
departmentId: 12,
testId: "spot-free-tooltip",
});
await wrapper.get('[data-testid="spot-free-tooltip"]').trigger("mouseenter");
await flushPromises();
expect(loadCatalogMock).toHaveBeenCalledWith({
customerNumber: 12345679,
departmentId: 12,
});
expect(wrapper.get('[data-testid="spot-free-tooltip-content"]').text()).toContain("Spot free rinse");
expect(wrapper.get('[data-testid="spot-free-tooltip-content"]').text()).not.toContain("Standard wash");
});
it("keeps the tooltip open while moving the pointer into the scrollable product panel", async () => {
vi.useFakeTimers();
const wrapper = mountTooltip({
active: true,
attribute: "restrictAdditionalServices",
products: [
{
id: 10,
category: 4,
name: "Truck wash",
addons: [
{
option_id: 62,
name: "Interior add-on",
product: { id: 62, category: 4, name: "Interior add-on" },
},
],
},
],
});
const tooltip = wrapper.get(".b-tooltip-stub");
const trigger = wrapper.get('[data-testid="rule-tooltip"]');
const content = wrapper.get('[data-testid="rule-tooltip-content"]');
expect(tooltip.attributes("data-active")).toBe("false");
await trigger.trigger("mouseenter");
expect(tooltip.attributes("data-active")).toBe("true");
await trigger.trigger("mouseleave");
await content.trigger("mouseenter");
vi.advanceTimersByTime(180);
await flushPromises();
expect(tooltip.attributes("data-active")).toBe("true");
await content.trigger("mouseleave");
vi.advanceTimersByTime(180);
await flushPromises();
expect(tooltip.attributes("data-active")).toBe("false");
});
});