Add e2e tests for admin module functionalities:

- Introduced tests for admin daily report features, including tile rendering, complaint management, and stale response handling.
- Added department visibility tests to ensure hidden departments are excluded from UI controls.
- Implemented night wash overview tests for breakdown validation, missing hours detection, and stable range updates.
This commit is contained in:
Jeppe Bundgaard
2026-04-08 19:00:24 +02:00
parent 8eb315f439
commit 29c6c9d135
54 changed files with 7210 additions and 1277 deletions
@@ -0,0 +1,175 @@
// @vitest-environment jsdom
import { flushPromises } from "@vue/test-utils";
import { 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 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,
};
});
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,
},
});
describe("DepartmentDashboardDailyReportComplaints", () => {
beforeEach(() => {
createComplaintMock.mockReset();
refreshOverviewMock.mockReset();
refreshOverviewMock.mockResolvedValue(undefined);
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];
});
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 to the first selected department and shows the historical note outside today", 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-date-note"]').text()).toContain("aktuelle tidspunkt");
});
it("requires a non-empty description before submitting", 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-submit"]').trigger("click");
await flushPromises();
expect(createComplaintMock).not.toHaveBeenCalled();
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();
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,
description: "Machine damaged cargo",
});
expect(refreshOverviewMock).toHaveBeenCalledTimes(1);
expect(wrapper.find('[data-testid="daily-report-complaints-modal"]').exists()).toBe(false);
});
it("includes an optional customer number when provided", async () => {
createComplaintMock.mockResolvedValue({ data: { data: { id: 2 } } });
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-number-input"]').setValue("12345");
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,
description: "Complaint with customer number",
});
});
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-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();
});
});