Add tests for DepartmentWeather and update daily report wiring:
- Added unit tests for `DepartmentWeather` component to validate weather API calls, state handling, and edge cases (e.g., no departments, stale responses, hidden hours). - Updated `DepartmentDailyReport` wiring to pass `department_ids`, `date_from`, and `date_to` to `DepartmentWeather`. - Enhanced OpenAPI definition for weather timeline API with refined query parameters (`date_from`, `date_to`) and updated descriptions. - Improved `GoalFormModal` layout, adding `department-grid--single-scroll` for better scrolling behavior and responsiveness.
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
// @vitest-environment jsdom
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { nextTick } from "vue";
|
||||
|
||||
const { getObjectsMock } = vi.hoisted(() => ({
|
||||
getObjectsMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue", () => ({
|
||||
ObjectsGlobal: {
|
||||
get: {
|
||||
objects: getObjectsMock,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
import DepartmentWeather from "@/views/dashboards/departmentDashboard/modules/daily-report/DepartmentWeather.vue";
|
||||
|
||||
const flushAll = async () => {
|
||||
await nextTick();
|
||||
await Promise.resolve();
|
||||
await nextTick();
|
||||
await Promise.resolve();
|
||||
};
|
||||
|
||||
const createDeferred = () => {
|
||||
let resolve;
|
||||
let reject;
|
||||
const promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
return { promise, resolve, reject };
|
||||
};
|
||||
|
||||
const makeEntry = (overrides = {}) => ({
|
||||
date: "2026-03-24",
|
||||
time: "00:00",
|
||||
current: false,
|
||||
weather: "clear",
|
||||
washes: 1,
|
||||
hours: 2,
|
||||
status: "healthy",
|
||||
...overrides,
|
||||
});
|
||||
|
||||
const getFirstWashesCellText = (wrapper) => {
|
||||
const rows = wrapper.findAll("tbody tr");
|
||||
const washesRow = rows[1];
|
||||
if (!washesRow) {
|
||||
return null;
|
||||
}
|
||||
const cells = washesRow.findAll("td");
|
||||
return cells[1]?.text() ?? null;
|
||||
};
|
||||
|
||||
const getRenderedHours = (wrapper) => {
|
||||
const headers = wrapper.findAll("thead tr th").slice(1);
|
||||
return headers.map((th) => th.text());
|
||||
};
|
||||
|
||||
describe("DepartmentWeather", () => {
|
||||
beforeEach(() => {
|
||||
getObjectsMock.mockReset();
|
||||
});
|
||||
|
||||
it("calls weather endpoint with ids/date_from/date_to", async () => {
|
||||
getObjectsMock.mockResolvedValueOnce([makeEntry()]);
|
||||
|
||||
mount(DepartmentWeather, {
|
||||
props: {
|
||||
department_ids: [3, 1, 3, 2],
|
||||
date_from: "2026-03-23",
|
||||
date_to: "2026-03-24",
|
||||
},
|
||||
});
|
||||
|
||||
await flushAll();
|
||||
|
||||
expect(getObjectsMock).toHaveBeenCalledTimes(1);
|
||||
expect(getObjectsMock).toHaveBeenCalledWith("/departments/weather", {
|
||||
ids: "1,2,3",
|
||||
date_from: "2026-03-23",
|
||||
date_to: "2026-03-24",
|
||||
});
|
||||
});
|
||||
|
||||
it("refetches when ids or dates change", async () => {
|
||||
getObjectsMock
|
||||
.mockResolvedValueOnce([makeEntry({ washes: 3 })])
|
||||
.mockResolvedValueOnce([makeEntry({ washes: 7 })]);
|
||||
|
||||
const wrapper = mount(DepartmentWeather, {
|
||||
props: {
|
||||
department_ids: [2],
|
||||
date_from: "2026-03-23",
|
||||
date_to: "2026-03-24",
|
||||
},
|
||||
});
|
||||
|
||||
await flushAll();
|
||||
|
||||
await wrapper.setProps({
|
||||
department_ids: [2, 5],
|
||||
date_from: "2026-03-24",
|
||||
date_to: "2026-03-25",
|
||||
});
|
||||
await flushAll();
|
||||
|
||||
expect(getObjectsMock).toHaveBeenCalledTimes(2);
|
||||
expect(getObjectsMock).toHaveBeenNthCalledWith(2, "/departments/weather", {
|
||||
ids: "2,5",
|
||||
date_from: "2026-03-24",
|
||||
date_to: "2026-03-25",
|
||||
});
|
||||
});
|
||||
|
||||
it("clears and skips fetch when no departments are selected", async () => {
|
||||
getObjectsMock.mockResolvedValueOnce([makeEntry()]);
|
||||
|
||||
const wrapper = mount(DepartmentWeather, {
|
||||
props: {
|
||||
department_ids: [9],
|
||||
date_from: "2026-03-23",
|
||||
date_to: "2026-03-24",
|
||||
},
|
||||
});
|
||||
|
||||
await flushAll();
|
||||
expect(wrapper.find("section.daily-metrics").exists()).toBe(true);
|
||||
|
||||
await wrapper.setProps({
|
||||
department_ids: [],
|
||||
});
|
||||
await flushAll();
|
||||
|
||||
expect(getObjectsMock).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.find("section.daily-metrics").exists()).toBe(false);
|
||||
});
|
||||
|
||||
it("ignores stale responses when a newer request finishes first", async () => {
|
||||
const first = createDeferred();
|
||||
const second = createDeferred();
|
||||
|
||||
getObjectsMock
|
||||
.mockImplementationOnce(() => first.promise)
|
||||
.mockImplementationOnce(() => second.promise);
|
||||
|
||||
const wrapper = mount(DepartmentWeather, {
|
||||
props: {
|
||||
department_ids: [1],
|
||||
date_from: "2026-03-23",
|
||||
date_to: "2026-03-24",
|
||||
},
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
|
||||
await wrapper.setProps({
|
||||
date_to: "2026-03-25",
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
second.resolve([makeEntry({ washes: 9002, time: "01:00" })]);
|
||||
await flushAll();
|
||||
expect(getFirstWashesCellText(wrapper)).toBe("9002");
|
||||
|
||||
first.resolve([makeEntry({ washes: 9001, time: "00:00" })]);
|
||||
await flushAll();
|
||||
expect(getFirstWashesCellText(wrapper)).toBe("9002");
|
||||
});
|
||||
|
||||
it("hides hour columns when both washes and hours are zero", async () => {
|
||||
getObjectsMock.mockResolvedValueOnce([
|
||||
makeEntry({ time: "00:00", washes: 0, hours: 0 }),
|
||||
makeEntry({ time: "01:00", washes: "0", hours: "0" }),
|
||||
makeEntry({ time: "06:00", washes: 1, hours: 0 }),
|
||||
makeEntry({ time: "07:00", washes: 0, hours: 2 }),
|
||||
]);
|
||||
|
||||
const wrapper = mount(DepartmentWeather, {
|
||||
props: {
|
||||
department_ids: [1],
|
||||
date_from: "2026-03-23",
|
||||
date_to: "2026-03-24",
|
||||
},
|
||||
});
|
||||
|
||||
await flushAll();
|
||||
|
||||
expect(getRenderedHours(wrapper)).toEqual(["06", "07"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user