Files
pleno-vue/tests/unit/department-daily-report-object.behavior.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

250 lines
7.6 KiB
JavaScript

import { nextTick } from "vue";
import { beforeEach, describe, expect, it, vi } from "vitest";
const getOverviewMock = vi.hoisted(() => vi.fn());
vi.mock("@/components/session/token/SessionUser.vue", () => ({
SessionUser: {
objects: {
department_daily_reports: {
functions: {
getOverview: getOverviewMock,
},
},
},
},
}));
const flushAll = async () => {
await nextTick();
await Promise.resolve();
await nextTick();
await Promise.resolve();
};
const deferred = () => {
let resolve;
let reject;
const promise = new Promise((nextResolve, nextReject) => {
resolve = nextResolve;
reject = nextReject;
});
return { promise, resolve, reject };
};
const makeOverview = ({
transactions = 0,
productsSold = 0,
revenue = 0,
washes = 0,
waterUsage = 0,
bookings = 0,
bookingsOutOf = 0,
complaints = 0,
complaintsState = "ready",
complaintsMessage = null,
nightWashesState = "ready",
nightWashes = 0,
nightWashesBySource = { orders: 0, xlvask: 0, selfserve: 0 },
nightWashesMissingDepartmentIds = [],
overtimeState = "ready",
overtime = 0,
} = {}) => ({
data: {
data: {
metrics: {
transactions: { state: "ready", value: transactions, out_of: null, message: null },
products_sold: { state: "ready", value: productsSold, out_of: null, message: null },
revenue: { state: "ready", value: revenue, out_of: null, message: null },
washes: { state: "ready", value: washes, out_of: null, message: null },
water_usage: { state: "ready", value: waterUsage, out_of: null, message: null },
bookings: { state: "ready", value: bookings, out_of: bookingsOutOf, message: null },
complaints: { state: complaintsState, value: complaints, out_of: null, message: complaintsMessage },
night_washes: {
state: nightWashesState,
value: nightWashes,
out_of: null,
message: null,
by_source: nightWashesBySource,
has_missing_opening_hours: nightWashesMissingDepartmentIds.length > 0,
missing_department_ids: nightWashesMissingDepartmentIds,
},
overtime: {
state: overtimeState,
value: overtime,
out_of: null,
message: overtimeState === "ready" ? null : "Overarbejde kræver Workfeed-kobling.",
},
},
products: [
{
product_id: 24,
slug: "spot-free-lastbil",
title: "Spot Free (Lastbil)",
state: "ready",
value: 3,
out_of: 9,
},
],
},
},
});
describe("DepartmentDailyReportObject behavior", () => {
beforeEach(() => {
vi.resetModules();
getOverviewMock.mockReset();
});
it("fetches once per filter change and lets the latest overview response win", async () => {
const firstRequest = deferred();
const secondRequest = deferred();
getOverviewMock.mockReturnValueOnce(firstRequest.promise).mockReturnValueOnce(secondRequest.promise);
const module = await import(
"@/views/dashboards/departmentDashboard/modules/daily-report/DepartmentDailyReportObject.vue"
);
module.initializeDailyReportFilters({
department_ids: [1],
date: "2026-03-23",
date_to: "2026-03-23",
});
await flushAll();
expect(getOverviewMock).toHaveBeenCalledTimes(1);
expect(getOverviewMock).toHaveBeenLastCalledWith([1], "2026-03-23", "2026-03-23");
module.selectDate("2026-03-23", "2026-03-24");
await flushAll();
expect(getOverviewMock).toHaveBeenCalledTimes(2);
expect(getOverviewMock).toHaveBeenLastCalledWith([1], "2026-03-23", "2026-03-24");
secondRequest.resolve(
makeOverview({
transactions: 9,
productsSold: 18,
revenue: 4200,
washes: 11,
waterUsage: 34,
bookings: 5,
bookingsOutOf: 7,
complaints: 2,
nightWashes: 2,
nightWashesBySource: { orders: 1, xlvask: 0, selfserve: 1 },
nightWashesMissingDepartmentIds: [7],
overtime: 1.25,
})
);
await flushAll();
firstRequest.resolve(
makeOverview({
transactions: 1,
productsSold: 2,
revenue: 300,
washes: 1,
waterUsage: 3,
bookings: 1,
bookingsOutOf: 1,
nightWashes: 0,
nightWashesBySource: { orders: 0, xlvask: 0, selfserve: 0 },
overtime: 0.25,
})
);
await flushAll();
expect(module.count_transactions.value).toBe(9);
expect(module.count_products_sold.value).toBe(18);
expect(module.count_earnings.value).toBe(4200);
expect(module.count_washes.value).toBe(11);
expect(module.count_water_usage.value).toBe(34);
expect(module.count_bookings.value).toBe(5);
expect(module.count_bookings_out_of.value).toBe(7);
expect(module.count_complaints.value).toBe(2);
expect(module.count_night_washes.value).toBe(2);
expect(module.night_washes_by_source.value).toEqual({ orders: 1, xlvask: 0, selfserve: 1 });
expect(module.night_washes_has_missing_opening_hours.value).toBe(true);
expect(module.night_washes_missing_department_ids.value).toEqual([7]);
expect(module.count_overtime.value).toBe(1.25);
});
it("keeps unavailable complaint and overtime tiles out of fake zero state", async () => {
getOverviewMock.mockResolvedValue(
makeOverview({
transactions: 4,
productsSold: 12,
revenue: 1800,
washes: 6,
waterUsage: 22,
bookings: 3,
bookingsOutOf: 4,
complaintsState: "unavailable",
complaintsMessage: "Kundeklager er ikke tilgængelig endnu.",
nightWashesState: "ready",
nightWashes: 1,
nightWashesBySource: { orders: 0, xlvask: 1, selfserve: 0 },
overtimeState: "unavailable",
overtime: 0,
})
);
const module = await import(
"@/views/dashboards/departmentDashboard/modules/daily-report/DepartmentDailyReportObject.vue"
);
module.initializeDailyReportFilters({
department_ids: [2],
date: "2026-03-25",
date_to: "2026-03-25",
});
await flushAll();
expect(module.complaints_metric_state.value.state).toBe("unavailable");
expect(module.complaints_metric_state.value.message).toContain("ikke tilgængelig");
expect(module.count_complaints.value).toBe(0);
expect(module.overtime_metric_state.value.state).toBe("unavailable");
expect(module.count_overtime.value).toBeNull();
expect(module.count_night_washes.value).toBe(1);
expect(module.night_washes_by_source.value).toEqual({ orders: 0, xlvask: 1, selfserve: 0 });
expect(module.night_washes_has_missing_opening_hours.value).toBe(false);
expect(module.night_washes_missing_department_ids.value).toEqual([]);
expect(module.daily_report_products.value[24]).toMatchObject({
slug: "spot-free-lastbil",
value: 3,
out_of: 9,
});
});
it("exposes an explicit overview refresh helper", async () => {
getOverviewMock.mockResolvedValue(
makeOverview({
transactions: 7,
complaints: 3,
})
);
const module = await import(
"@/views/dashboards/departmentDashboard/modules/daily-report/DepartmentDailyReportObject.vue"
);
module.initializeDailyReportFilters({
department_ids: [3],
date: "2026-03-26",
date_to: "2026-03-26",
});
await flushAll();
getOverviewMock.mockClear();
await module.refreshOverview();
await flushAll();
expect(getOverviewMock).toHaveBeenCalledTimes(1);
expect(getOverviewMock).toHaveBeenCalledWith([3], "2026-03-26", "2026-03-26");
expect(module.count_complaints.value).toBe(3);
});
});