Skip to content

Commit f1003ff

Browse files
authored
Merge pull request #26 from Curstantine/copilot/analyze-test-coverage
Add comprehensive test coverage across all packages
2 parents 2af5254 + 84db543 commit f1003ff

4 files changed

Lines changed: 135 additions & 1 deletion

File tree

packages/core/tests/enum.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,17 @@ describe("createEnum", () => {
6868
["B", symB],
6969
]);
7070
});
71+
72+
it("should allow direct property access on the enum values", () => {
73+
const Status = createEnum(/**@type {const}*/ ({ ACTIVE: "active", INACTIVE: "inactive" }));
74+
expect(Status.ACTIVE).toBe("active");
75+
expect(Status.INACTIVE).toBe("inactive");
76+
});
77+
78+
it("should return empty arrays for keys, values, and entries when given an empty object", () => {
79+
const Empty = createEnum({});
80+
expect(Empty.keys()).toEqual([]);
81+
expect(Empty.values()).toEqual([]);
82+
expect(Empty.entries()).toEqual([]);
83+
});
7184
});

packages/core/tests/index.test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,20 @@ describe("debounce", () => {
115115
expect(fn).toHaveBeenCalledTimes(1);
116116
expect(fn).toHaveBeenCalledWith("test");
117117
});
118+
119+
it("should allow multiple independent calls after each previous one resolves", async () => {
120+
const fn = vi.fn();
121+
const debounced = debounce(fn, 50);
122+
debounced.run("first");
123+
await wait(60);
124+
expect(fn).toHaveBeenCalledTimes(1);
125+
expect(fn).toHaveBeenCalledWith("first");
126+
127+
debounced.run("second");
128+
await wait(60);
129+
expect(fn).toHaveBeenCalledTimes(2);
130+
expect(fn).toHaveBeenCalledWith("second");
131+
});
118132
});
119133

120134
describe("wait", () => {
@@ -235,4 +249,17 @@ describe("getInitials", () => {
235249
expect(getInitials("John", null)).toBe("Jo");
236250
expect(getInitials("John", undefined)).toBe("Jo");
237251
});
252+
253+
it("should use default none fallback when options object provides only separator", () => {
254+
expect(getInitials("", "", { separator: "-" })).toBeUndefined();
255+
});
256+
257+
it("should apply both separator and none options together", () => {
258+
expect(getInitials("", "", { none: "??", separator: "_" })).toBe("??");
259+
expect(getInitials("John", "Doe", { none: "??", separator: "." })).toBe("J.D");
260+
});
261+
262+
it("should uppercase initials even when separator is provided", () => {
263+
expect(getInitials("alice", "bob", { separator: "-" })).toBe("A-B");
264+
});
238265
});

packages/form-data/tests/index.test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,48 @@ describe("parseFormData", () => {
148148
expect(result.items[1]).toBeUndefined();
149149
expect(result.items[2]).toBe("third");
150150
});
151+
152+
it("should handle three-level deep nesting", () => {
153+
const formData = new FormData();
154+
formData.set("a.b.c", "deep");
155+
156+
const result = parseFormData(formData);
157+
expect(result).toEqual({ a: { b: { c: "deep" } } });
158+
});
159+
160+
it("should convert a single existing value to an array when a second value is appended", () => {
161+
const formData = new FormData();
162+
formData.set("color", "red");
163+
formData.append("color", "blue");
164+
165+
const result = parseFormData(formData);
166+
expect(result).toEqual({ color: ["red", "blue"] });
167+
});
168+
169+
it("should grow an existing array when additional values are appended", () => {
170+
const formData = new FormData();
171+
formData.set("tags", "a");
172+
formData.append("tags", "b");
173+
formData.append("tags", "c");
174+
175+
const result = parseFormData(formData);
176+
expect(result).toEqual({ tags: ["a", "b", "c"] });
177+
});
178+
179+
it("should handle indexed arrays with objects inside nested paths", () => {
180+
const formData = new FormData();
181+
formData.set("order.items[0].sku", "ABC");
182+
formData.set("order.items[0].qty", "2");
183+
formData.set("order.items[1].sku", "XYZ");
184+
185+
const result = parseFormData(formData);
186+
expect(result).toEqual({
187+
order: {
188+
items: [
189+
{ sku: "ABC", qty: "2" },
190+
{ sku: "XYZ" },
191+
],
192+
},
193+
});
194+
});
151195
});

packages/query/tests/index.test.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, it } from "vitest";
22

3-
import { createSearchParams, createURL, parseSearchParams } from "../src/index.js";
3+
import { createSearchParams, createURL, getLiteralValue, parseSearchParams } from "../src/index.js";
44

55
describe("createSearchParams", () => {
66
it("should create basic search params", () => {
@@ -72,6 +72,27 @@ describe("createSearchParams", () => {
7272
"limit=10&search=term&offset=undefined&tagIds%5B%5D=123&tagIds%5B%5D=null&tagIds%5B%5D=321&active=Yes&skip=null",
7373
);
7474
});
75+
76+
it("should treat an empty array value as no params", () => {
77+
const params = createSearchParams({ a: [], b: "test" });
78+
expect(params.toString()).toBe("b=test");
79+
});
80+
81+
it("should treat a two-element array whose first element is not an object as a regular array", () => {
82+
const params = createSearchParams({ key: ["a", "b"] });
83+
expect(params.toString()).toBe("key=a&key=b");
84+
});
85+
86+
it("should treat a two-element array whose second element is not a string as a regular array", () => {
87+
const params = createSearchParams({ key: [{ val: "x" }, 42] });
88+
expect(params.toString()).toBe("key=%5Bobject+Object%5D&key=42");
89+
});
90+
91+
it("should serialize as 'undefined' for an Option tuple key that does not exist in the record", () => {
92+
const options = { eager: "EagerValue" };
93+
const params = createSearchParams({ mode: [options, "missing"] });
94+
expect(params.get("mode")).toBe("undefined");
95+
});
7596
});
7697

7798
describe("createURL", () => {
@@ -241,4 +262,33 @@ describe("parseSearchParams", () => {
241262
const result = parseSearchParams(searchParams);
242263
expect(result).toEqual({ key: ["value1", "value2"] });
243264
});
265+
266+
it("should skip null/undefined array entries by default", () => {
267+
const searchParams = new URLSearchParams("ids[]=1&ids[]=null&ids[]=2");
268+
const result = parseSearchParams(searchParams);
269+
expect(result).toEqual({ "ids[]": ["1", null, "2"] });
270+
});
271+
272+
it("should accumulate more than two values for the same non-[] key into an array", () => {
273+
const searchParams = new URLSearchParams("tag=a&tag=b&tag=c");
274+
const result = parseSearchParams(searchParams);
275+
expect(result).toEqual({ tag: ["a", "b", "c"] });
276+
});
277+
});
278+
279+
describe("getLiteralValue", () => {
280+
it("should convert the string 'null' to null", () => {
281+
expect(getLiteralValue("null")).toBeNull();
282+
});
283+
284+
it("should convert the string 'undefined' to undefined", () => {
285+
expect(getLiteralValue("undefined")).toBeUndefined();
286+
});
287+
288+
it("should return any other string unchanged", () => {
289+
expect(getLiteralValue("hello")).toBe("hello");
290+
expect(getLiteralValue("")).toBe("");
291+
expect(getLiteralValue("0")).toBe("0");
292+
expect(getLiteralValue("false")).toBe("false");
293+
});
244294
});

0 commit comments

Comments
 (0)