Remove configuration cache problems report

This commit is contained in:
Jeppe Bundgaard
2026-04-23 10:32:08 +02:00
parent 85f24bdb0c
commit fc26e12013
48 changed files with 4994 additions and 1125 deletions
+232 -1
View File
@@ -1,6 +1,6 @@
// @vitest-environment jsdom
import { mount } from "@vue/test-utils";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
import { SessionUser } from "@/components/session/token/SessionUser.vue";
import { createTestI18n } from "./helpers/mountWithApp.js";
@@ -73,6 +73,7 @@ vi.mock("@/components/session/token/SessionUser.vue", () => ({
functions: {
fetchAttachments: vi.fn(() => Promise.resolve([])),
get_department_id: vi.fn(() => Promise.resolve(1)),
removeAttachment: vi.fn(() => Promise.resolve({ success: true })),
showAttachWashCertificateForm: vi.fn(() => Promise.resolve()),
showChangeCustomerForm: vi.fn(() => Promise.resolve()),
showChangeInvoiceCollectionForm: vi.fn(() => Promise.resolve()),
@@ -152,6 +153,13 @@ const SETTINGS_WHEEL_TRANSLATION_KEYS = [
"admin.pos.settings_wheel.view_lane_setup_new_tab",
"admin.pos.settings_wheel.view_order_new_tab",
"admin.pos.settings_wheel.view_vehicle_new_tab",
"admin.pos.attachments_no_preview",
"admin.pos.attachments_office_preview_unavailable",
"global.delete",
"global.download",
"global.loading",
"global.preview",
"global.print",
"superuser.department_lane.force_disable_machine",
"superuser.department_lane.force_enable_machine",
];
@@ -186,10 +194,114 @@ const flushMicrotasks = async () => {
await Promise.resolve();
};
const setDesktopFlyoutViewport = () => {
Object.defineProperty(window, "innerWidth", {
configurable: true,
writable: true,
value: 1900,
});
Object.defineProperty(window, "innerHeight", {
configurable: true,
writable: true,
value: 900,
});
window.matchMedia = vi.fn().mockImplementation(() => ({
matches: true,
media: "",
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
}));
};
const mockMenuGeometry = () =>
vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(function getBoundingClientRectMock() {
if (this.classList?.contains("dropdown-trigger")) {
return {
x: 1750,
y: 96,
top: 96,
left: 1750,
right: 1850,
bottom: 136,
width: 100,
height: 40,
toJSON() {
return this;
},
};
}
return {
x: 1320,
y: 136,
top: 136,
left: 1320,
right: 1850,
bottom: 560,
width: 530,
height: 424,
toJSON() {
return this;
},
};
});
const mountDesktopFlyoutButton = (props = {}) => {
setDesktopFlyoutViewport();
return mount(ActionSettingsWheelButton, {
props: {
order_id: 42,
refreshFunction: vi.fn(() => Promise.resolve()),
...props,
},
slots: {
actions: "",
},
global: {
plugins: [i18n],
stubs: {
CustomerModal: { template: "<div />" },
},
},
});
};
const originalFetch = global.fetch;
const originalCreateObjectURL = global.URL.createObjectURL;
const originalRevokeObjectURL = global.URL.revokeObjectURL;
const originalMatchMedia = window.matchMedia;
describe("ActionSettingsWheelButton", () => {
beforeEach(() => {
getUserIdMock.mockClear();
SessionUser.objects.orders.functions.showChangeInvoiceCollectionForm.mockClear();
SessionUser.objects.orders.functions.fetchAttachments.mockReset();
SessionUser.objects.orders.functions.fetchAttachments.mockResolvedValue([]);
SessionUser.objects.orders.functions.downloadAttachment.mockReset();
SessionUser.objects.orders.functions.downloadAttachment.mockResolvedValue("https://cdn.example.test/attachment");
SessionUser.objects.orders.functions.removeAttachment.mockReset();
SessionUser.objects.orders.functions.removeAttachment.mockResolvedValue({ success: true });
global.fetch = vi.fn(() =>
Promise.resolve({
ok: true,
blob: () => Promise.resolve(new Blob(["preview"], { type: "application/pdf" })),
})
);
global.URL.createObjectURL = vi.fn((blob) => `blob:${blob.type}:${Date.now()}`);
global.URL.revokeObjectURL = vi.fn();
});
afterEach(() => {
global.fetch = originalFetch;
global.URL.createObjectURL = originalCreateObjectURL;
global.URL.revokeObjectURL = originalRevokeObjectURL;
window.matchMedia = originalMatchMedia;
vi.restoreAllMocks();
});
it("resolves customer user id once on mount and not on unrelated rerenders", async () => {
@@ -322,4 +434,123 @@ describe("ActionSettingsWheelButton", () => {
windowOpenSpy.mockRestore();
});
it("builds attachment flyout rows and switches the preview panel on hover and focus", async () => {
SessionUser.objects.orders.functions.fetchAttachments.mockResolvedValue([
{
id: 301,
content: {
document: "safety-seal.pdf",
other: "safety-seal.pdf",
},
},
{
id: 302,
content: {
image: "truck.jpg",
other: "truck.jpg",
},
},
]);
SessionUser.objects.orders.functions.downloadAttachment.mockImplementation((orderId, attachmentId) =>
Promise.resolve(`https://cdn.example.test/orders/${orderId}/attachments/${attachmentId}`)
);
global.fetch = vi.fn((url) =>
Promise.resolve({
ok: true,
blob: () =>
Promise.resolve(
new Blob(["preview"], {
type: String(url).includes("/301") ? "application/pdf" : "image/png",
})
),
})
);
const geometrySpy = mockMenuGeometry();
const wrapper = mountDesktopFlyoutButton();
await flushMicrotasks();
await wrapper.find(".dropdown-trigger button").trigger("click");
await flushMicrotasks();
const attachmentsSection = wrapper.get('[data-testid="action-settings-wheel-section-attachments"]');
await attachmentsSection.trigger("mouseenter");
await flushMicrotasks();
const pdfRow = wrapper.get('[data-testid="action-settings-wheel-attachment-row-301"]');
const imageRow = wrapper.get('[data-testid="action-settings-wheel-attachment-row-302"]');
expect(pdfRow.text()).toContain("safety-seal.pdf");
expect(imageRow.text()).toContain("truck.jpg");
await pdfRow.trigger("mouseenter");
await flushMicrotasks();
await flushMicrotasks();
const previewPanel = wrapper.get('[data-testid="action-settings-wheel-attachment-panel"]');
expect(previewPanel.find("iframe").exists()).toBe(true);
expect(wrapper.find('[data-testid="action-settings-wheel-attachment-action-preview-301"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="action-settings-wheel-attachment-action-download-301"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="action-settings-wheel-attachment-action-print-301"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="action-settings-wheel-attachment-action-delete-301"]').exists()).toBe(true);
await imageRow.trigger("focus");
await flushMicrotasks();
await flushMicrotasks();
expect(wrapper.get('[data-testid="action-settings-wheel-attachment-panel"]').find("img").exists()).toBe(true);
expect(global.fetch).toHaveBeenCalledTimes(2);
geometrySpy.mockRestore();
});
it("deletes attachments, refreshes the list, and clears preview object URLs on close", async () => {
const attachmentsBeforeDelete = [
{
id: 301,
content: {
document: "safety-seal.pdf",
other: "safety-seal.pdf",
},
},
];
SessionUser.objects.orders.functions.fetchAttachments
.mockResolvedValueOnce(attachmentsBeforeDelete)
.mockResolvedValueOnce([]);
SessionUser.objects.orders.functions.downloadAttachment.mockResolvedValue(
"https://cdn.example.test/orders/42/attachments/301"
);
const refreshFunction = vi.fn(() => Promise.resolve());
const geometrySpy = mockMenuGeometry();
const wrapper = mountDesktopFlyoutButton({ refreshFunction });
await flushMicrotasks();
await wrapper.find(".dropdown-trigger button").trigger("click");
await flushMicrotasks();
await wrapper.get('[data-testid="action-settings-wheel-section-attachments"]').trigger("mouseenter");
await flushMicrotasks();
await wrapper.get('[data-testid="action-settings-wheel-attachment-row-301"]').trigger("mouseenter");
await flushMicrotasks();
expect(global.URL.createObjectURL).toHaveBeenCalledTimes(1);
await wrapper.get('[data-testid="action-settings-wheel-attachment-action-delete-301"]').trigger("click");
await flushMicrotasks();
expect(SessionUser.objects.orders.functions.removeAttachment).toHaveBeenCalledTimes(1);
expect(SessionUser.objects.orders.functions.removeAttachment).toHaveBeenCalledWith(42, 301);
expect(refreshFunction).toHaveBeenCalledTimes(1);
expect(SessionUser.objects.orders.functions.fetchAttachments).toHaveBeenCalledTimes(2);
expect(wrapper.find('[data-testid="action-settings-wheel-section-attachments"]').exists()).toBe(false);
await wrapper.find(".dropdown-trigger button").trigger("click");
await flushMicrotasks();
expect(global.URL.revokeObjectURL).toHaveBeenCalledTimes(1);
wrapper.unmount();
geometrySpy.mockRestore();
});
});