From 84db543f7c30ee23fba3c374a534d12a1f9b8200 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Mar 2026 05:34:02 +0000 Subject: [PATCH] Add comprehensive test cases to improve coverage across all packages Agent-Logs-Url: https://github.com/Curstantine/jabascript/sessions/f30249b5-a789-44c4-b657-2220e1b44c91 Co-authored-by: Curstantine <69104500+Curstantine@users.noreply.github.com> --- packages/core/tests/enum.test.js | 13 +++++++ packages/core/tests/index.test.js | 27 +++++++++++++ packages/form-data/tests/index.test.js | 44 ++++++++++++++++++++++ packages/query/tests/index.test.js | 52 +++++++++++++++++++++++++- 4 files changed, 135 insertions(+), 1 deletion(-) diff --git a/packages/core/tests/enum.test.js b/packages/core/tests/enum.test.js index 634ebf2..c03660a 100644 --- a/packages/core/tests/enum.test.js +++ b/packages/core/tests/enum.test.js @@ -68,4 +68,17 @@ describe("createEnum", () => { ["B", symB], ]); }); + + it("should allow direct property access on the enum values", () => { + const Status = createEnum(/**@type {const}*/ ({ ACTIVE: "active", INACTIVE: "inactive" })); + expect(Status.ACTIVE).toBe("active"); + expect(Status.INACTIVE).toBe("inactive"); + }); + + it("should return empty arrays for keys, values, and entries when given an empty object", () => { + const Empty = createEnum({}); + expect(Empty.keys()).toEqual([]); + expect(Empty.values()).toEqual([]); + expect(Empty.entries()).toEqual([]); + }); }); diff --git a/packages/core/tests/index.test.js b/packages/core/tests/index.test.js index 5a2b223..58bc42e 100644 --- a/packages/core/tests/index.test.js +++ b/packages/core/tests/index.test.js @@ -115,6 +115,20 @@ describe("debounce", () => { expect(fn).toHaveBeenCalledTimes(1); expect(fn).toHaveBeenCalledWith("test"); }); + + it("should allow multiple independent calls after each previous one resolves", async () => { + const fn = vi.fn(); + const debounced = debounce(fn, 50); + debounced.run("first"); + await wait(60); + expect(fn).toHaveBeenCalledTimes(1); + expect(fn).toHaveBeenCalledWith("first"); + + debounced.run("second"); + await wait(60); + expect(fn).toHaveBeenCalledTimes(2); + expect(fn).toHaveBeenCalledWith("second"); + }); }); describe("wait", () => { @@ -235,4 +249,17 @@ describe("getInitials", () => { expect(getInitials("John", null)).toBe("Jo"); expect(getInitials("John", undefined)).toBe("Jo"); }); + + it("should use default none fallback when options object provides only separator", () => { + expect(getInitials("", "", { separator: "-" })).toBeUndefined(); + }); + + it("should apply both separator and none options together", () => { + expect(getInitials("", "", { none: "??", separator: "_" })).toBe("??"); + expect(getInitials("John", "Doe", { none: "??", separator: "." })).toBe("J.D"); + }); + + it("should uppercase initials even when separator is provided", () => { + expect(getInitials("alice", "bob", { separator: "-" })).toBe("A-B"); + }); }); diff --git a/packages/form-data/tests/index.test.js b/packages/form-data/tests/index.test.js index 1458035..5078597 100644 --- a/packages/form-data/tests/index.test.js +++ b/packages/form-data/tests/index.test.js @@ -148,4 +148,48 @@ describe("parseFormData", () => { expect(result.items[1]).toBeUndefined(); expect(result.items[2]).toBe("third"); }); + + it("should handle three-level deep nesting", () => { + const formData = new FormData(); + formData.set("a.b.c", "deep"); + + const result = parseFormData(formData); + expect(result).toEqual({ a: { b: { c: "deep" } } }); + }); + + it("should convert a single existing value to an array when a second value is appended", () => { + const formData = new FormData(); + formData.set("color", "red"); + formData.append("color", "blue"); + + const result = parseFormData(formData); + expect(result).toEqual({ color: ["red", "blue"] }); + }); + + it("should grow an existing array when additional values are appended", () => { + const formData = new FormData(); + formData.set("tags", "a"); + formData.append("tags", "b"); + formData.append("tags", "c"); + + const result = parseFormData(formData); + expect(result).toEqual({ tags: ["a", "b", "c"] }); + }); + + it("should handle indexed arrays with objects inside nested paths", () => { + const formData = new FormData(); + formData.set("order.items[0].sku", "ABC"); + formData.set("order.items[0].qty", "2"); + formData.set("order.items[1].sku", "XYZ"); + + const result = parseFormData(formData); + expect(result).toEqual({ + order: { + items: [ + { sku: "ABC", qty: "2" }, + { sku: "XYZ" }, + ], + }, + }); + }); }); diff --git a/packages/query/tests/index.test.js b/packages/query/tests/index.test.js index 9077657..2cbba67 100644 --- a/packages/query/tests/index.test.js +++ b/packages/query/tests/index.test.js @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import { createSearchParams, createURL, parseSearchParams } from "../src/index.js"; +import { createSearchParams, createURL, getLiteralValue, parseSearchParams } from "../src/index.js"; describe("createSearchParams", () => { it("should create basic search params", () => { @@ -72,6 +72,27 @@ describe("createSearchParams", () => { "limit=10&search=term&offset=undefined&tagIds%5B%5D=123&tagIds%5B%5D=null&tagIds%5B%5D=321&active=Yes&skip=null", ); }); + + it("should treat an empty array value as no params", () => { + const params = createSearchParams({ a: [], b: "test" }); + expect(params.toString()).toBe("b=test"); + }); + + it("should treat a two-element array whose first element is not an object as a regular array", () => { + const params = createSearchParams({ key: ["a", "b"] }); + expect(params.toString()).toBe("key=a&key=b"); + }); + + it("should treat a two-element array whose second element is not a string as a regular array", () => { + const params = createSearchParams({ key: [{ val: "x" }, 42] }); + expect(params.toString()).toBe("key=%5Bobject+Object%5D&key=42"); + }); + + it("should serialize as 'undefined' for an Option tuple key that does not exist in the record", () => { + const options = { eager: "EagerValue" }; + const params = createSearchParams({ mode: [options, "missing"] }); + expect(params.get("mode")).toBe("undefined"); + }); }); describe("createURL", () => { @@ -241,4 +262,33 @@ describe("parseSearchParams", () => { const result = parseSearchParams(searchParams); expect(result).toEqual({ key: ["value1", "value2"] }); }); + + it("should skip null/undefined array entries by default", () => { + const searchParams = new URLSearchParams("ids[]=1&ids[]=null&ids[]=2"); + const result = parseSearchParams(searchParams); + expect(result).toEqual({ "ids[]": ["1", null, "2"] }); + }); + + it("should accumulate more than two values for the same non-[] key into an array", () => { + const searchParams = new URLSearchParams("tag=a&tag=b&tag=c"); + const result = parseSearchParams(searchParams); + expect(result).toEqual({ tag: ["a", "b", "c"] }); + }); +}); + +describe("getLiteralValue", () => { + it("should convert the string 'null' to null", () => { + expect(getLiteralValue("null")).toBeNull(); + }); + + it("should convert the string 'undefined' to undefined", () => { + expect(getLiteralValue("undefined")).toBeUndefined(); + }); + + it("should return any other string unchanged", () => { + expect(getLiteralValue("hello")).toBe("hello"); + expect(getLiteralValue("")).toBe(""); + expect(getLiteralValue("0")).toBe("0"); + expect(getLiteralValue("false")).toBe("false"); + }); });