UNPKG

selectic

Version:
556 lines (478 loc) 15.2 kB
const tape = require('tape'); const toolFile = require('../dist/tools.js'); const { assignObject, convertToRegExp, deepClone, isDeepEqual, } = toolFile; tape.test('assignObject()', (st) => { st.test('behaves like Object.assign', (tst) => { const deep1 = { dp: 1, }; const deep2 = { dp: 2, other: 'value', }; const obj1 = { a: 1, b: 2, c: false, deep: deep1, }; const obj2 = { a: 3, c: true, d: false, deep: deep2, other: { attr: 'str', }, }; const result = assignObject(obj1, obj2); tst.is(result, obj1, 'should modify first argument'); tst.deepEqual(result, { a: 3, b: 2, c: true, d: false, deep: { dp: 2, other: 'value', }, other: { attr: 'str', }, }, 'should merge all attributes'); tst.is(result.deep, deep2, 'should keep references'); tst.deepEqual(obj2, { a: 3, c: true, d: false, deep: deep2, other: { attr: 'str', }, }, 'should not change second argument'); tst.end(); }); st.test('accept multiple arguments', (tst) => { const obj1 = { a: 1, b: 2, }; const obj2 = { a: 2, c: 3, }; const obj3 = { a: 3, d: 4, }; const obj4 = { a: 4, e: 5, }; const result = assignObject(obj1, obj2, obj3, obj4); tst.is(result, obj1, 'should modify first argument'); tst.deepEqual(result, { a: 4, b: 2, c: 3, d: 4, e: 5, }, 'should merge all attributes'); tst.deepEqual(obj2, { a: 2, c: 3, }, 'should not change second argument'); tst.deepEqual(obj3, { a: 3, d: 4, }, 'should not change third argument'); tst.deepEqual(obj4, { a: 4, e: 5, }, 'should not change fourth argument'); tst.end(); }); st.test('ignores undefined attributes', (tst) => { const obj1 = { a: 1, // modified by all b: 2, // not modified by all (undefined) c: 3, // obj2: undefined, modified by obj3 d: 4, // modified by obj2, obj3: undefined e: 5, // not set by obj2, obj3: undefined f: 6, // not set by all }; const obj2 = { a: 'a', b: undefined, c: undefined, d: 'd', }; const obj3 = { a: 2, b: undefined, c: 'c', d: undefined, e: undefined, }; const result = assignObject(obj1, obj2, obj3); tst.is(result, obj1, 'should modify first argument'); tst.deepEqual(result, { a: 2, b: 2, c: 'c', d: 'd', e: 5, f: 6, }, 'should merge all attributes'); tst.deepEqual(obj2, { a: 'a', b: undefined, c: undefined, d: 'd', }, 'should not change second argument'); tst.deepEqual(obj3, { a: 2, b: undefined, c: 'c', d: undefined, e: undefined, }, 'should not change third argument'); tst.end(); }); }); tape.test('convertToRegExp()', (st) => { st.test('convert wildcard', (tst) => { const str = '*the search*'; const result = convertToRegExp(str); tst.is(result instanceof RegExp, true, 'should create a RegExp'); const pattern = result.source; const flags = result.flags; tst.is(pattern, '.*the search.*', 'should create wildcard sequence'); tst.is(flags, 'i', 'should be case insensitive by default'); tst.end(); }); st.test('escape special characters', (tst) => { const str = '\\^$.+?(){}[]|'; const result = convertToRegExp(str); tst.is(result instanceof RegExp, true, 'should create a RegExp'); const pattern = result.source; const flags = result.flags; tst.is(pattern, '\\\\\\^\\$\\.\\+\\?\\(\\)\\{\\}\\[\\]\\|', 'should escape special characters'); tst.is(flags, 'i', 'should be case insensitive by default'); tst.end(); }); st.test('allow RegExp flags', (tst) => { const str = 'file*.*'; const result = convertToRegExp(str, 'gm'); tst.is(result instanceof RegExp, true, 'should create a RegExp'); const pattern = result.source; const flags = result.flags; tst.is(pattern, 'file.*\\..*', 'should convert special characters'); tst.is(flags, 'gm', 'should set flags'); tst.end(); }); }); tape.test('deepClone()', (st) => { st.test('should copy simple object', (tst) => { const fn = () => {}; const objRef = { a: 1, b: 'b', c: false, d: undefined, e: null, f: {}, g: fn, spe1: NaN, spe2: Infinity, spe3: '', spe4: [], }; const result = deepClone(objRef); tst.isNot(result, objRef, 'should create a copy'); tst.deepEqual(result, objRef, 'should have been similar to original'); tst.end(); }); st.test('should copy nested object', (tst) => { const fn = () => {}; const deep1 = { a: 1, b: 'b', c: false, d: undefined, e: null, f: {}, g: fn, spe1: NaN, spe2: Infinity, spe3: '', spe4: [], }; const deep2 = { deep: deep1, added: 'a value', }; const objRef = { d: deep2, } const result = deepClone(objRef); tst.isNot(result, objRef, 'should create a copy'); tst.deepEqual(result, objRef, 'should have been similar to original'); tst.isNot(result.d, deep2, 'should copy nested object'); tst.isNot(result.d.deep, deep1, 'should copy deeper nested object'); tst.end(); }); st.test('with arrays', (tst) => { const fn = () => {}; const objRef = { a: 1, b: 'b', c: false, d: undefined, e: null, f: {}, g: fn, spe1: NaN, spe2: Infinity, spe3: '', spe4: [], }; const nestedArray1 = [ objRef, { a: 'value' }, null, undefined, 42, 'value', ]; const nestedArray2 = [ objRef, { a: 'value' }, null, undefined, 42, 'value', ]; const arrayRef = [ { deep: nestedArray1, }, nestedArray2, 42, 'value', null, undefined, [[]], ]; const result = deepClone(arrayRef); tst.isNot(result, arrayRef, 'should create a copy'); tst.is(Array.isArray(arrayRef), true, 'should create an array'); tst.deepEqual(result, arrayRef, 'should have been similar to original'); tst.isNot(result[1], nestedArray2, 'should copy nested array'); tst.isNot(result[0].deep, nestedArray1, 'should copy deeper nested array'); tst.isNot(result[1][0], objRef, 'should copy nested object'); tst.isNot(result[0].deep[0], objRef, 'should copy deeper nested object'); tst.end(); }); st.test('with RegExp', (tst) => { const r1 = /hello?/gi; const r2 = /.* [aA]+?/; const result1 = deepClone(r1); const result2 = deepClone({rgx: r2}); tst.isNot(result1, r1, 'should copy RegExp'); tst.is(result1 instanceof RegExp, true, 'should create a RegExp'); tst.is(result1.source, 'hello?', 'should copy pattern'); tst.is(result1.flags, 'gi', 'should copy flags'); tst.isNot(result2.rgx, r2, 'should copy the RegExp'); tst.is(result2.rgx.source, '.* [aA]+?', 'should copy the attribute pattern'); tst.is(result2.rgx.flags, '', 'should copy the attribute flags'); tst.end(); }); st.test('with primitives', (tst) => { const result1 = deepClone(1); const result2 = deepClone('a'); const result3 = deepClone(false); const result4 = deepClone(null); const result5 = deepClone(undefined); tst.is(result1, 1, 'should return number'); tst.is(result2, 'a', 'should return string'); tst.is(result3, false, 'should return boolean'); tst.is(result4, null, 'should return null'); tst.is(result5, undefined, 'should return undefined'); tst.end(); }); st.test('with circular references', (tst) => { const obj1 = { a: 'a', } const obj2 = { b: 'b', } obj1.child = obj1; obj1.sibling = obj2; obj2.sibling = obj1; const ref = [obj1, obj2]; const result = deepClone(ref); tst.isNot(result, ref, 'should create a new object'); tst.isNot(result[0], obj1, 'should copy inner objects'); tst.is(result[0].child, result[0], 'should keep the circular reference'); tst.is(result[1].sibling, result[0], 'should keep similar references'); tst.is(result[0].sibling, result[1], 'should keep similar references (2)'); tst.end(); }); st.test('can ignore some attributes', (tst) => { const noCopy1 = { ref: 1, }; const noCopy2 = new Set(['alpha', 'omega']); const noCopy3 = new Map([[1, 'alpha'], [22, 'omega']]); const deep1 = { a: 'alpha', noCopy: noCopy3, }; const ref = { id: 'ref', noCopy: noCopy1, nop: noCopy2, not: 42, deep: deep1, }; const result = deepClone(ref, ['noCopy', 'nothing', 'nop', 'not']); tst.isNot(result, ref, 'should create a new object'); tst.isNot(result.deep, deep1, 'should create a new object'); tst.is(result.noCopy, noCopy1, 'should keep original reference'); tst.is(result.nop, noCopy2, 'should keep original reference (2)'); tst.is(result.not, 42, 'should keep primitive'); tst.is(result.deep.noCopy, noCopy3, 'should keep nested original reference'); tst.end(); }); }); tape.test('isDeepEqual()', (st) => { const fn = () => {}; const obj = { a: 1, b: 'b', c: false, d: undefined, e: null, f: {}, g: fn, spe1: NaN, spe2: Infinity, spe3: '', spe4: [], }; st.test('should compare simple objects', (tst) => { const objA = obj; const objB = deepClone(obj); tst.is(isDeepEqual(objB, objA), true, 'should be equal'); objB.a = objB.a.toString(); tst.is(isDeepEqual(objA, objB), false, 'should not be equal'); tst.end(); }); st.test('should compare nested objects', (tst) => { const deep1 = obj; const deep2 = { deep: deep1, added: 'a value', }; const objA = { d: deep2, } const objB = deepClone(objA); tst.is(isDeepEqual(objA, objB), true, 'should be equal'); tst.end(); }); st.test('with arrays', (tst) => { const nestedArray1 = [ obj, { a: 'value' }, null, undefined, 42, 'value', ]; const nestedArray2 = deepClone(nestedArray1); const arrayA = [ { deep: nestedArray1, }, nestedArray2, 42, 'value', null, undefined, [[]], ]; const arrayB = deepClone(arrayA); tst.is(isDeepEqual(arrayA, arrayB), true, 'should be equal'); tst.end(); }); st.test('with RegExp', (tst) => { const regA1 = /hello?/gi; const regA2 = /.* [aA]+?/; const regB1 = deepClone(regA1); const regB2 = {rgx: regA2}; tst.is(isDeepEqual(regA1, regB1), true, 'should be equal'); tst.is(isDeepEqual(regA2, regB2), false, 'should not be equal'); tst.end(); }); st.test('with Date', (tst) => { const dateA = new Date('1996-06-27'); const dateB = new Date('1996-06-27'); tst.is(isDeepEqual(dateA, dateB), true, 'should be equal'); tst.end(); }); st.test('with functions', (tst) => { const fn1 = fn; const fn2 = () => {}; tst.is(isDeepEqual(fn1, fn), true, 'should be equal'); tst.is(isDeepEqual(fn2, fn), false, 'should not be equal'); tst.end(); }); st.test('with primitives', (tst) => { tst.is(isDeepEqual(10%3, 1), true, 'should be equal'); tst.is(isDeepEqual('Bingo'[0], 'B'), true, 'should be equal'); tst.is(isDeepEqual(!true, false), true, 'should be equal'); tst.is(isDeepEqual(obj.e, null), true, 'should be equal'); tst.is(isDeepEqual(obj.d, undefined), true, 'should be equal'); tst.end(); }); st.test('with circular references', (tst) => { const obj1 = { a: 'a', } const obj2 = { b: 'b', } obj1.child = obj1; obj1.sibling = obj2; obj2.sibling = obj1; const objA = [obj1, obj2]; const objB = deepClone(objA); tst.is(isDeepEqual(objA, objB), true, 'should be equal'); tst.end(); }); st.test('can ignore some attributes', (tst) => { const noCompare1 = { ref: 1, }; const noCompare2 = new Set(['alpha', 'omega']); const noCompare3 = new Map([[1, 'alpha'], [22, 'omega']]); const deep1 = { a: 'alpha', noCompare: noCompare3, }; const objA = { id: 'ref', noCopy: noCompare1, nop: noCompare2, not: 42, deep: deep1, }; const objB = deepClone(objA); objB.not = 24; const result1 = isDeepEqual(objA, objB, ['noCopy', 'nothing', 'nop', 'not']); const result2 = isDeepEqual(objA, objB, ['noCopy', 'nothing', 'nop']); tst.is(result1, true, 'should be equal'); tst.is(result2, false, 'should not be equal'); tst.end(); }); });