-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21 from blackflux/dev
[Gally]: master <- dev
- Loading branch information
Showing
3 changed files
with
206 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,131 @@ | ||
const expect = require('chai').expect; | ||
const { describe } = require('node-tdd'); | ||
const clonedeep = require('lodash.clonedeep'); | ||
const Merge = require('../../src/core/merge'); | ||
const genData = require('./gen-data'); | ||
|
||
describe('Testing Merge', () => { | ||
it('Testing SO question: https://stackoverflow.com/questions/65822248', ({ fixture }) => { | ||
const json1 = fixture('json1'); | ||
const json2 = fixture('json2'); | ||
const merge = Merge({ | ||
'[*]': 'id', | ||
'[*].addresses[*]': 'type' | ||
}); | ||
expect(merge(json1, json2)).to.deep.equal(fixture('result')); | ||
}); | ||
describe('Default Merge', () => { | ||
let merge; | ||
before(() => { | ||
merge = Merge(); | ||
}); | ||
|
||
it('Testing string merge', () => { | ||
const d1 = 'A'; | ||
const d2 = 'B'; | ||
expect(Merge()(d1, d2)).to.deep.equal('B'); | ||
}); | ||
it('Batch test', ({ fixture }) => { | ||
const mergeRec = fixture('merge-rec'); | ||
for (let x = 0; x < 10000; x += 1) { | ||
const tree = genData(); | ||
const subtree = genData(); | ||
const treeX = clonedeep(tree); | ||
const subtreeX = clonedeep(subtree); | ||
const r1 = merge(tree, subtree); | ||
expect(treeX).to.deep.equal(tree); | ||
expect(subtreeX).to.deep.equal(subtree); | ||
const r2 = mergeRec(tree, subtree); | ||
expect(treeX).to.deep.equal(tree); | ||
expect(subtreeX).to.deep.equal(subtree); | ||
expect(r1).to.deep.equal(r2); | ||
} | ||
}); | ||
|
||
it('Testing array concat', () => { | ||
const d1 = [{ a: 1 }]; | ||
const d2 = [{ a: 2 }]; | ||
expect(Merge()(d1, d2)).to.deep.equal([{ a: 1 }, { a: 2 }]); | ||
}); | ||
it('Nested empty array concat', () => { | ||
expect(merge([[]], [[]])).to.deep.equal([[], []]); | ||
}); | ||
|
||
it('Nested arrays in object concat', () => { | ||
expect(merge( | ||
{ B: [{}, [2]] }, | ||
{ B: [1] } | ||
)).to.deep.equal({ B: [{}, [2], 1] }); | ||
}); | ||
|
||
it('Nested array concat objects', () => { | ||
expect(merge([{ A: [] }], [0])).to.deep.equal([{ A: [] }, 0]); | ||
}); | ||
|
||
it('Nested array overwrite with object', () => { | ||
expect(merge({ B: [{}, {}] }, { B: {} })).to.deep.equal({ B: {} }); | ||
}); | ||
|
||
it('Nested nested array concat', () => { | ||
expect(merge({ B: [[2]] }, { B: [[2]] })).to.deep.equal({ B: [[2], [2]] }); | ||
}); | ||
|
||
it('Object overwrite array', () => { | ||
expect(merge([1], { a: 1 })).to.deep.equal({ a: 1 }); | ||
}); | ||
|
||
it('Testing array merge', () => { | ||
const d1 = [{ a: 1, b: 1, c: 3 }]; | ||
const d2 = [{ a: 1, b: 2, d: 4 }]; | ||
expect(Merge({ '[*]': 'a' })(d1, d2)).to.deep.equal([{ ...d1[0], ...d2[0] }]); | ||
it('Array overwrite object', () => { | ||
expect(merge({ a: 1 }, [1])).to.deep.equal([1]); | ||
}); | ||
|
||
it('Testing string merge', () => { | ||
const d1 = 'A'; | ||
const d2 = 'B'; | ||
expect(merge(d1, d2)).to.deep.equal('B'); | ||
}); | ||
|
||
it('Testing array concat', () => { | ||
const d1 = [{ a: 1 }]; | ||
const d2 = [{ a: 2 }]; | ||
expect(merge(d1, d2)).to.deep.equal([{ a: 1 }, { a: 2 }]); | ||
}); | ||
}); | ||
|
||
it('Testing merge by sum', () => { | ||
const d1 = [[1, 2, 3], [2, 4], [1, 2]]; | ||
const d2 = [[3, 3], [1, 5], [3, 2]]; | ||
expect(Merge({ | ||
'[*]': (o) => o.reduce((a, b) => a + b, 0) | ||
})(d1, d2)).to.deep.equal([ | ||
[1, 2, 3, 2, 4, 3, 3, 1, 5], | ||
[1, 2], | ||
[3, 2] | ||
]); | ||
describe('Custom Merge', () => { | ||
it('Batch test', () => { | ||
const merge = Merge({ '**': 'A' }); | ||
for (let x = 0; x < 10000; x += 1) { | ||
const tree = genData(); | ||
const subtree = genData(); | ||
const treeX = clonedeep(tree); | ||
const subtreeX = clonedeep(subtree); | ||
expect(() => merge(tree, subtree)).to.not.throw(); | ||
expect(treeX).to.deep.equal(tree); | ||
expect(subtreeX).to.deep.equal(subtree); | ||
} | ||
}); | ||
|
||
it('Testing SO question: https://stackoverflow.com/questions/65822248', ({ fixture }) => { | ||
const json1 = fixture('json1'); | ||
const json2 = fixture('json2'); | ||
const merge = Merge({ | ||
'[*]': 'id', | ||
'[*].addresses[*]': 'type' | ||
}); | ||
expect(merge(json1, json2)).to.deep.equal(fixture('result')); | ||
}); | ||
|
||
it('Testing array merge', () => { | ||
const d1 = [{ a: 1, b: 1, c: 3 }]; | ||
const d2 = [{ a: 1, b: 2, d: 4 }]; | ||
expect(Merge({ '[*]': 'a' })(d1, d2)).to.deep.equal([{ ...d1[0], ...d2[0] }]); | ||
}); | ||
|
||
it('Testing merge by sum', () => { | ||
const d1 = [[1, 2, 3], [2, 4], [1, 2]]; | ||
const d2 = [[3, 3], [1, 5], [3, 2]]; | ||
expect(Merge({ | ||
'[*]': (o) => o.reduce((a, b) => a + b, 0) | ||
})(d1, d2)).to.deep.equal([ | ||
[1, 2, 3, 2, 4, 3, 3, 1, 5], | ||
[1, 2], | ||
[3, 2] | ||
]); | ||
}); | ||
|
||
it('Testing incompatible', () => { | ||
const d1 = [{ a: 1 }]; | ||
const d2 = [undefined]; | ||
const d3 = ['A']; | ||
expect(Merge({ '[*]': 'a' })(d1, d2, d3)).to.deep.equal([{ a: 1 }, undefined]); | ||
}); | ||
|
||
it('Testing overwrite', () => { | ||
const d1 = { a: [{ a: 1 }] }; | ||
const d2 = { a: [{ a: 2 }] }; | ||
const d3 = { a: null }; | ||
expect(Merge({ '[*]': 'a' })(d1, d2, d3)).to.deep.equal({ a: null }); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const mergeRec = (tree, subtree) => { | ||
if (!(subtree instanceof Object)) { | ||
return subtree; | ||
} | ||
const treeIsArray = Array.isArray(tree); | ||
const subtreeIsArray = Array.isArray(subtree); | ||
if (treeIsArray !== subtreeIsArray) { | ||
return subtreeIsArray ? [...subtree] : { ...subtree }; | ||
} | ||
if (tree instanceof Object && subtree instanceof Object) { | ||
const e1 = Object.entries(tree); | ||
const e2 = Object.entries(subtree); | ||
const r = Array.isArray(subtree) ? [] : {}; | ||
[e1, e2].forEach((e) => { | ||
e.forEach(([k, v]) => { | ||
if (Array.isArray(r)) { | ||
r.push(v); | ||
} else { | ||
r[k] = k in r ? mergeRec(r[k], v) : v; | ||
} | ||
}); | ||
}); | ||
return r; | ||
} | ||
return subtree; | ||
}; | ||
|
||
module.exports = mergeRec; |