220 lines
6.8 KiB
JavaScript
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");
|
|
});
|
|
});
|