From 990549b774668c1da2ce51fb1cfed9e3efaeb8c3 Mon Sep 17 00:00:00 2001 From: Pierre Inglebert Date: Tue, 31 Mar 2015 08:49:40 +0200 Subject: [PATCH] add patches merging --- README.md | 5 +++ lib/merge.js | 20 +++++++++++ test/lib/merge.js | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 lib/merge.js create mode 100644 test/lib/merge.js diff --git a/README.md b/README.md index 6e8892a..745b05f 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,11 @@ Applies `patch` on `obj`. Generates a `patch` Object from source and target Object. + +#### jsonmergepatch.merge (`patch1` Object, `patch2` Object) : `patch` Object + +Generates a `patch` Object by merging patch1 and patch2. + ## Running tests ```sh diff --git a/lib/merge.js b/lib/merge.js new file mode 100644 index 0000000..86eedbb --- /dev/null +++ b/lib/merge.js @@ -0,0 +1,20 @@ +'use strict'; + +module.exports = function merge(patch1, patch2) { + if(patch1 === null || patch2 === null || + typeof patch1 !== 'object' || typeof patch2 !== 'object' || + Array.isArray(patch1) !== Array.isArray(patch2)) { + return patch2; + } + var patch = JSON.parse(JSON.stringify(patch1)); + + Object.keys(patch2) + .forEach(function(key) { + if(patch1[key] !== undefined) { + patch[key] = merge(patch1[key], patch2[key]); + } else { + patch[key] = patch2[key]; + } + }); + return patch; +}; diff --git a/test/lib/merge.js b/test/lib/merge.js new file mode 100644 index 0000000..98d0c28 --- /dev/null +++ b/test/lib/merge.js @@ -0,0 +1,85 @@ +'use strict'; + +var assert = require('chai').assert; + +var merge = require('../../lib/merge'); + +describe('merge', function() { + + it('should merge 2 patches with different attributes', function() { + assert.deepEqual( + merge({a: 'b'}, {b: 'c'}), + {a: 'b', b: 'c'} + ); + }); + + it('should merge take last patch attributes for rewriting', function() { + assert.deepEqual( + merge({a: 'b'}, {a: 'c'}), + {a: 'c'} + ); + }); + + it('should merge take last patch attributes for rewriting and keep other attributes', function() { + assert.deepEqual( + merge({a: 'b', b: 'd'}, {a: 'c'}), + {a: 'c', b: 'd'} + ); + }); + + it('should keep null attributes for deleting', function() { + assert.deepEqual( + merge({a: null}, {b: 'c'}), + {a: null, b: 'c'} + ); + }); + + it('should replace null with newer attribute', function() { + assert.deepEqual( + merge({a: null}, {a: 'b'}), + {a: 'b'} + ); + }); + + it('should replace an attribute with null if newer', function() { + assert.deepEqual( + merge({a: 'b'}, {a: null}), + {a: null} + ); + }); + + it('should replace an array with an object', function() { + assert.deepEqual( + merge([], {a: 'b'}), + {a: 'b'} + ); + }); + + it('should replace an object with an array', function() { + assert.deepEqual( + merge({a: 'b'}, []), + [] + ); + }); + + it('should merge sub objects', function() { + assert.deepEqual( + merge({a: {b: {c: 'd'}}, d: 'e'}, {a: {b: 'a'}}), + {a: {b: 'a'}, d: 'e'} + ); + }); + + it('should merge recursively', function() { + assert.deepEqual( + merge({a: {b: {c: 'd'}, d: 'e'}}, {a: {b: {c: 'e'}}}), + {a: {b: {c: 'e'}, d: 'e'}} + ); + }); + + it('should replace object with with null value', function() { + assert.deepEqual( + merge({a: 'b'}, null), + null + ); + }); +});