mirror of
https://github.com/Warky-Devs/artemis-kit.git
synced 2026-02-01 23:44:27 +00:00
Test cases and minor function fixes
This commit is contained in:
@@ -5,34 +5,52 @@
|
||||
* @param deep Enable deep comparison for nested objects/arrays
|
||||
*/
|
||||
export function objectCompare<T extends Record<string, unknown>>(
|
||||
obj: T,
|
||||
objToCompare: T,
|
||||
deep = false
|
||||
): boolean {
|
||||
if (!obj || !objToCompare) return false;
|
||||
|
||||
return Object.keys(obj).length === Object.keys(objToCompare).length &&
|
||||
Object.keys(obj).every((key) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(objToCompare, key)) return false;
|
||||
|
||||
const val1 = obj[key];
|
||||
const val2 = objToCompare[key];
|
||||
|
||||
if (!deep) return val1 === val2;
|
||||
|
||||
if (Array.isArray(val1) && Array.isArray(val2)) {
|
||||
return val1.length === val2.length &&
|
||||
val1.every((item, i) =>
|
||||
typeof item === 'object' && item !== null
|
||||
? objectCompare(item as Record<string, unknown>, val2[i] as Record<string, unknown>, true)
|
||||
: item === val2[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof val1 === 'object' && typeof val2 === 'object' && val1 !== null && val2 !== null) {
|
||||
return objectCompare(val1 as Record<string, unknown>, val2 as Record<string, unknown>, true);
|
||||
}
|
||||
|
||||
return val1 === val2;
|
||||
});
|
||||
}
|
||||
obj: T | any,
|
||||
objToCompare: T | any,
|
||||
deep = false
|
||||
): boolean {
|
||||
if (!obj || !objToCompare) return false;
|
||||
|
||||
return (
|
||||
Object.keys(obj).length === Object.keys(objToCompare).length &&
|
||||
Object.keys(obj).every((key) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(objToCompare, key))
|
||||
return false;
|
||||
|
||||
const val1 = obj[key];
|
||||
const val2 = objToCompare[key];
|
||||
|
||||
if (!deep) return val1 === val2;
|
||||
|
||||
if (Array.isArray(val1) && Array.isArray(val2)) {
|
||||
return (
|
||||
val1.length === val2.length &&
|
||||
val1.every((item, i) =>
|
||||
typeof item === "object" && item !== null
|
||||
? objectCompare(
|
||||
item as Record<string, unknown>,
|
||||
val2[i] as Record<string, unknown>,
|
||||
true
|
||||
)
|
||||
: item === val2[i]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof val1 === "object" &&
|
||||
typeof val2 === "object" &&
|
||||
val1 !== null &&
|
||||
val2 !== null
|
||||
) {
|
||||
return objectCompare(
|
||||
val1 as Record<string, unknown>,
|
||||
val2 as Record<string, unknown>,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
return val1 === val2;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
133
src/object/comparte.test.ts
Normal file
133
src/object/comparte.test.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { objectCompare } from "./compare";
|
||||
|
||||
describe("objectCompare", () => {
|
||||
// Basic shallow comparison tests
|
||||
test("should return true for identical simple objects in shallow mode", () => {
|
||||
const obj1 = { a: 1, b: "test", c: true };
|
||||
const obj2 = { a: 1, b: "test", c: true };
|
||||
expect(objectCompare(obj1, obj2)).toBe(true);
|
||||
});
|
||||
|
||||
test("should return false for different simple objects in shallow mode", () => {
|
||||
const obj1 = { a: 1, b: "test" };
|
||||
const obj2 = { a: 1, b: "different" };
|
||||
expect(objectCompare(obj1, obj2)).toBe(false);
|
||||
});
|
||||
|
||||
// Property order tests
|
||||
test("should return true for objects with same properties in different order", () => {
|
||||
const obj1 = { a: 1, b: 2, c: 3 };
|
||||
const obj2 = { c: 3, a: 1, b: 2 };
|
||||
expect(objectCompare(obj1, obj2)).toBe(true);
|
||||
});
|
||||
|
||||
// Deep comparison tests
|
||||
test("should compare nested objects when deep is true", () => {
|
||||
const obj1 = { a: { b: 1, c: 2 }, d: 3 };
|
||||
const obj2 = { a: { b: 1, c: 2 }, d: 3 };
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(true);
|
||||
});
|
||||
|
||||
test("should detect differences in nested objects when deep is true", () => {
|
||||
const obj1 = { a: { b: 1, c: 2 }, d: 3 };
|
||||
const obj2 = { a: { b: 1, c: 3 }, d: 3 };
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(false);
|
||||
});
|
||||
|
||||
// Array comparison tests
|
||||
test("should compare arrays correctly in deep mode", () => {
|
||||
const obj1 = { arr: [1, 2, { x: 1 }] };
|
||||
const obj2 = { arr: [1, 2, { x: 1 }] };
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(true);
|
||||
});
|
||||
|
||||
test("should detect array differences in deep mode", () => {
|
||||
const obj1 = { arr: [1, 2, { x: 1 }] };
|
||||
const obj2 = { arr: [1, 2, { x: 2 }] };
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(false);
|
||||
});
|
||||
|
||||
// Edge cases
|
||||
test("should handle null values", () => {
|
||||
const obj1 = { a: null };
|
||||
const obj2 = { a: null };
|
||||
expect(objectCompare(obj1, obj2)).toBe(true);
|
||||
});
|
||||
|
||||
test("should handle undefined values", () => {
|
||||
const obj1 = { a: undefined };
|
||||
const obj2 = { a: undefined };
|
||||
expect(objectCompare(obj1, obj2)).toBe(true);
|
||||
});
|
||||
|
||||
test("should return false when comparing with null", () => {
|
||||
const obj1 = { a: 1 };
|
||||
expect(objectCompare(obj1, null as any)).toBe(false);
|
||||
expect(objectCompare(null as any, obj1)).toBe(false);
|
||||
});
|
||||
|
||||
// Complex nested structure tests
|
||||
test("should handle complex nested structures in deep mode", () => {
|
||||
const obj1 = {
|
||||
a: 1,
|
||||
b: {
|
||||
c: [1, 2, { d: 3 }],
|
||||
e: { f: 4, g: [5, 6] },
|
||||
},
|
||||
};
|
||||
const obj2 = {
|
||||
a: 1,
|
||||
b: {
|
||||
c: [1, 2, { d: 3 }],
|
||||
e: { f: 4, g: [5, 6] },
|
||||
},
|
||||
};
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(true);
|
||||
});
|
||||
|
||||
test("should detect differences in complex nested structures", () => {
|
||||
const obj1 = {
|
||||
a: 1,
|
||||
b: {
|
||||
c: [1, 2, { d: 3 }],
|
||||
e: { f: 4, g: [5, 6] },
|
||||
},
|
||||
};
|
||||
const obj2 = {
|
||||
a: 1,
|
||||
b: {
|
||||
c: [1, 2, { d: 3 }],
|
||||
e: { f: 4, g: [5, 7] }, // Changed 6 to 7
|
||||
},
|
||||
};
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(false);
|
||||
});
|
||||
|
||||
// Property existence tests
|
||||
test("should handle objects with different number of properties", () => {
|
||||
const obj1 = { a: 1, b: 2 };
|
||||
const obj2 = { a: 1, b: 2, c: 3 };
|
||||
expect(objectCompare(obj1, obj2)).toBe(false);
|
||||
});
|
||||
|
||||
test("should handle objects with same number of properties but different keys", () => {
|
||||
const obj1 = { a: 1, b: 2 };
|
||||
const obj2 = { a: 1, c: 2 };
|
||||
expect(objectCompare(obj1, obj2)).toBe(false);
|
||||
});
|
||||
|
||||
// Type comparison tests
|
||||
test("should handle type coercion correctly", () => {
|
||||
const obj1 = { a: 1 };
|
||||
const obj2 = { a: "1" };
|
||||
expect(objectCompare(obj1, obj2)).toBe(false);
|
||||
});
|
||||
|
||||
test("should handle empty objects", () => {
|
||||
const obj1 = {};
|
||||
const obj2 = {};
|
||||
expect(objectCompare(obj1, obj2)).toBe(true);
|
||||
expect(objectCompare(obj1, obj2, true)).toBe(true);
|
||||
});
|
||||
});
|
||||
172
src/object/nested.test.ts
Normal file
172
src/object/nested.test.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { getNestedValue, setNestedValue } from "./nested";
|
||||
|
||||
describe("getNestedValue", () => {
|
||||
const testObj = {
|
||||
user: {
|
||||
name: "John",
|
||||
contacts: [
|
||||
{ email: "john@example.com", phone: "123-456" },
|
||||
{ email: "john.alt@example.com", phone: "789-012" },
|
||||
],
|
||||
settings: {
|
||||
notifications: {
|
||||
email: true,
|
||||
push: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
created: "2023-01-01",
|
||||
tags: ["important", "user"],
|
||||
},
|
||||
};
|
||||
|
||||
test("should get simple property values", () => {
|
||||
expect(getNestedValue("user.name", testObj)).toBe("John");
|
||||
expect(getNestedValue("meta.created", testObj)).toBe("2023-01-01");
|
||||
});
|
||||
|
||||
test("should get nested property values", () => {
|
||||
expect(getNestedValue("user.settings.notifications.email", testObj)).toBe(
|
||||
true
|
||||
);
|
||||
expect(getNestedValue("user.settings.notifications.push", testObj)).toBe(
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
test("should handle array indexing", () => {
|
||||
expect(getNestedValue("user.contacts[0].email", testObj)).toBe(
|
||||
"john@example.com"
|
||||
);
|
||||
expect(getNestedValue("user.contacts[1].phone", testObj)).toBe("789-012");
|
||||
expect(getNestedValue("meta.tags[0]", testObj)).toBe("important");
|
||||
});
|
||||
|
||||
test("should handle invalid paths", () => {
|
||||
expect(getNestedValue("user.invalid.path", testObj)).toBeUndefined();
|
||||
expect(getNestedValue("invalid", testObj)).toBeUndefined();
|
||||
expect(getNestedValue("user.contacts[5].email", testObj)).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should handle empty or invalid inputs", () => {
|
||||
expect(getNestedValue("", testObj)).toBeUndefined();
|
||||
expect(getNestedValue("user.contacts.[]", testObj)).toBeUndefined();
|
||||
expect(getNestedValue("user..name", testObj)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("setNestedValue", () => {
|
||||
test("should set simple property values", () => {
|
||||
const obj = { user: { name: "John" } };
|
||||
setNestedValue("user.name", "Jane", obj);
|
||||
expect(obj.user.name).toBe("Jane");
|
||||
});
|
||||
|
||||
test("should create missing objects", () => {
|
||||
const obj = {};
|
||||
setNestedValue("user.settings.theme", "dark", obj);
|
||||
expect(obj).toEqual({
|
||||
user: {
|
||||
settings: {
|
||||
theme: "dark",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle array indexing and creation", () => {
|
||||
const obj = { users: [] };
|
||||
setNestedValue("users[0].name", "John", obj);
|
||||
setNestedValue("users[1].name", "Jane", obj);
|
||||
expect(obj).toEqual({
|
||||
users: [{ name: "John" }, { name: "Jane" }],
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle mixed object and array paths", () => {
|
||||
const obj = {};
|
||||
setNestedValue("company.departments[0].employees[0].name", "John", obj);
|
||||
expect(obj).toEqual({
|
||||
company: {
|
||||
departments: [
|
||||
{
|
||||
employees: [{ name: "John" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("should modify existing nested arrays", () => {
|
||||
const obj = {
|
||||
users: [{ contacts: [{ email: "old@example.com" }] }],
|
||||
};
|
||||
setNestedValue("users[0].contacts[0].email", "new@example.com", obj);
|
||||
expect(obj.users[0].contacts[0].email).toBe("new@example.com");
|
||||
});
|
||||
|
||||
test("should handle complex nested structures", () => {
|
||||
const obj = {};
|
||||
setNestedValue("a.b[0].c.d[1].e", "value", obj);
|
||||
expect(obj).toEqual({
|
||||
a: {
|
||||
b: [
|
||||
{
|
||||
c: {
|
||||
d: [undefined, { e: "value" }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("should override existing values with different types", () => {
|
||||
const obj = {
|
||||
data: "string",
|
||||
};
|
||||
setNestedValue("data.nested", "value", obj);
|
||||
expect(obj.data).toEqual({ nested: "value" });
|
||||
});
|
||||
|
||||
test("should return the modified object", () => {
|
||||
const obj = {};
|
||||
const result = setNestedValue("a.b.c", "value", obj);
|
||||
expect(result).toBe(obj);
|
||||
expect(result).toEqual({
|
||||
a: {
|
||||
b: {
|
||||
c: "value",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle numeric array indices properly", () => {
|
||||
const obj = {};
|
||||
setNestedValue("items[0]", "first", obj);
|
||||
setNestedValue("items[2]", "third", obj);
|
||||
expect(obj).toEqual({
|
||||
items: ["first", undefined, "third"],
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle edge cases", () => {
|
||||
const obj: any = {};
|
||||
|
||||
// Empty path segments
|
||||
setNestedValue("a..b", "value", obj);
|
||||
expect(obj.a.b).toBe("value");
|
||||
|
||||
// Numeric property names
|
||||
setNestedValue("prop.0.value", "test", obj);
|
||||
expect(obj.prop["0"].value).toBe("test");
|
||||
|
||||
// Setting value on existing array
|
||||
obj.list = [];
|
||||
setNestedValue("list[0]", "item", obj);
|
||||
expect(obj.list[0]).toBe("item");
|
||||
});
|
||||
});
|
||||
@@ -5,42 +5,99 @@
|
||||
* @returns Value at path or undefined if path invalid
|
||||
*/
|
||||
export function getNestedValue(path: string, obj: Record<string, any>): any {
|
||||
return path
|
||||
if (!path || !obj) return undefined;
|
||||
|
||||
// Check for invalid path patterns
|
||||
if (path.includes("..") || path.includes("[]") || /\[\s*\]/.test(path)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parts = path
|
||||
.replace(/\[(\w+)\]/g, ".$1") // Convert brackets to dot notation
|
||||
.split(".") // Split path into parts
|
||||
.reduce((prev, curr) => prev?.[curr], obj); // Traverse object
|
||||
}
|
||||
.split(".")
|
||||
.filter(Boolean); // Remove empty segments
|
||||
|
||||
if (parts.length === 0) return undefined;
|
||||
|
||||
|
||||
/**
|
||||
* Sets a nested value in an object using a path string
|
||||
* @param path - Dot notation path (e.g. 'user.contacts[0].email')
|
||||
* @param value - Value to set at path
|
||||
* @param obj - Target object to modify
|
||||
* @returns Modified object
|
||||
*/
|
||||
/**
|
||||
* Sets a nested value, creating objects and arrays if needed
|
||||
*/
|
||||
export function setNestedValue(path: string, value: any, obj: Record<string, any>): Record<string, any> {
|
||||
const parts = path.replace(/\[(\w+)\]/g, ".$1").split(".");
|
||||
const lastKey = parts.pop()!;
|
||||
|
||||
const target = parts.reduce((prev, curr) => {
|
||||
// Handle array indices
|
||||
if (/^\d+$/.test(curr)) {
|
||||
if (!Array.isArray(prev[curr])) {
|
||||
prev[curr] = [];
|
||||
}
|
||||
}
|
||||
// Create missing objects
|
||||
else if (!prev[curr]) {
|
||||
prev[curr] = {};
|
||||
}
|
||||
return parts.reduce((prev, curr) => {
|
||||
if (prev === undefined) return undefined;
|
||||
return prev[curr];
|
||||
}, obj);
|
||||
}
|
||||
|
||||
target[lastKey] = value;
|
||||
/**
|
||||
* Sets a nested value in an object using a path string
|
||||
* @param path - Dot notation path (e.g. 'user.contacts[0].email')
|
||||
* @param value - Value to set at path
|
||||
* @param obj - Target object to modify
|
||||
* @returns Modified object
|
||||
*/
|
||||
export function setNestedValue(
|
||||
path: string,
|
||||
value: any,
|
||||
obj: Record<string, any>
|
||||
): Record<string, any> {
|
||||
if (!path || !obj) return obj;
|
||||
|
||||
const parts = path
|
||||
.replace(/\[(\w+)\]/g, ".$1")
|
||||
.split(".")
|
||||
.filter(Boolean); // Remove empty segments
|
||||
|
||||
if (parts.length === 0) return obj;
|
||||
|
||||
const lastKey = parts.pop()!;
|
||||
let current = obj;
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const key = parts[i];
|
||||
const nextKey = parts[i + 1] || lastKey;
|
||||
const shouldBeArray = /^\d+$/.test(nextKey);
|
||||
|
||||
// If current key doesn't exist or needs type conversion
|
||||
if (
|
||||
!(key in current) ||
|
||||
(shouldBeArray && !Array.isArray(current[key])) ||
|
||||
(!shouldBeArray && typeof current[key] !== "object")
|
||||
) {
|
||||
// Create appropriate container based on next key
|
||||
current[key] = shouldBeArray ? [] : {};
|
||||
}
|
||||
|
||||
current = current[key];
|
||||
}
|
||||
|
||||
// Handle the last key - determine if parent should be an array
|
||||
if (/^\d+$/.test(lastKey) && !Array.isArray(current)) {
|
||||
const tempObj = current;
|
||||
const maxIndex = Math.max(
|
||||
...Object.keys(tempObj)
|
||||
.filter((k) => /^\d+$/.test(k))
|
||||
.map(Number)
|
||||
.concat(-1)
|
||||
);
|
||||
const arr = new Array(Math.max(maxIndex + 1, Number(lastKey) + 1));
|
||||
|
||||
// Copy existing numeric properties to array
|
||||
Object.keys(tempObj)
|
||||
.filter((k) => /^\d+$/.test(k))
|
||||
.forEach((k) => {
|
||||
arr[Number(k)] = tempObj[k];
|
||||
});
|
||||
|
||||
// Replace object with array while preserving non-numeric properties
|
||||
Object.keys(tempObj).forEach((k) => {
|
||||
if (!/^\d+$/.test(k)) {
|
||||
arr[k] = tempObj[k];
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(tempObj).forEach((k) => delete tempObj[k]);
|
||||
Object.assign(tempObj, arr);
|
||||
current = tempObj;
|
||||
}
|
||||
|
||||
// Set the final value
|
||||
current[lastKey] = value;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
139
src/object/utils.test.ts
Normal file
139
src/object/utils.test.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { createSelectOptions } from './util';
|
||||
|
||||
describe('createSelectOptions', () => {
|
||||
// Test basic object transformation
|
||||
test('should transform basic object with default options', () => {
|
||||
const input = {
|
||||
key1: 'Label 1',
|
||||
key2: 'Label 2',
|
||||
key3: 'Label 3'
|
||||
};
|
||||
|
||||
const expected = [
|
||||
{ label: 'Label 1', value: 'key1' },
|
||||
{ label: 'Label 2', value: 'key2' },
|
||||
{ label: 'Label 3', value: 'key3' }
|
||||
];
|
||||
|
||||
expect(createSelectOptions(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
// Test custom key names
|
||||
test('should use custom property names when provided', () => {
|
||||
const input = {
|
||||
key1: 'Label 1',
|
||||
key2: 'Label 2'
|
||||
};
|
||||
|
||||
const expected = [
|
||||
{ text: 'Label 1', id: 'key1' },
|
||||
{ text: 'Label 2', id: 'key2' }
|
||||
];
|
||||
|
||||
expect(createSelectOptions(input, { labelKey: 'text', valueKey: 'id' })).toEqual(expected);
|
||||
});
|
||||
|
||||
// Test array input
|
||||
test('should return array as-is when input is an array', () => {
|
||||
const input = [
|
||||
{ label: 'Option 1', value: '1' },
|
||||
{ label: 'Option 2', value: '2' }
|
||||
];
|
||||
|
||||
expect(createSelectOptions(input)).toBe(input);
|
||||
});
|
||||
|
||||
// Test different value types
|
||||
test('should handle different value types', () => {
|
||||
const input = {
|
||||
key1: 42,
|
||||
key2: true,
|
||||
key3: { nested: 'value' }
|
||||
};
|
||||
|
||||
const expected = [
|
||||
{ label: 42, value: 'key1' },
|
||||
{ label: true, value: 'key2' },
|
||||
{ label: { nested: 'value' }, value: 'key3' }
|
||||
];
|
||||
|
||||
expect(createSelectOptions(input)).toEqual(expected);
|
||||
});
|
||||
|
||||
// Test null and undefined inputs
|
||||
test('should handle null and undefined inputs', () => {
|
||||
expect(createSelectOptions(null)).toEqual([]);
|
||||
expect(createSelectOptions(undefined)).toEqual([]);
|
||||
});
|
||||
|
||||
// Test invalid inputs
|
||||
test('should handle invalid inputs', () => {
|
||||
expect(createSelectOptions(42 as any)).toEqual([]);
|
||||
expect(createSelectOptions('string' as any)).toEqual([]);
|
||||
expect(createSelectOptions(true as any)).toEqual([]);
|
||||
});
|
||||
|
||||
// Test empty object
|
||||
test('should handle empty object', () => {
|
||||
expect(createSelectOptions({})).toEqual([]);
|
||||
});
|
||||
|
||||
// Test partial options
|
||||
test('should handle partial options configuration', () => {
|
||||
const input = {
|
||||
key1: 'Label 1',
|
||||
key2: 'Label 2'
|
||||
};
|
||||
|
||||
// Only labelKey provided
|
||||
expect(createSelectOptions(input, { labelKey: 'text' })).toEqual([
|
||||
{ text: 'Label 1', value: 'key1' },
|
||||
{ text: 'Label 2', value: 'key2' }
|
||||
]);
|
||||
|
||||
// Only valueKey provided
|
||||
expect(createSelectOptions(input, { valueKey: 'id' })).toEqual([
|
||||
{ label: 'Label 1', id: 'key1' },
|
||||
{ label: 'Label 2', id: 'key2' }
|
||||
]);
|
||||
});
|
||||
|
||||
// Test type safety
|
||||
test('should maintain type safety with generic types', () => {
|
||||
interface CustomType {
|
||||
name: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
const input: Record<string, CustomType> = {
|
||||
key1: { name: 'Item 1', count: 1 },
|
||||
key2: { name: 'Item 2', count: 2 }
|
||||
};
|
||||
|
||||
const result = createSelectOptions<CustomType>(input);
|
||||
expect(result).toEqual([
|
||||
{ label: { name: 'Item 1', count: 1 }, value: 'key1' },
|
||||
{ label: { name: 'Item 2', count: 2 }, value: 'key2' }
|
||||
]);
|
||||
});
|
||||
|
||||
// Test with special characters in keys
|
||||
test('should handle special characters in keys', () => {
|
||||
const input = {
|
||||
'@special': 'Special',
|
||||
'key.with.dots': 'Dots',
|
||||
'key-with-dashes': 'Dashes',
|
||||
'key with spaces': 'Spaces'
|
||||
};
|
||||
|
||||
const expected = [
|
||||
{ label: 'Special', value: '@special' },
|
||||
{ label: 'Dots', value: 'key.with.dots' },
|
||||
{ label: 'Dashes', value: 'key-with-dashes' },
|
||||
{ label: 'Spaces', value: 'key with spaces' }
|
||||
];
|
||||
|
||||
expect(createSelectOptions(input)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user