diff --git a/functionsUnittests/objectFunctions/applyDefaults.test.ts b/functionsUnittests/objectFunctions/applyDefaults.test.ts new file mode 100644 index 00000000..021ccc1c --- /dev/null +++ b/functionsUnittests/objectFunctions/applyDefaults.test.ts @@ -0,0 +1,80 @@ +import { applyDefaults } from '../../objectFunctions/applyDefaults'; + +describe('applyDefaults', () => { + // Test case 1: Apply defaults to an object with missing properties + it('1. should apply defaults to an object with missing properties', () => { + const obj = { a: 1 }; + const defaults = { a: 0, b: 2 }; + const result = applyDefaults(obj, defaults); + const expected = { a: 1, b: 2 }; + expect(result).toEqual(expected); + }); + + // Test case 2: Apply defaults to an object with all properties present + it('2. should not overwrite existing properties with defaults', () => { + const obj = { a: 1, b: 2 }; + const defaults = { a: 0, b: 3 }; + const result = applyDefaults(obj, defaults); + const expected = { a: 1, b: 2 }; + expect(result).toEqual(expected); + }); + + // Test case 3: Apply defaults to an empty object + it('3. should apply defaults to an empty object', () => { + const obj = {}; + const defaults = { a: 1, b: 2 }; + const result = applyDefaults(obj as any, defaults); + const expected = { a: 1, b: 2 }; + expect(result).toEqual(expected); + }); + + // Test case 4: Handle non-object input for the first parameter (number) + it('4. should throw a TypeError if the first input is a number', () => { + expect(() => applyDefaults(42 as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 5: Handle non-object input for the first parameter (string) + it('5. should throw a TypeError if the first input is a string', () => { + expect(() => applyDefaults('string' as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 6: Handle non-object input for the first parameter (boolean) + it('6. should throw a TypeError if the first input is a boolean', () => { + expect(() => applyDefaults(true as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 7: Handle non-object input for the first parameter (null) + it('7. should throw a TypeError if the first input is null', () => { + expect(() => applyDefaults(null as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 8: Handle non-object input for the first parameter (undefined) + it('8. should throw a TypeError if the first input is undefined', () => { + expect(() => applyDefaults(undefined as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 9: Handle non-object input for the second parameter (number) + it('9. should throw a TypeError if the second input is a number', () => { + expect(() => applyDefaults({ a: 1 }, 42 as any)).toThrow(TypeError); + }); + + // Test case 10: Handle non-object input for the second parameter (string) + it('10. should throw a TypeError if the second input is a string', () => { + expect(() => applyDefaults({ a: 1 }, 'string' as any)).toThrow(TypeError); + }); + + // Test case 11: Handle non-object input for the second parameter (boolean) + it('11. should throw a TypeError if the second input is a boolean', () => { + expect(() => applyDefaults({ a: 1 }, true as any)).toThrow(TypeError); + }); + + // Test case 12: Handle non-object input for the second parameter (null) + it('12. should throw a TypeError if the second input is null', () => { + expect(() => applyDefaults({ a: 1 }, null as any)).toThrow(TypeError); + }); + + // Test case 13: Handle non-object input for the second parameter (undefined) + it('13. should throw a TypeError if the second input is undefined', () => { + expect(() => applyDefaults({ a: 1 }, undefined as any)).toThrow(TypeError); + }); +}); diff --git a/functionsUnittests/objectFunctions/countProperties.test.ts b/functionsUnittests/objectFunctions/countProperties.test.ts new file mode 100644 index 00000000..5a9c5d2d --- /dev/null +++ b/functionsUnittests/objectFunctions/countProperties.test.ts @@ -0,0 +1,52 @@ +import { countProperties } from '../../objectFunctions/countProperties'; + +describe('countProperties', () => { + // Test case 1: Count properties of a simple object + it('1. should count properties of a simple object', () => { + const obj = { a: 1, b: 2, c: 3 }; + const result = countProperties(obj); + const expected = 3; + expect(result).toBe(expected); + }); + + // Test case 2: Count properties of a nested object + it('2. should count properties of a nested object', () => { + const obj = { a: 1, b: { c: 2, d: 3 }, e: 4 }; + const result = countProperties(obj); + const expected = 3; // Only top-level properties are counted + expect(result).toBe(expected); + }); + + // Test case 3: Count properties of an empty object + it('3. should count properties of an empty object', () => { + const obj = {}; + const result = countProperties(obj); + const expected = 0; + expect(result).toBe(expected); + }); + + // Test case 4: Handle non-object input (number) + it('4. should throw a TypeError if input is a number', () => { + expect(() => countProperties(42 as any)).toThrow(TypeError); + }); + + // Test case 5: Handle non-object input (string) + it('5. should throw a TypeError if input is a string', () => { + expect(() => countProperties('string' as any)).toThrow(TypeError); + }); + + // Test case 6: Handle non-object input (boolean) + it('6. should throw a TypeError if input is a boolean', () => { + expect(() => countProperties(true as any)).toThrow(TypeError); + }); + + // Test case 7: Handle non-object input (null) + it('7. should throw a TypeError if input is null', () => { + expect(() => countProperties(null as any)).toThrow(TypeError); + }); + + // Test case 8: Handle non-object input (undefined) + it('8. should throw a TypeError if input is undefined', () => { + expect(() => countProperties(undefined as any)).toThrow(TypeError); + }); +}); diff --git a/functionsUnittests/objectFunctions/getObjectDifference.test.ts b/functionsUnittests/objectFunctions/getObjectDifference.test.ts new file mode 100644 index 00000000..656a2e3e --- /dev/null +++ b/functionsUnittests/objectFunctions/getObjectDifference.test.ts @@ -0,0 +1,80 @@ +import { getObjectDifference } from '../../objectFunctions/getObjectDifference'; + +describe('getObjectDifference', () => { + // Test case 1: Get difference between two objects with different values + it('1. should return the difference between two objects with different values', () => { + const obj1 = { a: 1, b: 2, c: 3 }; + const obj2 = { a: 1, b: 3, c: 3 }; + const result = getObjectDifference(obj1, obj2); + const expected = { b: 2 }; + expect(result).toEqual(expected); + }); + + // Test case 2: Get difference between two identical objects + it('2. should return an empty object for two identical objects', () => { + const obj1 = { a: 1, b: 2, c: 3 }; + const obj2 = { a: 1, b: 2, c: 3 }; + const result = getObjectDifference(obj1, obj2); + const expected = {}; + expect(result).toEqual(expected); + }); + + // Test case 3: Get difference between two objects with different keys + it('3. should return the difference for objects with different keys', () => { + const obj1 = { a: 1, b: 2 } as { [key: string]: number }; + const obj2 = { a: 1, c: 3 } as { [key: string]: number }; + const result = getObjectDifference(obj1, obj2); + const expected = { b: 2 }; + expect(result).toEqual(expected); + }); + + // Test case 4: Handle non-object input (number) + it('4. should throw a TypeError if the first input is a number', () => { + expect(() => getObjectDifference(42 as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 5: Handle non-object input (string) + it('5. should throw a TypeError if the first input is a string', () => { + expect(() => getObjectDifference('string' as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 6: Handle non-object input (boolean) + it('6. should throw a TypeError if the first input is a boolean', () => { + expect(() => getObjectDifference(true as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 7: Handle non-object input (null) + it('7. should throw a TypeError if the first input is null', () => { + expect(() => getObjectDifference(null as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 8: Handle non-object input (undefined) + it('8. should throw a TypeError if the first input is undefined', () => { + expect(() => getObjectDifference(undefined as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 9: Handle non-object input for the second parameter (number) + it('9. should throw a TypeError if the second input is a number', () => { + expect(() => getObjectDifference({ a: 1 }, 42 as any)).toThrow(TypeError); + }); + + // Test case 10: Handle non-object input for the second parameter (string) + it('10. should throw a TypeError if the second input is a string', () => { + expect(() => getObjectDifference({ a: 1 }, 'string' as any)).toThrow(TypeError); + }); + + // Test case 11: Handle non-object input for the second parameter (boolean) + it('11. should throw a TypeError if the second input is a boolean', () => { + expect(() => getObjectDifference({ a: 1 }, true as any)).toThrow(TypeError); + }); + + // Test case 12: Handle non-object input for the second parameter (null) + it('12. should throw a TypeError if the second input is null', () => { + expect(() => getObjectDifference({ a: 1 }, null as any)).toThrow(TypeError); + }); + + // Test case 13: Handle non-object input for the second parameter (undefined) + it('13. should throw a TypeError if the second input is undefined', () => { + expect(() => getObjectDifference({ a: 1 }, undefined as any)).toThrow(TypeError); + }); +}); diff --git a/functionsUnittests/objectFunctions/keysToCamelCase.test.ts b/functionsUnittests/objectFunctions/keysToCamelCase.test.ts new file mode 100644 index 00000000..a04626a0 --- /dev/null +++ b/functionsUnittests/objectFunctions/keysToCamelCase.test.ts @@ -0,0 +1,75 @@ +import { keysToCamelCase } from '../../objectFunctions/keysToCamelCase'; + +describe('keysToCamelCase', () => { + // Test case 1: Convert keys of a simple object + it('1. should convert keys of a simple object to camelCase', () => { + const obj = { first_name: 'John', last_name: 'Doe' }; + const result = keysToCamelCase(obj); + const expected = { firstName: 'John', lastName: 'Doe' }; + expect(result).toEqual(expected); + }); + + // Test case 2: Convert keys of a nested object + it('2. should convert keys of a nested object to camelCase', () => { + const obj = { user_info: { first_name: 'John', last_name: 'Doe' } }; + const result = keysToCamelCase(obj); + const expected = { userInfo: { firstName: 'John', lastName: 'Doe' } }; + expect(result).toEqual(expected); + }); + + // Test case 3: Convert keys of an array of objects + it('3. should convert keys of an array of objects to camelCase', () => { + const arr = [{ first_name: 'John' }, { last_name: 'Doe' }]; + const result = keysToCamelCase(arr); + const expected = [{ firstName: 'John' }, { lastName: 'Doe' }]; + expect(result).toEqual(expected); + }); + + // Test case 4: Handle non-object input (number) + it('4. should return the input if it is a number', () => { + const input = 42; + const result = keysToCamelCase(input); + const expected = 42; + expect(result).toBe(expected); + }); + + // Test case 5: Handle non-object input (string) + it('5. should return the input if it is a string', () => { + const input = 'string'; + const result = keysToCamelCase(input); + const expected = 'string'; + expect(result).toBe(expected); + }); + + // Test case 6: Handle non-object input (boolean) + it('6. should return the input if it is a boolean', () => { + const input = true; + const result = keysToCamelCase(input); + const expected = true; + expect(result).toBe(expected); + }); + + // Test case 7: Handle non-object input (null) + it('7. should return the input if it is null', () => { + const input = null; + const result = keysToCamelCase(input); + const expected = null; + expect(result).toBe(expected); + }); + + // Test case 8: Handle non-object input (undefined) + it('8. should return the input if it is undefined', () => { + const input = undefined; + const result = keysToCamelCase(input); + const expected = undefined; + expect(result).toBe(expected); + }); + + // Test case 9: Convert keys with mixed cases + it('9. should convert keys with mixed cases to camelCase', () => { + const obj = { 'first-name': 'John', 'Last_Name': 'Doe' }; + const result = keysToCamelCase(obj); + const expected = { firstName: 'John', lastName: 'Doe' }; + expect(result).toEqual(expected); + }); +}); diff --git a/functionsUnittests/objectFunctions/keysToSnakeCase.test.ts b/functionsUnittests/objectFunctions/keysToSnakeCase.test.ts new file mode 100644 index 00000000..8741a322 --- /dev/null +++ b/functionsUnittests/objectFunctions/keysToSnakeCase.test.ts @@ -0,0 +1,75 @@ +import { keysToSnakeCase } from '../../objectFunctions/keysToSnakeCase'; + +describe('keysToSnakeCase', () => { + // Test case 1: Convert keys of a simple object + it('1. should convert keys of a simple object to snake_case', () => { + const obj = { firstName: 'John', lastName: 'Doe' }; + const result = keysToSnakeCase(obj); + const expected = { first_name: 'John', last_name: 'Doe' }; + expect(result).toEqual(expected); + }); + + // Test case 2: Convert keys of a nested object + it('2. should convert keys of a nested object to snake_case', () => { + const obj = { userInfo: { firstName: 'John', lastName: 'Doe' } }; + const result = keysToSnakeCase(obj); + const expected = { user_info: { first_name: 'John', last_name: 'Doe' } }; + expect(result).toEqual(expected); + }); + + // Test case 3: Convert keys of an array of objects + it('3. should convert keys of an array of objects to snake_case', () => { + const arr = [{ firstName: 'John' }, { lastName: 'Doe' }]; + const result = keysToSnakeCase(arr); + const expected = [{ first_name: 'John' }, { last_name: 'Doe' }]; + expect(result).toEqual(expected); + }); + + // Test case 4: Handle non-object input (number) + it('4. should return the input if it is a number', () => { + const input = 42; + const result = keysToSnakeCase(input); + const expected = 42; + expect(result).toBe(expected); + }); + + // Test case 5: Handle non-object input (string) + it('5. should return the input if it is a string', () => { + const input = 'string'; + const result = keysToSnakeCase(input); + const expected = 'string'; + expect(result).toBe(expected); + }); + + // Test case 6: Handle non-object input (boolean) + it('6. should return the input if it is a boolean', () => { + const input = true; + const result = keysToSnakeCase(input); + const expected = true; + expect(result).toBe(expected); + }); + + // Test case 7: Handle non-object input (null) + it('7. should return the input if it is null', () => { + const input = null; + const result = keysToSnakeCase(input); + const expected = null; + expect(result).toBe(expected); + }); + + // Test case 8: Handle non-object input (undefined) + it('8. should return the input if it is undefined', () => { + const input = undefined; + const result = keysToSnakeCase(input); + const expected = undefined; + expect(result).toBe(expected); + }); + + // Test case 9: Convert keys with mixed cases + it('9. should convert keys with mixed cases to snake_case', () => { + const obj = { firstName: 'John', LastName: 'Doe' }; + const result = keysToSnakeCase(obj); + const expected = { first_name: 'John', last_name: 'Doe' }; + expect(result).toEqual(expected); + }); +}); diff --git a/functionsUnittests/objectFunctions/shallowEqual.test.ts b/functionsUnittests/objectFunctions/shallowEqual.test.ts new file mode 100644 index 00000000..be69e018 --- /dev/null +++ b/functionsUnittests/objectFunctions/shallowEqual.test.ts @@ -0,0 +1,115 @@ +import { shallowEqual } from '../../objectFunctions/shallowEqual'; + +describe('shallowEqual', () => { + // Test case 1: Compare two equal objects + it('1. should return true for two equal objects', () => { + const obj1 = { a: 1, b: 2 }; + const obj2 = { a: 1, b: 2 }; + const result = shallowEqual(obj1, obj2); + const expected = true; + expect(result).toBe(expected); + }); + + // Test case 2: Compare two different objects + it('2. should return false for two different objects', () => { + const obj1 = { a: 1, b: 2 }; + const obj2 = { a: 1, b: 3 }; + const result = shallowEqual(obj1, obj2); + const expected = false; + expect(result).toBe(expected); + }); + + // Test case 3: Compare objects with different keys + it('3. should return false for objects with different keys', () => { + const obj1 = { a: 1, b: 2 }; + const obj2 = { a: 1, c: 2 }; + const result = shallowEqual(obj1, obj2); + const expected = false; + expect(result).toBe(expected); + }); + + // Test case 4: Compare objects with different number of keys + it('4. should return false for objects with different number of keys', () => { + const obj1 = { a: 1, b: 2 }; + const obj2 = { a: 1 }; + const result = shallowEqual(obj1, obj2); + const expected = false; + expect(result).toBe(expected); + }); + + // Test case 5: Handle empty objects + it('5. should return true for two empty objects', () => { + const obj1 = {}; + const obj2 = {}; + const result = shallowEqual(obj1, obj2); + const expected = true; + expect(result).toBe(expected); + }); + + // Test case 6: Handle empty object and non-empty object + it('6. should return false for an empty object and a non-empty object', () => { + const obj1 = {}; + const obj2 = { a: 1 }; + const result = shallowEqual(obj1, obj2); + const expected = false; + expect(result).toBe(expected); + }); + + it('7. should return false for a non-empty object and an empty object', () => { + const obj1 = { a: 1 }; + const obj2 = {}; + const result = shallowEqual(obj1, obj2); + const expected = false; + expect(result).toBe(expected); + }); + + // Test case 8: Handle non-object input (number) + it('8. should throw a TypeError if the first input is a number', () => { + expect(() => shallowEqual(42 as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 9: Handle non-object input (string) + it('9. should throw a TypeError if the first input is a string', () => { + expect(() => shallowEqual('string' as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 10: Handle non-object input (boolean) + it('10. should throw a TypeError if the first input is a boolean', () => { + expect(() => shallowEqual(true as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 11: Handle non-object input (null) + it('11. should throw a TypeError if the first input is null', () => { + expect(() => shallowEqual(null as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 12: Handle non-object input (undefined) + it('12. should throw a TypeError if the first input is undefined', () => { + expect(() => shallowEqual(undefined as any, { a: 1 })).toThrow(TypeError); + }); + + // Test case 13: Handle non-object input for the second parameter (number) + it('13. should throw a TypeError if the second input is a number', () => { + expect(() => shallowEqual({ a: 1 }, 42 as any)).toThrow(TypeError); + }); + + // Test case 14: Handle non-object input for the second parameter (string) + it('14. should throw a TypeError if the second input is a string', () => { + expect(() => shallowEqual({ a: 1 }, 'string' as any)).toThrow(TypeError); + }); + + // Test case 15: Handle non-object input for the second parameter (boolean) + it('15. should throw a TypeError if the second input is a boolean', () => { + expect(() => shallowEqual({ a: 1 }, true as any)).toThrow(TypeError); + }); + + // Test case 16: Handle non-object input for the second parameter (null) + it('16. should throw a TypeError if the second input is null', () => { + expect(() => shallowEqual({ a: 1 }, null as any)).toThrow(TypeError); + }); + + // Test case 17: Handle non-object input for the second parameter (undefined) + it('17. should throw a TypeError if the second input is undefined', () => { + expect(() => shallowEqual({ a: 1 }, undefined as any)).toThrow(TypeError); + }); +}); \ No newline at end of file diff --git a/objectFunctions/applyDefaults.ts b/objectFunctions/applyDefaults.ts new file mode 100644 index 00000000..0fba5d59 --- /dev/null +++ b/objectFunctions/applyDefaults.ts @@ -0,0 +1,14 @@ +/** + * Applies default values to an object. + * + * @param {T} obj - The object to apply defaults to. + * @param {Partial} defaults - The default values to apply. + * @returns {T} - A new object with defaults applied. + * @throws {TypeError} - If the input object or defaults are not objects or are null. + */ +export function applyDefaults>(obj: T, defaults: Partial): T { + if (typeof obj !== 'object' || obj === null || typeof defaults !== 'object' || defaults === null) { + throw new TypeError('Both inputs must be non-null objects'); + } + return { ...defaults, ...obj }; +} \ No newline at end of file diff --git a/objectFunctions/countProperties.ts b/objectFunctions/countProperties.ts new file mode 100644 index 00000000..8a48a0d0 --- /dev/null +++ b/objectFunctions/countProperties.ts @@ -0,0 +1,13 @@ +/** + * Counts the number of properties in an object. + * + * @param {Record} obj - The object to count properties of. + * @returns {number} - The number of properties in the object. + * @throws {TypeError} - If the input is not an object or is null. + */ +export function countProperties(obj: Record): number { + if (typeof obj !== 'object' || obj === null) { + throw new TypeError('Input must be a non-null object'); + } + return Object.keys(obj).length; +} diff --git a/objectFunctions/getObjectDifference.ts b/objectFunctions/getObjectDifference.ts new file mode 100644 index 00000000..218d242c --- /dev/null +++ b/objectFunctions/getObjectDifference.ts @@ -0,0 +1,16 @@ +/** + * Returns the difference between two objects. + * + * @param {T} obj1 - The first object to compare. + * @param {T} obj2 - The second object to compare. + * @returns {Partial} - An object containing the properties that differ between the two objects. + * @throws {TypeError} - If either input is not an object or is null. + */ +export function getObjectDifference>(obj1: T, obj2: T): Partial { + if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) { + throw new TypeError('Both inputs must be non-null objects'); + } + return Object.fromEntries( + Object.entries(obj1).filter(([key, value]) => obj2[key] !== value) + ) as Partial; +} \ No newline at end of file diff --git a/objectFunctions/keysToCamelCase.ts b/objectFunctions/keysToCamelCase.ts new file mode 100644 index 00000000..ac95fe2a --- /dev/null +++ b/objectFunctions/keysToCamelCase.ts @@ -0,0 +1,20 @@ +/** + * Converts the keys of an object to camelCase. + * + * @param {any} obj - The object to convert. + * @returns {any} - A new object with keys converted to camelCase. + * @throws {TypeError} - If the input is not an object or is null. + */ +export function keysToCamelCase(obj: any): any { + if (Array.isArray(obj)) { + return obj.map(keysToCamelCase); + } else if (obj !== null && typeof obj === 'object') { + return Object.fromEntries( + Object.entries(obj).map(([key, value]) => [ + key.replace(/([-_][a-z])/g, group => group.toUpperCase().replace('-', '').replace('_', '')), + keysToCamelCase(value) + ]) + ); + } + return obj; +} \ No newline at end of file diff --git a/objectFunctions/keysToSnakeCase.ts b/objectFunctions/keysToSnakeCase.ts new file mode 100644 index 00000000..e07dbbf9 --- /dev/null +++ b/objectFunctions/keysToSnakeCase.ts @@ -0,0 +1,20 @@ +/** + * Converts the keys of an object to snake_case. + * + * @param {any} obj - The object to convert. + * @returns {any} - A new object with keys converted to snake_case. + * @throws {TypeError} - If the input is not an object or is null. + */ +export function keysToSnakeCase(obj: any): any { + if (Array.isArray(obj)) { + return obj.map(keysToSnakeCase); + } else if (obj !== null && typeof obj === 'object') { + return Object.fromEntries( + Object.entries(obj).map(([key, value]) => [ + key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`), + keysToSnakeCase(value) + ]) + ); + } + return obj; +} \ No newline at end of file diff --git a/objectFunctions/shallowEqual.ts b/objectFunctions/shallowEqual.ts new file mode 100644 index 00000000..72f63d37 --- /dev/null +++ b/objectFunctions/shallowEqual.ts @@ -0,0 +1,20 @@ +/** + * Performs a shallow comparison between two objects to determine if they are equal. + * + * @param {Record} obj1 - The first object to compare. + * @param {Record} obj2 - The second object to compare. + * @returns {boolean} - True if the objects are shallowly equal, false otherwise. + * @throws {TypeError} - If either input is not an object or is null. + */ +export function shallowEqual(obj1: Record, obj2: Record): boolean { + if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) { + throw new TypeError('Both inputs must be non-null objects'); + } + + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + + if (keys1.length !== keys2.length) return false; + + return keys1.every(key => obj1[key] === obj2[key]); +}