Files
pleno-vue/tests/unit/department-daily-report-complaints.spec.js
T
Jeppe Bundgaard b39b458f4f Add .prettierrc.json and refactor test files for improved formatting consistency:
- Introduced `.prettierrc.json` to enforce consistent code formatting across the project.
- Updated unit and e2e test files to address formatting issues, improve readability, and ensure alignment with the new Prettier configuration.
2026-04-13 09:13:27 +02:00

308 lines
13 KiB
JavaScript

// @vitest-environment jsdom
import { flushPromises } from "@vue/test-utils";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { mountWithApp } from "./helpers/mountWithApp.js";
const createComplaintMock = vi.hoisted(() => vi.fn());
const refreshOverviewMock = vi.hoisted(() => vi.fn());
const searchComplaintCustomersMock = vi.hoisted(() => vi.fn());
const permissionState = vi.hoisted(() => ({ canCreate: true }));
const sharedState = vi.hoisted(() => ({
selected_date: null,
selected_date_to: null,
selected_department_ids: null,
}));
vi.mock("@/components/session/token/SessionUser.vue", () => ({
SessionUser: {
hasPermission: (permission) =>
permission === "create_department_daily_report_complaints" && permissionState.canCreate,
objects: {
department_daily_reports: {
functions: {
createComplaint: createComplaintMock,
},
},
},
},
}));
vi.mock("@/components/pagination/departmentTabs.vue", async () => {
const { ref } = await import("vue");
return {
departments: ref([
{ id: 1, name: "North" },
{ id: 2, name: "South" },
]),
};
});
vi.mock("@/views/dashboards/departmentDashboard/modules/daily-report/DepartmentDailyReportObject.vue", async () => {
const { ref } = await import("vue");
sharedState.selected_date = ref("2026-03-23");
sharedState.selected_date_to = ref("2026-03-23");
sharedState.selected_department_ids = ref([1, 2]);
return {
refreshOverview: refreshOverviewMock,
selected_date: sharedState.selected_date,
selected_date_to: sharedState.selected_date_to,
selected_department_ids: sharedState.selected_department_ids,
};
});
vi.mock("@/services/departmentDailyReportComplaintCustomers.js", () => ({
COMPLAINT_CUSTOMER_SEARCH_DEBOUNCE_MS: 250,
COMPLAINT_CUSTOMER_SEARCH_MIN_LENGTH: 2,
formatComplaintCustomerLabel: (customer) =>
customer?.customer_name
? `${customer.customer_name} - ${customer.customer_number}`
: String(customer?.customer_number ?? ""),
normalizeComplaintCustomer: (customer) => customer,
searchComplaintCustomers: searchComplaintCustomersMock,
}));
vi.mock("@/services/departmentDailyReportComplaintCategories.js", () => ({
DEPARTMENT_DAILY_REPORT_COMPLAINT_CATEGORY_OPTIONS: [
{ value: "wash_quality", label: "Vaskekvalitet" },
{ value: "service", label: "Service" },
],
}));
import DepartmentDashboardDailyReportComplaints from "@/views/dashboards/departmentDashboard/modules/daily-report/displays/DepartmentDashboardDailyReportComplaints.vue";
const mountTile = (props = {}) =>
mountWithApp(DepartmentDashboardDailyReportComplaints, {
props: {
count: 3,
isLoading: false,
state: "ready",
unavailableMessage: null,
dataTestid: "daily-report-tile-complaints",
...props,
},
});
const formatDisplayedDate = (isoDate) => {
const [year, month, day] = String(isoDate || "").split("-");
if (!year || !month || !day) {
return "";
}
return `${day}/${month}/${year}`;
};
describe("DepartmentDashboardDailyReportComplaints", () => {
beforeEach(() => {
vi.useFakeTimers();
createComplaintMock.mockReset();
refreshOverviewMock.mockReset();
searchComplaintCustomersMock.mockReset();
refreshOverviewMock.mockResolvedValue(undefined);
searchComplaintCustomersMock.mockResolvedValue([]);
permissionState.canCreate = true;
sharedState.selected_date.value = "2026-03-23";
sharedState.selected_date_to.value = "2026-03-23";
sharedState.selected_department_ids.value = [1, 2];
});
afterEach(() => {
vi.runOnlyPendingTimers();
vi.useRealTimers();
});
it("shows the plus action only when the user has create permission", async () => {
const allowedWrapper = mountTile();
expect(allowedWrapper.find('[data-testid="daily-report-complaints-add-button"]').exists()).toBe(true);
permissionState.canCreate = false;
const deniedWrapper = mountTile();
expect(deniedWrapper.find('[data-testid="daily-report-complaints-add-button"]').exists()).toBe(false);
});
it("defaults the modal department and wash date to the selected day for single-day ranges", async () => {
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-department-select"]').element.value).toBe("1");
expect(wrapper.get('[data-testid="daily-report-complaints-wash-date-input"]').element.value).toBe("23/03/2026");
expect(wrapper.find('[data-testid="daily-report-complaints-date-note"]').exists()).toBe(false);
});
it("requires an explicit wash date for multi-day ranges and shows the updated date guidance", async () => {
sharedState.selected_department_ids.value = [2, 1];
sharedState.selected_date.value = "2026-03-20";
sharedState.selected_date_to.value = "2026-03-21";
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-department-select"]').element.value).toBe("2");
expect(wrapper.get('[data-testid="daily-report-complaints-wash-date-input"]').element.value).toBe("");
expect(wrapper.get('[data-testid="daily-report-complaints-date-note"]').text()).toContain("konkrete vask");
});
it("resets wash date, category, customer, and description state when the modal is reopened", async () => {
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-category-select"]').setValue("service");
await wrapper.get('[data-testid="daily-report-complaints-description-textarea"]').setValue("Temporary complaint");
await wrapper.get('[data-testid="daily-report-complaints-cancel"]').trigger("click");
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-wash-date-input"]').element.value).toBe("23/03/2026");
expect(wrapper.get('[data-testid="daily-report-complaints-category-select"]').element.value).toBe("");
expect(wrapper.get('[data-testid="daily-report-complaints-description-textarea"]').element.value).toBe("");
expect(wrapper.find('[data-testid="daily-report-complaints-customer-selected"]').exists()).toBe(false);
});
it("requires wash date, category, and description before submitting", async () => {
sharedState.selected_date.value = "2026-03-20";
sharedState.selected_date_to.value = "2026-03-21";
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(createComplaintMock).not.toHaveBeenCalled();
expect(wrapper.get('[data-testid="daily-report-complaints-validation-error"]').text()).toContain("Dato for vask");
await wrapper.get('[data-testid="daily-report-complaints-wash-date-input"]').setValue("21/03/2026");
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-validation-error"]').text()).toContain("Kategori");
await wrapper.get('[data-testid="daily-report-complaints-category-select"]').setValue("service");
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-validation-error"]').text()).toContain("Beskrivelse");
});
it("submits complaints without a customer number and refreshes the overview on success", async () => {
createComplaintMock.mockResolvedValue({ data: { data: { id: 1 } } });
const today = new Date().toISOString().split("T")[0];
sharedState.selected_date.value = today;
sharedState.selected_date_to.value = today;
const wrapper = mountTile({ count: 5 });
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-wash-date-input"]').element.value).toBe(
formatDisplayedDate(today)
);
await wrapper.get('[data-testid="daily-report-complaints-category-select"]').setValue("service");
await wrapper.get('[data-testid="daily-report-complaints-description-textarea"]').setValue("Machine damaged cargo");
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(createComplaintMock).toHaveBeenCalledWith({
department_id: 1,
customer_number: null,
wash_date: today,
category: "service",
description: "Machine damaged cargo",
});
expect(refreshOverviewMock).toHaveBeenCalledTimes(1);
expect(wrapper.find('[data-testid="daily-report-complaints-modal"]').exists()).toBe(false);
});
it("searches and selects an optional customer before submitting", async () => {
createComplaintMock.mockResolvedValue({ data: { data: { id: 2 } } });
searchComplaintCustomersMock.mockResolvedValue([{ customer_number: 12345, customer_name: "Acme Transport" }]);
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-customer-search-input"]').setValue("ac");
await vi.advanceTimersByTimeAsync(250);
await flushPromises();
expect(searchComplaintCustomersMock).toHaveBeenCalledWith("ac");
await wrapper.get('[data-testid="daily-report-complaints-customer-option-12345"]').trigger("mousedown");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-customer-selected"]').element.value).toBe(
"Acme Transport - 12345"
);
expect(wrapper.get('[data-testid="daily-report-complaints-wash-date-input"]').element.value).toBe("23/03/2026");
await wrapper.get('[data-testid="daily-report-complaints-category-select"]').setValue("wash_quality");
await wrapper
.get('[data-testid="daily-report-complaints-description-textarea"]')
.setValue("Complaint with customer number");
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(createComplaintMock).toHaveBeenCalledWith({
department_id: 1,
customer_number: 12345,
wash_date: "2026-03-23",
category: "wash_quality",
description: "Complaint with customer number",
});
});
it("requires the user to select a customer or clear the field when search text remains", async () => {
searchComplaintCustomersMock.mockResolvedValue([]);
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-customer-search-input"]').setValue("12345");
await vi.advanceTimersByTimeAsync(250);
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-category-select"]').setValue("service");
await wrapper
.get('[data-testid="daily-report-complaints-description-textarea"]')
.setValue("Complaint with unresolved customer");
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(createComplaintMock).not.toHaveBeenCalled();
expect(wrapper.get('[data-testid="daily-report-complaints-validation-error"]').text()).toContain("Vaelg en kunde");
});
it("keeps the modal open and shows an error message when submission fails", async () => {
createComplaintMock.mockRejectedValue({
response: {
data: {
message: "Customer not found",
},
},
});
const wrapper = mountTile();
await wrapper.get('[data-testid="daily-report-complaints-add-button"]').trigger("click");
await flushPromises();
await wrapper.get('[data-testid="daily-report-complaints-category-select"]').setValue("service");
await wrapper.get('[data-testid="daily-report-complaints-description-textarea"]').setValue("Broken mirror");
await wrapper.get('[data-testid="daily-report-complaints-submit"]').trigger("click");
await flushPromises();
expect(wrapper.get('[data-testid="daily-report-complaints-modal"]').exists()).toBe(true);
expect(wrapper.get('[data-testid="daily-report-complaints-error"]').text()).toContain("Customer not found");
expect(refreshOverviewMock).not.toHaveBeenCalled();
});
});