188 lines
7.9 KiB
TypeScript
188 lines
7.9 KiB
TypeScript
import { toQueryString } from "../../../src/core/url/index";
|
|
|
|
describe("Test qs toQueryString", () => {
|
|
describe("Basic functionality", () => {
|
|
it("should return empty string for null/undefined", () => {
|
|
expect(toQueryString(null)).toBe("");
|
|
expect(toQueryString(undefined)).toBe("");
|
|
});
|
|
|
|
it("should return empty string for primitive values", () => {
|
|
expect(toQueryString("hello")).toBe("");
|
|
expect(toQueryString(42)).toBe("");
|
|
expect(toQueryString(true)).toBe("");
|
|
expect(toQueryString(false)).toBe("");
|
|
});
|
|
|
|
it("should handle empty objects", () => {
|
|
expect(toQueryString({})).toBe("");
|
|
});
|
|
|
|
it("should handle simple key-value pairs", () => {
|
|
const obj = { name: "John", age: 30 };
|
|
expect(toQueryString(obj)).toBe("name=John&age=30");
|
|
});
|
|
});
|
|
|
|
describe("Array handling", () => {
|
|
it("should handle arrays with indices format (default)", () => {
|
|
const obj = { items: ["a", "b", "c"] };
|
|
expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=b&items%5B2%5D=c");
|
|
});
|
|
|
|
it("should handle arrays with repeat format", () => {
|
|
const obj = { items: ["a", "b", "c"] };
|
|
expect(toQueryString(obj, { arrayFormat: "repeat" })).toBe("items=a&items=b&items=c");
|
|
});
|
|
|
|
it("should handle empty arrays", () => {
|
|
const obj = { items: [] };
|
|
expect(toQueryString(obj)).toBe("");
|
|
});
|
|
|
|
it("should handle arrays with mixed types", () => {
|
|
const obj = { mixed: ["string", 42, true, false] };
|
|
expect(toQueryString(obj)).toBe("mixed%5B0%5D=string&mixed%5B1%5D=42&mixed%5B2%5D=true&mixed%5B3%5D=false");
|
|
});
|
|
|
|
it("should handle arrays with objects", () => {
|
|
const obj = { users: [{ name: "John" }, { name: "Jane" }] };
|
|
expect(toQueryString(obj)).toBe("users%5B0%5D%5Bname%5D=John&users%5B1%5D%5Bname%5D=Jane");
|
|
});
|
|
|
|
it("should handle arrays with objects in repeat format", () => {
|
|
const obj = { users: [{ name: "John" }, { name: "Jane" }] };
|
|
expect(toQueryString(obj, { arrayFormat: "repeat" })).toBe("users%5Bname%5D=John&users%5Bname%5D=Jane");
|
|
});
|
|
});
|
|
|
|
describe("Nested objects", () => {
|
|
it("should handle nested objects", () => {
|
|
const obj = { user: { name: "John", age: 30 } };
|
|
expect(toQueryString(obj)).toBe("user%5Bname%5D=John&user%5Bage%5D=30");
|
|
});
|
|
|
|
it("should handle deeply nested objects", () => {
|
|
const obj = { user: { profile: { name: "John", settings: { theme: "dark" } } } };
|
|
expect(toQueryString(obj)).toBe(
|
|
"user%5Bprofile%5D%5Bname%5D=John&user%5Bprofile%5D%5Bsettings%5D%5Btheme%5D=dark",
|
|
);
|
|
});
|
|
|
|
it("should handle empty nested objects", () => {
|
|
const obj = { user: {} };
|
|
expect(toQueryString(obj)).toBe("");
|
|
});
|
|
});
|
|
|
|
describe("Encoding", () => {
|
|
it("should encode by default", () => {
|
|
const obj = { name: "John Doe", email: "john@example.com" };
|
|
expect(toQueryString(obj)).toBe("name=John%20Doe&email=john%40example.com");
|
|
});
|
|
|
|
it("should not encode when encode is false", () => {
|
|
const obj = { name: "John Doe", email: "john@example.com" };
|
|
expect(toQueryString(obj, { encode: false })).toBe("name=John Doe&email=john@example.com");
|
|
});
|
|
|
|
it("should encode special characters in keys", () => {
|
|
const obj = { "user name": "John", "email[primary]": "john@example.com" };
|
|
expect(toQueryString(obj)).toBe("user%20name=John&email%5Bprimary%5D=john%40example.com");
|
|
});
|
|
|
|
it("should not encode special characters in keys when encode is false", () => {
|
|
const obj = { "user name": "John", "email[primary]": "john@example.com" };
|
|
expect(toQueryString(obj, { encode: false })).toBe("user name=John&email[primary]=john@example.com");
|
|
});
|
|
});
|
|
|
|
describe("Mixed scenarios", () => {
|
|
it("should handle complex nested structures", () => {
|
|
const obj = {
|
|
filters: {
|
|
status: ["active", "pending"],
|
|
category: {
|
|
type: "electronics",
|
|
subcategories: ["phones", "laptops"],
|
|
},
|
|
},
|
|
sort: { field: "name", direction: "asc" },
|
|
};
|
|
expect(toQueryString(obj)).toBe(
|
|
"filters%5Bstatus%5D%5B0%5D=active&filters%5Bstatus%5D%5B1%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D%5B0%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D%5B1%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc",
|
|
);
|
|
});
|
|
|
|
it("should handle complex nested structures with repeat format", () => {
|
|
const obj = {
|
|
filters: {
|
|
status: ["active", "pending"],
|
|
category: {
|
|
type: "electronics",
|
|
subcategories: ["phones", "laptops"],
|
|
},
|
|
},
|
|
sort: { field: "name", direction: "asc" },
|
|
};
|
|
expect(toQueryString(obj, { arrayFormat: "repeat" })).toBe(
|
|
"filters%5Bstatus%5D=active&filters%5Bstatus%5D=pending&filters%5Bcategory%5D%5Btype%5D=electronics&filters%5Bcategory%5D%5Bsubcategories%5D=phones&filters%5Bcategory%5D%5Bsubcategories%5D=laptops&sort%5Bfield%5D=name&sort%5Bdirection%5D=asc",
|
|
);
|
|
});
|
|
|
|
it("should handle arrays with null/undefined values", () => {
|
|
const obj = { items: ["a", null, "c", undefined, "e"] };
|
|
expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=&items%5B2%5D=c&items%5B4%5D=e");
|
|
});
|
|
|
|
it("should handle objects with null/undefined values", () => {
|
|
const obj = { name: "John", age: null, email: undefined, active: true };
|
|
expect(toQueryString(obj)).toBe("name=John&age=&active=true");
|
|
});
|
|
});
|
|
|
|
describe("Edge cases", () => {
|
|
it("should handle numeric keys", () => {
|
|
const obj = { "0": "zero", "1": "one" };
|
|
expect(toQueryString(obj)).toBe("0=zero&1=one");
|
|
});
|
|
|
|
it("should handle boolean values in objects", () => {
|
|
const obj = { enabled: true, disabled: false };
|
|
expect(toQueryString(obj)).toBe("enabled=true&disabled=false");
|
|
});
|
|
|
|
it("should handle empty strings", () => {
|
|
const obj = { name: "", description: "test" };
|
|
expect(toQueryString(obj)).toBe("name=&description=test");
|
|
});
|
|
|
|
it("should handle zero values", () => {
|
|
const obj = { count: 0, price: 0.0 };
|
|
expect(toQueryString(obj)).toBe("count=0&price=0");
|
|
});
|
|
|
|
it("should handle arrays with empty strings", () => {
|
|
const obj = { items: ["a", "", "c"] };
|
|
expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=&items%5B2%5D=c");
|
|
});
|
|
});
|
|
|
|
describe("Options combinations", () => {
|
|
it("should respect both arrayFormat and encode options", () => {
|
|
const obj = { items: ["a & b", "c & d"] };
|
|
expect(toQueryString(obj, { arrayFormat: "repeat", encode: false })).toBe("items=a & b&items=c & d");
|
|
});
|
|
|
|
it("should use default options when none provided", () => {
|
|
const obj = { items: ["a", "b"] };
|
|
expect(toQueryString(obj)).toBe("items%5B0%5D=a&items%5B1%5D=b");
|
|
});
|
|
|
|
it("should merge provided options with defaults", () => {
|
|
const obj = { items: ["a", "b"], name: "John Doe" };
|
|
expect(toQueryString(obj, { encode: false })).toBe("items[0]=a&items[1]=b&name=John Doe");
|
|
});
|
|
});
|
|
});
|