From fde125527608cf7bd09af89a2b10e0900e1356c1 Mon Sep 17 00:00:00 2001 From: Rebecca Stevens Date: Sat, 23 Jan 2021 23:12:55 +1300 Subject: [PATCH] test: upgrade and fix test code --- test/custom-array-merge.ts | 53 +-- test/custom-is-mergeable-object.ts | 39 +- test/merge-all.ts | 72 +-- test/merge-plain-objects.ts | 8 +- test/merge.ts | 694 ++++++++++++++--------------- test/prototype-poisoning.ts | 90 ++-- 6 files changed, 473 insertions(+), 483 deletions(-) diff --git a/test/custom-array-merge.ts b/test/custom-array-merge.ts index 78147cd..29084d0 100644 --- a/test/custom-array-merge.ts +++ b/test/custom-array-merge.ts @@ -1,17 +1,20 @@ +import type { Options } from "deepmerge" import { deepmerge as merge } from "deepmerge" import test from "tape" -test('custom merge array', function(t) { - var mergeFunctionCalled = false - function overwriteMerge(target, source, options) { +test(`custom merge array`, (t) => { + let mergeFunctionCalled = false + + const overwriteMerge: Options[`arrayMerge`] = (target, source, options) => { mergeFunctionCalled = true t.equal(options.arrayMerge, overwriteMerge) return source } + const destination = { someArray: [ 1, 2 ], - someObject: { what: 'yes' }, + someObject: { what: `yes` }, } const source = { someArray: [ 1, 2, 3 ], @@ -20,7 +23,7 @@ test('custom merge array', function(t) { const actual = merge(destination, source, { arrayMerge: overwriteMerge }) const expected = { someArray: [ 1, 2, 3 ], - someObject: { what: 'yes' }, + someObject: { what: `yes` }, } t.ok(mergeFunctionCalled) @@ -28,38 +31,36 @@ test('custom merge array', function(t) { t.end() }) -test('merge top-level arrays', function(t) { - function overwriteMerge(a, b) { - return b - } - var actual = merge([ 1, 2 ], [ 1, 2 ], { arrayMerge: overwriteMerge }) - var expected = [ 1, 2 ] +test(`merge top-level arrays`, (t) => { + const overwriteMerge: Options[`arrayMerge`] = (a, b) => b + + const actual = merge([ 1, 2 ], [ 1, 2 ], { arrayMerge: overwriteMerge }) + const expected = [ 1, 2 ] t.deepEqual(actual, expected) t.end() }) -test('cloner function is available for merge functions to use', function(t) { - var customMergeWasCalled = false - function cloneMerge(target, source, options) { +test(`cloner function is available for merge functions to use`, (t) => { + let customMergeWasCalled = false + + const cloneMerge: Options[`arrayMerge`] = (target, source, options) => { customMergeWasCalled = true - t.ok(options.cloneUnlessOtherwiseSpecified, 'cloner function is available') - return target.concat(source).map(function(element) { - return options.cloneUnlessOtherwiseSpecified(element, options) - }) + t.ok(options.cloneUnlessOtherwiseSpecified, `cloner function is available`) + return [ ...target, ...source ].map((element) => options.cloneUnlessOtherwiseSpecified(element, options)) } - var src = { - key1: [ 'one', 'three' ], - key2: [ 'four' ], + const src = { + key1: [ `one`, `three` ], + key2: [ `four` ], } - var target = { - key1: [ 'one', 'two' ], + const target = { + key1: [ `one`, `two` ], } - var expected = { - key1: [ 'one', 'two', 'one', 'three' ], - key2: [ 'four' ], + const expected = { + key1: [ `one`, `two`, `one`, `three` ], + key2: [ `four` ], } t.deepEqual(merge(target, src, { arrayMerge: cloneMerge }), expected) diff --git a/test/custom-is-mergeable-object.ts b/test/custom-is-mergeable-object.ts index 76903e0..d76f628 100644 --- a/test/custom-is-mergeable-object.ts +++ b/test/custom-is-mergeable-object.ts @@ -1,36 +1,35 @@ +import type { Options } from "deepmerge" import { deepmerge as merge } from "deepmerge" import test from "tape" -test('isMergeable function copying object over object', function(t) { - var src = { key: { isMergeable: false }, baz: 'yes' } - var target = { key: { foo: 'wat' }, baz: 'whatever' } +test(`isMergeable function copying object over object`, (t) => { + const src = { key: { isMergeable: false }, baz: `yes` } + const target = { key: { foo: `wat` }, baz: `whatever` } - function customIsMergeable(object) { - return object && typeof object === 'object' && object.isMergeable !== false - } + const customIsMergeable: Options[`isMergeable`] = (object) => + object && typeof object === `object` && object.isMergeable !== false - var res = merge(target, src, { - isMergeable: customIsMergeable + const res = merge(target, src, { + isMergeable: customIsMergeable, }) - t.deepEqual(res, { key: { isMergeable: false }, baz: 'yes' }) - t.equal(res.key, src.key, 'Object has the same identity and was not cloned') + t.deepEqual(res, { key: { isMergeable: false }, baz: `yes` }) + t.equal(res.key, src.key, `Object has the same identity and was not cloned`) t.end() }) -test('isMergeable function copying object over nothing', function(t) { - var src = { key: { isMergeable: false, foo: 'bar' }, baz: 'yes' } - var target = { baz: 'whatever' } +test(`isMergeable function copying object over nothing`, (t) => { + const src = { key: { isMergeable: false, foo: `bar` }, baz: `yes` } + const target = { baz: `whatever` } - function customIsMergeable(object) { - return object && typeof object === 'object' && object.isMergeable !== false - } + const customIsMergeable: Options[`isMergeable`] = (object) => + object && typeof object === `object` && object.isMergeable !== false - var res = merge(target, src, { - isMergeable: customIsMergeable + const res = merge(target, src, { + isMergeable: customIsMergeable, }) - t.deepEqual(res, { key: { isMergeable: false, foo: 'bar' }, baz: 'yes' }) - t.equal(res.key, src.key, 'Object has the same identity and was not cloned') + t.deepEqual(res, { key: { isMergeable: false, foo: `bar` }, baz: `yes` }) + t.equal(res.key, src.key, `Object has the same identity and was not cloned`) t.end() }) diff --git a/test/merge-all.ts b/test/merge-all.ts index 03f1074..aed5419 100644 --- a/test/merge-all.ts +++ b/test/merge-all.ts @@ -1,57 +1,57 @@ import { deepmergeAll as mergeAll } from "deepmerge" import test from "tape" -test('throw error if first argument is not an array', function(t) { - // @ts-expect-error - t.throws(mergeAll.bind(null, { example: true }, { another: '2' }), Error) +test(`throw error if first argument is not an array`, (t) => { + // @ts-expect-error -- Calling mergeAll without passing in an array. + t.throws(mergeAll.bind(null, { example: true }, { another: `2` }), Error) t.end() }) -test('return an empty object if first argument is an array with no elements', function(t) { +test(`return an empty object if first argument is an array with no elements`, (t) => { t.deepEqual(mergeAll([]), {}) t.end() }) -test('Work just fine if first argument is an array with least than two elements', function(t) { - var actual = mergeAll([{ example: true }]) - var expected = { example: true } +test(`Work just fine if first argument is an array with least than two elements`, (t) => { + const actual = mergeAll([{ example: true }]) + const expected = { example: true } t.deepEqual(actual, expected) t.end() }) -test('execute correctly if options object were not passed', function(t) { - var arrayToMerge = [{ example: true }, { another: '123' }] +test(`execute correctly if options object were not passed`, (t) => { + const arrayToMerge = [{ example: true }, { another: `123` }] t.doesNotThrow(mergeAll.bind(null, arrayToMerge)) t.end() }) -test('execute correctly if options object were passed', function(t) { - var arrayToMerge = [{ example: true }, { another: '123' }] +test(`execute correctly if options object were passed`, (t) => { + const arrayToMerge = [{ example: true }, { another: `123` }] t.doesNotThrow(mergeAll.bind(null, arrayToMerge, { clone: true })) t.end() }) -test('invoke merge on every item in array should result with all props', function(t) { - var firstObject = { first: true } - var secondObject = { second: false } - var thirdObject = { third: 123 } - var fourthObject = { fourth: 'some string' } +test(`invoke merge on every item in array should result with all props`, (t) => { + const firstObject = { first: true } + const secondObject = { second: false } + const thirdObject = { third: 123 } + const fourthObject = { fourth: `some string` } - var mergedObject = mergeAll([ firstObject, secondObject, thirdObject, fourthObject ]) + const mergedObject = mergeAll([ firstObject, secondObject, thirdObject, fourthObject ]) t.ok(mergedObject.first === true) t.ok(mergedObject.second === false) t.ok(mergedObject.third === 123) - t.ok(mergedObject.fourth === 'some string') + t.ok(mergedObject.fourth === `some string`) t.end() }) -test('invoke merge on every item in array with clone should clone all elements', function(t) { - var firstObject = { a: { d: 123 } } - var secondObject = { b: { e: true } } - var thirdObject = { c: { f: 'string' } } +test(`invoke merge on every item in array with clone should clone all elements`, (t) => { + const firstObject = { a: { d: 123 } } + const secondObject = { b: { e: true } } + const thirdObject = { c: { f: `string` } } - var mergedWithClone = mergeAll([ firstObject, secondObject, thirdObject ], { clone: true }) + const mergedWithClone = mergeAll([ firstObject, secondObject, thirdObject ], { clone: true }) t.notEqual(mergedWithClone.a, firstObject.a) t.notEqual(mergedWithClone.b, secondObject.b) @@ -60,12 +60,12 @@ test('invoke merge on every item in array with clone should clone all elements', t.end() }) -test('invoke merge on every item in array clone=false should not clone all elements', function(t) { - var firstObject = { a: { d: 123 } } - var secondObject = { b: { e: true } } - var thirdObject = { c: { f: 'string' } } +test(`invoke merge on every item in array clone=false should not clone all elements`, (t) => { + const firstObject = { a: { d: 123 } } + const secondObject = { b: { e: true } } + const thirdObject = { c: { f: `string` } } - var mergedWithoutClone = mergeAll([ firstObject, secondObject, thirdObject ], { clone: false }) + const mergedWithoutClone = mergeAll([ firstObject, secondObject, thirdObject ], { clone: false }) t.equal(mergedWithoutClone.a, firstObject.a) t.equal(mergedWithoutClone.b, secondObject.b) @@ -75,12 +75,12 @@ test('invoke merge on every item in array clone=false should not clone all eleme }) -test('invoke merge on every item in array without clone should clone all elements', function(t) { - var firstObject = { a: { d: 123 } } - var secondObject = { b: { e: true } } - var thirdObject = { c: { f: 'string' } } +test(`invoke merge on every item in array without clone should clone all elements`, (t) => { + const firstObject = { a: { d: 123 } } + const secondObject = { b: { e: true } } + const thirdObject = { c: { f: `string` } } - var mergedWithoutClone = mergeAll([ firstObject, secondObject, thirdObject ]) + const mergedWithoutClone = mergeAll([ firstObject, secondObject, thirdObject ]) t.notEqual(mergedWithoutClone.a, firstObject.a) t.notEqual(mergedWithoutClone.b, secondObject.b) @@ -89,12 +89,12 @@ test('invoke merge on every item in array without clone should clone all element t.end() }) -test('With clone: false, mergeAll should not clone the target root', t => { +test(`With clone: false, mergeAll should not clone the target root`, (t) => { const destination = {} const output = mergeAll([ destination, { - sup: true - } + sup: true, + }, ], { clone: false }) t.equal(destination, output) diff --git a/test/merge-plain-objects.ts b/test/merge-plain-objects.ts index 7722f87..c1c4964 100644 --- a/test/merge-plain-objects.ts +++ b/test/merge-plain-objects.ts @@ -1,10 +1,10 @@ import { deepmerge as merge } from "deepmerge" import test from "tape" -test('plain objects are merged by default', function(t) { +test(`plain objects are merged by default`, (t) => { const input = { newObject: new Object(), - objectLiteral: { a: 123 } + objectLiteral: { a: 123 }, } const output = merge({}, input) @@ -16,11 +16,11 @@ test('plain objects are merged by default', function(t) { t.end() }) -test('instantiated objects are copied by reference', function(t) { +test(`instantiated objects are copied by reference`, (t) => { const input = { date: new Date(), error: new Error(), - regex: /regex/ + regex: /regex/, } const output = merge({}, input) diff --git a/test/merge.ts b/test/merge.ts index 3d2be9d..159bbc2 100644 --- a/test/merge.ts +++ b/test/merge.ts @@ -1,104 +1,105 @@ +import type { Options } from "deepmerge" import { deepmerge as merge } from "deepmerge" import test from "tape" -test('add keys in target that do not exist at the root', function(t) { - var src = { key1: 'value1', key2: 'value2' } - var target = {} +test(`add keys in target that do not exist at the root`, (t) => { + const src = { key1: `value1`, key2: `value2` } + const target = {} - var res = merge(target, src) + const res = merge(target, src) - t.deepEqual(target, {}, 'merge should be immutable') + t.deepEqual(target, {}, `merge should be immutable`) t.deepEqual(res, src) t.end() }) -test('merge existing simple keys in target at the roots', function(t) { - var src = { key1: 'changed', key2: 'value2' } - var target = { key1: 'value1', key3: 'value3' } +test(`merge existing simple keys in target at the roots`, (t) => { + const src = { key1: `changed`, key2: `value2` } + const target = { key1: `value1`, key3: `value3` } - var expected = { - key1: 'changed', - key2: 'value2', - key3: 'value3', + const expected = { + key1: `changed`, + key2: `value2`, + key3: `value3`, } - t.deepEqual(target, { key1: 'value1', key3: 'value3' }) + t.deepEqual(target, { key1: `value1`, key3: `value3` }) t.deepEqual(merge(target, src), expected) t.end() }) -test('merge nested objects into target', function(t) { - var src = { +test(`merge nested objects into target`, (t) => { + const src = { key1: { - subkey1: 'changed', - subkey3: 'added', + subkey1: `changed`, + subkey3: `added`, }, } - var target = { + const target = { key1: { - subkey1: 'value1', - subkey2: 'value2', + subkey1: `value1`, + subkey2: `value2`, }, } - var expected = { + const expected = { key1: { - subkey1: 'changed', - subkey2: 'value2', - subkey3: 'added', + subkey1: `changed`, + subkey2: `value2`, + subkey3: `added`, }, } t.deepEqual(target, { key1: { - subkey1: 'value1', - subkey2: 'value2', + subkey1: `value1`, + subkey2: `value2`, }, }) t.deepEqual(merge(target, src), expected) t.end() }) -test('replace simple key with nested object in target', function(t) { - var src = { +test(`replace simple key with nested object in target`, (t) => { + const src = { key1: { - subkey1: 'subvalue1', - subkey2: 'subvalue2', + subkey1: `subvalue1`, + subkey2: `subvalue2`, }, } - var target = { - key1: 'value1', - key2: 'value2', + const target = { + key1: `value1`, + key2: `value2`, } - var expected = { + const expected = { key1: { - subkey1: 'subvalue1', - subkey2: 'subvalue2', + subkey1: `subvalue1`, + subkey2: `subvalue2`, }, - key2: 'value2', + key2: `value2`, } - t.deepEqual(target, { key1: 'value1', key2: 'value2' }) + t.deepEqual(target, { key1: `value1`, key2: `value2` }) t.deepEqual(merge(target, src), expected) t.end() }) -test('should add nested object in target', function(t) { - var src = { - "b": { - "c": {}, +test(`should add nested object in target`, (t) => { + const src = { + b: { + c: {}, }, } - var target = { - "a": {}, + const target = { + a: {}, } - var expected = { - "a": {}, - "b": { - "c": {}, + const expected = { + a: {}, + b: { + c: {}, }, } @@ -106,29 +107,29 @@ test('should add nested object in target', function(t) { t.end() }) -test('should clone source and target', function(t) { - var src = { - "b": { - "c": "foo", +test(`should clone source and target`, (t) => { + const src = { + b: { + c: `foo`, }, } - var target = { - "a": { - "d": "bar", + const target = { + a: { + d: `bar`, }, } - var expected = { - "a": { - "d": "bar", + const expected = { + a: { + d: `bar`, }, - "b": { - "c": "foo", + b: { + c: `foo`, }, } - var merged = merge(target, src, { clone: true }) + const merged = merge(target, src, { clone: true }) t.deepEqual(merged, expected) @@ -138,133 +139,133 @@ test('should clone source and target', function(t) { t.end() }) -test('should clone source and target', function(t) { - var src = { - "b": { - "c": "foo", +test(`should clone source and target`, (t) => { + const src = { + b: { + c: `foo`, }, } - var target = { - "a": { - "d": "bar", + const target = { + a: { + d: `bar`, }, } - var merged = merge(target, src) + const merged = merge(target, src) t.notEqual(merged.a, target.a) t.notEqual(merged.b, src.b) t.end() }) -test('should replace object with simple key in target', function(t) { - var src = { key1: 'value1' } - var target = { +test(`should replace object with simple key in target`, (t) => { + const src = { key1: `value1` } + const target = { key1: { - subkey1: 'subvalue1', - subkey2: 'subvalue2', + subkey1: `subvalue1`, + subkey2: `subvalue2`, }, - key2: 'value2', + key2: `value2`, } - var expected = { key1: 'value1', key2: 'value2' } + const expected = { key1: `value1`, key2: `value2` } t.deepEqual(target, { key1: { - subkey1: 'subvalue1', - subkey2: 'subvalue2', + subkey1: `subvalue1`, + subkey2: `subvalue2`, }, - key2: 'value2', + key2: `value2`, }) t.deepEqual(merge(target, src), expected) t.end() }) -test('should replace objects with arrays', function(t) { - var target = { key1: { subkey: 'one' } } +test(`should replace objects with arrays`, (t) => { + const target = { key1: { subkey: `one` } } - var src = { key1: [ 'subkey' ] } + const src = { key1: [ `subkey` ] } - var expected = { key1: [ 'subkey' ] } + const expected = { key1: [ `subkey` ] } t.deepEqual(merge(target, src), expected) t.end() }) -test('should replace arrays with objects', function(t) { - var target = { key1: [ "subkey" ] } +test(`should replace arrays with objects`, (t) => { + const target = { key1: [ `subkey` ] } - var src = { key1: { subkey: 'one' } } + const src = { key1: { subkey: `one` } } - var expected = { key1: { subkey: 'one' } } + const expected = { key1: { subkey: `one` } } t.deepEqual(merge(target, src), expected) t.end() }) -test('should replace dates with arrays', function(t) { - var target = { key1: new Date() } +test(`should replace dates with arrays`, (t) => { + const target = { key1: new Date() } - var src = { key1: [ "subkey" ] } + const src = { key1: [ `subkey` ] } - var expected = { key1: [ "subkey" ] } + const expected = { key1: [ `subkey` ] } t.deepEqual(merge(target, src), expected) t.end() }) -test('should replace null with arrays', function(t) { - var target = { +test(`should replace null with arrays`, (t) => { + const target = { key1: null, } - var src = { - key1: [ "subkey" ], + const src = { + key1: [ `subkey` ], } - var expected = { - key1: [ "subkey" ], + const expected = { + key1: [ `subkey` ], } t.deepEqual(merge(target, src), expected) t.end() }) -test('should work on simple array', function(t) { - var src = [ 'one', 'three' ] - var target = [ 'one', 'two' ] +test(`should work on simple array`, (t) => { + const src = [ `one`, `three` ] + const target = [ `one`, `two` ] - var expected = [ 'one', 'two', 'one', 'three' ] + const expected = [ `one`, `two`, `one`, `three` ] t.deepEqual(merge(target, src), expected) t.ok(Array.isArray(merge(target, src))) t.end() }) -test('should work on another simple array', function(t) { - var target = [ "a1", "a2", "c1", "f1", "p1" ] - var src = [ "t1", "s1", "c2", "r1", "p2", "p3" ] +test(`should work on another simple array`, (t) => { + const target = [ `a1`, `a2`, `c1`, `f1`, `p1` ] + const src = [ `t1`, `s1`, `c2`, `r1`, `p2`, `p3` ] - var expected = [ "a1", "a2", "c1", "f1", "p1", "t1", "s1", "c2", "r1", "p2", "p3" ] - t.deepEqual(target, [ "a1", "a2", "c1", "f1", "p1" ]) + const expected = [ `a1`, `a2`, `c1`, `f1`, `p1`, `t1`, `s1`, `c2`, `r1`, `p2`, `p3` ] + t.deepEqual(target, [ `a1`, `a2`, `c1`, `f1`, `p1` ]) t.deepEqual(merge(target, src), expected) t.ok(Array.isArray(merge(target, src))) t.end() }) -test('should work on array properties', function(t) { - var src = { - key1: [ 'one', 'three' ], - key2: [ 'four' ], +test(`should work on array properties`, (t) => { + const src = { + key1: [ `one`, `three` ], + key2: [ `four` ], } - var target = { - key1: [ 'one', 'two' ], + const target = { + key1: [ `one`, `two` ], } - var expected = { - key1: [ 'one', 'two', 'one', 'three' ], - key2: [ 'four' ], + const expected = { + key1: [ `one`, `two`, `one`, `three` ], + key2: [ `four` ], } t.deepEqual(merge(target, src), expected) @@ -273,183 +274,183 @@ test('should work on array properties', function(t) { t.end() }) -test('should work on array properties with clone option', function(t) { - var src = { - key1: [ 'one', 'three' ], - key2: [ 'four' ], +test(`should work on array properties with clone option`, (t) => { + const src = { + key1: [ `one`, `three` ], + key2: [ `four` ], } - var target = { - key1: [ 'one', 'two' ], + const target = { + key1: [ `one`, `two` ], } t.deepEqual(target, { - key1: [ 'one', 'two' ], + key1: [ `one`, `two` ], }) - var merged = merge(target, src, { clone: true }) + const merged = merge(target, src, { clone: true }) t.notEqual(merged.key1, src.key1) t.notEqual(merged.key1, target.key1) t.notEqual(merged.key2, src.key2) t.end() }) -test('should work on array of objects', function(t) { - var src = [ - { key1: [ 'one', 'three' ], key2: [ 'one' ] }, - { key3: [ 'five' ] }, +test(`should work on array of objects`, (t) => { + const src = [ + { key1: [ `one`, `three` ], key2: [ `one` ] }, + { key3: [ `five` ] }, ] - var target = [ - { key1: [ 'one', 'two' ] }, - { key3: [ 'four' ] }, + const target = [ + { key1: [ `one`, `two` ] }, + { key3: [ `four` ] }, ] - var expected = [ - { key1: [ 'one', 'two' ] }, - { key3: [ 'four' ] }, - { key1: [ 'one', 'three' ], key2: [ 'one' ] }, - { key3: [ 'five' ] }, + const expected = [ + { key1: [ `one`, `two` ] }, + { key3: [ `four` ] }, + { key1: [ `one`, `three` ], key2: [ `one` ] }, + { key3: [ `five` ] }, ] t.deepEqual(merge(target, src), expected) - t.ok(Array.isArray(merge(target, src)), 'result should be an array') - t.ok(Array.isArray(merge(target, src)[0].key1), 'subkey should be an array too') + t.ok(Array.isArray(merge(target, src)), `result should be an array`) + t.ok(Array.isArray(merge(target, src)[0].key1), `subkey should be an array too`) t.end() }) -test('should work on array of objects with clone option', function(t) { - var src = [ - { key1: [ 'one', 'three' ], key2: [ 'one' ] }, - { key3: [ 'five' ] }, +test(`should work on array of objects with clone option`, (t) => { + const src = [ + { key1: [ `one`, `three` ], key2: [ `one` ] }, + { key3: [ `five` ] }, ] - var target = [ - { key1: [ 'one', 'two' ] }, - { key3: [ 'four' ] }, + const target = [ + { key1: [ `one`, `two` ] }, + { key3: [ `four` ] }, ] - var expected = [ - { key1: [ 'one', 'two' ] }, - { key3: [ 'four' ] }, - { key1: [ 'one', 'three' ], key2: [ 'one' ] }, - { key3: [ 'five' ] }, + const expected = [ + { key1: [ `one`, `two` ] }, + { key3: [ `four` ] }, + { key1: [ `one`, `three` ], key2: [ `one` ] }, + { key3: [ `five` ] }, ] - var merged = merge(target, src, { clone: true }) + const merged = merge(target, src, { clone: true }) t.deepEqual(merged, expected) - t.ok(Array.isArray(merge(target, src)), 'result should be an array') - t.ok(Array.isArray(merge(target, src)[0].key1), 'subkey should be an array too') + t.ok(Array.isArray(merge(target, src)), `result should be an array`) + t.ok(Array.isArray(merge(target, src)[0].key1), `subkey should be an array too`) t.notEqual(merged[0].key1, src[0].key1) t.notEqual(merged[0].key1, target[0].key1) - t.false(Object.prototype.hasOwnProperty.call(merged[0], 'key2'), '"key2" should not exist on "merged[0]"'); + t.false(Object.prototype.hasOwnProperty.call(merged[0], `key2`), `"key2" should not exist on "merged[0]"`) t.notEqual(merged[1].key3, src[1].key3) t.notEqual(merged[1].key3, target[1].key3) t.end() }) -test('should treat regular expressions like primitive values', function(t) { - var target = { key1: /abc/ } - var src = { key1: /efg/ } - var expected = { key1: /efg/ } +test(`should treat regular expressions like primitive values`, (t) => { + const target = { key1: /abc/ } + const src = { key1: /efg/ } + const expected = { key1: /efg/ } t.deepEqual(merge(target, src), expected) - t.deepEqual(merge(target, src).key1.test('efg'), true) + t.deepEqual(merge(target, src).key1.test(`efg`), true) t.end() }) -test('should treat regular expressions like primitive values and should not' - + ' clone even with clone option', function(t) { - var target = { key1: /abc/ } - var src = { key1: /efg/ } +test(`should treat regular expressions like primitive values and should not` + + ` clone even with clone option`, (t) => { + const target = { key1: /abc/ } + const src = { key1: /efg/ } - var output = merge(target, src, { clone: true }) + const output = merge(target, src, { clone: true }) t.equal(output.key1, src.key1) t.end() -} +}, ) -test('should treat dates like primitives', function(t) { - var monday = new Date('2016-09-27T01:08:12.761Z') - var tuesday = new Date('2016-09-28T01:18:12.761Z') +test(`should treat dates like primitives`, (t) => { + const monday = new Date(`2016-09-27T01:08:12.761Z`) + const tuesday = new Date(`2016-09-28T01:18:12.761Z`) - var target = { + const target = { key: monday, } - var source = { + const source = { key: tuesday, } - var expected = { + const expected = { key: tuesday, } - var actual = merge(target, source) + const actual = merge(target, source) t.deepEqual(actual, expected) t.equal(actual.key.valueOf(), tuesday.valueOf()) t.end() }) -test('should treat dates like primitives and should not clone even with clone' - + ' option', function(t) { - var monday = new Date('2016-09-27T01:08:12.761Z') - var tuesday = new Date('2016-09-28T01:18:12.761Z') +test(`should treat dates like primitives and should not clone even with clone` + + ` option`, (t) => { + const monday = new Date(`2016-09-27T01:08:12.761Z`) + const tuesday = new Date(`2016-09-28T01:18:12.761Z`) - var target = { + const target = { key: monday, } - var source = { + const source = { key: tuesday, } - var actual = merge(target, source, { clone: true }) + const actual = merge(target, source, { clone: true }) t.equal(actual.key, tuesday) t.end() }) -test('should work on array with null in it', function(t) { - var target = [] +test(`should work on array with null in it`, (t) => { + const target = [] - var src = [ null ] + const src = [ null ] - var expected = [ null ] + const expected = [ null ] t.deepEqual(merge(target, src), expected) t.end() }) -test('should clone array\'s element if it is object', function(t) { - var a = { key: 'yup' } - var target = [] - var source = [ a ] +test(`should clone array's element if it is object`, (t) => { + const a = { key: `yup` } + const target = [] + const source = [ a ] - var output = merge(target, source, { clone: true }) + const output = merge(target, source, { clone: true }) t.notEqual(output[0], a) - t.equal(output[0].key, 'yup') + t.equal(output[0].key, `yup`) t.end() }) -test('should clone an array property when there is no target array', function(t) { +test(`should clone an array property when there is no target array`, (t) => { const someObject = {} - var target = {} - var source = { ary: [ someObject ] } - var output = merge(target, source, { clone: true }) + const target = {} + const source = { ary: [ someObject ] } + const output = merge(target, source, { clone: true }) t.deepEqual(output, { ary: [{}] }) t.notEqual(output.ary[0], someObject) t.end() }) -test('should overwrite values when property is initialised but undefined', function(t) { - var target1 = { value: [] } - var target2 = { value: null } - var target3 = { value: 2 } +test(`should overwrite values when property is initialised but undefined`, (t) => { + const target1 = { value: [] } + const target2 = { value: null } + const target3 = { value: 2 } - var src = { value: undefined } + const src = { value: undefined } function hasUndefinedProperty(o) { - t.ok(o.hasOwnProperty('value')) - t.equal(typeof o.value, 'undefined') + t.ok(Object.prototype.hasOwnProperty.call(o, `value`)) + t.equal(typeof o.value, `undefined`) } hasUndefinedProperty(merge(target1, src)) @@ -459,231 +460,220 @@ test('should overwrite values when property is initialised but undefined', funct t.end() }) -test('dates should copy correctly in an array', function(t) { - var monday = new Date('2016-09-27T01:08:12.761Z') - var tuesday = new Date('2016-09-28T01:18:12.761Z') +test(`dates should copy correctly in an array`, (t) => { + const monday = new Date(`2016-09-27T01:08:12.761Z`) + const tuesday = new Date(`2016-09-28T01:18:12.761Z`) - var target = [ monday, 'dude' ] - var source = [ tuesday, 'lol' ] + const target = [ monday, `dude` ] + const source = [ tuesday, `lol` ] - var expected = [ monday, 'dude', tuesday, 'lol' ] - var actual = merge(target, source) + const expected = [ monday, `dude`, tuesday, `lol` ] + const actual = merge(target, source) t.deepEqual(actual, expected) t.end() }) -test('should handle custom merge functions', function(t) { - var target = { - letters: ['a', 'b'], +test(`should handle custom merge functions`, (t) => { + const target = { + letters: [ `a`, `b` ], people: { - first: 'Alex', - second: 'Bert', - } + first: `Alex`, + second: `Bert`, + }, } - var source = { - letters: ['c'], + const source = { + letters: [ `c` ], people: { - first: 'Smith', - second: 'Bertson', - third: 'Car' - } - } - - const mergePeople = (target, source, options) => { - const keys = new Set(Object.keys(target).concat(Object.keys(source))) - const destination = {} - keys.forEach(key => { - if (key in target && key in source) { - destination[key] = `${target[key]}-${source[key]}` - } else if (key in target) { - destination[key] = target[key] - } else { - destination[key] = source[key] - } - }) - return destination - } - - const options = { - customMerge: (key) => { - if (key === 'people') { - return mergePeople - } - - return merge - } - } - - var expected = { - letters: ['a', 'b', 'c'], + first: `Smith`, + second: `Bertson`, + third: `Car`, + }, + } + + const mergePeople = (target: Record, source: Record) => { + const keys = new Set(Object.keys(target).concat(Object.keys(source))) + const destination = {} + keys.forEach((key) => { + if (key in target && key in source) { + destination[key] = `${ target[key] }-${ source[key] }` + } else if (key in target) { + destination[key] = target[key] + } else { + destination[key] = source[key] + } + }) + return destination + } + + const options: Options = { + customMerge: (key) => { + if (key === `people`) { + return mergePeople + } + + return merge + }, + } + + const expected = { + letters: [ `a`, `b`, `c` ], people: { - first: 'Alex-Smith', - second: 'Bert-Bertson', - third: 'Car' - } + first: `Alex-Smith`, + second: `Bert-Bertson`, + third: `Car`, + }, } - var actual = merge(target, source, options) + const actual = merge(target, source, options) t.deepEqual(actual, expected) t.end() }) -test('should handle custom merge functions', function(t) { - var target = { - letters: ['a', 'b'], +test(`should handle custom merge functions`, (t) => { + const target = { + letters: [ `a`, `b` ], people: { - first: 'Alex', - second: 'Bert', - } + first: `Alex`, + second: `Bert`, + }, + } + + const source = { + letters: [ `c` ], + people: { + first: `Smith`, + second: `Bertson`, + third: `Car`, + }, + } + + const mergeLetters = (_target: string, _source: string) => `merged letters` + + const options: Options = { + customMerge: (key) => { + if (key === `letters`) { + return mergeLetters + } + }, } - var source = { - letters: ['c'], + const expected = { + letters: `merged letters`, people: { - first: 'Smith', - second: 'Bertson', - third: 'Car' - } - } - - const mergeLetters = (target, source, options) => { - return 'merged letters' - } - - - const options = { - customMerge: (key) => { - if (key === 'letters') { - return mergeLetters - } - } - } - - const expected = { - letters: 'merged letters', - people: { - first: 'Smith', - second: 'Bertson', - third: 'Car' - } - } - - var actual = merge(target, source, options) + first: `Smith`, + second: `Bertson`, + third: `Car`, + }, + } + + const actual = merge(target, source, options) t.deepEqual(actual, expected) t.end() }) -test('should merge correctly if custom merge is not a valid function', function(t) { - var target = { - letters: ['a', 'b'], +test(`should merge correctly if custom merge is not a valid function`, (t) => { + const target = { + letters: [ `a`, `b` ], people: { - first: 'Alex', - second: 'Bert', - } + first: `Alex`, + second: `Bert`, + }, } - var source = { - letters: ['c'], + const source = { + letters: [ `c` ], people: { - first: 'Smith', - second: 'Bertson', - third: 'Car' - } - } - - const options = { - customMerge: (key, options) => { - return false - } - } - - const expected = { - letters: ['a', 'b', 'c'], - people: { - first: 'Smith', - second: 'Bertson', - third: 'Car' - } - } - - var actual = merge(target, source) + first: `Smith`, + second: `Bertson`, + third: `Car`, + }, + } + + const expected = { + letters: [ `a`, `b`, `c` ], + people: { + first: `Smith`, + second: `Bertson`, + third: `Car`, + }, + } + + const actual = merge(target, source) t.deepEqual(actual, expected) t.end() - }) -test('copy symbol keys in target that do not exist on the target', function(t) { - var mySymbol = Symbol(); - var src = { [mySymbol]: 'value1' } - var target = {} +test(`copy symbol keys in target that do not exist on the target`, (t) => { + const mySymbol = Symbol() + const src = { [mySymbol]: `value1` } + const target = {} - var res = merge(target, src) + const res = merge(target, src) - t.equal(res[mySymbol], 'value1') + t.equal(res[mySymbol], `value1`) t.deepEqual(Object.getOwnPropertySymbols(res), Object.getOwnPropertySymbols(src)) t.end() }) -test('copy symbol keys in target that do exist on the target', function(t) { - var mySymbol = Symbol(); - var src = { [mySymbol]: 'value1' } - var target = { [mySymbol]: 'wat'} +test(`copy symbol keys in target that do exist on the target`, (t) => { + const mySymbol = Symbol() + const src = { [mySymbol]: `value1` } + const target = { [mySymbol]: `wat` } - var res = merge(target, src) + const res = merge(target, src) - t.equal(res[mySymbol as unknown as string], 'value1') + t.equal(res[mySymbol as unknown as string], `value1`) t.end() }) -test('should not mutate options', function(t) { - var options = {}; +test(`should not mutate options`, (t) => { + const options: Options = {} - merge({}, {}, options); + merge({}, {}, options) - t.deepEqual(options, {}); - t.end(); + t.deepEqual(options, {}) + t.end() }) -test('Falsey properties should be mergeable', function(t) { - var uniqueValue = {} +test(`Falsey properties should be mergeable`, (t) => { + const uniqueValue = {} - var target = { - wat: false + const target = { + wat: false, } - var source = { - wat: false + const source = { + wat: false, } - var customMergeWasCalled = false + let customMergeWasCalled = false - var result = merge(target, source, { - isMergeable: function() { + const result = merge(target, source, { + isMergeable() { return true }, - customMerge: function() { + customMerge() { return function() { customMergeWasCalled = true return uniqueValue } - } + }, }) t.equal(result.wat, uniqueValue) - t.ok(customMergeWasCalled, 'custom merge function was called') + t.ok(customMergeWasCalled, `custom merge function was called`) t.end() }) -test('With clone: false, merge should not clone the target root', t => { +test(`With clone: false, merge should not clone the target root`, (t) => { const destination = {} const output = merge(destination, { - sup: true + sup: true, }, { clone: false }) t.equal(destination, output) t.end() }) - diff --git a/test/prototype-poisoning.ts b/test/prototype-poisoning.ts index 48308fc..95f580e 100644 --- a/test/prototype-poisoning.ts +++ b/test/prototype-poisoning.ts @@ -1,76 +1,76 @@ +import type { Options } from "deepmerge" import { deepmerge as merge } from "deepmerge" -import test from "tape" import isPlainObj from "is-plain-obj" +import test from "tape" -test('merging objects with own __proto__', function(t) { - var user = {} - var malicious = JSON.parse('{ "__proto__": { "admin": true } }') - var mergedObject = merge(user, malicious) - t.notOk(mergedObject.__proto__.admin, 'non-plain properties should not be merged') - t.notOk(mergedObject.admin, 'the destination should have an unmodified prototype') +test(`merging objects with own __proto__`, (t) => { + const user = {} + const malicious = JSON.parse(`{ "__proto__": { "admin": true } }`) + const mergedObject = merge(user, malicious) + t.notOk(mergedObject.__proto__.admin, `non-plain properties should not be merged`) + t.notOk(mergedObject.admin, `the destination should have an unmodified prototype`) t.end() }) -test('merging objects with plain and non-plain properties', function(t) { - var plainSymbolKey = Symbol('plainSymbolKey') - var parent = { - parentKey: 'should be undefined' +test(`merging objects with plain and non-plain properties`, (t) => { + const plainSymbolKey = Symbol(`plainSymbolKey`) + const parent = { + parentKey: `should be undefined`, } - var target = Object.create(parent) - target.plainKey = 'should be replaced' - target[plainSymbolKey] = 'should also be replaced' + const target = Object.create(parent) + target.plainKey = `should be replaced` + target[plainSymbolKey] = `should also be replaced` - var source = { - parentKey: 'foo', - plainKey: 'bar', - newKey: 'baz', - [plainSymbolKey]: 'qux' + const source = { + parentKey: `foo`, + plainKey: `bar`, + newKey: `baz`, + [plainSymbolKey]: `qux`, } - var mergedObject = merge(target, source) - t.equal(undefined, mergedObject.parentKey, 'inherited properties of target should be removed, not merged or ignored') - t.equal('bar', mergedObject.plainKey, 'enumerable own properties of target should be merged') - t.equal('baz', mergedObject.newKey, 'properties not yet on target should be merged') - t.equal('qux', mergedObject[plainSymbolKey], 'enumerable own symbol properties of target should be merged') + const mergedObject = merge(target, source) + t.equal(undefined, mergedObject.parentKey, `inherited properties of target should be removed, not merged or ignored`) + t.equal(`bar`, mergedObject.plainKey, `enumerable own properties of target should be merged`) + t.equal(`baz`, mergedObject.newKey, `properties not yet on target should be merged`) + t.equal(`qux`, mergedObject[plainSymbolKey], `enumerable own symbol properties of target should be merged`) t.end() }) // the following cases come from the thread here: https://github.com/TehShrike/deepmerge/pull/164 -test('merging strings works with a custom string merge', function(t) { - var target = { name: "Alexander" } - var source = { name: "Hamilton" } - function customMerge(key) { - if (key === 'name') { - return function(target, source, options) { - return target[0] + '. ' + source.substring(0, 3) +test(`merging strings works with a custom string merge`, (t) => { + const target = { name: `Alexander` } + const source = { name: `Hamilton` } + const customMerge: Options[`customMerge`] = (key) => { + if (key === `name`) { + return function(target, source) { + return target[0] + `. ` + source.substring(0, 3) } } else { return merge } } - function mergeable(target) { - return isPlainObj(target) || (typeof target === 'string' && target.length > 1) - } + const mergeable: Options[`isMergeable`] = (target) => + isPlainObj(target) || (typeof target === `string` && target.length > 1) - t.equal('A. Ham', merge(target, source, { customMerge: customMerge, isMergeable: mergeable }).name) + t.equal(`A. Ham`, merge(target, source, { customMerge, isMergeable: mergeable }).name) t.end() }) -test('merging objects with null prototype', function(t) { - var target = Object.create(null) - var source = Object.create(null) +test(`merging objects with null prototype`, (t) => { + const target = Object.create(null) + const source = Object.create(null) target.wheels = 4 - target.trunk = { toolbox: ['hammer'] } - source.trunk = { toolbox: ['wrench'] } - source.engine = 'v8' - var expected = { + target.trunk = { toolbox: [ `hammer` ] } + source.trunk = { toolbox: [ `wrench` ] } + source.engine = `v8` + const expected = { wheels: 4, - engine: 'v8', + engine: `v8`, trunk: { - toolbox: ['hammer', 'wrench' ] - } + toolbox: [ `hammer`, `wrench` ], + }, } t.deepEqual(expected, merge(target, source))