UNPKG

deep-object-assign-with-reduce

Version:

Minimalist deep merging of Objects with the same function signature as Object.assign()

498 lines (413 loc) 11.1 kB
import { deepAssign, deepAssignOptions } from "./index"; describe("deepAssign", () => { describe("readme examples", () => { test("1", () => { const result = deepAssign( {}, { dimensions: { width: 100, height: 100 } }, { dimensions: { width: 200 } } ); const expectedResult = { dimensions: { width: 200, height: 100 } }; expect(result).toEqual(expectedResult); }); test("2", () => { const result = deepAssign( {}, { numbers: [1, 2, 3] }, { numbers: [4, 5, 6] } ); const expectedResult = { numbers: [1, 2, 3, 4, 5, 6] }; expect(result).toEqual(expectedResult); }); test("3", () => { const result = deepAssign({}, { a: { b: 1 } }, { a: { c: 2 } }); const expectedResult = { a: { b: 1, c: 2 } }; expect(result).toEqual(expectedResult); }); test("super deep", () => { const startTimeMS = Date.now(); const obj1 = { a: { b: { c: { d: { e: { f: { g: { h: { i: { j: 1 } } } } } } } } } }; const obj2 = { a: { b: { c: { d: { e: { f: { g: { h: { i: { foo: "bar" } } } } } } } } } }; const result = deepAssign({}, obj1, obj2); const expectedResult = { a: { b: { c: { d: { e: { f: { g: { h: { i: { j: 1, foo: "bar" } } } } } } } } } }; const timeMS = Date.now() - startTimeMS; expect(timeMS < 50).toBe(true); expect(result).toEqual(expectedResult); }); }); describe("mutates receiver object (like Object.assign)", () => { test("1", () => { let receiver = {}; deepAssign(receiver, { foo: 1 }); expect(receiver.foo).toEqual(1); }); test("2", () => { let receiver = { a: { b: 1 } }; const result = deepAssign( receiver, { a: { b: 2 } }, { a: { b: 3 } } ); expect(result.a.b).toEqual(3); expect(receiver.a.b).toEqual(3); }); }); describe("does not mutate source objects", () => { test("1", () => { let receiver = { foo: 1 }; let source1 = { foo: 2 }; let source2 = { foo: 3 }; deepAssign(receiver, source1, source2); expect(source1.foo).toBe(2); expect(source2.foo).toBe(3); }); }); describe("arrays", () => { test("merges arrays", () => { const result = deepAssign( {}, { foo: [1, 2, 3] }, { foo: [4, 5, 6] } ); const expectedResult = { foo: [1, 2, 3, 4, 5, 6] }; expect(result).toEqual(expectedResult); }); }); describe("functions", () => { test("fn1 overrides fn2", () => { const fn1 = () => 1; const fn2 = () => 2; const result = deepAssign({}, { foo: fn1 }, { foo: fn2 }); const expectedResult = { foo: fn2 }; expect(result).toEqual(expectedResult); }); }); describe("symbols", () => { test("as keys", () => { const sym = Symbol(); const result = deepAssign({}, { [sym]: 1 }, { [sym]: 2 }); const expectedResult = { [sym]: 2 }; expect(result).toEqual(expectedResult); }); }); describe("basic", () => { test("merges simple objects 1", () => { const result = deepAssign({}, { a: 3 }, { a: 1, b: 2 }); const expectedResult = { a: 1, b: 2 }; expect(result).toEqual(expectedResult); }); test("merges simple objects 2", () => { const result = deepAssign({}, { foo: 0 }, { bar: 1 }); const expectedResult = { foo: 0, bar: 1 }; expect(result).toEqual(expectedResult); }); test("handles null and undefined inputs 1", () => { const result = deepAssign({}, null, undefined, { foo: "bar" }); const expectedResult = { foo: "bar" }; expect(result).toEqual(expectedResult); }); test("handles null and undefined inputs 2", () => { const result = deepAssign( {}, { foo: 0 }, null, undefined, { bar: 1 }, null ); const expectedResult = { foo: 0, bar: 1 }; expect(result).toEqual(expectedResult); }); test("handles null and undefined inputs 2", () => { const result = deepAssign( {}, { foo: 0 }, null, undefined, { bar: 1 }, null ); const expectedResult = { foo: 0, bar: 1 }; expect(result).toEqual(expectedResult); }); test("assigns to null targets", () => { const result = deepAssign({}, { foo: null }, { foo: {} }); const expectedResult = { foo: {} }; expect(result).toEqual(expectedResult); }); test("merges values even if undefined", () => { const result = deepAssign({}, { foo: "f" }, { foo: undefined }); const expectedResult = { foo: undefined }; expect(result).toEqual(expectedResult); }); test("object overrides number", () => { const result = deepAssign( {}, { answer: 42 }, { answer: { rainbows: "many" } } ); const expectedResult = { answer: { rainbows: "many" } }; expect(result).toEqual(expectedResult); }); test("number overrides object", () => { const result = deepAssign( {}, { answer: { rainbows: "many" } }, { answer: 42 } ); const expectedResult = { answer: 42 }; expect(result).toEqual(expectedResult); }); test("object overrides boolean", () => { const result = deepAssign( {}, { answer: true }, { answer: { rainbows: "many" } } ); const expectedResult = { answer: { rainbows: "many" } }; expect(result).toEqual(expectedResult); }); test("boolean overrides object", () => { const result = deepAssign( {}, { answer: { rainbows: "many" } }, { answer: true } ); const expectedResult = { answer: true }; expect(result).toEqual(expectedResult); }); test("object overrides string", () => { const result = deepAssign( {}, { answer: "fff" }, { answer: { rainbows: "many" } } ); const expectedResult = { answer: { rainbows: "many" } }; expect(result).toEqual(expectedResult); }); test("string overrides object", () => { const result = deepAssign( {}, { answer: { rainbows: "many" } }, { answer: "fff" } ); const expectedResult = { answer: "fff" }; expect(result).toEqual(expectedResult); }); test("object overrides date", () => { const date = new Date(1511410546435); const result = deepAssign( {}, { answer: date }, { answer: { rainbows: "many" } } ); const expectedResult = { answer: { rainbows: "many" } }; expect(result).toEqual(expectedResult); }); test("date overrides object", () => { const date = new Date(1511410546435); const result = deepAssign( {}, { answer: { rainbows: "many" } }, { answer: date } ); const expectedResult = { answer: date }; expect(result).toEqual(expectedResult); }); test("object overrides array", () => { const result = deepAssign( {}, { answer: [1, 2, 3] }, { answer: { rainbows: "many" } } ); const expectedResult = { answer: { rainbows: "many" } }; expect(result).toEqual(expectedResult); }); test("array overrides object", () => { const result = deepAssign( {}, { answer: { rainbows: "many" } }, { answer: [1, 2, 3] } ); const expectedResult = { answer: [1, 2, 3] }; expect(result).toEqual(expectedResult); }); test("function overrides object", () => { const fn = () => 1; const result = deepAssign( {}, { answer: { rainbows: "many" } }, { answer: fn } ); const expectedResult = { answer: fn }; expect(result).toEqual(expectedResult); }); test("object overrides function", () => { const fn = () => 1; const result = deepAssign( {}, { answer: fn }, { answer: { rainbows: "many" } } ); const expectedResult = { answer: { rainbows: "many" } }; expect(result).toEqual(expectedResult); }); test("symbol overrides object", () => { const symbol = Symbol(); const result = deepAssign({}, { foo: {} }, { foo: symbol }); const expectedResult = { foo: symbol }; expect(result).toEqual(expectedResult); }); test("null handling", () => { const result = deepAssign({}, { foo: {} }, { foo: null }); const expectedResult = { foo: null }; expect(result).toEqual(expectedResult); }); test("object overrides symbol", () => { const symbol = Symbol(); const result = deepAssign({}, { foo: symbol }, { foo: {} }); const expectedResult = { foo: {} }; expect(result).toEqual(expectedResult); }); test("regexp overrides object", () => { const regexp = new RegExp(); const result = deepAssign({}, { foo: {} }, { foo: regexp }); const expectedResult = { foo: regexp }; expect(result).toEqual(expectedResult); }); test("object overrides regexp", () => { const regexp = new RegExp(); const result = deepAssign({}, { foo: regexp }, { foo: {} }); const expectedResult = { foo: {} }; expect(result).toEqual(expectedResult); }); test("multiple objects", () => { const result = deepAssign( { foo: 0 }, { bar: 1 }, { bar: 2 }, { foo: 3 } ); const expectedResult = { bar: 2, foo: 3 }; expect(result).toEqual(expectedResult); }); test("doesnt iterate prototype props", () => { const Unicorn = function() {}; Unicorn.prototype.bar = 1; const unicorn = new Unicorn(); expect(unicorn.bar).toBe(1); const result = deepAssign(unicorn, { foo: 2 }); const expectedResult = { foo: 2 }; expect(result).toEqual(expectedResult); }); test("deep", () => { const startTimeMS = Date.now(); const result = deepAssign( { foo: { foo: { foo: true, a: 1, b: 2 }, bar: { bar: false } } }, { foo: { foo: { foo: false, bar: true } }, bar: true } ); const expectedResult = { foo: { foo: { foo: false, bar: true, a: 1, b: 2 }, bar: { bar: false } }, bar: true }; const timeMS = Date.now() - startTimeMS; expect(timeMS < 5).toBe(true); expect(result).toEqual(expectedResult); }); }); }); describe("deepAssignOptions", () => { test("array overwrite", () => { const result = deepAssignOptions( { overwriteArrays: true }, {}, { numbers: [1, 2, 3] }, { numbers: [4, 5, 6] } ); const expectedResult = { numbers: [4, 5, 6] }; expect(result).toEqual(expectedResult); }); test("deep array overwrite", () => { const result = deepAssignOptions( { overwriteArrays: true, overwriteObjects: false }, {}, { a: { numbers: [1, 2, 3] } }, { a: { numbers: [4, 5, 6] } } ); const expectedResult = { a: { numbers: [4, 5, 6] } }; expect(result).toEqual(expectedResult); }); test("object overwrite", () => { const result = deepAssignOptions( { overwriteObjects: true }, {}, { a: { b: 1 } }, { a: { c: 2 } } ); const expectedResult = { a: { c: 2 } }; expect(result).toEqual(expectedResult); }); test("object overwrite and array overwrite", () => { const result = deepAssignOptions( { overwriteArrays: true, overwriteObjects: true }, {}, { a: { b: 1 }, arr: [1, 2, 3] }, { a: { c: 2 }, arr: [4, 5, 6] } ); const expectedResult = { a: { c: 2 }, arr: [4, 5, 6] }; expect(result).toEqual(expectedResult); }); });