UNPKG

122 kBJavaScriptView Raw
1/*!
2 * should - test framework agnostic BDD-style assertions
3 * @version v13.2.3
4 * @author TJ Holowaychuk <tj@vision-media.ca>, Denis Bardadym <bardadymchik@gmail.com>
5 * @link https://github.com/shouldjs/should.js
6 * @license MIT
7 */
8
9(function () {
10'use strict';
11
12var types = {
13 NUMBER: 'number',
14 UNDEFINED: 'undefined',
15 STRING: 'string',
16 BOOLEAN: 'boolean',
17 OBJECT: 'object',
18 FUNCTION: 'function',
19 NULL: 'null',
20 ARRAY: 'array',
21 REGEXP: 'regexp',
22 DATE: 'date',
23 ERROR: 'error',
24 ARGUMENTS: 'arguments',
25 SYMBOL: 'symbol',
26 ARRAY_BUFFER: 'array-buffer',
27 TYPED_ARRAY: 'typed-array',
28 DATA_VIEW: 'data-view',
29 MAP: 'map',
30 SET: 'set',
31 WEAK_SET: 'weak-set',
32 WEAK_MAP: 'weak-map',
33 PROMISE: 'promise',
34
35// node buffer
36 BUFFER: 'buffer',
37
38// dom html element
39 HTML_ELEMENT: 'html-element',
40 HTML_ELEMENT_TEXT: 'html-element-text',
41 DOCUMENT: 'document',
42 WINDOW: 'window',
43 FILE: 'file',
44 FILE_LIST: 'file-list',
45 BLOB: 'blob',
46
47 HOST: 'host',
48
49 XHR: 'xhr',
50
51 // simd
52 SIMD: 'simd'
53};
54
55/*
56 * Simple data function to store type information
57 * @param {string} type Usually what is returned from typeof
58 * @param {string} cls Sanitized @Class via Object.prototype.toString
59 * @param {string} sub If type and cls the same, and need to specify somehow
60 * @private
61 * @example
62 *
63 * //for null
64 * new Type('null');
65 *
66 * //for Date
67 * new Type('object', 'date');
68 *
69 * //for Uint8Array
70 *
71 * new Type('object', 'typed-array', 'uint8');
72 */
73function Type(type, cls, sub) {
74 if (!type) {
75 throw new Error('Type class must be initialized at least with `type` information');
76 }
77 this.type = type;
78 this.cls = cls;
79 this.sub = sub;
80}
81
82Type.prototype = {
83 toString: function(sep) {
84 sep = sep || ';';
85 var str = [this.type];
86 if (this.cls) {
87 str.push(this.cls);
88 }
89 if (this.sub) {
90 str.push(this.sub);
91 }
92 return str.join(sep);
93 },
94
95 toTryTypes: function() {
96 var _types = [];
97 if (this.sub) {
98 _types.push(new Type(this.type, this.cls, this.sub));
99 }
100 if (this.cls) {
101 _types.push(new Type(this.type, this.cls));
102 }
103 _types.push(new Type(this.type));
104
105 return _types;
106 }
107};
108
109var toString = Object.prototype.toString;
110
111
112
113/**
114 * Function to store type checks
115 * @private
116 */
117function TypeChecker() {
118 this.checks = [];
119}
120
121TypeChecker.prototype = {
122 add: function(func) {
123 this.checks.push(func);
124 return this;
125 },
126
127 addBeforeFirstMatch: function(obj, func) {
128 var match = this.getFirstMatch(obj);
129 if (match) {
130 this.checks.splice(match.index, 0, func);
131 } else {
132 this.add(func);
133 }
134 },
135
136 addTypeOf: function(type, res) {
137 return this.add(function(obj, tpeOf) {
138 if (tpeOf === type) {
139 return new Type(res);
140 }
141 });
142 },
143
144 addClass: function(cls, res, sub) {
145 return this.add(function(obj, tpeOf, objCls) {
146 if (objCls === cls) {
147 return new Type(types.OBJECT, res, sub);
148 }
149 });
150 },
151
152 getFirstMatch: function(obj) {
153 var typeOf = typeof obj;
154 var cls = toString.call(obj);
155
156 for (var i = 0, l = this.checks.length; i < l; i++) {
157 var res = this.checks[i].call(this, obj, typeOf, cls);
158 if (typeof res !== 'undefined') {
159 return { result: res, func: this.checks[i], index: i };
160 }
161 }
162 },
163
164 getType: function(obj) {
165 var match = this.getFirstMatch(obj);
166 return match && match.result;
167 }
168};
169
170var main = new TypeChecker();
171
172//TODO add iterators
173
174main
175 .addTypeOf(types.NUMBER, types.NUMBER)
176 .addTypeOf(types.UNDEFINED, types.UNDEFINED)
177 .addTypeOf(types.STRING, types.STRING)
178 .addTypeOf(types.BOOLEAN, types.BOOLEAN)
179 .addTypeOf(types.FUNCTION, types.FUNCTION)
180 .addTypeOf(types.SYMBOL, types.SYMBOL)
181 .add(function(obj) {
182 if (obj === null) {
183 return new Type(types.NULL);
184 }
185 })
186 .addClass('[object String]', types.STRING)
187 .addClass('[object Boolean]', types.BOOLEAN)
188 .addClass('[object Number]', types.NUMBER)
189 .addClass('[object Array]', types.ARRAY)
190 .addClass('[object RegExp]', types.REGEXP)
191 .addClass('[object Error]', types.ERROR)
192 .addClass('[object Date]', types.DATE)
193 .addClass('[object Arguments]', types.ARGUMENTS)
194
195 .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER)
196 .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8')
197 .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8')
198 .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped')
199 .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16')
200 .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16')
201 .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32')
202 .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32')
203 .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32')
204 .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64')
205
206 .addClass('[object Bool16x8]', types.SIMD, 'bool16x8')
207 .addClass('[object Bool32x4]', types.SIMD, 'bool32x4')
208 .addClass('[object Bool8x16]', types.SIMD, 'bool8x16')
209 .addClass('[object Float32x4]', types.SIMD, 'float32x4')
210 .addClass('[object Int16x8]', types.SIMD, 'int16x8')
211 .addClass('[object Int32x4]', types.SIMD, 'int32x4')
212 .addClass('[object Int8x16]', types.SIMD, 'int8x16')
213 .addClass('[object Uint16x8]', types.SIMD, 'uint16x8')
214 .addClass('[object Uint32x4]', types.SIMD, 'uint32x4')
215 .addClass('[object Uint8x16]', types.SIMD, 'uint8x16')
216
217 .addClass('[object DataView]', types.DATA_VIEW)
218 .addClass('[object Map]', types.MAP)
219 .addClass('[object WeakMap]', types.WEAK_MAP)
220 .addClass('[object Set]', types.SET)
221 .addClass('[object WeakSet]', types.WEAK_SET)
222 .addClass('[object Promise]', types.PROMISE)
223 .addClass('[object Blob]', types.BLOB)
224 .addClass('[object File]', types.FILE)
225 .addClass('[object FileList]', types.FILE_LIST)
226 .addClass('[object XMLHttpRequest]', types.XHR)
227 .add(function(obj) {
228 if ((typeof Promise === types.FUNCTION && obj instanceof Promise) ||
229 (typeof obj.then === types.FUNCTION)) {
230 return new Type(types.OBJECT, types.PROMISE);
231 }
232 })
233 .add(function(obj) {
234 if (typeof Buffer !== 'undefined' && obj instanceof Buffer) {// eslint-disable-line no-undef
235 return new Type(types.OBJECT, types.BUFFER);
236 }
237 })
238 .add(function(obj) {
239 if (typeof Node !== 'undefined' && obj instanceof Node) {
240 return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName);
241 }
242 })
243 .add(function(obj) {
244 // probably at the begginging should be enough these checks
245 if (obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) {
246 return new Type(types.OBJECT, types.HOST);
247 }
248 })
249 .add(function() {
250 return new Type(types.OBJECT);
251 });
252
253/**
254 * Get type information of anything
255 *
256 * @param {any} obj Anything that could require type information
257 * @return {Type} type info
258 * @private
259 */
260function getGlobalType(obj) {
261 return main.getType(obj);
262}
263
264getGlobalType.checker = main;
265getGlobalType.TypeChecker = TypeChecker;
266getGlobalType.Type = Type;
267
268Object.keys(types).forEach(function(typeName) {
269 getGlobalType[typeName] = types[typeName];
270});
271
272function format(msg) {
273 var args = arguments;
274 for (var i = 1, l = args.length; i < l; i++) {
275 msg = msg.replace(/%s/, args[i]);
276 }
277 return msg;
278}
279
280var hasOwnProperty = Object.prototype.hasOwnProperty;
281
282function EqualityFail(a, b, reason, path) {
283 this.a = a;
284 this.b = b;
285 this.reason = reason;
286 this.path = path;
287}
288
289function typeToString(tp) {
290 return tp.type + (tp.cls ? "(" + tp.cls + (tp.sub ? " " + tp.sub : "") + ")" : "");
291}
292
293var PLUS_0_AND_MINUS_0 = "+0 is not equal to -0";
294var DIFFERENT_TYPES = "A has type %s and B has type %s";
295var EQUALITY = "A is not equal to B";
296var EQUALITY_PROTOTYPE = "A and B have different prototypes";
297var WRAPPED_VALUE = "A wrapped value is not equal to B wrapped value";
298var FUNCTION_SOURCES = "function A is not equal to B by source code value (via .toString call)";
299var MISSING_KEY = "%s has no key %s";
300var SET_MAP_MISSING_KEY = "Set/Map missing key %s";
301
302var DEFAULT_OPTIONS = {
303 checkProtoEql: true,
304 checkSubType: true,
305 plusZeroAndMinusZeroEqual: true,
306 collectAllFails: false
307};
308
309function setBooleanDefault(property, obj, opts, defaults) {
310 obj[property] = typeof opts[property] !== "boolean" ? defaults[property] : opts[property];
311}
312
313var METHOD_PREFIX = "_check_";
314
315function EQ(opts, a, b, path) {
316 opts = opts || {};
317
318 setBooleanDefault("checkProtoEql", this, opts, DEFAULT_OPTIONS);
319 setBooleanDefault("plusZeroAndMinusZeroEqual", this, opts, DEFAULT_OPTIONS);
320 setBooleanDefault("checkSubType", this, opts, DEFAULT_OPTIONS);
321 setBooleanDefault("collectAllFails", this, opts, DEFAULT_OPTIONS);
322
323 this.a = a;
324 this.b = b;
325
326 this._meet = opts._meet || [];
327
328 this.fails = opts.fails || [];
329
330 this.path = path || [];
331}
332
333function ShortcutError(fail) {
334 this.name = "ShortcutError";
335 this.message = "fail fast";
336 this.fail = fail;
337}
338
339ShortcutError.prototype = Object.create(Error.prototype);
340
341EQ.checkStrictEquality = function(a, b) {
342 this.collectFail(a !== b, EQUALITY);
343};
344
345EQ.add = function add(type, cls, sub, f) {
346 var args = Array.prototype.slice.call(arguments);
347 f = args.pop();
348 EQ.prototype[METHOD_PREFIX + args.join("_")] = f;
349};
350
351EQ.prototype = {
352 check: function() {
353 try {
354 this.check0();
355 } catch (e) {
356 if (e instanceof ShortcutError) {
357 return [e.fail];
358 }
359 throw e;
360 }
361 return this.fails;
362 },
363
364 check0: function() {
365 var a = this.a;
366 var b = this.b;
367
368 // equal a and b exit early
369 if (a === b) {
370 // check for +0 !== -0;
371 return this.collectFail(a === 0 && 1 / a !== 1 / b && !this.plusZeroAndMinusZeroEqual, PLUS_0_AND_MINUS_0);
372 }
373
374 var typeA = getGlobalType(a);
375 var typeB = getGlobalType(b);
376
377 // if objects has different types they are not equal
378 if (typeA.type !== typeB.type || typeA.cls !== typeB.cls || typeA.sub !== typeB.sub) {
379 return this.collectFail(true, format(DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB)));
380 }
381
382 // as types the same checks type specific things
383 var name1 = typeA.type,
384 name2 = typeA.type;
385 if (typeA.cls) {
386 name1 += "_" + typeA.cls;
387 name2 += "_" + typeA.cls;
388 }
389 if (typeA.sub) {
390 name2 += "_" + typeA.sub;
391 }
392
393 var f =
394 this[METHOD_PREFIX + name2] ||
395 this[METHOD_PREFIX + name1] ||
396 this[METHOD_PREFIX + typeA.type] ||
397 this.defaultCheck;
398
399 f.call(this, this.a, this.b);
400 },
401
402 collectFail: function(comparison, reason, showReason) {
403 if (comparison) {
404 var res = new EqualityFail(this.a, this.b, reason, this.path);
405 res.showReason = !!showReason;
406
407 this.fails.push(res);
408
409 if (!this.collectAllFails) {
410 throw new ShortcutError(res);
411 }
412 }
413 },
414
415 checkPlainObjectsEquality: function(a, b) {
416 // compare deep objects and arrays
417 // stacks contain references only
418 //
419 var meet = this._meet;
420 var m = this._meet.length;
421 while (m--) {
422 var st = meet[m];
423 if (st[0] === a && st[1] === b) {
424 return;
425 }
426 }
427
428 // add `a` and `b` to the stack of traversed objects
429 meet.push([a, b]);
430
431 // TODO maybe something else like getOwnPropertyNames
432 var key;
433 for (key in b) {
434 if (hasOwnProperty.call(b, key)) {
435 if (hasOwnProperty.call(a, key)) {
436 this.checkPropertyEquality(key);
437 } else {
438 this.collectFail(true, format(MISSING_KEY, "A", key));
439 }
440 }
441 }
442
443 // ensure both objects have the same number of properties
444 for (key in a) {
445 if (hasOwnProperty.call(a, key)) {
446 this.collectFail(!hasOwnProperty.call(b, key), format(MISSING_KEY, "B", key));
447 }
448 }
449
450 meet.pop();
451
452 if (this.checkProtoEql) {
453 //TODO should i check prototypes for === or use eq?
454 this.collectFail(Object.getPrototypeOf(a) !== Object.getPrototypeOf(b), EQUALITY_PROTOTYPE, true);
455 }
456 },
457
458 checkPropertyEquality: function(propertyName) {
459 var _eq = new EQ(this, this.a[propertyName], this.b[propertyName], this.path.concat([propertyName]));
460 _eq.check0();
461 },
462
463 defaultCheck: EQ.checkStrictEquality
464};
465
466EQ.add(getGlobalType.NUMBER, function(a, b) {
467 this.collectFail((a !== a && b === b) || (b !== b && a === a) || (a !== b && a === a && b === b), EQUALITY);
468});
469
470[getGlobalType.SYMBOL, getGlobalType.BOOLEAN, getGlobalType.STRING].forEach(function(tp) {
471 EQ.add(tp, EQ.checkStrictEquality);
472});
473
474EQ.add(getGlobalType.FUNCTION, function(a, b) {
475 // functions are compared by their source code
476 this.collectFail(a.toString() !== b.toString(), FUNCTION_SOURCES);
477 // check user properties
478 this.checkPlainObjectsEquality(a, b);
479});
480
481EQ.add(getGlobalType.OBJECT, getGlobalType.REGEXP, function(a, b) {
482 // check regexp flags
483 var flags = ["source", "global", "multiline", "lastIndex", "ignoreCase", "sticky", "unicode"];
484 while (flags.length) {
485 this.checkPropertyEquality(flags.shift());
486 }
487 // check user properties
488 this.checkPlainObjectsEquality(a, b);
489});
490
491EQ.add(getGlobalType.OBJECT, getGlobalType.DATE, function(a, b) {
492 //check by timestamp only (using .valueOf)
493 this.collectFail(+a !== +b, EQUALITY);
494 // check user properties
495 this.checkPlainObjectsEquality(a, b);
496});
497
498[getGlobalType.NUMBER, getGlobalType.BOOLEAN, getGlobalType.STRING].forEach(function(tp) {
499 EQ.add(getGlobalType.OBJECT, tp, function(a, b) {
500 //primitive type wrappers
501 this.collectFail(a.valueOf() !== b.valueOf(), WRAPPED_VALUE);
502 // check user properties
503 this.checkPlainObjectsEquality(a, b);
504 });
505});
506
507EQ.add(getGlobalType.OBJECT, function(a, b) {
508 this.checkPlainObjectsEquality(a, b);
509});
510
511[getGlobalType.ARRAY, getGlobalType.ARGUMENTS, getGlobalType.TYPED_ARRAY].forEach(function(tp) {
512 EQ.add(getGlobalType.OBJECT, tp, function(a, b) {
513 this.checkPropertyEquality("length");
514
515 this.checkPlainObjectsEquality(a, b);
516 });
517});
518
519EQ.add(getGlobalType.OBJECT, getGlobalType.ARRAY_BUFFER, function(a, b) {
520 this.checkPropertyEquality("byteLength");
521
522 this.checkPlainObjectsEquality(a, b);
523});
524
525EQ.add(getGlobalType.OBJECT, getGlobalType.ERROR, function(a, b) {
526 this.checkPropertyEquality("name");
527 this.checkPropertyEquality("message");
528
529 this.checkPlainObjectsEquality(a, b);
530});
531
532EQ.add(getGlobalType.OBJECT, getGlobalType.BUFFER, function(a) {
533 this.checkPropertyEquality("length");
534
535 var l = a.length;
536 while (l--) {
537 this.checkPropertyEquality(l);
538 }
539
540 //we do not check for user properties because
541 //node Buffer have some strange hidden properties
542});
543
544function checkMapByKeys(a, b) {
545 var iteratorA = a.keys();
546
547 for (var nextA = iteratorA.next(); !nextA.done; nextA = iteratorA.next()) {
548 var key = nextA.value;
549 var hasKey = b.has(key);
550 this.collectFail(!hasKey, format(SET_MAP_MISSING_KEY, key));
551
552 if (hasKey) {
553 var valueB = b.get(key);
554 var valueA = a.get(key);
555
556 eq(valueA, valueB, this);
557 }
558 }
559}
560
561function checkSetByKeys(a, b) {
562 var iteratorA = a.keys();
563
564 for (var nextA = iteratorA.next(); !nextA.done; nextA = iteratorA.next()) {
565 var key = nextA.value;
566 var hasKey = b.has(key);
567 this.collectFail(!hasKey, format(SET_MAP_MISSING_KEY, key));
568 }
569}
570
571EQ.add(getGlobalType.OBJECT, getGlobalType.MAP, function(a, b) {
572 this._meet.push([a, b]);
573
574 checkMapByKeys.call(this, a, b);
575 checkMapByKeys.call(this, b, a);
576
577 this._meet.pop();
578
579 this.checkPlainObjectsEquality(a, b);
580});
581EQ.add(getGlobalType.OBJECT, getGlobalType.SET, function(a, b) {
582 this._meet.push([a, b]);
583
584 checkSetByKeys.call(this, a, b);
585 checkSetByKeys.call(this, b, a);
586
587 this._meet.pop();
588
589 this.checkPlainObjectsEquality(a, b);
590});
591
592function eq(a, b, opts) {
593 return new EQ(opts, a, b).check();
594}
595
596eq.EQ = EQ;
597
598var _hasOwnProperty = Object.prototype.hasOwnProperty;
599var _propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
600
601function hasOwnProperty$1(obj, key) {
602 return _hasOwnProperty.call(obj, key);
603}
604
605function propertyIsEnumerable(obj, key) {
606 return _propertyIsEnumerable.call(obj, key);
607}
608
609function merge(a, b) {
610 if (a && b) {
611 for (var key in b) {
612 a[key] = b[key];
613 }
614 }
615 return a;
616}
617
618function isIterator(obj) {
619 if (!obj) {
620 return false;
621 }
622
623 if (obj.__shouldIterator__) {
624 return true;
625 }
626
627 return typeof obj.next === 'function' &&
628 typeof Symbol === 'function' &&
629 typeof Symbol.iterator === 'symbol' &&
630 typeof obj[Symbol.iterator] === 'function' &&
631 obj[Symbol.iterator]() === obj;
632}
633
634//TODO find better way
635function isGeneratorFunction(f) {
636 return typeof f === 'function' && /^function\s*\*\s*/.test(f.toString());
637}
638
639// TODO in future add generators instead of forEach and iterator implementation
640
641
642function ObjectIterator(obj) {
643 this._obj = obj;
644}
645
646ObjectIterator.prototype = {
647 __shouldIterator__: true, // special marker
648
649 next: function() {
650 if (this._done) {
651 throw new Error('Iterator already reached the end');
652 }
653
654 if (!this._keys) {
655 this._keys = Object.keys(this._obj);
656 this._index = 0;
657 }
658
659 var key = this._keys[this._index];
660 this._done = this._index === this._keys.length;
661 this._index += 1;
662
663 return {
664 value: this._done ? void 0: [key, this._obj[key]],
665 done: this._done
666 };
667 }
668};
669
670if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
671 ObjectIterator.prototype[Symbol.iterator] = function() {
672 return this;
673 };
674}
675
676
677function TypeAdaptorStorage() {
678 this._typeAdaptors = [];
679 this._iterableTypes = {};
680}
681
682TypeAdaptorStorage.prototype = {
683 add: function(type, cls, sub, adaptor) {
684 return this.addType(new getGlobalType.Type(type, cls, sub), adaptor);
685 },
686
687 addType: function(type, adaptor) {
688 this._typeAdaptors[type.toString()] = adaptor;
689 },
690
691 getAdaptor: function(tp, funcName) {
692 var tries = tp.toTryTypes();
693 while (tries.length) {
694 var toTry = tries.shift();
695 var ad = this._typeAdaptors[toTry];
696 if (ad && ad[funcName]) {
697 return ad[funcName];
698 }
699 }
700 },
701
702 requireAdaptor: function(tp, funcName) {
703 var a = this.getAdaptor(tp, funcName);
704 if (!a) {
705 throw new Error('There is no type adaptor `' + funcName + '` for ' + tp.toString());
706 }
707 return a;
708 },
709
710 addIterableType: function(tp) {
711 this._iterableTypes[tp.toString()] = true;
712 },
713
714 isIterableType: function(tp) {
715 return !!this._iterableTypes[tp.toString()];
716 }
717};
718
719var defaultTypeAdaptorStorage = new TypeAdaptorStorage();
720
721var objectAdaptor = {
722 forEach: function(obj, f, context) {
723 for (var prop in obj) {
724 if (hasOwnProperty$1(obj, prop) && propertyIsEnumerable(obj, prop)) {
725 if (f.call(context, obj[prop], prop, obj) === false) {
726 return;
727 }
728 }
729 }
730 },
731
732 has: function(obj, prop) {
733 return hasOwnProperty$1(obj, prop);
734 },
735
736 get: function(obj, prop) {
737 return obj[prop];
738 },
739
740 iterator: function(obj) {
741 return new ObjectIterator(obj);
742 }
743};
744
745// default for objects
746defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.OBJECT), objectAdaptor);
747defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.FUNCTION), objectAdaptor);
748
749var mapAdaptor = {
750 has: function(obj, key) {
751 return obj.has(key);
752 },
753
754 get: function(obj, key) {
755 return obj.get(key);
756 },
757
758 forEach: function(obj, f, context) {
759 var iter = obj.entries();
760 forEach(iter, function(value) {
761 return f.call(context, value[1], value[0], obj);
762 });
763 },
764
765 size: function(obj) {
766 return obj.size;
767 },
768
769 isEmpty: function(obj) {
770 return obj.size === 0;
771 },
772
773 iterator: function(obj) {
774 return obj.entries();
775 }
776};
777
778var setAdaptor = merge({}, mapAdaptor);
779setAdaptor.get = function(obj, key) {
780 if (obj.has(key)) {
781 return key;
782 }
783};
784setAdaptor.iterator = function(obj) {
785 return obj.values();
786};
787
788defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.MAP), mapAdaptor);
789defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SET), setAdaptor);
790defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.WEAK_SET), setAdaptor);
791defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.WEAK_MAP), mapAdaptor);
792
793defaultTypeAdaptorStorage.addType(new getGlobalType.Type(getGlobalType.STRING), {
794 isEmpty: function(obj) {
795 return obj === '';
796 },
797
798 size: function(obj) {
799 return obj.length;
800 }
801});
802
803defaultTypeAdaptorStorage.addIterableType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.ARRAY));
804defaultTypeAdaptorStorage.addIterableType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.ARGUMENTS));
805defaultTypeAdaptorStorage.addIterableType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SET));
806
807function forEach(obj, f, context) {
808 if (isGeneratorFunction(obj)) {
809 return forEach(obj(), f, context);
810 } else if (isIterator(obj)) {
811 var value = obj.next();
812 while (!value.done) {
813 if (f.call(context, value.value, 'value', obj) === false) {
814 return;
815 }
816 value = obj.next();
817 }
818 } else {
819 var type = getGlobalType(obj);
820 var func = defaultTypeAdaptorStorage.requireAdaptor(type, 'forEach');
821 func(obj, f, context);
822 }
823}
824
825
826function size(obj) {
827 var type = getGlobalType(obj);
828 var func = defaultTypeAdaptorStorage.getAdaptor(type, 'size');
829 if (func) {
830 return func(obj);
831 } else {
832 var len = 0;
833 forEach(obj, function() {
834 len += 1;
835 });
836 return len;
837 }
838}
839
840function isEmpty(obj) {
841 var type = getGlobalType(obj);
842 var func = defaultTypeAdaptorStorage.getAdaptor(type, 'isEmpty');
843 if (func) {
844 return func(obj);
845 } else {
846 var res = true;
847 forEach(obj, function() {
848 res = false;
849 return false;
850 });
851 return res;
852 }
853}
854
855// return boolean if obj has such 'key'
856function has(obj, key) {
857 var type = getGlobalType(obj);
858 var func = defaultTypeAdaptorStorage.requireAdaptor(type, 'has');
859 return func(obj, key);
860}
861
862// return value for given key
863function get(obj, key) {
864 var type = getGlobalType(obj);
865 var func = defaultTypeAdaptorStorage.requireAdaptor(type, 'get');
866 return func(obj, key);
867}
868
869function some(obj, f, context) {
870 var res = false;
871 forEach(obj, function(value, key) {
872 if (f.call(context, value, key, obj)) {
873 res = true;
874 return false;
875 }
876 }, context);
877 return res;
878}
879
880function isIterable(obj) {
881 return defaultTypeAdaptorStorage.isIterableType(getGlobalType(obj));
882}
883
884function iterator(obj) {
885 return defaultTypeAdaptorStorage.requireAdaptor(getGlobalType(obj), 'iterator')(obj);
886}
887
888function looksLikeANumber(n) {
889 return !!n.match(/\d+/);
890}
891
892function keyCompare(a, b) {
893 var aNum = looksLikeANumber(a);
894 var bNum = looksLikeANumber(b);
895 if (aNum && bNum) {
896 return 1*a - 1*b;
897 } else if (aNum && !bNum) {
898 return -1;
899 } else if (!aNum && bNum) {
900 return 1;
901 } else {
902 return a.localeCompare(b);
903 }
904}
905
906function genKeysFunc(f) {
907 return function(value) {
908 var k = f(value);
909 k.sort(keyCompare);
910 return k;
911 };
912}
913
914function Formatter(opts) {
915 opts = opts || {};
916
917 this.seen = [];
918
919 var keysFunc;
920 if (typeof opts.keysFunc === 'function') {
921 keysFunc = opts.keysFunc;
922 } else if (opts.keys === false) {
923 keysFunc = Object.getOwnPropertyNames;
924 } else {
925 keysFunc = Object.keys;
926 }
927
928 this.getKeys = genKeysFunc(keysFunc);
929
930 this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60;
931 this.propSep = opts.propSep || ',';
932
933 this.isUTCdate = !!opts.isUTCdate;
934}
935
936
937
938Formatter.prototype = {
939 constructor: Formatter,
940
941 format: function(value) {
942 var tp = getGlobalType(value);
943
944 if (this.alreadySeen(value)) {
945 return '[Circular]';
946 }
947
948 var tries = tp.toTryTypes();
949 var f = this.defaultFormat;
950 while (tries.length) {
951 var toTry = tries.shift();
952 var name = Formatter.formatterFunctionName(toTry);
953 if (this[name]) {
954 f = this[name];
955 break;
956 }
957 }
958 return f.call(this, value).trim();
959 },
960
961 defaultFormat: function(obj) {
962 return String(obj);
963 },
964
965 alreadySeen: function(value) {
966 return this.seen.indexOf(value) >= 0;
967 }
968
969};
970
971Formatter.addType = function addType(tp, f) {
972 Formatter.prototype[Formatter.formatterFunctionName(tp)] = f;
973};
974
975Formatter.formatterFunctionName = function formatterFunctionName(tp) {
976 return '_format_' + tp.toString('_');
977};
978
979var EOL = '\n';
980
981function indent(v, indentation) {
982 return v
983 .split(EOL)
984 .map(function(vv) {
985 return indentation + vv;
986 })
987 .join(EOL);
988}
989
990function pad(str, value, filler) {
991 str = String(str);
992 var isRight = false;
993
994 if (value < 0) {
995 isRight = true;
996 value = -value;
997 }
998
999 if (str.length < value) {
1000 var padding = new Array(value - str.length + 1).join(filler);
1001 return isRight ? str + padding : padding + str;
1002 } else {
1003 return str;
1004 }
1005}
1006
1007function pad0(str, value) {
1008 return pad(str, value, '0');
1009}
1010
1011var functionNameRE = /^\s*function\s*(\S*)\s*\(/;
1012
1013function functionName(f) {
1014 if (f.name) {
1015 return f.name;
1016 }
1017 var matches = f.toString().match(functionNameRE);
1018 if (matches === null) {
1019 // `functionNameRE` doesn't match arrow functions.
1020 return '';
1021 }
1022 var name = matches[1];
1023 return name;
1024}
1025
1026function constructorName(obj) {
1027 while (obj) {
1028 var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
1029 if (descriptor !== undefined && typeof descriptor.value === 'function') {
1030 var name = functionName(descriptor.value);
1031 if (name !== '') {
1032 return name;
1033 }
1034 }
1035
1036 obj = Object.getPrototypeOf(obj);
1037 }
1038}
1039
1040var INDENT = ' ';
1041
1042function addSpaces(str) {
1043 return indent(str, INDENT);
1044}
1045
1046function typeAdaptorForEachFormat(obj, opts) {
1047 opts = opts || {};
1048 var filterKey = opts.filterKey || function() { return true; };
1049
1050 var formatKey = opts.formatKey || this.format;
1051 var formatValue = opts.formatValue || this.format;
1052
1053 var keyValueSep = typeof opts.keyValueSep !== 'undefined' ? opts.keyValueSep : ': ';
1054
1055 this.seen.push(obj);
1056
1057 var formatLength = 0;
1058 var pairs = [];
1059
1060 forEach(obj, function(value, key) {
1061 if (!filterKey(key)) {
1062 return;
1063 }
1064
1065 var formattedKey = formatKey.call(this, key);
1066 var formattedValue = formatValue.call(this, value, key);
1067
1068 var pair = formattedKey ? (formattedKey + keyValueSep + formattedValue) : formattedValue;
1069
1070 formatLength += pair.length;
1071 pairs.push(pair);
1072 }, this);
1073
1074 this.seen.pop();
1075
1076 (opts.additionalKeys || []).forEach(function(keyValue) {
1077 var pair = keyValue[0] + keyValueSep + this.format(keyValue[1]);
1078 formatLength += pair.length;
1079 pairs.push(pair);
1080 }, this);
1081
1082 var prefix = opts.prefix || constructorName(obj) || '';
1083 if (prefix.length > 0) {
1084 prefix += ' ';
1085 }
1086
1087 var lbracket, rbracket;
1088 if (Array.isArray(opts.brackets)) {
1089 lbracket = opts.brackets[0];
1090 rbracket = opts.brackets[1];
1091 } else {
1092 lbracket = '{';
1093 rbracket = '}';
1094 }
1095
1096 var rootValue = opts.value || '';
1097
1098 if (pairs.length === 0) {
1099 return rootValue || (prefix + lbracket + rbracket);
1100 }
1101
1102 if (formatLength <= this.maxLineLength) {
1103 return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + pairs.join(this.propSep + ' ') + ' ' + rbracket;
1104 } else {
1105 return prefix + lbracket + '\n' + (rootValue ? ' ' + rootValue + '\n' : '') + pairs.map(addSpaces).join(this.propSep + '\n') + '\n' + rbracket;
1106 }
1107}
1108
1109function formatPlainObjectKey(key) {
1110 return typeof key === 'string' && key.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? key : this.format(key);
1111}
1112
1113function getPropertyDescriptor(obj, key) {
1114 var desc;
1115 try {
1116 desc = Object.getOwnPropertyDescriptor(obj, key) || { value: obj[key] };
1117 } catch (e) {
1118 desc = { value: e };
1119 }
1120 return desc;
1121}
1122
1123function formatPlainObjectValue(obj, key) {
1124 var desc = getPropertyDescriptor(obj, key);
1125 if (desc.get && desc.set) {
1126 return '[Getter/Setter]';
1127 }
1128 if (desc.get) {
1129 return '[Getter]';
1130 }
1131 if (desc.set) {
1132 return '[Setter]';
1133 }
1134
1135 return this.format(desc.value);
1136}
1137
1138function formatPlainObject(obj, opts) {
1139 opts = opts || {};
1140 opts.keyValueSep = ': ';
1141 opts.formatKey = opts.formatKey || formatPlainObjectKey;
1142 opts.formatValue = opts.formatValue || function(value, key) {
1143 return formatPlainObjectValue.call(this, obj, key);
1144 };
1145 return typeAdaptorForEachFormat.call(this, obj, opts);
1146}
1147
1148function formatWrapper1(value) {
1149 return formatPlainObject.call(this, value, {
1150 additionalKeys: [['[[PrimitiveValue]]', value.valueOf()]]
1151 });
1152}
1153
1154
1155function formatWrapper2(value) {
1156 var realValue = value.valueOf();
1157
1158 return formatPlainObject.call(this, value, {
1159 filterKey: function(key) {
1160 //skip useless indexed properties
1161 return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length);
1162 },
1163 additionalKeys: [['[[PrimitiveValue]]', realValue]]
1164 });
1165}
1166
1167function formatRegExp(value) {
1168 return formatPlainObject.call(this, value, {
1169 value: String(value)
1170 });
1171}
1172
1173function formatFunction(value) {
1174 return formatPlainObject.call(this, value, {
1175 prefix: 'Function',
1176 additionalKeys: [['name', functionName(value)]]
1177 });
1178}
1179
1180function formatArray(value) {
1181 return formatPlainObject.call(this, value, {
1182 formatKey: function(key) {
1183 if (!key.match(/\d+/)) {
1184 return formatPlainObjectKey.call(this, key);
1185 }
1186 },
1187 brackets: ['[', ']']
1188 });
1189}
1190
1191function formatArguments(value) {
1192 return formatPlainObject.call(this, value, {
1193 formatKey: function(key) {
1194 if (!key.match(/\d+/)) {
1195 return formatPlainObjectKey.call(this, key);
1196 }
1197 },
1198 brackets: ['[', ']'],
1199 prefix: 'Arguments'
1200 });
1201}
1202
1203function _formatDate(value, isUTC) {
1204 var prefix = isUTC ? 'UTC' : '';
1205
1206 var date = value['get' + prefix + 'FullYear']() +
1207 '-' +
1208 pad0(value['get' + prefix + 'Month']() + 1, 2) +
1209 '-' +
1210 pad0(value['get' + prefix + 'Date'](), 2);
1211
1212 var time = pad0(value['get' + prefix + 'Hours'](), 2) +
1213 ':' +
1214 pad0(value['get' + prefix + 'Minutes'](), 2) +
1215 ':' +
1216 pad0(value['get' + prefix + 'Seconds'](), 2) +
1217 '.' +
1218 pad0(value['get' + prefix + 'Milliseconds'](), 3);
1219
1220 var to = value.getTimezoneOffset();
1221 var absTo = Math.abs(to);
1222 var hours = Math.floor(absTo / 60);
1223 var minutes = absTo - hours * 60;
1224 var tzFormat = (to < 0 ? '+' : '-') + pad0(hours, 2) + pad0(minutes, 2);
1225
1226 return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat);
1227}
1228
1229function formatDate(value) {
1230 return formatPlainObject.call(this, value, { value: _formatDate(value, this.isUTCdate) });
1231}
1232
1233function formatError(value) {
1234 return formatPlainObject.call(this, value, {
1235 prefix: value.name,
1236 additionalKeys: [['message', value.message]]
1237 });
1238}
1239
1240function generateFormatForNumberArray(lengthProp, name, padding) {
1241 return function(value) {
1242 var max = this.byteArrayMaxLength || 50;
1243 var length = value[lengthProp];
1244 var formattedValues = [];
1245 var len = 0;
1246 for (var i = 0; i < max && i < length; i++) {
1247 var b = value[i] || 0;
1248 var v = pad0(b.toString(16), padding);
1249 len += v.length;
1250 formattedValues.push(v);
1251 }
1252 var prefix = value.constructor.name || name || '';
1253 if (prefix) {
1254 prefix += ' ';
1255 }
1256
1257 if (formattedValues.length === 0) {
1258 return prefix + '[]';
1259 }
1260
1261 if (len <= this.maxLineLength) {
1262 return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']';
1263 } else {
1264 return prefix + '[\n' + formattedValues.map(addSpaces).join(this.propSep + '\n') + '\n' + ']';
1265 }
1266 };
1267}
1268
1269function formatMap(obj) {
1270 return typeAdaptorForEachFormat.call(this, obj, {
1271 keyValueSep: ' => '
1272 });
1273}
1274
1275function formatSet(obj) {
1276 return typeAdaptorForEachFormat.call(this, obj, {
1277 keyValueSep: '',
1278 formatKey: function() { return ''; }
1279 });
1280}
1281
1282function genSimdVectorFormat(constructorName, length) {
1283 return function(value) {
1284 var Constructor = value.constructor;
1285 var extractLane = Constructor.extractLane;
1286
1287 var len = 0;
1288 var props = [];
1289
1290 for (var i = 0; i < length; i ++) {
1291 var key = this.format(extractLane(value, i));
1292 len += key.length;
1293 props.push(key);
1294 }
1295
1296 if (len <= this.maxLineLength) {
1297 return constructorName + ' [ ' + props.join(this.propSep + ' ') + ' ]';
1298 } else {
1299 return constructorName + ' [\n' + props.map(addSpaces).join(this.propSep + '\n') + '\n' + ']';
1300 }
1301 };
1302}
1303
1304function defaultFormat(value, opts) {
1305 return new Formatter(opts).format(value);
1306}
1307
1308defaultFormat.Formatter = Formatter;
1309defaultFormat.addSpaces = addSpaces;
1310defaultFormat.pad0 = pad0;
1311defaultFormat.functionName = functionName;
1312defaultFormat.constructorName = constructorName;
1313defaultFormat.formatPlainObjectKey = formatPlainObjectKey;
1314defaultFormat.formatPlainObject = formatPlainObject;
1315defaultFormat.typeAdaptorForEachFormat = typeAdaptorForEachFormat;
1316// adding primitive types
1317Formatter.addType(new getGlobalType.Type(getGlobalType.UNDEFINED), function() {
1318 return 'undefined';
1319});
1320Formatter.addType(new getGlobalType.Type(getGlobalType.NULL), function() {
1321 return 'null';
1322});
1323Formatter.addType(new getGlobalType.Type(getGlobalType.BOOLEAN), function(value) {
1324 return value ? 'true': 'false';
1325});
1326Formatter.addType(new getGlobalType.Type(getGlobalType.SYMBOL), function(value) {
1327 return value.toString();
1328});
1329Formatter.addType(new getGlobalType.Type(getGlobalType.NUMBER), function(value) {
1330 if (value === 0 && 1 / value < 0) {
1331 return '-0';
1332 }
1333 return String(value);
1334});
1335
1336Formatter.addType(new getGlobalType.Type(getGlobalType.STRING), function(value) {
1337 return '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
1338 .replace(/'/g, "\\'")
1339 .replace(/\\"/g, '"') + '\'';
1340});
1341
1342Formatter.addType(new getGlobalType.Type(getGlobalType.FUNCTION), formatFunction);
1343
1344// plain object
1345Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT), formatPlainObject);
1346
1347// type wrappers
1348Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.NUMBER), formatWrapper1);
1349Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.BOOLEAN), formatWrapper1);
1350Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.STRING), formatWrapper2);
1351
1352Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.REGEXP), formatRegExp);
1353Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.ARRAY), formatArray);
1354Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.ARGUMENTS), formatArguments);
1355Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.DATE), formatDate);
1356Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.ERROR), formatError);
1357Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SET), formatSet);
1358Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.MAP), formatMap);
1359Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.WEAK_MAP), formatMap);
1360Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.WEAK_SET), formatSet);
1361
1362Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.BUFFER), generateFormatForNumberArray('length', 'Buffer', 2));
1363
1364Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.ARRAY_BUFFER), generateFormatForNumberArray('byteLength', 'ArrayBuffer', 2));
1365
1366Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'int8'), generateFormatForNumberArray('length', 'Int8Array', 2));
1367Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'uint8'), generateFormatForNumberArray('length', 'Uint8Array', 2));
1368Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'uint8clamped'), generateFormatForNumberArray('length', 'Uint8ClampedArray', 2));
1369
1370Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'int16'), generateFormatForNumberArray('length', 'Int16Array', 4));
1371Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'uint16'), generateFormatForNumberArray('length', 'Uint16Array', 4));
1372
1373Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'int32'), generateFormatForNumberArray('length', 'Int32Array', 8));
1374Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.TYPED_ARRAY, 'uint32'), generateFormatForNumberArray('length', 'Uint32Array', 8));
1375
1376Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'bool16x8'), genSimdVectorFormat('Bool16x8', 8));
1377Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'bool32x4'), genSimdVectorFormat('Bool32x4', 4));
1378Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'bool8x16'), genSimdVectorFormat('Bool8x16', 16));
1379Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'float32x4'), genSimdVectorFormat('Float32x4', 4));
1380Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'int16x8'), genSimdVectorFormat('Int16x8', 8));
1381Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'int32x4'), genSimdVectorFormat('Int32x4', 4));
1382Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'int8x16'), genSimdVectorFormat('Int8x16', 16));
1383Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'uint16x8'), genSimdVectorFormat('Uint16x8', 8));
1384Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'uint32x4'), genSimdVectorFormat('Uint32x4', 4));
1385Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.SIMD, 'uint8x16'), genSimdVectorFormat('Uint8x16', 16));
1386
1387
1388Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.PROMISE), function() {
1389 return '[Promise]';//TODO it could be nice to inspect its state and value
1390});
1391
1392Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.XHR), function() {
1393 return '[XMLHttpRequest]';//TODO it could be nice to inspect its state
1394});
1395
1396Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.HTML_ELEMENT), function(value) {
1397 return value.outerHTML;
1398});
1399
1400Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.HTML_ELEMENT, '#text'), function(value) {
1401 return value.nodeValue;
1402});
1403
1404Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.HTML_ELEMENT, '#document'), function(value) {
1405 return value.documentElement.outerHTML;
1406});
1407
1408Formatter.addType(new getGlobalType.Type(getGlobalType.OBJECT, getGlobalType.HOST), function() {
1409 return '[Host]';
1410});
1411
1412/*
1413 * should.js - assertion library
1414 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
1415 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
1416 * MIT Licensed
1417 */
1418function isWrapperType(obj) {
1419 return obj instanceof Number || obj instanceof String || obj instanceof Boolean;
1420}
1421
1422// XXX make it more strict: numbers, strings, symbols - and nothing else
1423function convertPropertyName(name) {
1424 return typeof name === "symbol" ? name : String(name);
1425}
1426
1427var functionName$1 = defaultFormat.functionName;
1428
1429function isPlainObject(obj) {
1430 if (typeof obj == "object" && obj !== null) {
1431 var proto = Object.getPrototypeOf(obj);
1432 return proto === Object.prototype || proto === null;
1433 }
1434
1435 return false;
1436}
1437
1438/*
1439 * should.js - assertion library
1440 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
1441 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
1442 * MIT Licensed
1443 */
1444
1445var config = {
1446 typeAdaptors: defaultTypeAdaptorStorage,
1447
1448 getFormatter: function(opts) {
1449 return new defaultFormat.Formatter(opts || config);
1450 }
1451};
1452
1453function format$2(value, opts) {
1454 return config.getFormatter(opts).format(value);
1455}
1456
1457function formatProp(value) {
1458 var formatter = config.getFormatter();
1459 return defaultFormat.formatPlainObjectKey.call(formatter, value);
1460}
1461
1462/*
1463 * should.js - assertion library
1464 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
1465 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
1466 * MIT Licensed
1467 */
1468/**
1469 * should AssertionError
1470 * @param {Object} options
1471 * @constructor
1472 * @memberOf should
1473 * @static
1474 */
1475function AssertionError(options) {
1476 merge(this, options);
1477
1478 if (!options.message) {
1479 Object.defineProperty(this, "message", {
1480 get: function() {
1481 if (!this._message) {
1482 this._message = this.generateMessage();
1483 this.generatedMessage = true;
1484 }
1485 return this._message;
1486 },
1487 configurable: true,
1488 enumerable: false
1489 });
1490 }
1491
1492 if (Error.captureStackTrace) {
1493 Error.captureStackTrace(this, this.stackStartFunction);
1494 } else {
1495 // non v8 browsers so we can have a stacktrace
1496 var err = new Error();
1497 if (err.stack) {
1498 var out = err.stack;
1499
1500 if (this.stackStartFunction) {
1501 // try to strip useless frames
1502 var fn_name = functionName$1(this.stackStartFunction);
1503 var idx = out.indexOf("\n" + fn_name);
1504 if (idx >= 0) {
1505 // once we have located the function frame
1506 // we need to strip out everything before it (and its line)
1507 var next_line = out.indexOf("\n", idx + 1);
1508 out = out.substring(next_line + 1);
1509 }
1510 }
1511
1512 this.stack = out;
1513 }
1514 }
1515}
1516
1517var indent$1 = " ";
1518function prependIndent(line) {
1519 return indent$1 + line;
1520}
1521
1522function indentLines(text) {
1523 return text
1524 .split("\n")
1525 .map(prependIndent)
1526 .join("\n");
1527}
1528
1529// assert.AssertionError instanceof Error
1530AssertionError.prototype = Object.create(Error.prototype, {
1531 name: {
1532 value: "AssertionError"
1533 },
1534
1535 generateMessage: {
1536 value: function() {
1537 if (!this.operator && this.previous) {
1538 return this.previous.message;
1539 }
1540 var actual = format$2(this.actual);
1541 var expected = "expected" in this ? " " + format$2(this.expected) : "";
1542 var details =
1543 "details" in this && this.details ? " (" + this.details + ")" : "";
1544
1545 var previous = this.previous
1546 ? "\n" + indentLines(this.previous.message)
1547 : "";
1548
1549 return (
1550 "expected " +
1551 actual +
1552 (this.negate ? " not " : " ") +
1553 this.operator +
1554 expected +
1555 details +
1556 previous
1557 );
1558 }
1559 }
1560});
1561
1562/*
1563 * should.js - assertion library
1564 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
1565 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
1566 * MIT Licensed
1567 */
1568
1569// a bit hacky way how to get error to do not have stack
1570function LightAssertionError(options) {
1571 merge(this, options);
1572
1573 if (!options.message) {
1574 Object.defineProperty(this, "message", {
1575 get: function() {
1576 if (!this._message) {
1577 this._message = this.generateMessage();
1578 this.generatedMessage = true;
1579 }
1580 return this._message;
1581 }
1582 });
1583 }
1584}
1585
1586LightAssertionError.prototype = {
1587 generateMessage: AssertionError.prototype.generateMessage
1588};
1589
1590/**
1591 * should Assertion
1592 * @param {*} obj Given object for assertion
1593 * @constructor
1594 * @memberOf should
1595 * @static
1596 */
1597function Assertion(obj) {
1598 this.obj = obj;
1599
1600 this.anyOne = false;
1601 this.negate = false;
1602
1603 this.params = { actual: obj };
1604}
1605
1606Assertion.prototype = {
1607 constructor: Assertion,
1608
1609 /**
1610 * Base method for assertions.
1611 *
1612 * Before calling this method need to fill Assertion#params object. This method usually called from other assertion methods.
1613 * `Assertion#params` can contain such properties:
1614 * * `operator` - required string containing description of this assertion
1615 * * `obj` - optional replacement for this.obj, it is useful if you prepare more clear object then given
1616 * * `message` - if this property filled with string any others will be ignored and this one used as assertion message
1617 * * `expected` - any object used when you need to assert relation between given object and expected. Like given == expected (== is a relation)
1618 * * `details` - additional string with details to generated message
1619 *
1620 * @memberOf Assertion
1621 * @category assertion
1622 * @param {*} expr Any expression that will be used as a condition for asserting.
1623 * @example
1624 *
1625 * var a = new should.Assertion(42);
1626 *
1627 * a.params = {
1628 * operator: 'to be magic number',
1629 * }
1630 *
1631 * a.assert(false);
1632 * //throws AssertionError: expected 42 to be magic number
1633 */
1634 assert: function(expr) {
1635 if (expr) {
1636 return this;
1637 }
1638
1639 var params = this.params;
1640
1641 if ("obj" in params && !("actual" in params)) {
1642 params.actual = params.obj;
1643 } else if (!("obj" in params) && !("actual" in params)) {
1644 params.actual = this.obj;
1645 }
1646
1647 params.stackStartFunction = params.stackStartFunction || this.assert;
1648 params.negate = this.negate;
1649
1650 params.assertion = this;
1651
1652 if (this.light) {
1653 throw new LightAssertionError(params);
1654 } else {
1655 throw new AssertionError(params);
1656 }
1657 },
1658
1659 /**
1660 * Shortcut for `Assertion#assert(false)`.
1661 *
1662 * @memberOf Assertion
1663 * @category assertion
1664 * @example
1665 *
1666 * var a = new should.Assertion(42);
1667 *
1668 * a.params = {
1669 * operator: 'to be magic number',
1670 * }
1671 *
1672 * a.fail();
1673 * //throws AssertionError: expected 42 to be magic number
1674 */
1675 fail: function() {
1676 return this.assert(false);
1677 },
1678
1679 assertZeroArguments: function(args) {
1680 if (args.length !== 0) {
1681 throw new TypeError("This assertion does not expect any arguments. You may need to check your code");
1682 }
1683 }
1684};
1685
1686/**
1687 * Assertion used to delegate calls of Assertion methods inside of Promise.
1688 * It has almost all methods of Assertion.prototype
1689 *
1690 * @param {Promise} obj
1691 */
1692function PromisedAssertion(/* obj */) {
1693 Assertion.apply(this, arguments);
1694}
1695
1696/**
1697 * Make PromisedAssertion to look like promise. Delegate resolve and reject to given promise.
1698 *
1699 * @private
1700 * @returns {Promise}
1701 */
1702PromisedAssertion.prototype.then = function(resolve, reject) {
1703 return this.obj.then(resolve, reject);
1704};
1705
1706/**
1707 * Way to extend Assertion function. It uses some logic
1708 * to define only positive assertions and itself rule with negative assertion.
1709 *
1710 * All actions happen in subcontext and this method take care about negation.
1711 * Potentially we can add some more modifiers that does not depends from state of assertion.
1712 *
1713 * @memberOf Assertion
1714 * @static
1715 * @param {String} name Name of assertion. It will be used for defining method or getter on Assertion.prototype
1716 * @param {Function} func Function that will be called on executing assertion
1717 * @example
1718 *
1719 * Assertion.add('asset', function() {
1720 * this.params = { operator: 'to be asset' }
1721 *
1722 * this.obj.should.have.property('id').which.is.a.Number()
1723 * this.obj.should.have.property('path')
1724 * })
1725 */
1726Assertion.add = function(name, func) {
1727 Object.defineProperty(Assertion.prototype, name, {
1728 enumerable: true,
1729 configurable: true,
1730 value: function() {
1731 var context = new Assertion(this.obj, this, name);
1732 context.anyOne = this.anyOne;
1733 context.onlyThis = this.onlyThis;
1734 // hack
1735 context.light = true;
1736
1737 try {
1738 func.apply(context, arguments);
1739 } catch (e) {
1740 // check for fail
1741 if (e instanceof AssertionError || e instanceof LightAssertionError) {
1742 // negative fail
1743 if (this.negate) {
1744 this.obj = context.obj;
1745 this.negate = false;
1746 return this;
1747 }
1748
1749 if (context !== e.assertion) {
1750 context.params.previous = e;
1751 }
1752
1753 // positive fail
1754 context.negate = false;
1755 // hack
1756 context.light = false;
1757 context.fail();
1758 }
1759 // throw if it is another exception
1760 throw e;
1761 }
1762
1763 // negative pass
1764 if (this.negate) {
1765 context.negate = true; // because .fail will set negate
1766 context.params.details = "false negative fail";
1767 // hack
1768 context.light = false;
1769 context.fail();
1770 }
1771
1772 // positive pass
1773 if (!this.params.operator) {
1774 this.params = context.params; // shortcut
1775 }
1776 this.obj = context.obj;
1777 this.negate = false;
1778 return this;
1779 }
1780 });
1781
1782 Object.defineProperty(PromisedAssertion.prototype, name, {
1783 enumerable: true,
1784 configurable: true,
1785 value: function() {
1786 var args = arguments;
1787 this.obj = this.obj.then(function(a) {
1788 return a[name].apply(a, args);
1789 });
1790
1791 return this;
1792 }
1793 });
1794};
1795
1796/**
1797 * Add chaining getter to Assertion like .a, .which etc
1798 *
1799 * @memberOf Assertion
1800 * @static
1801 * @param {string} name name of getter
1802 * @param {function} [onCall] optional function to call
1803 */
1804Assertion.addChain = function(name, onCall) {
1805 onCall = onCall || function() {};
1806 Object.defineProperty(Assertion.prototype, name, {
1807 get: function() {
1808 onCall.call(this);
1809 return this;
1810 },
1811 enumerable: true
1812 });
1813
1814 Object.defineProperty(PromisedAssertion.prototype, name, {
1815 enumerable: true,
1816 configurable: true,
1817 get: function() {
1818 this.obj = this.obj.then(function(a) {
1819 return a[name];
1820 });
1821
1822 return this;
1823 }
1824 });
1825};
1826
1827/**
1828 * Create alias for some `Assertion` property
1829 *
1830 * @memberOf Assertion
1831 * @static
1832 * @param {String} from Name of to map
1833 * @param {String} to Name of alias
1834 * @example
1835 *
1836 * Assertion.alias('true', 'True')
1837 */
1838Assertion.alias = function(from, to) {
1839 var desc = Object.getOwnPropertyDescriptor(Assertion.prototype, from);
1840 if (!desc) {
1841 throw new Error("Alias " + from + " -> " + to + " could not be created as " + from + " not defined");
1842 }
1843 Object.defineProperty(Assertion.prototype, to, desc);
1844
1845 var desc2 = Object.getOwnPropertyDescriptor(PromisedAssertion.prototype, from);
1846 if (desc2) {
1847 Object.defineProperty(PromisedAssertion.prototype, to, desc2);
1848 }
1849};
1850/**
1851 * Negation modifier. Current assertion chain become negated. Each call invert negation on current assertion.
1852 *
1853 * @name not
1854 * @property
1855 * @memberOf Assertion
1856 * @category assertion
1857 */
1858Assertion.addChain("not", function() {
1859 this.negate = !this.negate;
1860});
1861
1862/**
1863 * Any modifier - it affect on execution of sequenced assertion to do not `check all`, but `check any of`.
1864 *
1865 * @name any
1866 * @property
1867 * @memberOf Assertion
1868 * @category assertion
1869 */
1870Assertion.addChain("any", function() {
1871 this.anyOne = true;
1872});
1873
1874/**
1875 * Only modifier - currently used with .keys to check if object contains only exactly this .keys
1876 *
1877 * @name only
1878 * @property
1879 * @memberOf Assertion
1880 * @category assertion
1881 */
1882Assertion.addChain("only", function() {
1883 this.onlyThis = true;
1884});
1885
1886// implement assert interface using already written peaces of should.js
1887
1888// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
1889//
1890// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
1891//
1892// Originally from narwhal.js (http://narwhaljs.org)
1893// Copyright (c) 2009 Thomas Robinson <280north.com>
1894//
1895// Permission is hereby granted, free of charge, to any person obtaining a copy
1896// of this software and associated documentation files (the 'Software'), to
1897// deal in the Software without restriction, including without limitation the
1898// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1899// sell copies of the Software, and to permit persons to whom the Software is
1900// furnished to do so, subject to the following conditions:
1901//
1902// The above copyright notice and this permission notice shall be included in
1903// all copies or substantial portions of the Software.
1904//
1905// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1906// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1907// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1908// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1909// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1910// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1911
1912// when used in node, this will actually load the util module we depend on
1913// versus loading the builtin util module as happens otherwise
1914// this is a bug in node module loading as far as I am concerned
1915var pSlice = Array.prototype.slice;
1916
1917// 1. The assert module provides functions that throw
1918// AssertionError's when particular conditions are not met. The
1919// assert module must conform to the following interface.
1920
1921var assert = ok;
1922// 3. All of the following functions must throw an AssertionError
1923// when a corresponding condition is not met, with a message that
1924// may be undefined if not provided. All assertion methods provide
1925// both the actual and expected values to the assertion error for
1926// display purposes.
1927/**
1928 * Node.js standard [`assert.fail`](http://nodejs.org/api/assert.html#assert_assert_fail_actual_expected_message_operator).
1929 * @static
1930 * @memberOf should
1931 * @category assertion assert
1932 * @param {*} actual Actual object
1933 * @param {*} expected Expected object
1934 * @param {string} message Message for assertion
1935 * @param {string} operator Operator text
1936 */
1937function fail(actual, expected, message, operator, stackStartFunction) {
1938 var a = new Assertion(actual);
1939 a.params = {
1940 operator: operator,
1941 expected: expected,
1942 message: message,
1943 stackStartFunction: stackStartFunction || fail
1944 };
1945
1946 a.fail();
1947}
1948
1949// EXTENSION! allows for well behaved errors defined elsewhere.
1950assert.fail = fail;
1951
1952// 4. Pure assertion tests whether a value is truthy, as determined
1953// by !!guard.
1954// assert.ok(guard, message_opt);
1955// This statement is equivalent to assert.equal(true, !!guard,
1956// message_opt);. To test strictly for the value true, use
1957// assert.strictEqual(true, guard, message_opt);.
1958/**
1959 * Node.js standard [`assert.ok`](http://nodejs.org/api/assert.html#assert_assert_value_message_assert_ok_value_message).
1960 * @static
1961 * @memberOf should
1962 * @category assertion assert
1963 * @param {*} value
1964 * @param {string} [message]
1965 */
1966function ok(value, message) {
1967 if (!value) {
1968 fail(value, true, message, "==", assert.ok);
1969 }
1970}
1971assert.ok = ok;
1972
1973// 5. The equality assertion tests shallow, coercive equality with
1974// ==.
1975// assert.equal(actual, expected, message_opt);
1976
1977/**
1978 * Node.js standard [`assert.equal`](http://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message).
1979 * @static
1980 * @memberOf should
1981 * @category assertion assert
1982 * @param {*} actual
1983 * @param {*} expected
1984 * @param {string} [message]
1985 */
1986assert.equal = function equal(actual, expected, message) {
1987 if (actual != expected) {
1988 fail(actual, expected, message, "==", assert.equal);
1989 }
1990};
1991
1992// 6. The non-equality assertion tests for whether two objects are not equal
1993// with != assert.notEqual(actual, expected, message_opt);
1994/**
1995 * Node.js standard [`assert.notEqual`](http://nodejs.org/api/assert.html#assert_assert_notequal_actual_expected_message).
1996 * @static
1997 * @memberOf should
1998 * @category assertion assert
1999 * @param {*} actual
2000 * @param {*} expected
2001 * @param {string} [message]
2002 */
2003assert.notEqual = function notEqual(actual, expected, message) {
2004 if (actual == expected) {
2005 fail(actual, expected, message, "!=", assert.notEqual);
2006 }
2007};
2008
2009// 7. The equivalence assertion tests a deep equality relation.
2010// assert.deepEqual(actual, expected, message_opt);
2011/**
2012 * Node.js standard [`assert.deepEqual`](http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message).
2013 * But uses should.js .eql implementation instead of Node.js own deepEqual.
2014 *
2015 * @static
2016 * @memberOf should
2017 * @category assertion assert
2018 * @param {*} actual
2019 * @param {*} expected
2020 * @param {string} [message]
2021 */
2022assert.deepEqual = function deepEqual(actual, expected, message) {
2023 if (eq(actual, expected).length !== 0) {
2024 fail(actual, expected, message, "deepEqual", assert.deepEqual);
2025 }
2026};
2027
2028// 8. The non-equivalence assertion tests for any deep inequality.
2029// assert.notDeepEqual(actual, expected, message_opt);
2030/**
2031 * Node.js standard [`assert.notDeepEqual`](http://nodejs.org/api/assert.html#assert_assert_notdeepequal_actual_expected_message).
2032 * But uses should.js .eql implementation instead of Node.js own deepEqual.
2033 *
2034 * @static
2035 * @memberOf should
2036 * @category assertion assert
2037 * @param {*} actual
2038 * @param {*} expected
2039 * @param {string} [message]
2040 */
2041assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
2042 if (eq(actual, expected).result) {
2043 fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);
2044 }
2045};
2046
2047// 9. The strict equality assertion tests strict equality, as determined by ===.
2048// assert.strictEqual(actual, expected, message_opt);
2049/**
2050 * Node.js standard [`assert.strictEqual`](http://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message).
2051 * @static
2052 * @memberOf should
2053 * @category assertion assert
2054 * @param {*} actual
2055 * @param {*} expected
2056 * @param {string} [message]
2057 */
2058assert.strictEqual = function strictEqual(actual, expected, message) {
2059 if (actual !== expected) {
2060 fail(actual, expected, message, "===", assert.strictEqual);
2061 }
2062};
2063
2064// 10. The strict non-equality assertion tests for strict inequality, as
2065// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
2066/**
2067 * Node.js standard [`assert.notStrictEqual`](http://nodejs.org/api/assert.html#assert_assert_notstrictequal_actual_expected_message).
2068 * @static
2069 * @memberOf should
2070 * @category assertion assert
2071 * @param {*} actual
2072 * @param {*} expected
2073 * @param {string} [message]
2074 */
2075assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
2076 if (actual === expected) {
2077 fail(actual, expected, message, "!==", assert.notStrictEqual);
2078 }
2079};
2080
2081function expectedException(actual, expected) {
2082 if (!actual || !expected) {
2083 return false;
2084 }
2085
2086 if (Object.prototype.toString.call(expected) == "[object RegExp]") {
2087 return expected.test(actual);
2088 } else if (actual instanceof expected) {
2089 return true;
2090 } else if (expected.call({}, actual) === true) {
2091 return true;
2092 }
2093
2094 return false;
2095}
2096
2097function _throws(shouldThrow, block, expected, message) {
2098 var actual;
2099
2100 if (typeof expected == "string") {
2101 message = expected;
2102 expected = null;
2103 }
2104
2105 try {
2106 block();
2107 } catch (e) {
2108 actual = e;
2109 }
2110
2111 message =
2112 (expected && expected.name ? " (" + expected.name + ")" : ".") +
2113 (message ? " " + message : ".");
2114
2115 if (shouldThrow && !actual) {
2116 fail(actual, expected, "Missing expected exception" + message);
2117 }
2118
2119 if (!shouldThrow && expectedException(actual, expected)) {
2120 fail(actual, expected, "Got unwanted exception" + message);
2121 }
2122
2123 if (
2124 (shouldThrow &&
2125 actual &&
2126 expected &&
2127 !expectedException(actual, expected)) ||
2128 (!shouldThrow && actual)
2129 ) {
2130 throw actual;
2131 }
2132}
2133
2134// 11. Expected to throw an error:
2135// assert.throws(block, Error_opt, message_opt);
2136/**
2137 * Node.js standard [`assert.throws`](http://nodejs.org/api/assert.html#assert_assert_throws_block_error_message).
2138 * @static
2139 * @memberOf should
2140 * @category assertion assert
2141 * @param {Function} block
2142 * @param {Function} [error]
2143 * @param {String} [message]
2144 */
2145assert.throws = function(/*block, error, message*/) {
2146 _throws.apply(this, [true].concat(pSlice.call(arguments)));
2147};
2148
2149// EXTENSION! This is annoying to write outside this module.
2150/**
2151 * Node.js standard [`assert.doesNotThrow`](http://nodejs.org/api/assert.html#assert_assert_doesnotthrow_block_message).
2152 * @static
2153 * @memberOf should
2154 * @category assertion assert
2155 * @param {Function} block
2156 * @param {String} [message]
2157 */
2158assert.doesNotThrow = function(/*block, message*/) {
2159 _throws.apply(this, [false].concat(pSlice.call(arguments)));
2160};
2161
2162/**
2163 * Node.js standard [`assert.ifError`](http://nodejs.org/api/assert.html#assert_assert_iferror_value).
2164 * @static
2165 * @memberOf should
2166 * @category assertion assert
2167 * @param {Error} err
2168 */
2169assert.ifError = function(err) {
2170 if (err) {
2171 throw err;
2172 }
2173};
2174
2175/*
2176 * should.js - assertion library
2177 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2178 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2179 * MIT Licensed
2180 */
2181
2182function assertExtensions(should) {
2183 var i = should.format;
2184
2185 /*
2186 * Expose assert to should
2187 *
2188 * This allows you to do things like below
2189 * without require()ing the assert module.
2190 *
2191 * should.equal(foo.bar, undefined);
2192 *
2193 */
2194 merge(should, assert);
2195
2196 /**
2197 * Assert _obj_ exists, with optional message.
2198 *
2199 * @static
2200 * @memberOf should
2201 * @category assertion assert
2202 * @alias should.exists
2203 * @param {*} obj
2204 * @param {String} [msg]
2205 * @example
2206 *
2207 * should.exist(1);
2208 * should.exist(new Date());
2209 */
2210 should.exist = should.exists = function(obj, msg) {
2211 if (null == obj) {
2212 throw new AssertionError({
2213 message: msg || "expected " + i(obj) + " to exist",
2214 stackStartFunction: should.exist
2215 });
2216 }
2217 };
2218
2219 should.not = {};
2220 /**
2221 * Asserts _obj_ does not exist, with optional message.
2222 *
2223 * @name not.exist
2224 * @static
2225 * @memberOf should
2226 * @category assertion assert
2227 * @alias should.not.exists
2228 * @param {*} obj
2229 * @param {String} [msg]
2230 * @example
2231 *
2232 * should.not.exist(null);
2233 * should.not.exist(void 0);
2234 */
2235 should.not.exist = should.not.exists = function(obj, msg) {
2236 if (null != obj) {
2237 throw new AssertionError({
2238 message: msg || "expected " + i(obj) + " to not exist",
2239 stackStartFunction: should.not.exist
2240 });
2241 }
2242 };
2243}
2244
2245/*
2246 * should.js - assertion library
2247 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2248 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2249 * MIT Licensed
2250 */
2251
2252function chainAssertions(should, Assertion) {
2253 /**
2254 * Simple chaining to improve readability. Does nothing.
2255 *
2256 * @memberOf Assertion
2257 * @name be
2258 * @property {should.Assertion} be
2259 * @alias Assertion#an
2260 * @alias Assertion#of
2261 * @alias Assertion#a
2262 * @alias Assertion#and
2263 * @alias Assertion#been
2264 * @alias Assertion#have
2265 * @alias Assertion#has
2266 * @alias Assertion#with
2267 * @alias Assertion#is
2268 * @alias Assertion#which
2269 * @alias Assertion#the
2270 * @alias Assertion#it
2271 * @category assertion chaining
2272 */
2273 [
2274 "an",
2275 "of",
2276 "a",
2277 "and",
2278 "be",
2279 "been",
2280 "has",
2281 "have",
2282 "with",
2283 "is",
2284 "which",
2285 "the",
2286 "it"
2287 ].forEach(function(name) {
2288 Assertion.addChain(name);
2289 });
2290}
2291
2292/*
2293 * should.js - assertion library
2294 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2295 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2296 * MIT Licensed
2297 */
2298
2299function booleanAssertions(should, Assertion) {
2300 /**
2301 * Assert given object is exactly `true`.
2302 *
2303 * @name true
2304 * @memberOf Assertion
2305 * @category assertion bool
2306 * @alias Assertion#True
2307 * @param {string} [message] Optional message
2308 * @example
2309 *
2310 * (true).should.be.true();
2311 * false.should.not.be.true();
2312 *
2313 * ({ a: 10}).should.not.be.true();
2314 */
2315 Assertion.add("true", function(message) {
2316 this.is.exactly(true, message);
2317 });
2318
2319 Assertion.alias("true", "True");
2320
2321 /**
2322 * Assert given object is exactly `false`.
2323 *
2324 * @name false
2325 * @memberOf Assertion
2326 * @category assertion bool
2327 * @alias Assertion#False
2328 * @param {string} [message] Optional message
2329 * @example
2330 *
2331 * (true).should.not.be.false();
2332 * false.should.be.false();
2333 */
2334 Assertion.add("false", function(message) {
2335 this.is.exactly(false, message);
2336 });
2337
2338 Assertion.alias("false", "False");
2339
2340 /**
2341 * Assert given object is truthy according javascript type conversions.
2342 *
2343 * @name ok
2344 * @memberOf Assertion
2345 * @category assertion bool
2346 * @example
2347 *
2348 * (true).should.be.ok();
2349 * ''.should.not.be.ok();
2350 * should(null).not.be.ok();
2351 * should(void 0).not.be.ok();
2352 *
2353 * (10).should.be.ok();
2354 * (0).should.not.be.ok();
2355 */
2356 Assertion.add("ok", function() {
2357 this.assertZeroArguments(arguments);
2358 this.params = { operator: "to be truthy" };
2359
2360 this.assert(this.obj);
2361 });
2362}
2363
2364/*
2365 * should.js - assertion library
2366 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2367 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2368 * MIT Licensed
2369 */
2370
2371function numberAssertions(should, Assertion) {
2372 /**
2373 * Assert given object is NaN
2374 * @name NaN
2375 * @memberOf Assertion
2376 * @category assertion numbers
2377 * @example
2378 *
2379 * (10).should.not.be.NaN();
2380 * NaN.should.be.NaN();
2381 */
2382 Assertion.add("NaN", function() {
2383 this.assertZeroArguments(arguments);
2384 this.params = { operator: "to be NaN" };
2385
2386 this.assert(this.obj !== this.obj);
2387 });
2388
2389 /**
2390 * Assert given object is not finite (positive or negative)
2391 *
2392 * @name Infinity
2393 * @memberOf Assertion
2394 * @category assertion numbers
2395 * @example
2396 *
2397 * (10).should.not.be.Infinity();
2398 * NaN.should.not.be.Infinity();
2399 */
2400 Assertion.add("Infinity", function() {
2401 this.assertZeroArguments(arguments);
2402 this.params = { operator: "to be Infinity" };
2403
2404 this.is.a
2405 .Number()
2406 .and.not.a.NaN()
2407 .and.assert(!isFinite(this.obj));
2408 });
2409
2410 /**
2411 * Assert given number between `start` and `finish` or equal one of them.
2412 *
2413 * @name within
2414 * @memberOf Assertion
2415 * @category assertion numbers
2416 * @param {number} start Start number
2417 * @param {number} finish Finish number
2418 * @param {string} [description] Optional message
2419 * @example
2420 *
2421 * (10).should.be.within(0, 20);
2422 */
2423 Assertion.add("within", function(start, finish, description) {
2424 this.params = {
2425 operator: "to be within " + start + ".." + finish,
2426 message: description
2427 };
2428
2429 this.assert(this.obj >= start && this.obj <= finish);
2430 });
2431
2432 /**
2433 * Assert given number near some other `value` within `delta`
2434 *
2435 * @name approximately
2436 * @memberOf Assertion
2437 * @category assertion numbers
2438 * @param {number} value Center number
2439 * @param {number} delta Radius
2440 * @param {string} [description] Optional message
2441 * @example
2442 *
2443 * (9.99).should.be.approximately(10, 0.1);
2444 */
2445 Assertion.add("approximately", function(value, delta, description) {
2446 this.params = {
2447 operator: "to be approximately " + value + " ±" + delta,
2448 message: description
2449 };
2450
2451 this.assert(Math.abs(this.obj - value) <= delta);
2452 });
2453
2454 /**
2455 * Assert given number above `n`.
2456 *
2457 * @name above
2458 * @alias Assertion#greaterThan
2459 * @memberOf Assertion
2460 * @category assertion numbers
2461 * @param {number} n Margin number
2462 * @param {string} [description] Optional message
2463 * @example
2464 *
2465 * (10).should.be.above(0);
2466 */
2467 Assertion.add("above", function(n, description) {
2468 this.params = { operator: "to be above " + n, message: description };
2469
2470 this.assert(this.obj > n);
2471 });
2472
2473 /**
2474 * Assert given number below `n`.
2475 *
2476 * @name below
2477 * @alias Assertion#lessThan
2478 * @memberOf Assertion
2479 * @category assertion numbers
2480 * @param {number} n Margin number
2481 * @param {string} [description] Optional message
2482 * @example
2483 *
2484 * (0).should.be.below(10);
2485 */
2486 Assertion.add("below", function(n, description) {
2487 this.params = { operator: "to be below " + n, message: description };
2488
2489 this.assert(this.obj < n);
2490 });
2491
2492 Assertion.alias("above", "greaterThan");
2493 Assertion.alias("below", "lessThan");
2494
2495 /**
2496 * Assert given number above `n`.
2497 *
2498 * @name aboveOrEqual
2499 * @alias Assertion#greaterThanOrEqual
2500 * @memberOf Assertion
2501 * @category assertion numbers
2502 * @param {number} n Margin number
2503 * @param {string} [description] Optional message
2504 * @example
2505 *
2506 * (10).should.be.aboveOrEqual(0);
2507 * (10).should.be.aboveOrEqual(10);
2508 */
2509 Assertion.add("aboveOrEqual", function(n, description) {
2510 this.params = {
2511 operator: "to be above or equal " + n,
2512 message: description
2513 };
2514
2515 this.assert(this.obj >= n);
2516 });
2517
2518 /**
2519 * Assert given number below `n`.
2520 *
2521 * @name belowOrEqual
2522 * @alias Assertion#lessThanOrEqual
2523 * @memberOf Assertion
2524 * @category assertion numbers
2525 * @param {number} n Margin number
2526 * @param {string} [description] Optional message
2527 * @example
2528 *
2529 * (0).should.be.belowOrEqual(10);
2530 * (0).should.be.belowOrEqual(0);
2531 */
2532 Assertion.add("belowOrEqual", function(n, description) {
2533 this.params = {
2534 operator: "to be below or equal " + n,
2535 message: description
2536 };
2537
2538 this.assert(this.obj <= n);
2539 });
2540
2541 Assertion.alias("aboveOrEqual", "greaterThanOrEqual");
2542 Assertion.alias("belowOrEqual", "lessThanOrEqual");
2543}
2544
2545/*
2546 * should.js - assertion library
2547 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2548 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2549 * MIT Licensed
2550 */
2551
2552function typeAssertions(should, Assertion) {
2553 /**
2554 * Assert given object is number
2555 * @name Number
2556 * @memberOf Assertion
2557 * @category assertion types
2558 */
2559 Assertion.add("Number", function() {
2560 this.assertZeroArguments(arguments);
2561 this.params = { operator: "to be a number" };
2562
2563 this.have.type("number");
2564 });
2565
2566 /**
2567 * Assert given object is arguments
2568 * @name arguments
2569 * @alias Assertion#Arguments
2570 * @memberOf Assertion
2571 * @category assertion types
2572 */
2573 Assertion.add("arguments", function() {
2574 this.assertZeroArguments(arguments);
2575 this.params = { operator: "to be arguments" };
2576
2577 this.have.class("Arguments");
2578 });
2579
2580 Assertion.alias("arguments", "Arguments");
2581
2582 /**
2583 * Assert given object has some type using `typeof`
2584 * @name type
2585 * @memberOf Assertion
2586 * @param {string} type Type name
2587 * @param {string} [description] Optional message
2588 * @category assertion types
2589 */
2590 Assertion.add("type", function(type, description) {
2591 this.params = { operator: "to have type " + type, message: description };
2592
2593 should(typeof this.obj).be.exactly(type);
2594 });
2595
2596 /**
2597 * Assert given object is instance of `constructor`
2598 * @name instanceof
2599 * @alias Assertion#instanceOf
2600 * @memberOf Assertion
2601 * @param {Function} constructor Constructor function
2602 * @param {string} [description] Optional message
2603 * @category assertion types
2604 */
2605 Assertion.add("instanceof", function(constructor, description) {
2606 this.params = {
2607 operator: "to be an instance of " + functionName$1(constructor),
2608 message: description
2609 };
2610
2611 this.assert(Object(this.obj) instanceof constructor);
2612 });
2613
2614 Assertion.alias("instanceof", "instanceOf");
2615
2616 /**
2617 * Assert given object is function
2618 * @name Function
2619 * @memberOf Assertion
2620 * @category assertion types
2621 */
2622 Assertion.add("Function", function() {
2623 this.assertZeroArguments(arguments);
2624 this.params = { operator: "to be a function" };
2625
2626 this.have.type("function");
2627 });
2628
2629 /**
2630 * Assert given object is object
2631 * @name Object
2632 * @memberOf Assertion
2633 * @category assertion types
2634 */
2635 Assertion.add("Object", function() {
2636 this.assertZeroArguments(arguments);
2637 this.params = { operator: "to be an object" };
2638
2639 this.is.not.null().and.have.type("object");
2640 });
2641
2642 /**
2643 * Assert given object is string
2644 * @name String
2645 * @memberOf Assertion
2646 * @category assertion types
2647 */
2648 Assertion.add("String", function() {
2649 this.assertZeroArguments(arguments);
2650 this.params = { operator: "to be a string" };
2651
2652 this.have.type("string");
2653 });
2654
2655 /**
2656 * Assert given object is array
2657 * @name Array
2658 * @memberOf Assertion
2659 * @category assertion types
2660 */
2661 Assertion.add("Array", function() {
2662 this.assertZeroArguments(arguments);
2663 this.params = { operator: "to be an array" };
2664
2665 this.have.class("Array");
2666 });
2667
2668 /**
2669 * Assert given object is boolean
2670 * @name Boolean
2671 * @memberOf Assertion
2672 * @category assertion types
2673 */
2674 Assertion.add("Boolean", function() {
2675 this.assertZeroArguments(arguments);
2676 this.params = { operator: "to be a boolean" };
2677
2678 this.have.type("boolean");
2679 });
2680
2681 /**
2682 * Assert given object is error
2683 * @name Error
2684 * @memberOf Assertion
2685 * @category assertion types
2686 */
2687 Assertion.add("Error", function() {
2688 this.assertZeroArguments(arguments);
2689 this.params = { operator: "to be an error" };
2690
2691 this.have.instanceOf(Error);
2692 });
2693
2694 /**
2695 * Assert given object is a date
2696 * @name Date
2697 * @memberOf Assertion
2698 * @category assertion types
2699 */
2700 Assertion.add("Date", function() {
2701 this.assertZeroArguments(arguments);
2702 this.params = { operator: "to be a date" };
2703
2704 this.have.instanceOf(Date);
2705 });
2706
2707 /**
2708 * Assert given object is null
2709 * @name null
2710 * @alias Assertion#Null
2711 * @memberOf Assertion
2712 * @category assertion types
2713 */
2714 Assertion.add("null", function() {
2715 this.assertZeroArguments(arguments);
2716 this.params = { operator: "to be null" };
2717
2718 this.assert(this.obj === null);
2719 });
2720
2721 Assertion.alias("null", "Null");
2722
2723 /**
2724 * Assert given object has some internal [[Class]], via Object.prototype.toString call
2725 * @name class
2726 * @alias Assertion#Class
2727 * @memberOf Assertion
2728 * @category assertion types
2729 */
2730 Assertion.add("class", function(cls) {
2731 this.params = { operator: "to have [[Class]] " + cls };
2732
2733 this.assert(Object.prototype.toString.call(this.obj) === "[object " + cls + "]");
2734 });
2735
2736 Assertion.alias("class", "Class");
2737
2738 /**
2739 * Assert given object is undefined
2740 * @name undefined
2741 * @alias Assertion#Undefined
2742 * @memberOf Assertion
2743 * @category assertion types
2744 */
2745 Assertion.add("undefined", function() {
2746 this.assertZeroArguments(arguments);
2747 this.params = { operator: "to be undefined" };
2748
2749 this.assert(this.obj === void 0);
2750 });
2751
2752 Assertion.alias("undefined", "Undefined");
2753
2754 /**
2755 * Assert given object supports es6 iterable protocol (just check
2756 * that object has property Symbol.iterator, which is a function)
2757 * @name iterable
2758 * @memberOf Assertion
2759 * @category assertion es6
2760 */
2761 Assertion.add("iterable", function() {
2762 this.assertZeroArguments(arguments);
2763 this.params = { operator: "to be iterable" };
2764
2765 should(this.obj)
2766 .have.property(Symbol.iterator)
2767 .which.is.a.Function();
2768 });
2769
2770 /**
2771 * Assert given object supports es6 iterator protocol (just check
2772 * that object has property next, which is a function)
2773 * @name iterator
2774 * @memberOf Assertion
2775 * @category assertion es6
2776 */
2777 Assertion.add("iterator", function() {
2778 this.assertZeroArguments(arguments);
2779 this.params = { operator: "to be iterator" };
2780
2781 should(this.obj)
2782 .have.property("next")
2783 .which.is.a.Function();
2784 });
2785
2786 /**
2787 * Assert given object is a generator object
2788 * @name generator
2789 * @memberOf Assertion
2790 * @category assertion es6
2791 */
2792 Assertion.add("generator", function() {
2793 this.assertZeroArguments(arguments);
2794 this.params = { operator: "to be generator" };
2795
2796 should(this.obj).be.iterable.and.iterator.and.it.is.equal(this.obj[Symbol.iterator]());
2797 });
2798}
2799
2800/*
2801 * should.js - assertion library
2802 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2803 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2804 * MIT Licensed
2805 */
2806
2807function formatEqlResult(r, a, b) {
2808 return ((r.path.length > 0
2809 ? "at " + r.path.map(formatProp).join(" -> ")
2810 : "") +
2811 (r.a === a ? "" : ", A has " + format$2(r.a)) +
2812 (r.b === b ? "" : " and B has " + format$2(r.b)) +
2813 (r.showReason ? " because " + r.reason : "")).trim();
2814}
2815
2816function equalityAssertions(should, Assertion) {
2817 /**
2818 * Deep object equality comparison. For full spec see [`should-equal tests`](https://github.com/shouldjs/equal/blob/master/test.js).
2819 *
2820 * @name eql
2821 * @memberOf Assertion
2822 * @category assertion equality
2823 * @alias Assertion#eqls
2824 * @alias Assertion#deepEqual
2825 * @param {*} val Expected value
2826 * @param {string} [description] Optional message
2827 * @example
2828 *
2829 * (10).should.be.eql(10);
2830 * ('10').should.not.be.eql(10);
2831 * (-0).should.not.be.eql(+0);
2832 *
2833 * NaN.should.be.eql(NaN);
2834 *
2835 * ({ a: 10}).should.be.eql({ a: 10 });
2836 * [ 'a' ].should.not.be.eql({ '0': 'a' });
2837 */
2838 Assertion.add("eql", function(val, description) {
2839 this.params = { operator: "to equal", expected: val, message: description };
2840 var obj = this.obj;
2841 var fails = eq(this.obj, val, should.config);
2842 this.params.details = fails
2843 .map(function(fail) {
2844 return formatEqlResult(fail, obj, val);
2845 })
2846 .join(", ");
2847
2848 this.params.showDiff = eq(getGlobalType(obj), getGlobalType(val)).length === 0;
2849
2850 this.assert(fails.length === 0);
2851 });
2852
2853 /**
2854 * Exact comparison using ===.
2855 *
2856 * @name equal
2857 * @memberOf Assertion
2858 * @category assertion equality
2859 * @alias Assertion#equals
2860 * @alias Assertion#exactly
2861 * @param {*} val Expected value
2862 * @param {string} [description] Optional message
2863 * @example
2864 *
2865 * 10.should.be.equal(10);
2866 * 'a'.should.be.exactly('a');
2867 *
2868 * should(null).be.exactly(null);
2869 */
2870 Assertion.add("equal", function(val, description) {
2871 this.params = { operator: "to be", expected: val, message: description };
2872
2873 this.params.showDiff = eq(getGlobalType(this.obj), getGlobalType(val)).length === 0;
2874
2875 this.assert(val === this.obj);
2876 });
2877
2878 Assertion.alias("equal", "equals");
2879 Assertion.alias("equal", "exactly");
2880 Assertion.alias("eql", "eqls");
2881 Assertion.alias("eql", "deepEqual");
2882
2883 function addOneOf(name, message, method) {
2884 Assertion.add(name, function(vals) {
2885 if (arguments.length !== 1) {
2886 vals = Array.prototype.slice.call(arguments);
2887 } else {
2888 should(vals).be.Array();
2889 }
2890
2891 this.params = { operator: message, expected: vals };
2892
2893 var obj = this.obj;
2894 var found = false;
2895
2896 forEach(vals, function(val) {
2897 try {
2898 should(val)[method](obj);
2899 found = true;
2900 return false;
2901 } catch (e) {
2902 if (e instanceof should.AssertionError) {
2903 return; //do nothing
2904 }
2905 throw e;
2906 }
2907 });
2908
2909 this.assert(found);
2910 });
2911 }
2912
2913 /**
2914 * Exact comparison using === to be one of supplied objects.
2915 *
2916 * @name equalOneOf
2917 * @memberOf Assertion
2918 * @category assertion equality
2919 * @param {Array|*} vals Expected values
2920 * @example
2921 *
2922 * 'ab'.should.be.equalOneOf('a', 10, 'ab');
2923 * 'ab'.should.be.equalOneOf(['a', 10, 'ab']);
2924 */
2925 addOneOf("equalOneOf", "to be equals one of", "equal");
2926
2927 /**
2928 * Exact comparison using .eql to be one of supplied objects.
2929 *
2930 * @name oneOf
2931 * @memberOf Assertion
2932 * @category assertion equality
2933 * @param {Array|*} vals Expected values
2934 * @example
2935 *
2936 * ({a: 10}).should.be.oneOf('a', 10, 'ab', {a: 10});
2937 * ({a: 10}).should.be.oneOf(['a', 10, 'ab', {a: 10}]);
2938 */
2939 addOneOf("oneOf", "to be one of", "eql");
2940}
2941
2942/*
2943 * should.js - assertion library
2944 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
2945 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
2946 * MIT Licensed
2947 */
2948
2949function promiseAssertions(should, Assertion$$1) {
2950 /**
2951 * Assert given object is a Promise
2952 *
2953 * @name Promise
2954 * @memberOf Assertion
2955 * @category assertion promises
2956 * @example
2957 *
2958 * promise.should.be.Promise()
2959 * (new Promise(function(resolve, reject) { resolve(10); })).should.be.a.Promise()
2960 * (10).should.not.be.a.Promise()
2961 */
2962 Assertion$$1.add("Promise", function() {
2963 this.assertZeroArguments(arguments);
2964 this.params = { operator: "to be promise" };
2965
2966 var obj = this.obj;
2967
2968 should(obj)
2969 .have.property("then")
2970 .which.is.a.Function();
2971 });
2972
2973 /**
2974 * Assert given promise will be fulfilled. Result of assertion is still .thenable and should be handled accordingly.
2975 *
2976 * @name fulfilled
2977 * @memberOf Assertion
2978 * @alias Assertion#resolved
2979 * @returns {Promise}
2980 * @category assertion promises
2981 * @example
2982 *
2983 * // don't forget to handle async nature
2984 * (new Promise(function(resolve, reject) { resolve(10); })).should.be.fulfilled();
2985 *
2986 * // test example with mocha it is possible to return promise
2987 * it('is async', () => {
2988 * return new Promise(resolve => resolve(10))
2989 * .should.be.fulfilled();
2990 * });
2991 */
2992 Assertion$$1.prototype.fulfilled = function Assertion$fulfilled() {
2993 this.assertZeroArguments(arguments);
2994 this.params = { operator: "to be fulfilled" };
2995
2996 should(this.obj).be.a.Promise();
2997
2998 var that = this;
2999 return this.obj.then(
3000 function next$onResolve(value) {
3001 if (that.negate) {
3002 that.fail();
3003 }
3004 return value;
3005 },
3006 function next$onReject(err) {
3007 if (!that.negate) {
3008 that.params.operator += ", but it was rejected with " + should.format(err);
3009 that.fail();
3010 }
3011 return err;
3012 }
3013 );
3014 };
3015
3016 Assertion$$1.prototype.resolved = Assertion$$1.prototype.fulfilled;
3017
3018 /**
3019 * Assert given promise will be rejected. Result of assertion is still .thenable and should be handled accordingly.
3020 *
3021 * @name rejected
3022 * @memberOf Assertion
3023 * @category assertion promises
3024 * @returns {Promise}
3025 * @example
3026 *
3027 * // don't forget to handle async nature
3028 * (new Promise(function(resolve, reject) { resolve(10); }))
3029 * .should.not.be.rejected();
3030 *
3031 * // test example with mocha it is possible to return promise
3032 * it('is async', () => {
3033 * return new Promise((resolve, reject) => reject(new Error('boom')))
3034 * .should.be.rejected();
3035 * });
3036 */
3037 Assertion$$1.prototype.rejected = function() {
3038 this.assertZeroArguments(arguments);
3039 this.params = { operator: "to be rejected" };
3040
3041 should(this.obj).be.a.Promise();
3042
3043 var that = this;
3044 return this.obj.then(
3045 function(value) {
3046 if (!that.negate) {
3047 that.params.operator += ", but it was fulfilled";
3048 if (arguments.length != 0) {
3049 that.params.operator += " with " + should.format(value);
3050 }
3051 that.fail();
3052 }
3053 return value;
3054 },
3055 function next$onError(err) {
3056 if (that.negate) {
3057 that.fail();
3058 }
3059 return err;
3060 }
3061 );
3062 };
3063
3064 /**
3065 * Assert given promise will be fulfilled with some expected value (value compared using .eql).
3066 * Result of assertion is still .thenable and should be handled accordingly.
3067 *
3068 * @name fulfilledWith
3069 * @memberOf Assertion
3070 * @alias Assertion#resolvedWith
3071 * @category assertion promises
3072 * @returns {Promise}
3073 * @example
3074 *
3075 * // don't forget to handle async nature
3076 * (new Promise(function(resolve, reject) { resolve(10); }))
3077 * .should.be.fulfilledWith(10);
3078 *
3079 * // test example with mocha it is possible to return promise
3080 * it('is async', () => {
3081 * return new Promise((resolve, reject) => resolve(10))
3082 * .should.be.fulfilledWith(10);
3083 * });
3084 */
3085 Assertion$$1.prototype.fulfilledWith = function(expectedValue) {
3086 this.params = {
3087 operator: "to be fulfilled with " + should.format(expectedValue)
3088 };
3089
3090 should(this.obj).be.a.Promise();
3091
3092 var that = this;
3093 return this.obj.then(
3094 function(value) {
3095 if (that.negate) {
3096 that.fail();
3097 }
3098 should(value).eql(expectedValue);
3099 return value;
3100 },
3101 function next$onError(err) {
3102 if (!that.negate) {
3103 that.params.operator += ", but it was rejected with " + should.format(err);
3104 that.fail();
3105 }
3106 return err;
3107 }
3108 );
3109 };
3110
3111 Assertion$$1.prototype.resolvedWith = Assertion$$1.prototype.fulfilledWith;
3112
3113 /**
3114 * Assert given promise will be rejected with some sort of error. Arguments is the same for Assertion#throw.
3115 * Result of assertion is still .thenable and should be handled accordingly.
3116 *
3117 * @name rejectedWith
3118 * @memberOf Assertion
3119 * @category assertion promises
3120 * @returns {Promise}
3121 * @example
3122 *
3123 * function failedPromise() {
3124 * return new Promise(function(resolve, reject) {
3125 * reject(new Error('boom'))
3126 * })
3127 * }
3128 * failedPromise().should.be.rejectedWith(Error);
3129 * failedPromise().should.be.rejectedWith('boom');
3130 * failedPromise().should.be.rejectedWith(/boom/);
3131 * failedPromise().should.be.rejectedWith(Error, { message: 'boom' });
3132 * failedPromise().should.be.rejectedWith({ message: 'boom' });
3133 *
3134 * // test example with mocha it is possible to return promise
3135 * it('is async', () => {
3136 * return failedPromise().should.be.rejectedWith({ message: 'boom' });
3137 * });
3138 */
3139 Assertion$$1.prototype.rejectedWith = function(message, properties) {
3140 this.params = { operator: "to be rejected" };
3141
3142 should(this.obj).be.a.Promise();
3143
3144 var that = this;
3145 return this.obj.then(
3146 function(value) {
3147 if (!that.negate) {
3148 that.fail();
3149 }
3150 return value;
3151 },
3152 function next$onError(err) {
3153 if (that.negate) {
3154 that.fail();
3155 }
3156
3157 var errorMatched = true;
3158 var errorInfo = "";
3159
3160 if ("string" === typeof message) {
3161 errorMatched = message === err.message;
3162 } else if (message instanceof RegExp) {
3163 errorMatched = message.test(err.message);
3164 } else if ("function" === typeof message) {
3165 errorMatched = err instanceof message;
3166 } else if (message !== null && typeof message === "object") {
3167 try {
3168 should(err).match(message);
3169 } catch (e) {
3170 if (e instanceof should.AssertionError) {
3171 errorInfo = ": " + e.message;
3172 errorMatched = false;
3173 } else {
3174 throw e;
3175 }
3176 }
3177 }
3178
3179 if (!errorMatched) {
3180 if (typeof message === "string" || message instanceof RegExp) {
3181 errorInfo = " with a message matching " + should.format(message) + ", but got '" + err.message + "'";
3182 } else if ("function" === typeof message) {
3183 errorInfo = " of type " + functionName$1(message) + ", but got " + functionName$1(err.constructor);
3184 }
3185 } else if ("function" === typeof message && properties) {
3186 try {
3187 should(err).match(properties);
3188 } catch (e) {
3189 if (e instanceof should.AssertionError) {
3190 errorInfo = ": " + e.message;
3191 errorMatched = false;
3192 } else {
3193 throw e;
3194 }
3195 }
3196 }
3197
3198 that.params.operator += errorInfo;
3199
3200 that.assert(errorMatched);
3201
3202 return err;
3203 }
3204 );
3205 };
3206
3207 /**
3208 * Assert given object is promise and wrap it in PromisedAssertion, which has all properties of Assertion.
3209 * That means you can chain as with usual Assertion.
3210 * Result of assertion is still .thenable and should be handled accordingly.
3211 *
3212 * @name finally
3213 * @memberOf Assertion
3214 * @alias Assertion#eventually
3215 * @category assertion promises
3216 * @returns {PromisedAssertion} Like Assertion, but .then this.obj in Assertion
3217 * @example
3218 *
3219 * (new Promise(function(resolve, reject) { resolve(10); }))
3220 * .should.be.eventually.equal(10);
3221 *
3222 * // test example with mocha it is possible to return promise
3223 * it('is async', () => {
3224 * return new Promise(resolve => resolve(10))
3225 * .should.be.finally.equal(10);
3226 * });
3227 */
3228 Object.defineProperty(Assertion$$1.prototype, "finally", {
3229 get: function() {
3230 should(this.obj).be.a.Promise();
3231
3232 var that = this;
3233
3234 return new PromisedAssertion(
3235 this.obj.then(function(obj) {
3236 var a = should(obj);
3237
3238 a.negate = that.negate;
3239 a.anyOne = that.anyOne;
3240
3241 return a;
3242 })
3243 );
3244 }
3245 });
3246
3247 Assertion$$1.alias("finally", "eventually");
3248}
3249
3250/*
3251 * should.js - assertion library
3252 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
3253 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
3254 * MIT Licensed
3255 */
3256
3257function stringAssertions(should, Assertion) {
3258 /**
3259 * Assert given string starts with prefix
3260 * @name startWith
3261 * @memberOf Assertion
3262 * @category assertion strings
3263 * @param {string} str Prefix
3264 * @param {string} [description] Optional message
3265 * @example
3266 *
3267 * 'abc'.should.startWith('a');
3268 */
3269 Assertion.add("startWith", function(str, description) {
3270 this.params = {
3271 operator: "to start with " + should.format(str),
3272 message: description
3273 };
3274
3275 this.assert(0 === this.obj.indexOf(str));
3276 });
3277
3278 /**
3279 * Assert given string ends with prefix
3280 * @name endWith
3281 * @memberOf Assertion
3282 * @category assertion strings
3283 * @param {string} str Prefix
3284 * @param {string} [description] Optional message
3285 * @example
3286 *
3287 * 'abca'.should.endWith('a');
3288 */
3289 Assertion.add("endWith", function(str, description) {
3290 this.params = {
3291 operator: "to end with " + should.format(str),
3292 message: description
3293 };
3294
3295 this.assert(this.obj.indexOf(str, this.obj.length - str.length) >= 0);
3296 });
3297}
3298
3299/*
3300 * should.js - assertion library
3301 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
3302 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
3303 * MIT Licensed
3304 */
3305
3306function containAssertions(should, Assertion) {
3307 var i = should.format;
3308
3309 /**
3310 * Assert that given object contain something that equal to `other`. It uses `should-equal` for equality checks.
3311 * If given object is array it search that one of elements was equal to `other`.
3312 * If given object is string it checks if `other` is a substring - expected that `other` is a string.
3313 * If given object is Object it checks that `other` is a subobject - expected that `other` is a object.
3314 *
3315 * @name containEql
3316 * @memberOf Assertion
3317 * @category assertion contain
3318 * @param {*} other Nested object
3319 * @example
3320 *
3321 * [1, 2, 3].should.containEql(1);
3322 * [{ a: 1 }, 'a', 10].should.containEql({ a: 1 });
3323 *
3324 * 'abc'.should.containEql('b');
3325 * 'ab1c'.should.containEql(1);
3326 *
3327 * ({ a: 10, c: { d: 10 }}).should.containEql({ a: 10 });
3328 * ({ a: 10, c: { d: 10 }}).should.containEql({ c: { d: 10 }});
3329 * ({ a: 10, c: { d: 10 }}).should.containEql({ b: 10 });
3330 * // throws AssertionError: expected { a: 10, c: { d: 10 } } to contain { b: 10 }
3331 * // expected { a: 10, c: { d: 10 } } to have property b
3332 */
3333 Assertion.add("containEql", function(other) {
3334 this.params = { operator: "to contain " + i(other) };
3335
3336 this.is.not.null().and.not.undefined();
3337
3338 var obj = this.obj;
3339
3340 if (typeof obj == "string") {
3341 this.assert(obj.indexOf(String(other)) >= 0);
3342 } else if (isIterable(obj)) {
3343 this.assert(
3344 some(obj, function(v) {
3345 return eq(v, other).length === 0;
3346 })
3347 );
3348 } else {
3349 forEach(
3350 other,
3351 function(value, key) {
3352 should(obj).have.value(key, value);
3353 },
3354 this
3355 );
3356 }
3357 });
3358
3359 /**
3360 * Assert that given object is contain equally structured object on the same depth level.
3361 * If given object is an array and `other` is an array it checks that the eql elements is going in the same sequence in given array (recursive)
3362 * If given object is an object it checks that the same keys contain deep equal values (recursive)
3363 * On other cases it try to check with `.eql`
3364 *
3365 * @name containDeepOrdered
3366 * @memberOf Assertion
3367 * @category assertion contain
3368 * @param {*} other Nested object
3369 * @example
3370 *
3371 * [ 1, 2, 3].should.containDeepOrdered([1, 2]);
3372 * [ 1, 2, [ 1, 2, 3 ]].should.containDeepOrdered([ 1, [ 2, 3 ]]);
3373 *
3374 * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({a: 10});
3375 * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {c: 10}});
3376 * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {d: [1, 3]}});
3377 */
3378 Assertion.add("containDeepOrdered", function(other) {
3379 this.params = { operator: "to contain " + i(other) };
3380
3381 var obj = this.obj;
3382 if (typeof obj == "string") {
3383 // expect other to be string
3384 this.is.equal(String(other));
3385 } else if (isIterable(obj) && isIterable(other)) {
3386 var objIterator = iterator(obj);
3387 var otherIterator = iterator(other);
3388
3389 var nextObj = objIterator.next();
3390 var nextOther = otherIterator.next();
3391 while (!nextObj.done && !nextOther.done) {
3392 try {
3393 should(nextObj.value[1]).containDeepOrdered(nextOther.value[1]);
3394 nextOther = otherIterator.next();
3395 } catch (e) {
3396 if (!(e instanceof should.AssertionError)) {
3397 throw e;
3398 }
3399 }
3400 nextObj = objIterator.next();
3401 }
3402
3403 this.assert(nextOther.done);
3404 } else if (obj != null && typeof obj == "object" && other != null && typeof other == "object") {
3405 //TODO compare types object contains object case
3406 forEach(other, function(value, key) {
3407 should(obj[key]).containDeepOrdered(value);
3408 });
3409
3410 // if both objects is empty means we finish traversing - and we need to compare for hidden values
3411 if (isEmpty(other)) {
3412 this.eql(other);
3413 }
3414 } else {
3415 this.eql(other);
3416 }
3417 });
3418
3419 /**
3420 * The same like `Assertion#containDeepOrdered` but all checks on arrays without order.
3421 *
3422 * @name containDeep
3423 * @memberOf Assertion
3424 * @category assertion contain
3425 * @param {*} other Nested object
3426 * @example
3427 *
3428 * [ 1, 2, 3].should.containDeep([2, 1]);
3429 * [ 1, 2, [ 1, 2, 3 ]].should.containDeep([ 1, [ 3, 1 ]]);
3430 */
3431 Assertion.add("containDeep", function(other) {
3432 this.params = { operator: "to contain " + i(other) };
3433
3434 var obj = this.obj;
3435 if (typeof obj === "string" && typeof other === "string") {
3436 // expect other to be string
3437 this.is.equal(String(other));
3438 } else if (isIterable(obj) && isIterable(other)) {
3439 var usedKeys = {};
3440 forEach(
3441 other,
3442 function(otherItem) {
3443 this.assert(
3444 some(obj, function(item, index) {
3445 if (index in usedKeys) {
3446 return false;
3447 }
3448
3449 try {
3450 should(item).containDeep(otherItem);
3451 usedKeys[index] = true;
3452 return true;
3453 } catch (e) {
3454 if (e instanceof should.AssertionError) {
3455 return false;
3456 }
3457 throw e;
3458 }
3459 })
3460 );
3461 },
3462 this
3463 );
3464 } else if (obj != null && other != null && typeof obj == "object" && typeof other == "object") {
3465 // object contains object case
3466 forEach(other, function(value, key) {
3467 should(obj[key]).containDeep(value);
3468 });
3469
3470 // if both objects is empty means we finish traversing - and we need to compare for hidden values
3471 if (isEmpty(other)) {
3472 this.eql(other);
3473 }
3474 } else {
3475 this.eql(other);
3476 }
3477 });
3478}
3479
3480/*
3481 * should.js - assertion library
3482 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
3483 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
3484 * MIT Licensed
3485 */
3486
3487var aSlice = Array.prototype.slice;
3488
3489function propertyAssertions(should, Assertion) {
3490 var i = should.format;
3491 /**
3492 * Asserts given object has some descriptor. **On success it change given object to be value of property**.
3493 *
3494 * @name propertyWithDescriptor
3495 * @memberOf Assertion
3496 * @category assertion property
3497 * @param {string} name Name of property
3498 * @param {Object} desc Descriptor like used in Object.defineProperty (not required to add all properties)
3499 * @example
3500 *
3501 * ({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true });
3502 */
3503 Assertion.add("propertyWithDescriptor", function(name, desc) {
3504 this.params = {
3505 actual: this.obj,
3506 operator: "to have own property with descriptor " + i(desc)
3507 };
3508 var obj = this.obj;
3509 this.have.ownProperty(name);
3510 should(Object.getOwnPropertyDescriptor(Object(obj), name)).have.properties(desc);
3511 });
3512
3513 /**
3514 * Asserts given object has property with optionally value. **On success it change given object to be value of property**.
3515 *
3516 * @name property
3517 * @memberOf Assertion
3518 * @category assertion property
3519 * @param {string} name Name of property
3520 * @param {*} [val] Optional property value to check
3521 * @example
3522 *
3523 * ({ a: 10 }).should.have.property('a');
3524 */
3525 Assertion.add("property", function(name, val) {
3526 name = convertPropertyName(name);
3527 if (arguments.length > 1) {
3528 var p = {};
3529 p[name] = val;
3530 this.have.properties(p);
3531 } else {
3532 this.have.properties(name);
3533 }
3534 this.obj = this.obj[name];
3535 });
3536
3537 /**
3538 * Asserts given object has properties. On this method affect .any modifier, which allow to check not all properties.
3539 *
3540 * @name properties
3541 * @memberOf Assertion
3542 * @category assertion property
3543 * @param {Array|...string|Object} names Names of property
3544 * @example
3545 *
3546 * ({ a: 10 }).should.have.properties('a');
3547 * ({ a: 10, b: 20 }).should.have.properties([ 'a' ]);
3548 * ({ a: 10, b: 20 }).should.have.properties({ b: 20 });
3549 */
3550 Assertion.add("properties", function(names) {
3551 var values = {};
3552 if (arguments.length > 1) {
3553 names = aSlice.call(arguments);
3554 } else if (!Array.isArray(names)) {
3555 if (typeof names == "string" || typeof names == "symbol") {
3556 names = [names];
3557 } else {
3558 values = names;
3559 names = Object.keys(names);
3560 }
3561 }
3562
3563 var obj = Object(this.obj),
3564 missingProperties = [];
3565
3566 //just enumerate properties and check if they all present
3567 names.forEach(function(name) {
3568 if (!(name in obj)) {
3569 missingProperties.push(formatProp(name));
3570 }
3571 });
3572
3573 var props = missingProperties;
3574 if (props.length === 0) {
3575 props = names.map(formatProp);
3576 } else if (this.anyOne) {
3577 props = names
3578 .filter(function(name) {
3579 return missingProperties.indexOf(formatProp(name)) < 0;
3580 })
3581 .map(formatProp);
3582 }
3583
3584 var operator =
3585 (props.length === 1
3586 ? "to have property "
3587 : "to have " + (this.anyOne ? "any of " : "") + "properties ") + props.join(", ");
3588
3589 this.params = { obj: this.obj, operator: operator };
3590
3591 //check that all properties presented
3592 //or if we request one of them that at least one them presented
3593 this.assert(
3594 missingProperties.length === 0 || (this.anyOne && missingProperties.length != names.length)
3595 );
3596
3597 // check if values in object matched expected
3598 var valueCheckNames = Object.keys(values);
3599 if (valueCheckNames.length) {
3600 var wrongValues = [];
3601 props = [];
3602
3603 // now check values, as there we have all properties
3604 valueCheckNames.forEach(function(name) {
3605 var value = values[name];
3606 if (eq(obj[name], value).length !== 0) {
3607 wrongValues.push(formatProp(name) + " of " + i(value) + " (got " + i(obj[name]) + ")");
3608 } else {
3609 props.push(formatProp(name) + " of " + i(value));
3610 }
3611 });
3612
3613 if ((wrongValues.length !== 0 && !this.anyOne) || (this.anyOne && props.length === 0)) {
3614 props = wrongValues;
3615 }
3616
3617 operator =
3618 (props.length === 1
3619 ? "to have property "
3620 : "to have " + (this.anyOne ? "any of " : "") + "properties ") + props.join(", ");
3621
3622 this.params = { obj: this.obj, operator: operator };
3623
3624 //if there is no not matched values
3625 //or there is at least one matched
3626 this.assert(
3627 wrongValues.length === 0 || (this.anyOne && wrongValues.length != valueCheckNames.length)
3628 );
3629 }
3630 });
3631
3632 /**
3633 * Asserts given object has property `length` with given value `n`
3634 *
3635 * @name length
3636 * @alias Assertion#lengthOf
3637 * @memberOf Assertion
3638 * @category assertion property
3639 * @param {number} n Expected length
3640 * @param {string} [description] Optional message
3641 * @example
3642 *
3643 * [1, 2].should.have.length(2);
3644 */
3645 Assertion.add("length", function(n, description) {
3646 this.have.property("length", n, description);
3647 });
3648
3649 Assertion.alias("length", "lengthOf");
3650
3651 /**
3652 * Asserts given object has own property. **On success it change given object to be value of property**.
3653 *
3654 * @name ownProperty
3655 * @alias Assertion#hasOwnProperty
3656 * @memberOf Assertion
3657 * @category assertion property
3658 * @param {string} name Name of property
3659 * @param {string} [description] Optional message
3660 * @example
3661 *
3662 * ({ a: 10 }).should.have.ownProperty('a');
3663 */
3664 Assertion.add("ownProperty", function(name, description) {
3665 name = convertPropertyName(name);
3666 this.params = {
3667 actual: this.obj,
3668 operator: "to have own property " + formatProp(name),
3669 message: description
3670 };
3671
3672 this.assert(hasOwnProperty$1(this.obj, name));
3673
3674 this.obj = this.obj[name];
3675 });
3676
3677 Assertion.alias("ownProperty", "hasOwnProperty");
3678
3679 /**
3680 * Asserts given object is empty. For strings, arrays and arguments it checks .length property, for objects it checks keys.
3681 *
3682 * @name empty
3683 * @memberOf Assertion
3684 * @category assertion property
3685 * @example
3686 *
3687 * ''.should.be.empty();
3688 * [].should.be.empty();
3689 * ({}).should.be.empty();
3690 */
3691 Assertion.add(
3692 "empty",
3693 function() {
3694 this.params = { operator: "to be empty" };
3695 this.assert(isEmpty(this.obj));
3696 },
3697 true
3698 );
3699
3700 /**
3701 * Asserts given object has such keys. Compared to `properties`, `keys` does not accept Object as a argument.
3702 * When calling via .key current object in assertion changed to value of this key
3703 *
3704 * @name keys
3705 * @alias Assertion#key
3706 * @memberOf Assertion
3707 * @category assertion property
3708 * @param {...*} keys Keys to check
3709 * @example
3710 *
3711 * ({ a: 10 }).should.have.keys('a');
3712 * ({ a: 10, b: 20 }).should.have.keys('a', 'b');
3713 * (new Map([[1, 2]])).should.have.key(1);
3714 *
3715 * json.should.have.only.keys('type', 'version')
3716 */
3717 Assertion.add("keys", function(keys) {
3718 keys = aSlice.call(arguments);
3719
3720 var obj = Object(this.obj);
3721
3722 // first check if some keys are missing
3723 var missingKeys = keys.filter(function(key) {
3724 return !has(obj, key);
3725 });
3726
3727 var verb = "to have " + (this.onlyThis ? "only " : "") + (keys.length === 1 ? "key " : "keys ");
3728
3729 this.params = { operator: verb + keys.join(", ") };
3730
3731 if (missingKeys.length > 0) {
3732 this.params.operator += "\n\tmissing keys: " + missingKeys.join(", ");
3733 }
3734
3735 this.assert(missingKeys.length === 0);
3736
3737 if (this.onlyThis) {
3738 should(obj).have.size(keys.length);
3739 }
3740 });
3741
3742 Assertion.add("key", function(key) {
3743 this.have.keys(key);
3744 this.obj = get(this.obj, key);
3745 });
3746
3747 /**
3748 * Asserts given object has such value for given key
3749 *
3750 * @name value
3751 * @memberOf Assertion
3752 * @category assertion property
3753 * @param {*} key Key to check
3754 * @param {*} value Value to check
3755 * @example
3756 *
3757 * ({ a: 10 }).should.have.value('a', 10);
3758 * (new Map([[1, 2]])).should.have.value(1, 2);
3759 */
3760 Assertion.add("value", function(key, value) {
3761 this.have.key(key).which.is.eql(value);
3762 });
3763
3764 /**
3765 * Asserts given object has such size.
3766 *
3767 * @name size
3768 * @memberOf Assertion
3769 * @category assertion property
3770 * @param {number} s Size to check
3771 * @example
3772 *
3773 * ({ a: 10 }).should.have.size(1);
3774 * (new Map([[1, 2]])).should.have.size(1);
3775 */
3776 Assertion.add("size", function(s) {
3777 this.params = { operator: "to have size " + s };
3778 should(size(this.obj)).be.exactly(s);
3779 });
3780
3781 /**
3782 * Asserts given object has nested property in depth by path. **On success it change given object to be value of final property**.
3783 *
3784 * @name propertyByPath
3785 * @memberOf Assertion
3786 * @category assertion property
3787 * @param {Array|...string} properties Properties path to search
3788 * @example
3789 *
3790 * ({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10);
3791 */
3792 Assertion.add("propertyByPath", function(properties) {
3793 properties = aSlice.call(arguments);
3794
3795 var allProps = properties.map(formatProp);
3796
3797 properties = properties.map(convertPropertyName);
3798
3799 var obj = should(Object(this.obj));
3800
3801 var foundProperties = [];
3802
3803 var currentProperty;
3804 while (properties.length) {
3805 currentProperty = properties.shift();
3806 this.params = {
3807 operator:
3808 "to have property by path " +
3809 allProps.join(", ") +
3810 " - failed on " +
3811 formatProp(currentProperty)
3812 };
3813 obj = obj.have.property(currentProperty);
3814 foundProperties.push(currentProperty);
3815 }
3816
3817 this.params = {
3818 obj: this.obj,
3819 operator: "to have property by path " + allProps.join(", ")
3820 };
3821
3822 this.obj = obj.obj;
3823 });
3824}
3825
3826/*
3827 * should.js - assertion library
3828 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
3829 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
3830 * MIT Licensed
3831 */
3832function errorAssertions(should, Assertion) {
3833 var i = should.format;
3834
3835 /**
3836 * Assert given function throws error with such message.
3837 *
3838 * @name throw
3839 * @memberOf Assertion
3840 * @category assertion errors
3841 * @alias Assertion#throwError
3842 * @param {string|RegExp|Function|Object|GeneratorFunction|GeneratorObject} [message] Message to match or properties
3843 * @param {Object} [properties] Optional properties that will be matched to thrown error
3844 * @example
3845 *
3846 * (function(){ throw new Error('fail') }).should.throw();
3847 * (function(){ throw new Error('fail') }).should.throw('fail');
3848 * (function(){ throw new Error('fail') }).should.throw(/fail/);
3849 *
3850 * (function(){ throw new Error('fail') }).should.throw(Error);
3851 * var error = new Error();
3852 * error.a = 10;
3853 * (function(){ throw error; }).should.throw(Error, { a: 10 });
3854 * (function(){ throw error; }).should.throw({ a: 10 });
3855 * (function*() {
3856 * yield throwError();
3857 * }).should.throw();
3858 */
3859 Assertion.add("throw", function(message, properties) {
3860 var fn = this.obj;
3861 var err = {};
3862 var errorInfo = "";
3863 var thrown = false;
3864
3865 if (isGeneratorFunction(fn)) {
3866 return should(fn()).throw(message, properties);
3867 } else if (isIterator(fn)) {
3868 return should(fn.next.bind(fn)).throw(message, properties);
3869 }
3870
3871 this.is.a.Function();
3872
3873 var errorMatched = true;
3874
3875 try {
3876 fn();
3877 } catch (e) {
3878 thrown = true;
3879 err = e;
3880 }
3881
3882 if (thrown) {
3883 if (message) {
3884 if ("string" == typeof message) {
3885 errorMatched = message == err.message;
3886 } else if (message instanceof RegExp) {
3887 errorMatched = message.test(err.message);
3888 } else if ("function" == typeof message) {
3889 errorMatched = err instanceof message;
3890 } else if (null != message) {
3891 try {
3892 should(err).match(message);
3893 } catch (e) {
3894 if (e instanceof should.AssertionError) {
3895 errorInfo = ": " + e.message;
3896 errorMatched = false;
3897 } else {
3898 throw e;
3899 }
3900 }
3901 }
3902
3903 if (!errorMatched) {
3904 if ("string" == typeof message || message instanceof RegExp) {
3905 errorInfo =
3906 " with a message matching " +
3907 i(message) +
3908 ", but got '" +
3909 err.message +
3910 "'";
3911 } else if ("function" == typeof message) {
3912 errorInfo =
3913 " of type " +
3914 functionName$1(message) +
3915 ", but got " +
3916 functionName$1(err.constructor);
3917 }
3918 } else if ("function" == typeof message && properties) {
3919 try {
3920 should(err).match(properties);
3921 } catch (e) {
3922 if (e instanceof should.AssertionError) {
3923 errorInfo = ": " + e.message;
3924 errorMatched = false;
3925 } else {
3926 throw e;
3927 }
3928 }
3929 }
3930 } else {
3931 errorInfo = " (got " + i(err) + ")";
3932 }
3933 }
3934
3935 this.params = { operator: "to throw exception" + errorInfo };
3936
3937 this.assert(thrown);
3938 this.assert(errorMatched);
3939 });
3940
3941 Assertion.alias("throw", "throwError");
3942}
3943
3944/*
3945 * should.js - assertion library
3946 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
3947 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
3948 * MIT Licensed
3949 */
3950
3951function matchingAssertions(should, Assertion) {
3952 var i = should.format;
3953
3954 /**
3955 * Asserts if given object match `other` object, using some assumptions:
3956 * First object matched if they are equal,
3957 * If `other` is a regexp and given object is a string check on matching with regexp
3958 * If `other` is a regexp and given object is an array check if all elements matched regexp
3959 * If `other` is a regexp and given object is an object check values on matching regexp
3960 * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
3961 * If `other` is an object check if the same keys matched with above rules
3962 * All other cases failed.
3963 *
3964 * Usually it is right idea to add pre type assertions, like `.String()` or `.Object()` to be sure assertions will do what you are expecting.
3965 * Object iteration happen by keys (properties with enumerable: true), thus some objects can cause small pain. Typical example is js
3966 * Error - it by default has 2 properties `name` and `message`, but they both non-enumerable. In this case make sure you specify checking props (see examples).
3967 *
3968 * @name match
3969 * @memberOf Assertion
3970 * @category assertion matching
3971 * @param {*} other Object to match
3972 * @param {string} [description] Optional message
3973 * @example
3974 * 'foobar'.should.match(/^foo/);
3975 * 'foobar'.should.not.match(/^bar/);
3976 *
3977 * ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
3978 *
3979 * ['a', 'b', 'c'].should.match(/[a-z]/);
3980 *
3981 * (5).should.not.match(function(n) {
3982 * return n < 0;
3983 * });
3984 * (5).should.not.match(function(it) {
3985 * it.should.be.an.Array();
3986 * });
3987 * ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
3988 * .match({ a: 10, b: /c$/, c: function(it) {
3989 * return it.should.have.property('d', 10);
3990 * }});
3991 *
3992 * [10, 'abc', { d: 10 }, 0].should
3993 * .match({ '0': 10, '1': /c$/, '2': function(it) {
3994 * return it.should.have.property('d', 10);
3995 * }});
3996 *
3997 * var myString = 'abc';
3998 *
3999 * myString.should.be.a.String().and.match(/abc/);
4000 *
4001 * myString = {};
4002 *
4003 * myString.should.match(/abc/); //yes this will pass
4004 * //better to do
4005 * myString.should.be.an.Object().and.not.empty().and.match(/abc/);//fixed
4006 *
4007 * (new Error('boom')).should.match(/abc/);//passed because no keys
4008 * (new Error('boom')).should.not.match({ message: /abc/ });//check specified property
4009 */
4010 Assertion.add("match", function(other, description) {
4011 this.params = { operator: "to match " + i(other), message: description };
4012
4013 if (eq(this.obj, other).length !== 0) {
4014 if (other instanceof RegExp) {
4015 // something - regex
4016
4017 if (typeof this.obj == "string") {
4018 this.assert(other.exec(this.obj));
4019 } else if (null != this.obj && typeof this.obj == "object") {
4020 var notMatchedProps = [],
4021 matchedProps = [];
4022 forEach(
4023 this.obj,
4024 function(value, name) {
4025 if (other.exec(value)) {
4026 matchedProps.push(formatProp(name));
4027 } else {
4028 notMatchedProps.push(formatProp(name) + " (" + i(value) + ")");
4029 }
4030 },
4031 this
4032 );
4033
4034 if (notMatchedProps.length) {
4035 this.params.operator += "\n not matched properties: " + notMatchedProps.join(", ");
4036 }
4037 if (matchedProps.length) {
4038 this.params.operator += "\n matched properties: " + matchedProps.join(", ");
4039 }
4040
4041 this.assert(notMatchedProps.length === 0);
4042 } else {
4043 // should we try to convert to String and exec?
4044 this.assert(false);
4045 }
4046 } else if (typeof other == "function") {
4047 var res;
4048
4049 res = other(this.obj);
4050
4051 //if we throw exception ok - it is used .should inside
4052 if (typeof res == "boolean") {
4053 this.assert(res); // if it is just boolean function assert on it
4054 }
4055 } else if (typeof this.obj == "object" && this.obj != null && (isPlainObject(other) || Array.isArray(other))) {
4056 // try to match properties (for Object and Array)
4057 notMatchedProps = [];
4058 matchedProps = [];
4059
4060 forEach(
4061 other,
4062 function(value, key) {
4063 try {
4064 should(this.obj)
4065 .have.property(key)
4066 .which.match(value);
4067 matchedProps.push(formatProp(key));
4068 } catch (e) {
4069 if (e instanceof should.AssertionError) {
4070 notMatchedProps.push(formatProp(key) + " (" + i(this.obj[key]) + ")");
4071 } else {
4072 throw e;
4073 }
4074 }
4075 },
4076 this
4077 );
4078
4079 if (notMatchedProps.length) {
4080 this.params.operator += "\n not matched properties: " + notMatchedProps.join(", ");
4081 }
4082 if (matchedProps.length) {
4083 this.params.operator += "\n matched properties: " + matchedProps.join(", ");
4084 }
4085
4086 this.assert(notMatchedProps.length === 0);
4087 } else {
4088 this.assert(false);
4089 }
4090 }
4091 });
4092
4093 /**
4094 * Asserts if given object values or array elements all match `other` object, using some assumptions:
4095 * First object matched if they are equal,
4096 * If `other` is a regexp - matching with regexp
4097 * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
4098 * All other cases check if this `other` equal to each element
4099 *
4100 * @name matchEach
4101 * @memberOf Assertion
4102 * @category assertion matching
4103 * @alias Assertion#matchEvery
4104 * @param {*} other Object to match
4105 * @param {string} [description] Optional message
4106 * @example
4107 * [ 'a', 'b', 'c'].should.matchEach(/\w+/);
4108 * [ 'a', 'a', 'a'].should.matchEach('a');
4109 *
4110 * [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });
4111 *
4112 * { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });
4113 */
4114 Assertion.add("matchEach", function(other, description) {
4115 this.params = {
4116 operator: "to match each " + i(other),
4117 message: description
4118 };
4119
4120 forEach(
4121 this.obj,
4122 function(value) {
4123 should(value).match(other);
4124 },
4125 this
4126 );
4127 });
4128
4129 /**
4130 * Asserts if any of given object values or array elements match `other` object, using some assumptions:
4131 * First object matched if they are equal,
4132 * If `other` is a regexp - matching with regexp
4133 * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched
4134 * All other cases check if this `other` equal to each element
4135 *
4136 * @name matchAny
4137 * @memberOf Assertion
4138 * @category assertion matching
4139 * @param {*} other Object to match
4140 * @alias Assertion#matchSome
4141 * @param {string} [description] Optional message
4142 * @example
4143 * [ 'a', 'b', 'c'].should.matchAny(/\w+/);
4144 * [ 'a', 'b', 'c'].should.matchAny('a');
4145 *
4146 * [ 'a', 'b', 'c'].should.matchAny(function(value) { value.should.be.eql('a') });
4147 *
4148 * { a: 'a', b: 'b', c: 'c' }.should.matchAny(function(value) { value.should.be.eql('a') });
4149 */
4150 Assertion.add("matchAny", function(other, description) {
4151 this.params = {
4152 operator: "to match any " + i(other),
4153 message: description
4154 };
4155
4156 this.assert(
4157 some(this.obj, function(value) {
4158 try {
4159 should(value).match(other);
4160 return true;
4161 } catch (e) {
4162 if (e instanceof should.AssertionError) {
4163 // Caught an AssertionError, return false to the iterator
4164 return false;
4165 }
4166 throw e;
4167 }
4168 })
4169 );
4170 });
4171
4172 Assertion.alias("matchAny", "matchSome");
4173 Assertion.alias("matchEach", "matchEvery");
4174}
4175
4176/*
4177 * should.js - assertion library
4178 * Copyright(c) 2010-2013 TJ Holowaychuk <tj@vision-media.ca>
4179 * Copyright(c) 2013-2017 Denis Bardadym <bardadymchik@gmail.com>
4180 * MIT Licensed
4181 */
4182/**
4183 * Our function should
4184 *
4185 * @param {*} obj Object to assert
4186 * @returns {should.Assertion} Returns new Assertion for beginning assertion chain
4187 * @example
4188 *
4189 * var should = require('should');
4190 * should('abc').be.a.String();
4191 */
4192function should$1(obj) {
4193 return new Assertion(obj);
4194}
4195
4196should$1.AssertionError = AssertionError;
4197should$1.Assertion = Assertion;
4198
4199// exposing modules dirty way
4200should$1.modules = {
4201 format: defaultFormat,
4202 type: getGlobalType,
4203 equal: eq
4204};
4205should$1.format = format$2;
4206
4207/**
4208 * Object with configuration.
4209 * It contains such properties:
4210 * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes
4211 * * `plusZeroAndMinusZeroEqual` boolean - Affect if `.eql` will treat +0 and -0 as equal
4212 * Also it can contain options for should-format.
4213 *
4214 * @type {Object}
4215 * @memberOf should
4216 * @static
4217 * @example
4218 *
4219 * var a = { a: 10 }, b = Object.create(null);
4220 * b.a = 10;
4221 *
4222 * a.should.be.eql(b);
4223 * //not throws
4224 *
4225 * should.config.checkProtoEql = true;
4226 * a.should.be.eql(b);
4227 * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes)
4228 */
4229should$1.config = config;
4230
4231/**
4232 * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`.
4233 * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc).
4234 *
4235 * To add new assertions, need to use Assertion.add method.
4236 *
4237 * @param {string} [propertyName] Name of property to add. Default is `'should'`.
4238 * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`.
4239 * @memberOf should
4240 * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back
4241 * @static
4242 * @example
4243 *
4244 * var prev = should.extend('must', Object.prototype);
4245 *
4246 * 'abc'.must.startWith('a');
4247 *
4248 * var should = should.noConflict(prev);
4249 * should.not.exist(Object.prototype.must);
4250 */
4251should$1.extend = function(propertyName, proto) {
4252 propertyName = propertyName || "should";
4253 proto = proto || Object.prototype;
4254
4255 var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName);
4256
4257 Object.defineProperty(proto, propertyName, {
4258 set: function() {},
4259 get: function() {
4260 return should$1(isWrapperType(this) ? this.valueOf() : this);
4261 },
4262 configurable: true
4263 });
4264
4265 return { name: propertyName, descriptor: prevDescriptor, proto: proto };
4266};
4267
4268/**
4269 * Delete previous extension. If `desc` missing it will remove default extension.
4270 *
4271 * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object
4272 * @memberOf should
4273 * @returns {Function} Returns should function
4274 * @static
4275 * @example
4276 *
4277 * var should = require('should').noConflict();
4278 *
4279 * should(Object.prototype).not.have.property('should');
4280 *
4281 * var prev = should.extend('must', Object.prototype);
4282 * 'abc'.must.startWith('a');
4283 * should.noConflict(prev);
4284 *
4285 * should(Object.prototype).not.have.property('must');
4286 */
4287should$1.noConflict = function(desc) {
4288 desc = desc || should$1._prevShould;
4289
4290 if (desc) {
4291 delete desc.proto[desc.name];
4292
4293 if (desc.descriptor) {
4294 Object.defineProperty(desc.proto, desc.name, desc.descriptor);
4295 }
4296 }
4297 return should$1;
4298};
4299
4300/**
4301 * Simple utility function for a bit more easier should assertion extension
4302 * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor
4303 * @memberOf should
4304 * @returns {Function} Returns `should` function
4305 * @static
4306 * @example
4307 *
4308 * should.use(function(should, Assertion) {
4309 * Assertion.add('asset', function() {
4310 * this.params = { operator: 'to be asset' };
4311 *
4312 * this.obj.should.have.property('id').which.is.a.Number();
4313 * this.obj.should.have.property('path');
4314 * })
4315 * })
4316 */
4317should$1.use = function(f) {
4318 f(should$1, should$1.Assertion);
4319 return this;
4320};
4321
4322should$1
4323 .use(assertExtensions)
4324 .use(chainAssertions)
4325 .use(booleanAssertions)
4326 .use(numberAssertions)
4327 .use(equalityAssertions)
4328 .use(typeAssertions)
4329 .use(stringAssertions)
4330 .use(propertyAssertions)
4331 .use(errorAssertions)
4332 .use(matchingAssertions)
4333 .use(containAssertions)
4334 .use(promiseAssertions);
4335
4336var defaultProto = Object.prototype;
4337var defaultProperty = "should";
4338
4339var freeGlobal =
4340 typeof global == "object" && global && global.Object === Object && global;
4341
4342/** Detect free variable `self`. */
4343var freeSelf =
4344 typeof self == "object" && self && self.Object === Object && self;
4345
4346/** Used as a reference to the global object. */
4347var root = freeGlobal || freeSelf || Function("return this")();
4348
4349//Expose api via `Object#should`.
4350try {
4351 var prevShould = should$1.extend(defaultProperty, defaultProto);
4352 should$1._prevShould = prevShould;
4353
4354 Object.defineProperty(root, "should", {
4355 enumerable: false,
4356 configurable: true,
4357 value: should$1
4358 });
4359} catch (e) {
4360 //ignore errors
4361}
4362
4363if (typeof define === "function" && define.amd) {
4364 define([], function() {
4365 return should$1;
4366 });
4367} else if (typeof module === "object" && module.exports) {
4368 module.exports = should$1;
4369}
4370
4371}());