hoek
Advanced tools
Comparing version 2.6.0 to 2.7.0
@@ -221,2 +221,95 @@ // Load modules | ||
// Deep object or array comparison | ||
exports.deepEqual = function (obj, ref, seen) { | ||
var type = typeof obj; | ||
if (type !== typeof ref) { | ||
return false; | ||
} | ||
if (type !== 'object' || | ||
obj === null || | ||
ref === null) { | ||
if (obj === ref) { // Copied from Deep-eql, copyright(c) 2013 Jake Luer, jake@alogicalparadox.com, MIT Licensed, https://github.com/chaijs/deep-eql | ||
return obj !== 0 || 1 / obj === 1 / ref; // -0 / +0 | ||
} | ||
return obj !== obj && ref !== ref; // NaN | ||
} | ||
seen = seen || []; | ||
if (seen.indexOf(obj) !== -1) { | ||
return true; // If previous comparison failed, it would have stopped execution | ||
} | ||
seen.push(obj); | ||
if (Array.isArray(obj)) { | ||
if (!Array.isArray(ref)) { | ||
return false; | ||
} | ||
if (obj.length !== ref.length) { | ||
return false; | ||
} | ||
for (var i = 0, il = obj.length; i < il; ++i) { | ||
if (obj[i] !== ref[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
if (Buffer.isBuffer(obj)) { | ||
if (!Buffer.isBuffer(ref)) { | ||
return false; | ||
} | ||
if (obj.length !== ref.length) { | ||
return false; | ||
} | ||
for (var i = 0, il = obj.length; i < il; ++i) { | ||
if (obj[i] !== ref[i]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
if (obj instanceof Date) { | ||
return (ref instanceof Date && obj.getTime() === ref.getTime()); | ||
} | ||
if (obj instanceof RegExp) { | ||
return (ref instanceof RegExp && obj.toString() === ref.toString()); | ||
} | ||
if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) { | ||
return false; | ||
} | ||
for (var i in obj) { | ||
if (obj.hasOwnProperty(i)) { | ||
var descriptor = Object.getOwnPropertyDescriptor(obj, i); | ||
if (descriptor.get) { | ||
if (!exports.deepEqual(descriptor, Object.getOwnPropertyDescriptor(ref, i), seen)) { | ||
return false; | ||
} | ||
} | ||
else if (!exports.deepEqual(obj[i], ref[i], seen)) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
}; | ||
// Remove duplicate items from array | ||
@@ -223,0 +316,0 @@ |
{ | ||
"name": "hoek", | ||
"description": "General purpose node utilities", | ||
"version": "2.6.0", | ||
"version": "2.7.0", | ||
"repository": "git://github.com/hapijs/hoek", | ||
@@ -6,0 +6,0 @@ "main": "index", |
@@ -18,2 +18,3 @@ ![hoek Logo](https://raw.github.com/hapijs/hoek/master/images/hoek.png) | ||
* [applyToDefaultsWithShallow](#applytodefaultswithshallowdefaults-options-keys "applyToDefaultsWithShallow") | ||
* [deepEqual](#deepequala-b "deepEqual") | ||
* [unique](#uniquearray-key "unique") | ||
@@ -178,2 +179,10 @@ * [mapToObject](#maptoobjectarray-key "mapToObject") | ||
### deepEqual(b, a) | ||
Performs a deep comparison of the two values including support for circular dependencies, prototype, and properties. | ||
```javascript | ||
Hoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); | ||
``` | ||
### unique(array, key) | ||
@@ -180,0 +189,0 @@ |
@@ -311,3 +311,3 @@ // Load modules | ||
}, | ||
d: [{ e: 1}] | ||
d: [{ e: 1 }] | ||
}; | ||
@@ -673,2 +673,190 @@ | ||
describe('deepEqual()', function () { | ||
it('compares simple values', function (done) { | ||
expect(Hoek.deepEqual('x', 'x')).to.be.true; | ||
expect(Hoek.deepEqual('x', 'y')).to.be.false; | ||
expect(Hoek.deepEqual('x1', 'x')).to.be.false; | ||
expect(Hoek.deepEqual(-0, +0)).to.be.false; | ||
expect(Hoek.deepEqual(-0, -0)).to.be.true; | ||
expect(Hoek.deepEqual(+0, +0)).to.be.true; | ||
expect(Hoek.deepEqual(+0, -0)).to.be.false; | ||
expect(Hoek.deepEqual(1, 1)).to.be.true; | ||
expect(Hoek.deepEqual(0, 0)).to.be.true; | ||
expect(Hoek.deepEqual(-1, 1)).to.be.false; | ||
expect(Hoek.deepEqual(NaN, 0)).to.be.false; | ||
expect(Hoek.deepEqual(NaN, NaN)).to.be.true; | ||
done(); | ||
}); | ||
it('compares different types', function (done) { | ||
expect(Hoek.deepEqual([], 5)).to.be.false; | ||
expect(Hoek.deepEqual(5, [])).to.be.false; | ||
expect(Hoek.deepEqual({}, null)).to.be.false; | ||
expect(Hoek.deepEqual(null, {})).to.be.false; | ||
expect(Hoek.deepEqual('abc', {})).to.be.false; | ||
expect(Hoek.deepEqual({}, 'abc')).to.be.false; | ||
done(); | ||
}); | ||
it('compares empty structures', function (done) { | ||
expect(Hoek.deepEqual([], [])).to.be.true; | ||
expect(Hoek.deepEqual({}, {})).to.be.true; | ||
expect(Hoek.deepEqual([], {})).to.be.false; | ||
done(); | ||
}); | ||
it('compares empty arguments object', function (done) { | ||
var compare = function () { | ||
expect(Hoek.deepEqual([], arguments)).to.be.false; | ||
}; | ||
compare(); | ||
done(); | ||
}); | ||
it('compares empty arguments objects', function (done) { | ||
var compare = function () { | ||
var arg1 = arguments; | ||
var inner = function () { | ||
expect(Hoek.deepEqual(arg1, arguments)).to.be.true; | ||
}; | ||
inner(); | ||
}; | ||
compare(); | ||
done(); | ||
}); | ||
it('compares dates', function (done) { | ||
expect(Hoek.deepEqual(new Date(), new Date())).to.be.true; | ||
expect(Hoek.deepEqual(new Date(100), new Date(101))).to.be.false; | ||
expect(Hoek.deepEqual(new Date(), {})).to.be.false; | ||
done(); | ||
}); | ||
it('compares regular expressions', function (done) { | ||
expect(Hoek.deepEqual(/\s/, new RegExp('\\\s'))).to.be.true; | ||
expect(Hoek.deepEqual(/\s/g, /\s/g)).to.be.true; | ||
expect(Hoek.deepEqual(/a/, {})).to.be.false; | ||
expect(Hoek.deepEqual(/\s/g, /\s/i)).to.be.false; | ||
expect(Hoek.deepEqual(/a/g, /b/g)).to.be.false; | ||
done(); | ||
}); | ||
it('compares arrays', function (done) { | ||
expect(Hoek.deepEqual([1, 2, 3], [1, 2, 3])).to.be.true; | ||
expect(Hoek.deepEqual([1, 2, 3], [1, 3, 2])).to.be.false; | ||
expect(Hoek.deepEqual([1, 2, 3], [1, 2])).to.be.false; | ||
done(); | ||
}); | ||
it('compares buffers', function (done) { | ||
expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2, 3]))).to.be.true; | ||
expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 3, 2]))).to.be.false; | ||
expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2]))).to.be.false; | ||
expect(Hoek.deepEqual(new Buffer([1, 2, 3]), {})).to.be.false; | ||
expect(Hoek.deepEqual(new Buffer([1, 2, 3]), [1, 2, 3])).to.be.false; | ||
done(); | ||
}); | ||
it('compares objects', function (done) { | ||
expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).to.be.true; | ||
expect(Hoek.deepEqual({ foo: 'bar' }, { foo: 'baz' })).to.be.false; | ||
expect(Hoek.deepEqual({ foo: { bar: 'foo' } }, { foo: { bar: 'baz' } })).to.be.false; | ||
done(); | ||
}); | ||
it('handles circular dependency', function (done) { | ||
var a = {}; | ||
a.x = a; | ||
var b = Hoek.clone(a); | ||
expect(Hoek.deepEqual(a, b)).to.equal.true; | ||
done(); | ||
}); | ||
it('compares an object with property getter without executing it', function (done) { | ||
var obj = {}; | ||
var value = 1; | ||
var execCount = 0; | ||
Object.defineProperty(obj, 'test', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { | ||
++execCount; | ||
return value; | ||
} | ||
}); | ||
var copy = Hoek.clone(obj); | ||
expect(Hoek.deepEqual(obj, copy)).to.equal.true; | ||
expect(execCount).to.equal(0); | ||
expect(copy.test).to.equal(1); | ||
expect(execCount).to.equal(1); | ||
done(); | ||
}); | ||
it('compares objects with property getters', function (done) { | ||
var obj = {}; | ||
Object.defineProperty(obj, 'test', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return 1; } | ||
}); | ||
var ref = {}; | ||
Object.defineProperty(ref, 'test', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return 2; } | ||
}); | ||
expect(Hoek.deepEqual(obj, ref)).to.equal.false; | ||
done(); | ||
}); | ||
it('compared object prototypes', function (done) { | ||
var Obj = function () { | ||
this.a = 5; | ||
}; | ||
Obj.prototype.b = function () { return this.a; }; | ||
var Ref = function () { | ||
this.a = 5; | ||
}; | ||
Ref.prototype.b = function () { return this.a; }; | ||
expect(Hoek.deepEqual(new Obj(), new Ref())).to.equal.false; | ||
expect(Hoek.deepEqual(new Obj(), new Obj())).to.equal.true; | ||
expect(Hoek.deepEqual(new Ref(), new Ref())).to.equal.true; | ||
done(); | ||
}); | ||
}); | ||
describe('unique()', function () { | ||
@@ -873,3 +1061,3 @@ | ||
expect(Hoek.reach(obj, 'a.b.q', {default: 'defaultValue'})).to.equal('defaultValue'); | ||
expect(Hoek.reach(obj, 'a.b.q', { default: 'defaultValue' })).to.equal('defaultValue'); | ||
done(); | ||
@@ -880,3 +1068,3 @@ }); | ||
expect(Hoek.reach(obj, 'q', {default: 'defaultValue'})).to.equal('defaultValue'); | ||
expect(Hoek.reach(obj, 'q', { default: 'defaultValue' })).to.equal('defaultValue'); | ||
done(); | ||
@@ -887,3 +1075,3 @@ }); | ||
expect(Hoek.reach(obj, 'q', {default: ''})).to.equal(''); | ||
expect(Hoek.reach(obj, 'q', { default: '' })).to.equal(''); | ||
done(); | ||
@@ -890,0 +1078,0 @@ }); |
122623
1978
472