3 var Fs = require('fs');
4 var Path = require('path');
5 var Code = require('code');
6 var Hoek = require('../lib');
7 var Lab = require('lab');
17 var lab = exports.lab = Lab.script();
18 var describe = lab.experiment;
20 var expect = Code.expect;
34 z: new Date(1378775452757)
37 var dupsArray = [nestedObj, { z: 'z' }, nestedObj];
38 var reducedDupsArray = [nestedObj, { z: 'z' }];
40 describe('clone()', function () {
42 it('clones a nested object', function (done) {
45 var b = Hoek.clone(a);
47 expect(a).to.deep.equal(b);
48 expect(a.z.getTime()).to.equal(b.z.getTime());
52 it('clones a null object', function (done) {
54 var b = Hoek.clone(null);
56 expect(b).to.equal(null);
60 it('should not convert undefined properties to null', function (done) {
62 var obj = { something: undefined };
63 var b = Hoek.clone(obj);
65 expect(typeof b.something).to.equal('undefined');
69 it('should not throw on circular reference', function (done) {
74 var test = function () {
76 var b = Hoek.clone(a);
79 expect(test).to.not.throw();
83 it('clones circular reference', function (done) {
90 var b = Hoek.clone(x);
91 expect(Object.keys(b.y)).to.deep.equal(Object.keys(x));
92 expect(b.z).to.not.equal(x.z);
93 expect(b.y).to.not.equal(x.y);
94 expect(b.y.z).to.not.equal(x.y.z);
95 expect(b.y).to.equal(b);
96 expect(b.y.y.y.y).to.equal(b);
100 it('clones an object with a null prototype', function (done) {
102 var obj = Object.create(null);
103 var b = Hoek.clone(obj);
105 expect(b).to.deep.equal(obj);
109 it('clones deeply nested object', function (done) {
123 var b = Hoek.clone(a);
125 expect(a).to.deep.equal(b);
126 expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime());
130 it('clones arrays', function (done) {
134 var b = Hoek.clone(a);
136 expect(a).to.deep.equal(b);
140 it('performs actual copy for shallow keys (no pass by reference)', function (done) {
142 var x = Hoek.clone(nestedObj);
143 var y = Hoek.clone(nestedObj);
146 expect(x.z).to.not.equal(nestedObj.z);
147 expect(x.z).to.not.equal(y.z);
150 expect(x.w).to.not.equal(nestedObj.w);
151 expect(x.w).to.not.equal(y.w);
154 expect(x.v).to.not.equal(nestedObj.v);
155 expect(x.v).to.not.equal(y.v);
159 expect(x.y).to.not.equal(nestedObj.y);
160 expect(x.y).to.not.equal(y.y);
165 it('performs actual copy for deep keys (no pass by reference)', function (done) {
167 var x = Hoek.clone(nestedObj);
168 var y = Hoek.clone(nestedObj);
170 expect(x.x.c).to.not.equal(nestedObj.x.c);
171 expect(x.x.c).to.not.equal(y.x.c);
173 expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime());
174 expect(x.x.c.getTime()).to.equal(y.x.c.getTime());
178 it('copies functions with properties', function (done) {
187 a.x.z = 'string in function';
188 a.x.v = function () {
194 var b = Hoek.clone(a);
195 expect(b.x()).to.equal(1);
196 expect(b.x.v()).to.equal(2);
197 expect(b.y.u).to.equal(b.x);
198 expect(b.x.z).to.equal('string in function');
202 it('should copy a buffer', function (done) {
205 key: new Buffer([1, 2, 3, 4, 5]),
206 cert: new Buffer([1, 2, 3, 4, 5, 6, 10])
209 var copiedTls = Hoek.clone(tls);
210 expect(Buffer.isBuffer(copiedTls.key)).to.equal(true);
211 expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key));
212 expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true);
213 expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert));
217 it('clones an object with a prototype', function (done) {
219 var Obj = function () {
224 Obj.prototype.b = function () {
230 var b = Hoek.clone(a);
232 expect(b.a).to.equal(5);
233 expect(b.b()).to.equal('c');
234 expect(a).to.deep.equal(b);
238 it('reuses cloned Date object', function (done) {
246 var copy = Hoek.clone(obj);
247 expect(copy.a).to.equal(copy.b);
251 it('shallow copies an object with a prototype and isImmutable flag', function (done) {
253 var Obj = function () {
258 Obj.prototype.b = function () {
263 Obj.prototype.isImmutable = true;
269 var copy = Hoek.clone(obj);
271 expect(obj.a.value).to.equal(5);
272 expect(copy.a.value).to.equal(5);
273 expect(copy.a.b()).to.equal('c');
274 expect(obj.a).to.equal(copy.a);
278 it('clones an object with property getter without executing it', function (done) {
284 Object.defineProperty(obj, 'test', {
294 var copy = Hoek.clone(obj);
295 expect(execCount).to.equal(0);
296 expect(copy.test).to.equal(1);
297 expect(execCount).to.equal(1);
301 it('clones an object with property getter and setter', function (done) {
307 Object.defineProperty(obj, 'test', {
314 set: function (value) {
316 this._test = value - 1;
320 var copy = Hoek.clone(obj);
321 expect(copy.test).to.equal(0);
323 expect(copy.test).to.equal(4);
327 it('clones an object with only property setter', function (done) {
333 Object.defineProperty(obj, 'test', {
336 set: function (value) {
338 this._test = value - 1;
342 var copy = Hoek.clone(obj);
343 expect(copy._test).to.equal(0);
345 expect(copy._test).to.equal(4);
349 it('clones an object with non-enumerable properties', function (done) {
355 Object.defineProperty(obj, 'test', {
358 set: function (value) {
360 this._test = value - 1;
364 var copy = Hoek.clone(obj);
365 expect(copy._test).to.equal(0);
367 expect(copy._test).to.equal(4);
371 it('clones an object where getOwnPropertyDescriptor returns undefined', function (done) {
373 var oldGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
374 var obj = { a: 'b' };
375 Object.getOwnPropertyDescriptor = function () {
380 var copy = Hoek.clone(obj);
381 Object.getOwnPropertyDescriptor = oldGetOwnPropertyDescriptor;
382 expect(copy).to.deep.equal(obj);
387 describe('merge()', function () {
389 it('deep copies source items', function (done) {
403 Hoek.merge(target, source);
404 expect(target.c).to.not.equal(source.c);
405 expect(target.c).to.deep.equal(source.c);
406 expect(target.d).to.not.equal(source.d);
407 expect(target.d[0]).to.not.equal(source.d[0]);
408 expect(target.d).to.deep.equal(source.d);
412 it('merges array over an object', function (done) {
426 expect(a.x[0]).to.equal('n');
427 expect(a.x.n).to.not.exist();
431 it('merges object over an array', function (done) {
445 expect(a.x.n).to.equal('1');
446 expect(a.x[0]).to.not.exist();
450 it('does not throw if source is null', function (done) {
458 c = Hoek.merge(a, b);
461 expect(c).to.equal(a);
465 it('does not throw if source is undefined', function (done) {
473 c = Hoek.merge(a, b);
476 expect(c).to.equal(a);
480 it('throws if source is not an object', function (done) {
488 }).to.throw('Invalid source value: must be null, undefined, or an object');
492 it('throws if target is not an object', function (done) {
500 }).to.throw('Invalid target value: must be an object');
504 it('throws if target is not an array and source is', function (done) {
512 }).to.throw('Cannot merge array onto an object');
516 it('returns the same object when merging arrays', function (done) {
521 expect(Hoek.merge(a, b)).to.equal(a);
525 it('combines an empty object with a non-empty object', function (done) {
530 var c = Hoek.merge(a, b);
531 expect(a).to.deep.equal(b);
532 expect(c).to.deep.equal(b);
536 it('overrides values in target', function (done) {
538 var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
539 var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
541 var c = Hoek.merge(a, b);
542 expect(c.x).to.equal(null);
543 expect(c.y).to.equal(2);
544 expect(c.z).to.equal(4);
545 expect(c.v).to.equal(0);
546 expect(c.m).to.equal('123');
547 expect(c.t).to.deep.equal({ u: 6 });
551 it('overrides values in target (flip)', function (done) {
553 var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
554 var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
556 var d = Hoek.merge(b, a);
557 expect(d.x).to.equal(1);
558 expect(d.y).to.equal(2);
559 expect(d.z).to.equal(3);
560 expect(d.v).to.equal(5);
561 expect(d.m).to.equal('abc');
562 expect(d.t).to.deep.equal('test');
566 it('retains Date properties', function (done) {
568 var a = { x: new Date(1378776452757) };
570 var b = Hoek.merge({}, a);
571 expect(a.x.getTime()).to.equal(b.x.getTime());
575 it('retains Date properties when merging keys', function (done) {
577 var a = { x: new Date(1378776452757) };
579 var b = Hoek.merge({ x: {} }, a);
580 expect(a.x.getTime()).to.equal(b.x.getTime());
584 it('overrides Buffer', function (done) {
586 var a = { x: new Buffer('abc') };
588 var b = Hoek.merge({ x: {} }, a);
589 expect(a.x.toString()).to.equal('abc');
594 describe('applyToDefaults()', function () {
607 it('throws when target is null', function (done) {
611 Hoek.applyToDefaults(null, {});
612 }).to.throw('Invalid defaults value: must be an object');
616 it('returns null if options is false', function (done) {
618 var result = Hoek.applyToDefaults(defaults, false);
619 expect(result).to.equal(null);
623 it('returns null if options is null', function (done) {
625 var result = Hoek.applyToDefaults(defaults, null);
626 expect(result).to.equal(null);
630 it('returns null if options is undefined', function (done) {
632 var result = Hoek.applyToDefaults(defaults, undefined);
633 expect(result).to.equal(null);
637 it('returns a copy of defaults if options is true', function (done) {
639 var result = Hoek.applyToDefaults(defaults, true);
640 expect(result).to.deep.equal(defaults);
644 it('applies object to defaults', function (done) {
657 var result = Hoek.applyToDefaults(defaults, obj);
658 expect(result.c.e).to.deep.equal([4]);
659 expect(result.a).to.equal(1);
660 expect(result.b).to.equal(2);
661 expect(result.f).to.equal(0);
662 expect(result.g).to.deep.equal({ h: 5 });
666 it('applies object to defaults with null', function (done) {
679 var result = Hoek.applyToDefaults(defaults, obj, true);
680 expect(result.c.e).to.deep.equal([4]);
681 expect(result.a).to.equal(null);
682 expect(result.b).to.equal(2);
683 expect(result.f).to.equal(0);
684 expect(result.g).to.deep.equal({ h: 5 });
689 describe('cloneWithShallow()', function () {
691 it('deep clones except for listed keys', function (done) {
702 var copy = Hoek.cloneWithShallow(source, ['c']);
703 expect(copy).to.deep.equal(source);
704 expect(copy).to.not.equal(source);
705 expect(copy.a).to.not.equal(source.a);
706 expect(copy.b).to.equal(source.b);
710 it('returns immutable value', function (done) {
712 expect(Hoek.cloneWithShallow(5)).to.equal(5);
716 it('returns null value', function (done) {
718 expect(Hoek.cloneWithShallow(null)).to.equal(null);
722 it('returns undefined value', function (done) {
724 expect(Hoek.cloneWithShallow(undefined)).to.equal(undefined);
728 it('deep clones except for listed keys (including missing keys)', function (done) {
739 var copy = Hoek.cloneWithShallow(source, ['c', 'v']);
740 expect(copy).to.deep.equal(source);
741 expect(copy).to.not.equal(source);
742 expect(copy.a).to.not.equal(source.a);
743 expect(copy.b).to.equal(source.b);
748 describe('applyToDefaultsWithShallow()', function () {
750 it('shallow copies the listed keys from options without merging', function (done) {
773 var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['a']);
774 expect(merged).to.deep.equal({ a: { b: 4 }, c: { d: 6, g: 1, f: 7 } });
775 expect(merged.a).to.equal(options.a);
776 expect(merged.a).to.not.equal(defaults.a);
777 expect(merged.c).to.not.equal(options.c);
778 expect(merged.c).to.not.equal(defaults.c);
782 it('shallow copies the nested keys (override)', function (done) {
806 var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']);
807 expect(merged).to.deep.equal({ a: { b: 4 }, c: { d: 6, g: { h: 8 } } });
808 expect(merged.c.g).to.equal(options.c.g);
812 it('shallow copies the nested keys (missing)', function (done) {
831 var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']);
832 expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { h: 8 } } });
833 expect(merged.c.g).to.equal(options.c.g);
837 it('shallow copies the nested keys (override)', function (done) {
861 var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']);
862 expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { h: 8 } } });
863 expect(merged.c.g).to.equal(options.c.g);
867 it('shallow copies the nested keys (deeper)', function (done) {
888 var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g.r']);
889 expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } });
890 expect(merged.c.g.r).to.equal(options.c.g.r);
894 it('shallow copies the nested keys (not present)', function (done) {
915 var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['x.y']);
916 expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } });
920 it('shallow copies the listed keys in the defaults', function (done) {
928 var merged = Hoek.applyToDefaultsWithShallow(defaults, {}, ['a']);
929 expect(merged.a).to.equal(defaults.a);
933 it('shallow copies the listed keys in the defaults (true)', function (done) {
941 var merged = Hoek.applyToDefaultsWithShallow(defaults, true, ['a']);
942 expect(merged.a).to.equal(defaults.a);
946 it('returns null on false', function (done) {
954 var merged = Hoek.applyToDefaultsWithShallow(defaults, false, ['a']);
955 expect(merged).to.equal(null);
959 it('throws on missing defaults', function (done) {
963 Hoek.applyToDefaultsWithShallow(null, {}, ['a']);
964 }).to.throw('Invalid defaults value: must be an object');
968 it('throws on invalid defaults', function (done) {
972 Hoek.applyToDefaultsWithShallow('abc', {}, ['a']);
973 }).to.throw('Invalid defaults value: must be an object');
977 it('throws on invalid options', function (done) {
981 Hoek.applyToDefaultsWithShallow({}, 'abc', ['a']);
982 }).to.throw('Invalid options value: must be true, falsy or an object');
986 it('throws on missing keys', function (done) {
990 Hoek.applyToDefaultsWithShallow({}, true);
991 }).to.throw('Invalid keys');
995 it('throws on invalid keys', function (done) {
999 Hoek.applyToDefaultsWithShallow({}, true, 'a');
1000 }).to.throw('Invalid keys');
1005 describe('deepEqual()', function () {
1007 it('compares simple values', function (done) {
1009 expect(Hoek.deepEqual('x', 'x')).to.be.true();
1010 expect(Hoek.deepEqual('x', 'y')).to.be.false();
1011 expect(Hoek.deepEqual('x1', 'x')).to.be.false();
1012 expect(Hoek.deepEqual(-0, +0)).to.be.false();
1013 expect(Hoek.deepEqual(-0, -0)).to.be.true();
1014 expect(Hoek.deepEqual(+0, +0)).to.be.true();
1015 expect(Hoek.deepEqual(+0, -0)).to.be.false();
1016 expect(Hoek.deepEqual(1, 1)).to.be.true();
1017 expect(Hoek.deepEqual(0, 0)).to.be.true();
1018 expect(Hoek.deepEqual(-1, 1)).to.be.false();
1019 expect(Hoek.deepEqual(NaN, 0)).to.be.false();
1020 expect(Hoek.deepEqual(NaN, NaN)).to.be.true();
1024 it('compares different types', function (done) {
1026 expect(Hoek.deepEqual([], 5)).to.be.false();
1027 expect(Hoek.deepEqual(5, [])).to.be.false();
1028 expect(Hoek.deepEqual({}, null)).to.be.false();
1029 expect(Hoek.deepEqual(null, {})).to.be.false();
1030 expect(Hoek.deepEqual('abc', {})).to.be.false();
1031 expect(Hoek.deepEqual({}, 'abc')).to.be.false();
1035 it('compares empty structures', function (done) {
1037 expect(Hoek.deepEqual([], [])).to.be.true();
1038 expect(Hoek.deepEqual({}, {})).to.be.true();
1039 expect(Hoek.deepEqual([], {})).to.be.false();
1043 it('compares empty arguments object', function (done) {
1045 var compare = function () {
1047 expect(Hoek.deepEqual([], arguments)).to.be.false();
1054 it('compares empty arguments objects', function (done) {
1056 var compare = function () {
1058 var arg1 = arguments;
1060 var inner = function () {
1062 expect(Hoek.deepEqual(arg1, arguments)).to.be.false(); // callee is not the same
1072 it('compares dates', function (done) {
1074 expect(Hoek.deepEqual(new Date(2015, 1, 1), new Date(2015, 1, 1))).to.be.true();
1075 expect(Hoek.deepEqual(new Date(100), new Date(101))).to.be.false();
1076 expect(Hoek.deepEqual(new Date(), {})).to.be.false();
1080 it('compares regular expressions', function (done) {
1082 expect(Hoek.deepEqual(/\s/, new RegExp('\\\s'))).to.be.true();
1083 expect(Hoek.deepEqual(/\s/g, /\s/g)).to.be.true();
1084 expect(Hoek.deepEqual(/a/, {})).to.be.false();
1085 expect(Hoek.deepEqual(/\s/g, /\s/i)).to.be.false();
1086 expect(Hoek.deepEqual(/a/g, /b/g)).to.be.false();
1090 it('compares arrays', function (done) {
1092 expect(Hoek.deepEqual([[1]], [[1]])).to.be.true();
1093 expect(Hoek.deepEqual([1, 2, 3], [1, 2, 3])).to.be.true();
1094 expect(Hoek.deepEqual([1, 2, 3], [1, 3, 2])).to.be.false();
1095 expect(Hoek.deepEqual([1, 2, 3], [1, 2])).to.be.false();
1096 expect(Hoek.deepEqual([1], [1])).to.be.true();
1100 it('compares buffers', function (done) {
1102 expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2, 3]))).to.be.true();
1103 expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 3, 2]))).to.be.false();
1104 expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2]))).to.be.false();
1105 expect(Hoek.deepEqual(new Buffer([1, 2, 3]), {})).to.be.false();
1106 expect(Hoek.deepEqual(new Buffer([1, 2, 3]), [1, 2, 3])).to.be.false();
1110 it('compares objects', function (done) {
1112 expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).to.be.true();
1113 expect(Hoek.deepEqual({ foo: 'bar' }, { foo: 'baz' })).to.be.false();
1114 expect(Hoek.deepEqual({ foo: { bar: 'foo' } }, { foo: { bar: 'baz' } })).to.be.false();
1118 it('handles circular dependency', function (done) {
1123 var b = Hoek.clone(a);
1124 expect(Hoek.deepEqual(a, b)).to.be.true();
1128 it('compares an object with property getter without executing it', function (done) {
1134 Object.defineProperty(obj, 'test', {
1144 var copy = Hoek.clone(obj);
1145 expect(Hoek.deepEqual(obj, copy)).to.be.true();
1146 expect(execCount).to.equal(0);
1147 expect(copy.test).to.equal(1);
1148 expect(execCount).to.equal(1);
1152 it('compares objects with property getters', function (done) {
1155 Object.defineProperty(obj, 'test', {
1165 Object.defineProperty(ref, 'test', {
1174 expect(Hoek.deepEqual(obj, ref)).to.be.false();
1178 it('compares object prototypes', function (done) {
1180 var Obj = function () {
1185 Obj.prototype.b = function () {
1190 var Ref = function () {
1195 Ref.prototype.b = function () {
1200 expect(Hoek.deepEqual(new Obj(), new Ref())).to.be.false();
1201 expect(Hoek.deepEqual(new Obj(), new Obj())).to.be.true();
1202 expect(Hoek.deepEqual(new Ref(), new Ref())).to.be.true();
1206 it('compares plain objects', function (done) {
1208 var a = Object.create(null);
1209 var b = Object.create(null);
1214 expect(Hoek.deepEqual(a, b)).to.be.true();
1215 expect(Hoek.deepEqual(a, { b: 'c' })).to.be.false();
1219 it('compares an object with an empty object', function (done) {
1221 var a = { a: 1, b: 2 };
1223 expect(Hoek.deepEqual({}, a)).to.be.false();
1224 expect(Hoek.deepEqual(a, {})).to.be.false();
1228 it('compares an object ignoring the prototype', function (done) {
1230 var a = Object.create(null);
1233 expect(Hoek.deepEqual(a, b, { prototype: false })).to.be.true();
1237 it('compares an object ignoring the prototype recursively', function (done) {
1239 var a = [Object.create(null)];
1242 expect(Hoek.deepEqual(a, b, { prototype: false })).to.be.true();
1247 describe('unique()', function () {
1249 it('ensures uniqueness within array of objects based on subkey', function (done) {
1251 var a = Hoek.unique(dupsArray, 'x');
1252 expect(a).to.deep.equal(reducedDupsArray);
1256 it('removes duplicated without key', function (done) {
1258 expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]);
1263 describe('mapToObject()', function () {
1265 it('returns null on null array', function (done) {
1267 var a = Hoek.mapToObject(null);
1268 expect(a).to.equal(null);
1272 it('converts basic array to existential object', function (done) {
1274 var keys = [1, 2, 3, 4];
1275 var a = Hoek.mapToObject(keys);
1276 for (var i in keys) {
1277 expect(a[keys[i]]).to.equal(true);
1282 it('converts array of objects to existential object', function (done) {
1284 var keys = [{ x: 1 }, { x: 2 }, { x: 3 }, { y: 4 }];
1286 var a = Hoek.mapToObject(keys, subkey);
1287 expect(a).to.deep.equal({ 1: true, 2: true, 3: true });
1292 describe('intersect()', function () {
1294 it('returns the common objects of two arrays', function (done) {
1296 var array1 = [1, 2, 3, 4, 4, 5, 5];
1297 var array2 = [5, 4, 5, 6, 7];
1298 var common = Hoek.intersect(array1, array2);
1299 expect(common.length).to.equal(2);
1303 it('returns just the first common object of two arrays', function (done) {
1305 var array1 = [1, 2, 3, 4, 4, 5, 5];
1306 var array2 = [5, 4, 5, 6, 7];
1307 var common = Hoek.intersect(array1, array2, true);
1308 expect(common).to.equal(5);
1312 it('returns null when no common and returning just the first common object of two arrays', function (done) {
1314 var array1 = [1, 2, 3, 4, 4, 5, 5];
1315 var array2 = [6, 7];
1316 var common = Hoek.intersect(array1, array2, true);
1317 expect(common).to.equal(null);
1321 it('returns an empty array if either input is null', function (done) {
1323 expect(Hoek.intersect([1], null).length).to.equal(0);
1324 expect(Hoek.intersect(null, [1]).length).to.equal(0);
1328 it('returns the common objects of object and array', function (done) {
1330 var array1 = [1, 2, 3, 4, 4, 5, 5];
1331 var array2 = [5, 4, 5, 6, 7];
1332 var common = Hoek.intersect(Hoek.mapToObject(array1), array2);
1333 expect(common.length).to.equal(2);
1338 describe('contain()', function () {
1340 it('tests strings', function (done) {
1342 expect(Hoek.contain('abc', 'ab')).to.be.true();
1343 expect(Hoek.contain('abc', 'abc', { only: true })).to.be.true();
1344 expect(Hoek.contain('aaa', 'a', { only: true })).to.be.true();
1345 expect(Hoek.contain('abc', 'b', { once: true })).to.be.true();
1346 expect(Hoek.contain('abc', ['a', 'c'])).to.be.true();
1347 expect(Hoek.contain('abc', ['a', 'd'], { part: true })).to.be.true();
1349 expect(Hoek.contain('abc', 'ac')).to.be.false();
1350 expect(Hoek.contain('abcd', 'abc', { only: true })).to.be.false();
1351 expect(Hoek.contain('aab', 'a', { only: true })).to.be.false();
1352 expect(Hoek.contain('abb', 'b', { once: true })).to.be.false();
1353 expect(Hoek.contain('abc', ['a', 'd'])).to.be.false();
1354 expect(Hoek.contain('abc', ['ab', 'bc'])).to.be.false(); // Overlapping values not supported
1358 it('tests arrays', function (done) {
1360 expect(Hoek.contain([1, 2, 3], 1)).to.be.true();
1361 expect(Hoek.contain([{ a: 1 }], { a: 1 }, { deep: true })).to.be.true();
1362 expect(Hoek.contain([1, 2, 3], [1, 2])).to.be.true();
1363 expect(Hoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true })).to.be.true();
1364 expect(Hoek.contain([1, 1, 2], [1, 2], { only: true })).to.be.true();
1365 expect(Hoek.contain([1, 2], [1, 2], { once: true })).to.be.true();
1366 expect(Hoek.contain([1, 2, 3], [1, 4], { part: true })).to.be.true();
1367 expect(Hoek.contain([[1], [2]], [[1]], { deep: true })).to.be.true();
1369 expect(Hoek.contain([1, 2, 3], 4)).to.be.false();
1370 expect(Hoek.contain([{ a: 1 }], { a: 2 }, { deep: true })).to.be.false();
1371 expect(Hoek.contain([{ a: 1 }], { a: 1 })).to.be.false();
1372 expect(Hoek.contain([1, 2, 3], [4, 5])).to.be.false();
1373 expect(Hoek.contain([[3], [2]], [[1]])).to.be.false();
1374 expect(Hoek.contain([[1], [2]], [[1]])).to.be.false();
1375 expect(Hoek.contain([{ a: 1 }], [{ a: 2 }], { deep: true })).to.be.false();
1376 expect(Hoek.contain([1, 3, 2], [1, 2], { only: true })).to.be.false();
1377 expect(Hoek.contain([1, 2, 2], [1, 2], { once: true })).to.be.false();
1378 expect(Hoek.contain([0, 2, 3], [1, 4], { part: true })).to.be.false();
1382 it('tests objects', function (done) {
1384 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, 'a')).to.be.true();
1385 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'c'])).to.be.true();
1386 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'b', 'c'], { only: true })).to.be.true();
1387 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1 })).to.be.true();
1388 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, c: 3 })).to.be.true();
1389 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true })).to.be.true();
1390 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 }, { only: true })).to.be.true();
1391 expect(Hoek.contain({ a: [1], b: [2], c: [3] }, { a: [1], c: [3] }, { deep: true })).to.be.true();
1392 expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true })).to.be.true();
1393 expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, part: true })).to.be.true();
1394 expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, part: false })).to.be.false();
1395 expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, only: true })).to.be.false();
1396 expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, only: false })).to.be.true();
1398 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, 'd')).to.be.false();
1399 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'd'])).to.be.false();
1400 expect(Hoek.contain({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'b', 'c'], { only: true })).to.be.false();
1401 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 2 })).to.be.false();
1402 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 2, b: 2 }, { part: true })).to.be.false(); // part does not ignore bad value
1403 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 3 })).to.be.false();
1404 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 })).to.be.false();
1405 expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 }, { only: true })).to.be.false();
1406 expect(Hoek.contain({ a: [1], b: [2], c: [3] }, { a: [1], c: [3] })).to.be.false();
1407 expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } })).to.be.false();
1408 expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true })).to.be.true();
1409 expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, only: true })).to.be.false();
1410 expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, only: false })).to.be.true();
1411 expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, part: true })).to.be.true();
1412 expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, part: false })).to.be.false();
1415 var Foo = function (bar) {
1420 Object.defineProperty(Foo.prototype, 'baz', {
1428 expect(Hoek.contain({ a: new Foo('b') }, { a: new Foo('b') }, { deep: true })).to.be.true();
1429 expect(Hoek.contain({ a: new Foo('b') }, { a: new Foo('b') }, { deep: true, part: true })).to.be.true();
1430 expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true })).to.be.true();
1431 expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, only: true })).to.be.false();
1432 expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, part: false })).to.be.false();
1433 expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, part: true })).to.be.true();
1439 describe('flatten()', function () {
1441 it('returns a flat array', function (done) {
1443 var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
1444 expect(result.length).to.equal(13);
1445 expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
1450 describe('reach()', function () {
1472 it('returns object itself', function (done) {
1474 expect(Hoek.reach(obj, null)).to.equal(obj);
1475 expect(Hoek.reach(obj, false)).to.equal(obj);
1476 expect(Hoek.reach(obj)).to.equal(obj);
1480 it('returns first value of array', function (done) {
1482 expect(Hoek.reach(obj, 'k.0')).to.equal(4);
1486 it('returns last value of array using negative index', function (done) {
1488 expect(Hoek.reach(obj, 'k.-2')).to.equal(9);
1492 it('returns a valid member', function (done) {
1494 expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1);
1498 it('returns a valid member with separator override', function (done) {
1500 expect(Hoek.reach(obj, 'a/b/c/d', '/')).to.equal(1);
1504 it('returns undefined on null object', function (done) {
1506 expect(Hoek.reach(null, 'a.b.c.d')).to.equal(undefined);
1510 it('returns undefined on missing object member', function (done) {
1512 expect(Hoek.reach(obj, 'a.b.c.d.x')).to.equal(undefined);
1516 it('returns undefined on missing function member', function (done) {
1518 expect(Hoek.reach(obj, 'i.y', { functions: true })).to.equal(undefined);
1522 it('throws on missing member in strict mode', function (done) {
1524 expect(function () {
1526 Hoek.reach(obj, 'a.b.c.o.x', { strict: true });
1527 }).to.throw('Missing segment o in reach path a.b.c.o.x');
1532 it('returns undefined on invalid member', function (done) {
1534 expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.equal(undefined);
1538 it('returns function member', function (done) {
1540 expect(typeof Hoek.reach(obj, 'i')).to.equal('function');
1544 it('returns function property', function (done) {
1546 expect(Hoek.reach(obj, 'i.x')).to.equal(5);
1550 it('returns null', function (done) {
1552 expect(Hoek.reach(obj, 'j')).to.equal(null);
1556 it('throws on function property when functions not allowed', function (done) {
1558 expect(function () {
1560 Hoek.reach(obj, 'i.x', { functions: false });
1561 }).to.throw('Invalid segment x in reach path i.x');
1566 it('will return a default value if property is not found', function (done) {
1568 expect(Hoek.reach(obj, 'a.b.q', { default: 'defaultValue' })).to.equal('defaultValue');
1572 it('will return a default value if path is not found', function (done) {
1574 expect(Hoek.reach(obj, 'q', { default: 'defaultValue' })).to.equal('defaultValue');
1578 it('allows a falsey value to be used as the default value', function (done) {
1580 expect(Hoek.reach(obj, 'q', { default: '' })).to.equal('');
1585 describe('reachTemplate()', function () {
1587 it('applies object to template', function (done) {
1601 var template = '{k.0}:{k.-2}:{a.b.c.d}:{x.y}:{j}';
1603 expect(Hoek.reachTemplate(obj, template)).to.equal('4:9:1::');
1607 it('applies object to template (options)', function (done) {
1621 var template = '{k/0}:{k/-2}:{a/b/c/d}:{x/y}:{j}';
1623 expect(Hoek.reachTemplate(obj, template, '/')).to.equal('4:9:1::');
1628 describe('callStack()', function () {
1630 it('returns the full call stack', function (done) {
1632 var stack = Hoek.callStack();
1633 expect(stack[0][0]).to.contain('index.js');
1634 expect(stack[0][2]).to.equal(26);
1639 describe('displayStack ()', function () {
1641 it('returns the full call stack for display', function (done) {
1643 var stack = Hoek.displayStack();
1644 expect(stack[0]).to.contain(Path.normalize('/test/index.js') + ':');
1648 it('includes constructor functions correctly', function (done) {
1650 var Something = function (next) {
1655 var something = new Something(function () {
1657 var stack = Hoek.displayStack();
1658 expect(stack[1]).to.contain('new Something');
1664 describe('abort()', function () {
1666 it('exits process when not in test mode', function (done) {
1668 var env = process.env.NODE_ENV;
1669 var write = process.stdout.write;
1670 var exit = process.exit;
1672 process.env.NODE_ENV = 'nottatest';
1673 process.stdout.write = function () { };
1674 process.exit = function (state) {
1676 process.exit = exit;
1677 process.env.NODE_ENV = env;
1678 process.stdout.write = write;
1680 expect(state).to.equal(1);
1687 it('throws when not in test mode and abortThrow is true', function (done) {
1689 var env = process.env.NODE_ENV;
1690 process.env.NODE_ENV = 'nottatest';
1691 Hoek.abortThrow = true;
1693 var fn = function () {
1695 Hoek.abort('my error message');
1698 expect(fn).to.throw('my error message');
1699 Hoek.abortThrow = false;
1700 process.env.NODE_ENV = env;
1705 it('respects hideStack argument', function (done) {
1707 var env = process.env.NODE_ENV;
1708 var write = process.stdout.write;
1709 var exit = process.exit;
1712 process.exit = function () { };
1713 process.env.NODE_ENV = '';
1714 process.stdout.write = function (message) {
1719 Hoek.abort('my error message', true);
1721 process.env.NODE_ENV = env;
1722 process.stdout.write = write;
1723 process.exit = exit;
1725 expect(output).to.equal('ABORT: my error message\n\t\n');
1730 it('throws in test mode', function (done) {
1732 var env = process.env.NODE_ENV;
1733 process.env.NODE_ENV = 'test';
1735 expect(function () {
1737 Hoek.abort('my error message', true);
1738 }).to.throw('my error message');
1740 process.env.NODE_ENV = env;
1744 it('throws in test mode with default message', function (done) {
1746 var env = process.env.NODE_ENV;
1747 process.env.NODE_ENV = 'test';
1749 expect(function () {
1751 Hoek.abort('', true);
1752 }).to.throw('Unknown error');
1754 process.env.NODE_ENV = env;
1758 it('defaults to showing stack', function (done) {
1760 var env = process.env.NODE_ENV;
1761 var write = process.stdout.write;
1762 var exit = process.exit;
1765 process.exit = function () { };
1766 process.env.NODE_ENV = '';
1767 process.stdout.write = function (message) {
1772 Hoek.abort('my error message');
1774 process.env.NODE_ENV = env;
1775 process.stdout.write = write;
1776 process.exit = exit;
1778 expect(output).to.contain('index.js');
1784 describe('assert()', function () {
1786 it('throws an Error when using assert in a test', function (done) {
1788 var fn = function () {
1790 Hoek.assert(false, 'my error message');
1793 expect(fn).to.throw('my error message');
1797 it('throws an Error when using assert in a test with no message', function (done) {
1799 var fn = function () {
1804 expect(fn).to.throw('Unknown error');
1808 it('throws an Error when using assert in a test with multipart message', function (done) {
1810 var fn = function () {
1812 Hoek.assert(false, 'This', 'is', 'my message');
1815 expect(fn).to.throw('This is my message');
1819 it('throws an Error when using assert in a test with multipart message (empty)', function (done) {
1821 var fn = function () {
1823 Hoek.assert(false, 'This', 'is', '', 'my message');
1826 expect(fn).to.throw('This is my message');
1830 it('throws an Error when using assert in a test with object message', function (done) {
1832 var fn = function () {
1834 Hoek.assert(false, 'This', 'is', { spinal: 'tap' });
1837 expect(fn).to.throw('This is {"spinal":"tap"}');
1841 it('throws an Error when using assert in a test with multipart string and error messages', function (done) {
1843 var fn = function () {
1845 Hoek.assert(false, 'This', 'is', new Error('spinal'), new Error('tap'));
1848 expect(fn).to.throw('This is spinal tap');
1852 it('throws an Error when using assert in a test with error object message', function (done) {
1854 var fn = function () {
1856 Hoek.assert(false, new Error('This is spinal tap'));
1859 expect(fn).to.throw('This is spinal tap');
1863 it('throws the same Error that is passed to it if there is only one error passed', function (done) {
1865 var error = new Error('ruh roh');
1866 var error2 = new Error('ruh roh');
1868 var fn = function () {
1870 Hoek.assert(false, error);
1876 expect(error).to.equal(error); // should be the same reference
1877 expect(error).to.not.equal(error2); // error with the same message should not match
1884 describe('Timer', function () {
1886 it('returns time elapsed', function (done) {
1888 var timer = new Hoek.Timer();
1889 setTimeout(function () {
1891 expect(timer.elapsed()).to.be.above(9);
1897 describe('Bench', function () {
1899 it('returns time elapsed', function (done) {
1901 var timer = new Hoek.Bench();
1902 setTimeout(function () {
1904 expect(timer.elapsed()).to.be.above(9);
1910 describe('escapeRegex()', function () {
1912 it('escapes all special regular expression characters', function (done) {
1914 var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
1915 expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
1920 describe('Base64Url', function () {
1922 var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w';
1923 var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF');
1925 describe('base64urlEncode()', function () {
1927 it('should base64 URL-safe a string', function (done) {
1929 expect(Hoek.base64urlEncode(str)).to.equal(base64str);
1933 it('encodes a buffer', function (done) {
1935 expect(Hoek.base64urlEncode(new Buffer(str, 'binary'))).to.equal(base64str);
1939 it('should base64 URL-safe a hex string', function (done) {
1941 var buffer = new Buffer(str, 'binary');
1942 expect(Hoek.base64urlEncode(buffer.toString('hex'), 'hex')).to.equal(base64str);
1946 it('works on larger input strings', function (done) {
1948 var input = Fs.readFileSync(Path.join(__dirname, 'index.js')).toString();
1949 var encoded = Hoek.base64urlEncode(input);
1951 expect(encoded).to.not.contain('+');
1952 expect(encoded).to.not.contain('/');
1954 var decoded = Hoek.base64urlDecode(encoded);
1956 expect(decoded).to.equal(input);
1961 describe('base64urlDecode()', function () {
1963 it('should un-base64 URL-safe a string', function (done) {
1965 expect(Hoek.base64urlDecode(base64str)).to.equal(str);
1969 it('should un-base64 URL-safe a string into hex', function (done) {
1971 expect(Hoek.base64urlDecode(base64str, 'hex')).to.equal(new Buffer(str, 'binary').toString('hex'));
1975 it('should un-base64 URL-safe a string and return a buffer', function (done) {
1977 var buf = Hoek.base64urlDecode(base64str, 'buffer');
1978 expect(buf instanceof Buffer).to.equal(true);
1979 expect(buf.toString('binary')).to.equal(str);
1983 it('returns error on undefined input', function (done) {
1985 expect(Hoek.base64urlDecode().message).to.exist();
1989 it('returns error on invalid input', function (done) {
1991 expect(Hoek.base64urlDecode('*').message).to.exist();
1997 describe('escapeHeaderAttribute()', function () {
1999 it('should not alter ascii values', function (done) {
2001 var a = Hoek.escapeHeaderAttribute('My Value');
2002 expect(a).to.equal('My Value');
2006 it('escapes all special HTTP header attribute characters', function (done) {
2008 var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
2009 expect(a).to.equal('I said go!!!#\\"\\\\');
2013 it('throws on large unicode characters', function (done) {
2015 var fn = function () {
2017 Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300));
2020 expect(fn).to.throw(Error);
2024 it('throws on CRLF to prevent response splitting', function (done) {
2026 var fn = function () {
2028 Hoek.escapeHeaderAttribute('this is a test\r\n');
2031 expect(fn).to.throw(Error);
2036 describe('escapeHtml()', function () {
2038 it('escapes all special HTML characters', function (done) {
2040 var a = Hoek.escapeHtml('&<>"\'`');
2041 expect(a).to.equal('&<>"'`');
2045 it('returns empty string on falsy input', function (done) {
2047 var a = Hoek.escapeHtml('');
2048 expect(a).to.equal('');
2052 it('returns unchanged string on no reserved input', function (done) {
2054 var a = Hoek.escapeHtml('abc');
2055 expect(a).to.equal('abc');
2060 describe('nextTick()', function () {
2062 it('calls the provided callback on nextTick', function (done) {
2066 var inc = function (step, next) {
2072 var ticked = Hoek.nextTick(inc);
2074 ticked(5, function () {
2076 expect(a).to.equal(6);
2080 expect(a).to.equal(0);
2081 inc(1, function () {
2083 expect(a).to.equal(1);
2088 describe('once()', function () {
2090 it('allows function to only execute once', function (done) {
2093 var add = function (x) {
2099 expect(gen).to.equal(5);
2100 add = Hoek.once(add);
2102 expect(gen).to.equal(10);
2104 expect(gen).to.equal(10);
2108 it('double once wraps one time', function (done) {
2110 var method = function () { };
2111 method = Hoek.once(method);
2113 method = Hoek.once(method);
2114 expect(method.x).to.equal(1);
2119 describe('isAbsoltePath()', function () {
2121 it('identifies if path is absolute on Unix without node support', { parallel: false }, function (done) {
2123 var orig = Path.isAbsolute;
2124 Path.isAbsolute = undefined;
2126 expect(Hoek.isAbsolutePath('')).to.equal(false);
2127 expect(Hoek.isAbsolutePath('a')).to.equal(false);
2128 expect(Hoek.isAbsolutePath('./a')).to.equal(false);
2129 expect(Hoek.isAbsolutePath('/a')).to.equal(true);
2130 expect(Hoek.isAbsolutePath('/')).to.equal(true);
2132 Path.isAbsolute = orig;
2137 it('identifies if path is absolute with fake node support', { parallel: false }, function (done) {
2139 var orig = Path.isAbsolute;
2140 Path.isAbsolute = function (path) {
2142 return path[0] === '/';
2145 expect(Hoek.isAbsolutePath('', 'linux')).to.equal(false);
2146 expect(Hoek.isAbsolutePath('a', 'linux')).to.equal(false);
2147 expect(Hoek.isAbsolutePath('./a', 'linux')).to.equal(false);
2148 expect(Hoek.isAbsolutePath('/a', 'linux')).to.equal(true);
2149 expect(Hoek.isAbsolutePath('/', 'linux')).to.equal(true);
2151 Path.isAbsolute = orig;
2156 it('identifies if path is absolute on Windows without node support', { parallel: false }, function (done) {
2158 var orig = Path.isAbsolute;
2159 Path.isAbsolute = undefined;
2161 expect(Hoek.isAbsolutePath('//server/file', 'win32')).to.equal(true);
2162 expect(Hoek.isAbsolutePath('//server/file', 'win32')).to.equal(true);
2163 expect(Hoek.isAbsolutePath('\\\\server\\file', 'win32')).to.equal(true);
2164 expect(Hoek.isAbsolutePath('C:/Users/', 'win32')).to.equal(true);
2165 expect(Hoek.isAbsolutePath('C:\\Users\\', 'win32')).to.equal(true);
2166 expect(Hoek.isAbsolutePath('C:cwd/another', 'win32')).to.equal(false);
2167 expect(Hoek.isAbsolutePath('C:cwd\\another', 'win32')).to.equal(false);
2168 expect(Hoek.isAbsolutePath('directory/directory', 'win32')).to.equal(false);
2169 expect(Hoek.isAbsolutePath('directory\\directory', 'win32')).to.equal(false);
2171 Path.isAbsolute = orig;
2177 describe('isInteger()', function () {
2179 it('validates integers', function (done) {
2181 expect(Hoek.isInteger(0)).to.equal(true);
2182 expect(Hoek.isInteger(1)).to.equal(true);
2183 expect(Hoek.isInteger(1394035612500)).to.equal(true);
2184 expect(Hoek.isInteger('0')).to.equal(false);
2185 expect(Hoek.isInteger(1.0)).to.equal(true);
2186 expect(Hoek.isInteger(1.1)).to.equal(false);
2191 describe('ignore()', function () {
2193 it('exists', function (done) {
2195 expect(Hoek.ignore).to.exist();
2196 expect(typeof Hoek.ignore).to.equal('function');
2201 describe('inherits()', function () {
2203 it('exists', function (done) {
2205 expect(Hoek.inherits).to.exist();
2206 expect(typeof Hoek.inherits).to.equal('function');
2211 describe('format()', function () {
2213 it('exists', function (done) {
2215 expect(Hoek.format).to.exist();
2216 expect(typeof Hoek.format).to.equal('function');
2220 it('is a reference to Util.format', function (done) {
2222 expect(Hoek.format('hello %s', 'world')).to.equal('hello world');
2227 describe('transform()', function () {
2231 one: '123 main street',
2242 var sourcesArray = [{
2244 one: '123 main street',
2255 one: '456 market street',
2266 it('transforms an object based on the input object', function (done) {
2268 var result = Hoek.transform(source, {
2269 'person.address.lineOne': 'address.one',
2270 'person.address.lineTwo': 'address.two',
2272 'person.address.region': 'state',
2273 'person.address.zip': 'zip.code',
2274 'person.address.location': 'zip.province'
2277 expect(result).to.deep.equal({
2280 lineOne: '123 main street',
2281 lineTwo: 'PO Box 1234',
2293 it('transforms an array of objects based on the input object', function (done) {
2295 var result = Hoek.transform(sourcesArray, {
2296 'person.address.lineOne': 'address.one',
2297 'person.address.lineTwo': 'address.two',
2299 'person.address.region': 'state',
2300 'person.address.zip': 'zip.code',
2301 'person.address.location': 'zip.province'
2304 expect(result).to.deep.equal([
2308 lineOne: '123 main street',
2309 lineTwo: 'PO Box 1234',
2320 lineOne: '456 market street',
2321 lineTwo: 'PO Box 5678',
2334 it('uses the reach options passed into it', function (done) {
2337 'person.address.lineOne': 'address-one',
2338 'person.address.lineTwo': 'address-two',
2340 'person.address.region': 'state',
2341 'person.prefix': 'person-title',
2342 'person.zip': 'zip-code'
2348 var result = Hoek.transform(source, schema, options);
2350 expect(result).to.deep.equal({
2353 lineOne: '123 main street',
2354 lineTwo: 'PO Box 1234',
2366 it('works to create shallow objects', function (done) {
2368 var result = Hoek.transform(source, {
2369 lineOne: 'address.one',
2370 lineTwo: 'address.two',
2373 province: 'zip.province'
2376 expect(result).to.deep.equal({
2377 lineOne: '123 main street',
2378 lineTwo: 'PO Box 1234',
2387 it('only allows strings in the map', function (done) {
2389 expect(function () {
2391 var result = Hoek.transform(source, {
2394 }).to.throw('All mappings must be "." delineated strings');
2399 it('throws an error on invalid arguments', function (done) {
2401 expect(function () {
2403 var result = Hoek.transform(NaN, {});
2404 }).to.throw('Invalid source object: must be null, undefined, an object, or an array');
2409 it('is safe to pass null', function (done) {
2411 var result = Hoek.transform(null, {});
2412 expect(result).to.deep.equal({});
2417 it('is safe to pass undefined', function (done) {
2419 var result = Hoek.transform(undefined, {});
2420 expect(result).to.deep.equal({});
2426 describe('uniqueFilename()', function () {
2428 it('generates a random file path', function (done) {
2430 var result = Hoek.uniqueFilename('./test/modules');
2432 expect(result).to.exist();
2433 expect(result).to.be.a.string();
2434 expect(result).to.contain('test/modules');
2438 it('is random enough to use in fast loops', function (done) {
2442 for (var i = 0; i < 10; ++i) {
2443 results[i] = Hoek.uniqueFilename('./test/modules');
2446 var filter = results.filter(function (item, index, array) {
2448 return array.indexOf(item) === index;
2451 expect(filter.length).to.equal(10);
2452 expect(results.length).to.equal(10);
2457 it('combines the random elements with a supplied character', function (done) {
2459 var result = Hoek.uniqueFilename('./test', 'txt');
2461 expect(result).to.contain('test/');
2462 expect(result).to.contain('.txt');
2467 it('accepts extensions with a "." in it', function (done) {
2469 var result = Hoek.uniqueFilename('./test', '.mp3');
2471 expect(result).to.contain('test/');
2472 expect(result).to.contain('.mp3');
2478 describe('stringify()', function (done) {
2480 it('converts object to string', function (done) {
2483 expect(Hoek.stringify(obj)).to.equal('{"a":1}');
2487 it('returns error in result string', function (done) {
2491 expect(Hoek.stringify(obj)).to.equal('[Cannot display object: Converting circular structure to JSON]');
2496 describe('shallow()', function (done) {
2498 it('shallow copies an object', function (done) {
2507 var shallow = Hoek.shallow(obj);
2508 expect(shallow).to.not.equal(obj);
2509 expect(shallow).to.deep.equal(obj);
2510 expect(shallow.b).to.equal(obj.b);