Skip to content

Commit b0dc13f

Browse files
committed
fix: add some tests
1 parent 2ca12cb commit b0dc13f

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

frontend/src/__test__/components/Dashboard/OpeningSubmissionTrend.test.tsx

+46
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,50 @@ describe("OpeningSubmissionTrend Component", () => {
9797

9898
await waitFor(() => expect(screen.getByTestId("grouped-bar-chart")).toBeInTheDocument());
9999
});
100+
101+
it("should update year and refetch data", async () => {
102+
(fetchOpeningsOrgUnits as vi.Mock).mockResolvedValueOnce([
103+
{ code: "DAS", description: "District A" },
104+
]);
105+
(fetchUserSubmissionTrends as vi.Mock).mockResolvedValue([]);
106+
107+
const { getByLabelText, getByText } = await renderWithProviders();
108+
109+
// Wait for dropdowns to appear
110+
await waitFor(() => {
111+
expect(getByText("Opening submission year")).toBeInTheDocument();
112+
});
113+
114+
const yearDropdownInput = getByLabelText("Opening submission year", {
115+
selector: 'input',
116+
});
117+
118+
// Simulate input value change
119+
fireEvent.change(yearDropdownInput, { target: { value: "2022" } });
120+
121+
// Verify it still renders correctly after interaction
122+
expect(getByText("Opening submission per year")).toBeInTheDocument();
123+
});
124+
125+
it("should update org units and trigger data fetch", async () => {
126+
(fetchOpeningsOrgUnits as vi.Mock).mockResolvedValueOnce([
127+
{ code: "DAS", description: "District A" },
128+
]);
129+
(fetchUserSubmissionTrends as vi.Mock).mockResolvedValue([]); // allow refetch
130+
131+
const { getByText, getAllByRole } = await renderWithProviders();
132+
133+
await waitFor(() => expect(getByText("District")).toBeInTheDocument());
134+
135+
const dropdowns = getAllByRole("combobox");
136+
expect(dropdowns.length).toBeGreaterThan(0);
137+
});
138+
139+
it("should show loading spinner when fetching", async () => {
140+
(fetchUserSubmissionTrends as vi.Mock).mockImplementation(() => new Promise(() => { }));
141+
const { container } = await renderWithProviders();
142+
143+
const spinner = container.querySelector(".trend-loading-spinner");
144+
expect(spinner).toBeInTheDocument();
145+
});
100146
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { describe, it, expect } from "vitest";
2+
import { hasAnyActiveFilters } from "../../../components/SilvicultureSearch/OpeningSearch/utils";
3+
import { OpeningSearchFilterType } from "../../../components/SilvicultureSearch/OpeningSearch/definitions";
4+
import CodeDescriptionDto from "../../../types/CodeDescriptionType";
5+
6+
describe("hasAnyActiveFilters", () => {
7+
const mockCodeDesc = (code: string, desc: string): CodeDescriptionDto => ({
8+
code,
9+
description: desc,
10+
});
11+
12+
it("should return false when all filters are empty or undefined", () => {
13+
const filters: OpeningSearchFilterType = {};
14+
expect(hasAnyActiveFilters(filters)).toBe(false);
15+
});
16+
17+
it("should return false when only dateType is set", () => {
18+
const filters: OpeningSearchFilterType = {
19+
dateType: { code: "update", description: "Update" },
20+
};
21+
expect(hasAnyActiveFilters(filters)).toBe(false);
22+
});
23+
24+
it("should return true if an array filter has values", () => {
25+
const filters: OpeningSearchFilterType = {
26+
orgUnit: [mockCodeDesc("DAS", "District A")],
27+
};
28+
expect(hasAnyActiveFilters(filters)).toBe(true);
29+
});
30+
31+
it("should return true if a string filter has non-empty value", () => {
32+
const filters: OpeningSearchFilterType = {
33+
mainSearchTerm: "test search",
34+
};
35+
expect(hasAnyActiveFilters(filters)).toBe(true);
36+
});
37+
38+
it("should return false if string filter is empty or whitespace", () => {
39+
expect(hasAnyActiveFilters({ mainSearchTerm: "" })).toBe(false);
40+
expect(hasAnyActiveFilters({ mainSearchTerm: " " })).toBe(false);
41+
});
42+
43+
it("should return true if a boolean filter is true", () => {
44+
expect(hasAnyActiveFilters({ myOpenings: true })).toBe(true);
45+
expect(hasAnyActiveFilters({ submittedToFrpa: true })).toBe(true);
46+
});
47+
48+
it("should return false if boolean is false or undefined", () => {
49+
expect(hasAnyActiveFilters({ myOpenings: false })).toBe(false);
50+
expect(hasAnyActiveFilters({ submittedToFrpa: false })).toBe(false);
51+
});
52+
53+
it("should return true if a date string is set", () => {
54+
const filters: OpeningSearchFilterType = {
55+
updateDateStart: "2024-01-01",
56+
};
57+
expect(hasAnyActiveFilters(filters)).toBe(true);
58+
});
59+
60+
it("should return true if a number filter is present", () => {
61+
const filters: OpeningSearchFilterType = {
62+
page: 1,
63+
};
64+
expect(hasAnyActiveFilters(filters)).toBe(true);
65+
});
66+
67+
it("should return true if multiple filters are present", () => {
68+
const filters: OpeningSearchFilterType = {
69+
statusList: [mockCodeDesc("APP", "Approved")],
70+
mainSearchTerm: "waldo",
71+
cuttingPermitId: "WA-001",
72+
myOpenings: true,
73+
dateType: { code: "update", description: "Update" },
74+
};
75+
expect(hasAnyActiveFilters(filters)).toBe(true);
76+
});
77+
78+
it("should return false if all filters are explicitly empty", () => {
79+
const filters: OpeningSearchFilterType = {
80+
mainSearchTerm: "",
81+
statusList: [],
82+
orgUnit: [],
83+
myOpenings: false,
84+
submittedToFrpa: false,
85+
disturbanceDateStart: "",
86+
updateDateEnd: "",
87+
dateType: { code: "update", description: "Update" },
88+
};
89+
expect(hasAnyActiveFilters(filters)).toBe(false);
90+
});
91+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { describe, it, expect } from "vitest";
2+
import { buildQueryString } from "../../utils/UrlUtils";
3+
4+
describe("buildQueryString", () => {
5+
it("should build query string from flat key-value pairs", () => {
6+
const params = {
7+
page: 1,
8+
search: "tree",
9+
active: true,
10+
};
11+
12+
const query = buildQueryString(params);
13+
expect(query).toBe("page=1&search=tree&active=true");
14+
});
15+
16+
it("should omit keys with undefined or null values", () => {
17+
const params = {
18+
search: "forest",
19+
sort: undefined,
20+
filter: null,
21+
};
22+
23+
const query = buildQueryString(params);
24+
expect(query).toBe("search=forest");
25+
});
26+
27+
it("should convert arrays into comma-separated strings", () => {
28+
const params = {
29+
orgUnit: ["A", "B", "C"],
30+
status: ["Open", "Closed"],
31+
};
32+
33+
const query = buildQueryString(params);
34+
expect(query).toBe("orgUnit=A%2CB%2CC&status=Open%2CClosed");
35+
});
36+
37+
it("should skip empty arrays", () => {
38+
const params = {
39+
orgUnit: [],
40+
region: "North",
41+
};
42+
43+
const query = buildQueryString(params);
44+
expect(query).toBe("region=North");
45+
});
46+
47+
it("should handle mixed types and skip empty or falsy fields properly", () => {
48+
const params = {
49+
page: 1,
50+
dateType: "Update",
51+
updateDateStart: "2024-03-01",
52+
updateDateEnd: "2024-03-10",
53+
tags: [],
54+
extra: null,
55+
debug: undefined,
56+
};
57+
58+
const query = buildQueryString(params);
59+
expect(query).toBe("page=1&dateType=Update&updateDateStart=2024-03-01&updateDateEnd=2024-03-10");
60+
});
61+
62+
it("should return empty string if all values are null/undefined/empty arrays", () => {
63+
const params = {
64+
foo: undefined,
65+
bar: null,
66+
list: [],
67+
};
68+
69+
const query = buildQueryString(params);
70+
expect(query).toBe("");
71+
});
72+
});

0 commit comments

Comments
 (0)