123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759 |
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef
- define(['deep-diff', 'expect.js'], factory);// eslint-disable-line no-undef
- } else if (typeof module === 'object' && module.exports) {
- module.exports = factory(require('../'), require('expect.js'));
- } else {
- root.returnExports = factory(root.DeepDiff, root.expect);
- }
- // eslint-disable-next-line no-undef
- }(typeof self !== 'undefined' ? self : this, function (deep, expect) {
- describe('deep-diff', function () {
- var empty = {};
- describe('A target that has no properties', function () {
- it('shows no differences when compared to another empty object', function () {
- expect(deep.diff(empty, {})).to.be.an('undefined');
- });
- describe('when compared to a different type of keyless object', function () {
- var comparandTuples = [
- ['an array', {
- key: []
- }],
- ['an object', {
- key: {}
- }],
- ['a date', {
- key: new Date()
- }],
- ['a null', {
- key: null
- }],
- ['a regexp literal', {
- key: /a/
- }],
- ['Math', {
- key: Math
- }]
- ];
- comparandTuples.forEach(function (lhsTuple) {
- comparandTuples.forEach(function (rhsTuple) {
- if (lhsTuple[0] === rhsTuple[0]) {
- return;
- }
- it('shows differences when comparing ' + lhsTuple[0] + ' to ' + rhsTuple[0], function () {
- var diff = deep.diff(lhsTuple[1], rhsTuple[1]);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- });
- });
- });
- describe('when compared with an object having other properties', function () {
- var comparand = {
- other: 'property',
- another: 13.13
- };
- var diff = deep.diff(empty, comparand);
- it('the differences are reported', function () {
- expect(diff).to.be.ok();
- expect(diff.length).to.be(2);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('N');
- expect(diff[0]).to.have.property('path');
- expect(diff[0].path).to.be.an(Array);
- expect(diff[0].path[0]).to.eql('other');
- expect(diff[0]).to.have.property('rhs');
- expect(diff[0].rhs).to.be('property');
- expect(diff[1]).to.have.property('kind');
- expect(diff[1].kind).to.be('N');
- expect(diff[1]).to.have.property('path');
- expect(diff[1].path).to.be.an(Array);
- expect(diff[1].path[0]).to.eql('another');
- expect(diff[1]).to.have.property('rhs');
- expect(diff[1].rhs).to.be(13.13);
- });
- });
- });
- describe('A target that has one property', function () {
- var lhs = {
- one: 'property'
- };
- it('shows no differences when compared to itself', function () {
- expect(deep.diff(lhs, lhs)).to.be.an('undefined');
- });
- it('shows the property as removed when compared to an empty object', function () {
- var diff = deep.diff(lhs, empty);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('D');
- });
- it('shows the property as edited when compared to an object with null', function () {
- var diff = deep.diff(lhs, {
- one: null
- });
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- it('shows the property as edited when compared to an array', function () {
- var diff = deep.diff(lhs, ['one']);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- });
- describe('A target that has null value', function () {
- var lhs = {
- key: null
- };
- it('shows no differences when compared to itself', function () {
- expect(deep.diff(lhs, lhs)).to.be.an('undefined');
- });
- it('shows the property as removed when compared to an empty object', function () {
- var diff = deep.diff(lhs, empty);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('D');
- });
- it('shows the property is changed when compared to an object that has value', function () {
- var diff = deep.diff(lhs, {
- key: 'value'
- });
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- it('shows that an object property is changed when it is set to null', function () {
- lhs.key = {
- nested: 'value'
- };
- var diff = deep.diff(lhs, {
- key: null
- });
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- });
- describe('A target that has a date value', function () {
- var lhs = {
- key: new Date(555555555555)
- };
- it('shows the property is changed with a new date value', function () {
- var diff = deep.diff(lhs, {
- key: new Date(777777777777)
- });
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- });
- describe('A target that has a NaN', function () {
- var lhs = {
- key: NaN
- };
- it('shows the property is changed when compared to another number', function () {
- var diff = deep.diff(lhs, {
- key: 0
- });
- expect(diff).to.be.ok();
- expect(diff.length).to.be(1);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- });
- it('shows no differences when compared to another NaN', function () {
- var diff = deep.diff(lhs, {
- key: NaN
- });
- expect(diff).to.be.an('undefined');
- });
- });
- describe('can revert namespace using noConflict', function () {
- if (deep.noConflict) {
- deep = deep.noConflict();
- it('conflict is restored (when applicable)', function () {
- // In node there is no global conflict.
- if (typeof globalConflict !== 'undefined') {
- expect(DeepDiff).to.be(deep); // eslint-disable-line no-undef
- }
- });
- it('DeepDiff functionality available through result of noConflict()', function () {
- expect(deep.applyDiff).to.be.a('function');
- });
- }
- });
- describe('When filtering keys', function () {
- var lhs = {
- enhancement: 'Filter/Ignore Keys?',
- numero: 11,
- submittedBy: 'ericclemmons',
- supportedBy: ['ericclemmons'],
- status: 'open'
- };
- var rhs = {
- enhancement: 'Filter/Ignore Keys?',
- numero: 11,
- submittedBy: 'ericclemmons',
- supportedBy: [
- 'ericclemmons',
- 'TylerGarlick',
- 'flitbit',
- 'ergdev'
- ],
- status: 'closed',
- fixedBy: 'flitbit'
- };
- describe('if the filtered property is an array', function () {
- it('changes to the array do not appear as a difference', function () {
- var prefilter = function (path, key) {
- return key === 'supportedBy';
- };
- var diff = deep(lhs, rhs, prefilter);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(2);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('E');
- expect(diff[1]).to.have.property('kind');
- expect(diff[1].kind).to.be('N');
- });
- });
- describe('if the filtered property is not an array', function () {
- it('changes do not appear as a difference', function () {
- var prefilter = function (path, key) {
- return key === 'fixedBy';
- };
- var diff = deep(lhs, rhs, prefilter);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(4);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('A');
- expect(diff[1]).to.have.property('kind');
- expect(diff[1].kind).to.be('A');
- expect(diff[2]).to.have.property('kind');
- expect(diff[2].kind).to.be('A');
- expect(diff[3]).to.have.property('kind');
- expect(diff[3].kind).to.be('E');
- });
- });
- });
- describe('A target that has nested values', function () {
- var nestedOne = {
- noChange: 'same',
- levelOne: {
- levelTwo: 'value'
- },
- arrayOne: [{
- objValue: 'value'
- }]
- };
- var nestedTwo = {
- noChange: 'same',
- levelOne: {
- levelTwo: 'another value'
- },
- arrayOne: [{
- objValue: 'new value'
- }, {
- objValue: 'more value'
- }]
- };
- it('shows no differences when compared to itself', function () {
- expect(deep.diff(nestedOne, nestedOne)).to.be.an('undefined');
- });
- it('shows the property as removed when compared to an empty object', function () {
- var diff = deep(nestedOne, empty);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(3);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('D');
- expect(diff[1]).to.have.property('kind');
- expect(diff[1].kind).to.be('D');
- });
- it('shows the property is changed when compared to an object that has value', function () {
- var diff = deep.diff(nestedOne, nestedTwo);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(3);
- });
- it('shows the property as added when compared to an empty object on left', function () {
- var diff = deep.diff(empty, nestedOne);
- expect(diff).to.be.ok();
- expect(diff.length).to.be(3);
- expect(diff[0]).to.have.property('kind');
- expect(diff[0].kind).to.be('N');
- });
- describe('when diff is applied to a different empty object', function () {
- var diff = deep.diff(nestedOne, nestedTwo);
- it('has result with nested values', function () {
- var result = {};
- deep.applyChange(result, nestedTwo, diff[0]);
- expect(result.levelOne).to.be.ok();
- expect(result.levelOne).to.be.an('object');
- expect(result.levelOne.levelTwo).to.be.ok();
- expect(result.levelOne.levelTwo).to.eql('another value');
- });
- it('has result with array object values', function () {
- var result = {};
- deep.applyChange(result, nestedTwo, diff[2]);
- expect(result.arrayOne).to.be.ok();
- expect(result.arrayOne).to.be.an('array');
- expect(result.arrayOne[0]).to.be.ok();
- expect(result.arrayOne[0].objValue).to.be.ok();
- expect(result.arrayOne[0].objValue).to.equal('new value');
- });
- it('has result with added array objects', function () {
- var result = {};
- deep.applyChange(result, nestedTwo, diff[1]);
- expect(result.arrayOne).to.be.ok();
- expect(result.arrayOne).to.be.an('array');
- expect(result.arrayOne[1]).to.be.ok();
- expect(result.arrayOne[1].objValue).to.be.ok();
- expect(result.arrayOne[1].objValue).to.equal('more value');
- });
- });
- });
- describe('regression test for bug #10, ', function () {
- var lhs = {
- id: 'Release',
- phases: [{
- id: 'Phase1',
- tasks: [{
- id: 'Task1'
- }, {
- id: 'Task2'
- }]
- }, {
- id: 'Phase2',
- tasks: [{
- id: 'Task3'
- }]
- }]
- };
- var rhs = {
- id: 'Release',
- phases: [{
- // E: Phase1 -> Phase2
- id: 'Phase2',
- tasks: [{
- id: 'Task3'
- }]
- }, {
- id: 'Phase1',
- tasks: [{
- id: 'Task1'
- }, {
- id: 'Task2'
- }]
- }]
- };
- describe('differences in nested arrays are detected', function () {
- var diff = deep.diff(lhs, rhs);
- // there should be differences
- expect(diff).to.be.ok();
- expect(diff.length).to.be(6);
- it('differences can be applied', function () {
- var applied = deep.applyDiff(lhs, rhs);
- it('and the result equals the rhs', function () {
- expect(applied).to.eql(rhs);
- });
- });
- });
- });
- describe('regression test for bug #35', function () {
- var lhs = ['a', 'a', 'a'];
- var rhs = ['a'];
- it('can apply diffs between two top level arrays', function () {
- var differences = deep.diff(lhs, rhs);
- differences.forEach(function (it) {
- deep.applyChange(lhs, true, it);
- });
- expect(lhs).to.eql(['a']);
- });
- });
- describe('Objects from different frames', function () {
- if (typeof globalConflict === 'undefined') { return; }
- // eslint-disable-next-line no-undef
- var frame = document.createElement('iframe');
- // eslint-disable-next-line no-undef
- document.body.appendChild(frame);
- var lhs = new frame.contentWindow.Date(2010, 1, 1);
- var rhs = new frame.contentWindow.Date(2010, 1, 1);
- it('can compare date instances from a different frame', function () {
- var differences = deep.diff(lhs, rhs);
- expect(differences).to.be(undefined);
- });
- });
- describe('Comparing regexes should work', function () {
- var lhs = /foo/;
- var rhs = /foo/i;
- it('can compare regex instances', function () {
- var diff = deep.diff(lhs, rhs);
- expect(diff.length).to.be(1);
- expect(diff[0].kind).to.be('E');
- expect(diff[0].path).to.not.be.ok();
- expect(diff[0].lhs).to.be('/foo/');
- expect(diff[0].rhs).to.be('/foo/i');
- });
- });
- describe('subject.toString is not a function', function () {
- var lhs = {
- left: 'yes',
- right: 'no',
- };
- var rhs = {
- left: {
- toString: true,
- },
- right: 'no',
- };
- it('should not throw a TypeError', function () {
- var diff = deep.diff(lhs, rhs);
- expect(diff.length).to.be(1);
- });
- });
- describe('regression test for issue #83', function () {
- var lhs = {
- date: null
- };
- var rhs = {
- date: null
- };
- it('should not detect a difference', function () {
- expect(deep.diff(lhs, rhs)).to.be(undefined);
- });
- });
- describe('regression test for issue #70', function () {
- it('should detect a difference with undefined property on lhs', function () {
- var diff = deep.diff({ foo: undefined }, {});
- expect(diff).to.be.an(Array);
- expect(diff.length).to.be(1);
- expect(diff[0].kind).to.be('D');
- expect(diff[0].path).to.be.an('array');
- expect(diff[0].path).to.have.length(1);
- expect(diff[0].path[0]).to.be('foo');
- expect(diff[0].lhs).to.be(undefined);
- });
- it('should detect a difference with undefined property on rhs', function () {
- var diff = deep.diff({}, { foo: undefined });
- expect(diff).to.be.an(Array);
- expect(diff.length).to.be(1);
- expect(diff[0].kind).to.be('N');
- expect(diff[0].path).to.be.an('array');
- expect(diff[0].path).to.have.length(1);
- expect(diff[0].path[0]).to.be('foo');
- expect(diff[0].rhs).to.be(undefined);
- });
- });
- describe('regression test for issue #98', function () {
- var lhs = { foo: undefined };
- var rhs = { foo: undefined };
- it('should not detect a difference with two undefined property values', function () {
- var diff = deep.diff(lhs, rhs);
- expect(diff).to.be(undefined);
- });
- });
- describe('regression tests for issue #102', function () {
- it('should not throw a TypeError', function () {
- var diff = deep.diff(null, undefined);
- expect(diff).to.be.an(Array);
- expect(diff.length).to.be(1);
- expect(diff[0].kind).to.be('D');
- expect(diff[0].lhs).to.be(null);
- });
- it('should not throw a TypeError', function () {
- var diff = deep.diff(Object.create(null), { foo: undefined });
- expect(diff).to.be.an(Array);
- expect(diff.length).to.be(1);
- expect(diff[0].kind).to.be('N');
- expect(diff[0].rhs).to.be(undefined);
- });
- });
- describe('Order independent hash testing', function () {
- function sameHash(a, b) {
- expect(deep.orderIndepHash(a)).to.equal(deep.orderIndepHash(b));
- }
- function differentHash(a, b) {
- expect(deep.orderIndepHash(a)).to.not.equal(deep.orderIndepHash(b));
- }
- describe('Order indepdendent hash function should give different values for different objects', function () {
- it('should give different values for different "simple" types', function () {
- differentHash(1, -20);
- differentHash('foo', 45);
- differentHash('pie', 'something else');
- differentHash(1.3332, 1);
- differentHash(1, null);
- differentHash('this is kind of a long string, don\'t you think?', 'the quick brown fox jumped over the lazy doge');
- differentHash(true, 2);
- differentHash(false, 'flooog');
- });
- it('should give different values for string and object with string', function () {
- differentHash('some string', { key: 'some string' });
- });
- it('should give different values for number and array', function () {
- differentHash(1, [1]);
- });
- it('should give different values for string and array of string', function () {
- differentHash('string', ['string']);
- });
- it('should give different values for boolean and object with boolean', function () {
- differentHash(true, { key: true });
- });
- it('should give different values for different arrays', function () {
- differentHash([1, 2, 3], [1, 2]);
- differentHash([1, 4, 5, 6], ['foo', 1, true, undefined]);
- differentHash([1, 4, 6], [1, 4, 7]);
- differentHash([1, 3, 5], ['1', '3', '5']);
- });
- it('should give different values for different objects', function () {
- differentHash({ key: 'value' }, { other: 'value' });
- differentHash({ a: { b: 'c' } }, { a: 'b' });
- });
- it('should differentiate between arrays and objects', function () {
- differentHash([1, true, '1'], { a: 1, b: true, c: '1' });
- });
- });
- describe('Order independent hash function should work in pathological cases', function () {
- it('should work in funky javascript cases', function () {
- differentHash(undefined, null);
- differentHash(0, undefined);
- differentHash(0, null);
- differentHash(0, false);
- differentHash(0, []);
- differentHash('', []);
- differentHash(3.22, '3.22');
- differentHash(true, 'true');
- differentHash(false, 0);
- });
- it('should work on empty array and object', function () {
- differentHash([], {});
- });
- it('should work on empty object and undefined', function () {
- differentHash({}, undefined);
- });
- it('should work on empty array and array with 0', function () {
- differentHash([], [0]);
- });
- });
- describe('Order independent hash function should be order independent', function () {
- it('should not care about array order', function () {
- sameHash([1, 2, 3], [3, 2, 1]);
- sameHash(['hi', true, 9.4], [true, 'hi', 9.4]);
- });
- it('should not care about key order in an object', function () {
- sameHash({ foo: 'bar', foz: 'baz' }, { foz: 'baz', foo: 'bar' });
- });
- it('should work with complicated objects', function () {
- var obj1 = {
- foo: 'bar',
- faz: [
- 1,
- 'pie',
- {
- food: 'yum'
- }
- ]
- };
- var obj2 = {
- faz: [
- 'pie',
- {
- food: 'yum'
- },
- 1
- ],
- foo: 'bar'
- };
- sameHash(obj1, obj2);
- });
- });
- });
- describe('Order indepedent array comparison should work', function () {
- it('can compare simple arrays in an order independent fashion', function () {
- var lhs = [1, 2, 3];
- var rhs = [1, 3, 2];
- var diff = deep.orderIndependentDiff(lhs, rhs);
- expect(diff).to.be(undefined);
- });
- it('still works with repeated elements', function () {
- var lhs = [1, 1, 2];
- var rhs = [1, 2, 1];
- var diff = deep.orderIndependentDiff(lhs, rhs);
- expect(diff).to.be(undefined);
- });
- it('works on complex objects', function () {
- var obj1 = {
- foo: 'bar',
- faz: [
- 1,
- 'pie',
- {
- food: 'yum'
- }
- ]
- };
- var obj2 = {
- faz: [
- 'pie',
- {
- food: 'yum'
- },
- 1
- ],
- foo: 'bar'
- };
- var diff = deep.orderIndependentDiff(obj1, obj2);
- expect(diff).to.be(undefined);
- });
- it('should report some difference in non-equal arrays', function () {
- var lhs = [1, 2, 3];
- var rhs = [2, 2, 3];
- var diff = deep.orderIndependentDiff(lhs, rhs);
- expect(diff.length).to.be.ok();
- });
- });
- });
- }));
|