UNPKG

@qntm-code/utils

Version:

A collection of useful utility functions with associated TypeScript types. All functions have been unit tested.

806 lines (805 loc) 24.7 kB
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ import * as moment from 'moment'; function func1() { } function func2() { } class MyMap extends Map { } class MySet extends Set { } const emptyObj = {}; function map(obj, Class) { const a = new (Class || Map)(); for (const key in obj) { a.set(key, obj[key]); } return a; } function myMap(obj) { return map(obj, MyMap); } function set(arr, Class) { const a = new (Class || Set)(); for (const value of arr) { a.add(value); } return a; } function mySet(arr) { return set(arr, MySet); } export const isEqualTests = [ { description: 'single values', tests: [ { description: 'null and null', a: null, b: null, expected: true, }, { description: 'null and "null"', a: null, b: 'null', expected: false, }, { description: 'null and undefined', a: null, b: undefined, expected: false, }, { description: 'null and 0', a: null, b: 0, expected: false, }, { description: 'NaN and NaN', a: NaN, b: NaN, expected: true, }, { description: 'NaN and "NaN"', a: NaN, b: 'NaN', expected: false, }, { description: 'NaN and undefined', a: NaN, b: undefined, expected: false, }, { description: 'undefined and undefined', a: undefined, b: undefined, expected: true, }, { description: 'undefined and "undefined"', a: undefined, b: 'undefined', expected: false, }, ], }, { description: 'strings', tests: [ { description: 'equal strings', a: 'abc', b: 'abc', expected: true, }, { description: 'not equal strings', a: 'abc', b: 'def', expected: false, }, { description: 'empty strings', a: '', b: '', expected: true, }, { description: 'empty string and null', a: '', b: null, expected: false, }, { description: 'empty string and undefined', a: '', b: undefined, expected: false, }, ], }, { description: 'numbers', tests: [ { description: 'equal numbers', a: 123, b: 123, expected: true, }, { description: 'not equal numbers', a: 123, b: 456, expected: false, }, { description: 'numbers and strings', a: 123, b: '123', expected: false, }, { description: '0 and -0', a: 0, b: -0, expected: true, }, ], }, { description: 'booleans', tests: [ { description: 'equal booleans (true)', a: true, b: true, expected: true, }, { description: 'equal booleans (false)', a: false, b: false, expected: true, }, { description: 'not equal booleans', a: true, b: false, expected: false, }, { description: 'true and 1', a: true, b: 1, expected: false, }, { description: 'false and 0', a: false, b: 0, expected: false, }, { description: 'true and "true"', a: true, b: 'true', expected: false, }, { description: 'false and "empty string"', a: false, b: '', expected: false, }, ], }, { description: 'dates', tests: [ { description: 'equal dates', a: new Date(2020, 8, 3, 0, 0, 0, 0), b: new Date(2020, 8, 3, 0, 0, 0, 0), expected: true, }, { description: 'not equal dates', a: new Date(2020, 8, 3, 0, 0, 0, 0), b: new Date(2020, 8, 3, 0, 0, 0, 1), expected: false, }, { description: 'dates and strings', a: new Date(2020, 8, 3, 0, 0, 0, 0), b: '2020-09-03T00:00:00.000Z', expected: false, }, { description: 'dates and numbers', a: new Date(2020, 8, 3, 0, 0, 0, 0), b: 1599129600000, expected: false, }, { description: 'dates objects', a: new Date(2020, 8, 3, 0, 0, 0, 0), b: {}, expected: false, }, ], }, { description: 'functions', tests: [ { description: 'equal functions', a: func1, b: func1, expected: true, }, { description: 'equal functions created separately', a: func1, b: func2, expected: false, }, ], }, { description: 'arrays', tests: [ { description: 'equal arrays in same order', a: [1, 'a', { key: 'value' }], b: [1, 'a', { key: 'value' }], expected: true, }, { description: 'equal arrays in different order', a: [1, 'a', { key: 'value' }], b: ['a', { key: 'value' }, 1], expected: false, }, { description: 'not equal arrays', a: [1, 'a', { key: 'value' }], b: [2, 'a', { key: 'value' }], expected: false, }, { description: 'arrays of different lengths', a: [1, 'a', { key: 'value' }], b: [1, 'a', { key: 'value' }, 2], expected: false, }, { description: 'differing number arrays', a: [1, 2, 3], b: [1, 2, 4], expected: false, }, { description: 'nested arrays', a: [1, [2, 3]], b: [1, [2, 3]], expected: true, }, { description: 'not equal nested arrays', a: [1, [2, 3]], b: [1, [2, 4]], expected: false, }, { description: 'empty arrays', a: [], b: [], expected: true, }, { description: 'empty array and null', a: [], b: null, expected: false, }, { description: 'empty array and undefined', a: [], b: undefined, expected: false, }, { description: 'pseudo arrays', a: { '0': 0, '1': 1, length: 2 }, b: [0, 1], expected: false, }, ], }, { description: 'objects', tests: [ { description: 'equal objects', a: { a: 'yes', b: 0, c: [1, 'b', [3, 4]] }, b: { a: 'yes', b: 0, c: [1, 'b', [3, 4]] }, expected: true, }, { description: 'equal objects with properties in different order', a: { a: 'yes', b: 0, c: [1, 'b', [3, 4]] }, b: { b: 0, c: [1, 'b', [3, 4]], a: 'yes' }, expected: true, }, { description: 'not equal objects', a: { a: 'yes', b: 0, c: [1, 'b', [3, 4]] }, b: { a: 'yes', b: 0, c: [1, 'b', [3, 5]] }, expected: false, }, { description: 'empty objects', a: {}, b: {}, expected: true, }, { description: 'big object', a: { prop1: 'value1', prop2: 'value2', prop3: 'value3', prop4: { subProp1: 'sub value1', subProp2: { subSubProp1: 'sub sub value1', subSubProp2: [1, 2, { prop2: 1, prop: 2 }, 4, 5], }, }, prop5: 1000, prop6: new Date(2016, 2, 10), }, b: { prop1: 'value1', prop2: 'value2', prop3: 'value3', prop4: { subProp1: 'sub value1', subProp2: { subSubProp1: 'sub sub value1', subSubProp2: [1, 2, { prop2: 1, prop: 2 }, 4, 5], }, }, prop5: 1000, prop6: new Date(2016, 2, 10), }, expected: true, }, { description: 'not equal big objects', a: { prop1: 'value1', prop2: 'value2', prop3: 'value3', prop4: { subProp1: 'sub value1', subProp2: { subSubProp1: 'sub sub value', subSubProp2: [1, 2, { prop2: 1, prop: 2 }, 4, 5], }, }, prop5: 1000, prop6: new Date(2016, 2, 10), }, b: { prop5: 1000, prop3: 'value3', prop1: 'value1', prop2: 'value2', prop6: new Date('2016/03/10'), prop4: { subProp2: { subSubProp1: 'sub sub value1', subSubProp2: [1, 2, { prop2: 1, prop: 2 }, 4, 5], }, subProp1: 'sub value1', }, }, expected: false, }, { description: 'objects with different "toString" functions returning the same values are equal', a: { toString: () => 'abc', }, b: { toString: () => 'abc', }, expected: true, }, { description: 'objects with different "toString" functions returning different values are not equal', a: { toString: () => 'abc', }, b: { toString: () => 'def', }, expected: false, }, ], }, { description: 'RegExp', tests: [ { description: 'equal RegExp', a: /abc/, b: /abc/, expected: true, }, { description: 'not equal RegExp', a: /abc/, b: /abcd/, expected: false, }, { description: 'equal RegExp with flags', a: /abc/gi, b: /abc/gi, expected: true, }, { description: 'not equal RegExp with flags', a: /abc/gi, b: /abc/g, expected: false, }, { description: 'RegExp and string', a: /abc/, b: 'abc', expected: false, }, { description: 'RegExp and object', a: /abc/, b: {}, expected: false, }, ], }, { description: 'bigint', tests: [ { description: 'equal bigints', a: BigInt(1), b: BigInt(1), expected: true, }, { description: 'not equal bigints', a: BigInt(1), b: BigInt(2), expected: false, }, ], }, { description: 'Maps', tests: [ { description: 'empty maps are equal', a: new Map(), b: new Map(), expected: true, }, { description: 'empty maps of different class are not equal', a: new Map(), b: new MyMap(), expected: false, }, { description: 'equal maps (same key "order")', a: map({ a: 1, b: '2' }), b: map({ a: 1, b: '2' }), expected: true, }, { description: 'not equal maps (same key "order" - instances of different classes)', a: map({ a: 1, b: '2' }), b: myMap({ a: 1, b: '2' }), expected: false, }, { description: 'equal maps (different key "order")', a: map({ a: 1, b: '2' }), b: map({ b: '2', a: 1 }), expected: true, }, { description: 'equal maps (different key "order" - instances of the same subclass)', a: myMap({ a: 1, b: '2' }), b: myMap({ b: '2', a: 1 }), expected: true, }, { description: 'not equal maps (extra key)', a: map({ a: 1, b: '2' }), b: map({ a: 1, b: '2', c: [] }), expected: false, }, { description: 'not equal maps (different key value)', a: map({ a: 1, b: '2', c: 3 }), b: map({ a: 1, b: '2', c: 4 }), expected: false, }, { description: 'not equal maps (different keys)', a: map({ a: 1, b: '2', c: 3 }), b: map({ a: 1, b: '2', d: 3 }), expected: false, }, { description: 'equal maps (same sub-keys)', a: map({ a: [map({ b: 'c' })] }), b: map({ a: [map({ b: 'c' })] }), expected: true, }, { description: 'not equal maps (different sub-key value)', a: map({ a: [map({ b: 'c' })] }), b: map({ a: [map({ b: 'd' })] }), expected: false, }, { description: 'not equal maps (different sub-key)', a: map({ a: [map({ b: 'c' })] }), b: map({ a: [map({ c: 'c' })] }), expected: false, }, { description: 'empty map and empty object are not equal', a: {}, b: new Map(), expected: false, }, { description: 'map with extra undefined key is not equal #1', a: map({}), b: map({ foo: undefined }), expected: false, }, { description: 'map with extra undefined key is not equal #2', a: map({ foo: undefined }), b: map({}), expected: false, }, { description: 'maps with extra undefined keys are not equal #3', a: map({ foo: undefined }), b: map({ bar: undefined }), expected: false, }, { description: 'null and empty map are not equal', a: null, b: new Map(), expected: false, }, { description: 'undefined and empty map are not equal', a: undefined, b: new Map(), expected: false, }, { description: 'map and a pseudo map are not equal', a: map({}), b: { constructor: Map, size: 0, has: () => true, get: () => 1, }, expected: false, }, ], }, { description: 'Sets', tests: [ { description: 'empty sets are equal', a: new Set(), b: new Set(), expected: true, }, { description: 'empty sets of different class are not equal', a: new Set(), b: new MySet(), expected: false, }, { description: 'equal sets (same value "order")', a: set(['a', 'b']), b: set(['a', 'b']), expected: true, }, { description: 'not equal sets (same value "order" - instances of different classes)', a: set(['a', 'b']), b: mySet(['a', 'b']), expected: false, }, { description: 'equal sets (different value "order")', a: set(['a', 'b']), b: set(['b', 'a']), expected: true, }, { description: 'equal sets (different value "order" - instances of the same subclass)', a: mySet(['a', 'b']), b: mySet(['b', 'a']), expected: true, }, { description: 'not equal sets (extra value)', a: set(['a', 'b']), b: set(['a', 'b', 'c']), expected: false, }, { description: 'not equal sets (different values)', a: set(['a', 'b', 'c']), b: set(['a', 'b', 'd']), expected: false, }, { description: 'not equal sets (different instances of objects)', a: set(['a', {}]), b: set(['a', {}]), expected: false, }, { description: 'equal sets (same instances of objects)', a: set(['a', emptyObj]), b: set(['a', emptyObj]), expected: true, }, { description: 'empty set and empty object are not equal', a: {}, b: new Set(), expected: false, }, { description: 'empty set and empty array are not equal', a: [], b: new Set(), expected: false, }, { description: 'set with extra undefined value is not equal #1', a: set([]), b: set([undefined]), expected: false, }, { description: 'set with extra undefined value is not equal #2', a: set([undefined]), b: set([]), expected: false, }, { description: 'set and pseudo set are not equal', a: new Set(), b: { constructor: Set, size: 0, has: () => true, }, expected: false, }, ], }, { description: 'Typed arrays', tests: [ { description: 'two empty arrays of the same class are equal', a: new Int32Array([]), b: new Int32Array([]), expected: true, }, { description: 'two empty arrays of the different class are not equal', a: new Int32Array([]), b: new Int16Array([]), expected: false, }, { description: 'equal arrays', a: new Int32Array([1, 2, 3]), b: new Int32Array([1, 2, 3]), expected: true, }, { description: 'equal BigUint64Array arrays', a: new BigUint64Array(['1', '2', '3']), b: new BigUint64Array(['1', '2', '3']), expected: true, }, { description: 'not equal BigUint64Array arrays', a: new BigUint64Array(['1', '2', '3']), b: new BigUint64Array(['1', '2', '4']), expected: false, }, { description: 'not equal arrays (same items, different class)', a: new Int32Array([1, 2, 3]), b: new Int16Array([1, 2, 3]), expected: false, }, { description: 'not equal arrays (different item)', a: new Int32Array([1, 2, 3]), b: new Int32Array([1, 2, 4]), expected: false, }, { description: 'not equal arrays (different length)', a: new Int32Array([1, 2, 3]), b: new Int32Array([1, 2]), expected: false, }, { description: 'pseudo array and equivalent typed array are not equal', a: { '0': 1, '1': 2, length: 2, constructor: Int32Array }, b: new Int32Array([1, 2]), expected: false, }, ], }, { description: 'Moment', tests: [ { description: 'Moment and any other object are not equal', a: moment(), b: new Date(), expected: false, }, { description: 'Two moments with the same value are equal', a: moment('2018-01-01'), b: moment('2018-01-01'), expected: true, }, { description: 'Two moments with different values are not equal', a: moment('2018-01-01'), b: moment('2018-01-02'), expected: false, }, ], }, ];