UNPKG

15.4 kBJavaScriptView Raw
1
2function compare(a, b) {
3 if (a === b) {
4 return 0;
5 }
6
7 var x = a.length;
8 var y = b.length;
9
10 for (var i = 0, len = Math.min(x, y); i < len; ++i) {
11 if (a[i] !== b[i]) {
12 x = a[i];
13 y = b[i];
14 break;
15 }
16 }
17
18 if (x < y) {
19 return -1;
20 }
21 if (y < x) {
22 return 1;
23 }
24 return 0;
25}
26var hasOwn = Object.prototype.hasOwnProperty;
27
28var objectKeys = Object.keys || function (obj) {
29 var keys = [];
30 for (var key in obj) {
31 if (hasOwn.call(obj, key)) keys.push(key);
32 }
33 return keys;
34};
35// based on node assert, original notice:
36
37// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
38//
39// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
40//
41// Originally from narwhal.js (http://narwhaljs.org)
42// Copyright (c) 2009 Thomas Robinson <280north.com>
43//
44// Permission is hereby granted, free of charge, to any person obtaining a copy
45// of this software and associated documentation files (the 'Software'), to
46// deal in the Software without restriction, including without limitation the
47// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
48// sell copies of the Software, and to permit persons to whom the Software is
49// furnished to do so, subject to the following conditions:
50//
51// The above copyright notice and this permission notice shall be included in
52// all copies or substantial portions of the Software.
53//
54// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
58// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
59// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
60import {isBuffer} from 'buffer';
61import {isPrimitive, inherits, isError, isFunction, isRegExp, isDate, inspect as utilInspect} from 'util';
62var pSlice = Array.prototype.slice;
63var _functionsHaveNames;
64function functionsHaveNames() {
65 if (typeof _functionsHaveNames !== 'undefined') {
66 return _functionsHaveNames;
67 }
68 return _functionsHaveNames = (function () {
69 return function foo() {}.name === 'foo';
70 }());
71}
72function pToString (obj) {
73 return Object.prototype.toString.call(obj);
74}
75function isView(arrbuf) {
76 if (isBuffer(arrbuf)) {
77 return false;
78 }
79 if (typeof global.ArrayBuffer !== 'function') {
80 return false;
81 }
82 if (typeof ArrayBuffer.isView === 'function') {
83 return ArrayBuffer.isView(arrbuf);
84 }
85 if (!arrbuf) {
86 return false;
87 }
88 if (arrbuf instanceof DataView) {
89 return true;
90 }
91 if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
92 return true;
93 }
94 return false;
95}
96// 1. The assert module provides functions that throw
97// AssertionError's when particular conditions are not met. The
98// assert module must conform to the following interface.
99
100function assert(value, message) {
101 if (!value) fail(value, true, message, '==', ok);
102}
103export default assert;
104
105// 2. The AssertionError is defined in assert.
106// new assert.AssertionError({ message: message,
107// actual: actual,
108// expected: expected })
109
110var regex = /\s*function\s+([^\(\s]*)\s*/;
111// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
112function getName(func) {
113 if (!isFunction(func)) {
114 return;
115 }
116 if (functionsHaveNames()) {
117 return func.name;
118 }
119 var str = func.toString();
120 var match = str.match(regex);
121 return match && match[1];
122}
123assert.AssertionError = AssertionError;
124export function AssertionError(options) {
125 this.name = 'AssertionError';
126 this.actual = options.actual;
127 this.expected = options.expected;
128 this.operator = options.operator;
129 if (options.message) {
130 this.message = options.message;
131 this.generatedMessage = false;
132 } else {
133 this.message = getMessage(this);
134 this.generatedMessage = true;
135 }
136 var stackStartFunction = options.stackStartFunction || fail;
137 if (Error.captureStackTrace) {
138 Error.captureStackTrace(this, stackStartFunction);
139 } else {
140 // non v8 browsers so we can have a stacktrace
141 var err = new Error();
142 if (err.stack) {
143 var out = err.stack;
144
145 // try to strip useless frames
146 var fn_name = getName(stackStartFunction);
147 var idx = out.indexOf('\n' + fn_name);
148 if (idx >= 0) {
149 // once we have located the function frame
150 // we need to strip out everything before it (and its line)
151 var next_line = out.indexOf('\n', idx + 1);
152 out = out.substring(next_line + 1);
153 }
154
155 this.stack = out;
156 }
157 }
158}
159
160// assert.AssertionError instanceof Error
161inherits(AssertionError, Error);
162
163function truncate(s, n) {
164 if (typeof s === 'string') {
165 return s.length < n ? s : s.slice(0, n);
166 } else {
167 return s;
168 }
169}
170function inspect(something) {
171 if (functionsHaveNames() || !isFunction(something)) {
172 return utilInspect(something);
173 }
174 var rawname = getName(something);
175 var name = rawname ? ': ' + rawname : '';
176 return '[Function' + name + ']';
177}
178function getMessage(self) {
179 return truncate(inspect(self.actual), 128) + ' ' +
180 self.operator + ' ' +
181 truncate(inspect(self.expected), 128);
182}
183
184// At present only the three keys mentioned above are used and
185// understood by the spec. Implementations or sub modules can pass
186// other keys to the AssertionError's constructor - they will be
187// ignored.
188
189// 3. All of the following functions must throw an AssertionError
190// when a corresponding condition is not met, with a message that
191// may be undefined if not provided. All assertion methods provide
192// both the actual and expected values to the assertion error for
193// display purposes.
194
195export function fail(actual, expected, message, operator, stackStartFunction) {
196 throw new AssertionError({
197 message: message,
198 actual: actual,
199 expected: expected,
200 operator: operator,
201 stackStartFunction: stackStartFunction
202 });
203}
204
205// EXTENSION! allows for well behaved errors defined elsewhere.
206assert.fail = fail;
207
208// 4. Pure assertion tests whether a value is truthy, as determined
209// by !!guard.
210// assert.ok(guard, message_opt);
211// This statement is equivalent to assert.equal(true, !!guard,
212// message_opt);. To test strictly for the value true, use
213// assert.strictEqual(true, guard, message_opt);.
214
215export function ok(value, message) {
216 if (!value) fail(value, true, message, '==', ok);
217}
218assert.ok = ok;
219export {ok as assert};
220
221// 5. The equality assertion tests shallow, coercive equality with
222// ==.
223// assert.equal(actual, expected, message_opt);
224assert.equal = equal;
225export function equal(actual, expected, message) {
226 if (actual != expected) fail(actual, expected, message, '==', equal);
227}
228
229// 6. The non-equality assertion tests for whether two objects are not equal
230// with != assert.notEqual(actual, expected, message_opt);
231assert.notEqual = notEqual;
232export function notEqual(actual, expected, message) {
233 if (actual == expected) {
234 fail(actual, expected, message, '!=', notEqual);
235 }
236}
237
238// 7. The equivalence assertion tests a deep equality relation.
239// assert.deepEqual(actual, expected, message_opt);
240assert.deepEqual = deepEqual;
241export function deepEqual(actual, expected, message) {
242 if (!_deepEqual(actual, expected, false)) {
243 fail(actual, expected, message, 'deepEqual', deepEqual);
244 }
245}
246assert.deepStrictEqual = deepStrictEqual;
247export function deepStrictEqual(actual, expected, message) {
248 if (!_deepEqual(actual, expected, true)) {
249 fail(actual, expected, message, 'deepStrictEqual', deepStrictEqual);
250 }
251}
252
253function _deepEqual(actual, expected, strict, memos) {
254 // 7.1. All identical values are equivalent, as determined by ===.
255 if (actual === expected) {
256 return true;
257 } else if (isBuffer(actual) && isBuffer(expected)) {
258 return compare(actual, expected) === 0;
259
260 // 7.2. If the expected value is a Date object, the actual value is
261 // equivalent if it is also a Date object that refers to the same time.
262 } else if (isDate(actual) && isDate(expected)) {
263 return actual.getTime() === expected.getTime();
264
265 // 7.3 If the expected value is a RegExp object, the actual value is
266 // equivalent if it is also a RegExp object with the same source and
267 // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
268 } else if (isRegExp(actual) && isRegExp(expected)) {
269 return actual.source === expected.source &&
270 actual.global === expected.global &&
271 actual.multiline === expected.multiline &&
272 actual.lastIndex === expected.lastIndex &&
273 actual.ignoreCase === expected.ignoreCase;
274
275 // 7.4. Other pairs that do not both pass typeof value == 'object',
276 // equivalence is determined by ==.
277 } else if ((actual === null || typeof actual !== 'object') &&
278 (expected === null || typeof expected !== 'object')) {
279 return strict ? actual === expected : actual == expected;
280
281 // If both values are instances of typed arrays, wrap their underlying
282 // ArrayBuffers in a Buffer each to increase performance
283 // This optimization requires the arrays to have the same type as checked by
284 // Object.prototype.toString (aka pToString). Never perform binary
285 // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
286 // bit patterns are not identical.
287 } else if (isView(actual) && isView(expected) &&
288 pToString(actual) === pToString(expected) &&
289 !(actual instanceof Float32Array ||
290 actual instanceof Float64Array)) {
291 return compare(new Uint8Array(actual.buffer),
292 new Uint8Array(expected.buffer)) === 0;
293
294 // 7.5 For all other Object pairs, including Array objects, equivalence is
295 // determined by having the same number of owned properties (as verified
296 // with Object.prototype.hasOwnProperty.call), the same set of keys
297 // (although not necessarily the same order), equivalent values for every
298 // corresponding key, and an identical 'prototype' property. Note: this
299 // accounts for both named and indexed properties on Arrays.
300 } else if (isBuffer(actual) !== isBuffer(expected)) {
301 return false;
302 } else {
303 memos = memos || {actual: [], expected: []};
304
305 var actualIndex = memos.actual.indexOf(actual);
306 if (actualIndex !== -1) {
307 if (actualIndex === memos.expected.indexOf(expected)) {
308 return true;
309 }
310 }
311
312 memos.actual.push(actual);
313 memos.expected.push(expected);
314
315 return objEquiv(actual, expected, strict, memos);
316 }
317}
318
319function isArguments(object) {
320 return Object.prototype.toString.call(object) == '[object Arguments]';
321}
322
323function objEquiv(a, b, strict, actualVisitedObjects) {
324 if (a === null || a === undefined || b === null || b === undefined)
325 return false;
326 // if one is a primitive, the other must be same
327 if (isPrimitive(a) || isPrimitive(b))
328 return a === b;
329 if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
330 return false;
331 var aIsArgs = isArguments(a);
332 var bIsArgs = isArguments(b);
333 if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
334 return false;
335 if (aIsArgs) {
336 a = pSlice.call(a);
337 b = pSlice.call(b);
338 return _deepEqual(a, b, strict);
339 }
340 var ka = objectKeys(a);
341 var kb = objectKeys(b);
342 var key, i;
343 // having the same number of owned properties (keys incorporates
344 // hasOwnProperty)
345 if (ka.length !== kb.length)
346 return false;
347 //the same set of keys (although not necessarily the same order),
348 ka.sort();
349 kb.sort();
350 //~~~cheap key test
351 for (i = ka.length - 1; i >= 0; i--) {
352 if (ka[i] !== kb[i])
353 return false;
354 }
355 //equivalent values for every corresponding key, and
356 //~~~possibly expensive deep test
357 for (i = ka.length - 1; i >= 0; i--) {
358 key = ka[i];
359 if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects))
360 return false;
361 }
362 return true;
363}
364
365// 8. The non-equivalence assertion tests for any deep inequality.
366// assert.notDeepEqual(actual, expected, message_opt);
367assert.notDeepEqual = notDeepEqual;
368export function notDeepEqual(actual, expected, message) {
369 if (_deepEqual(actual, expected, false)) {
370 fail(actual, expected, message, 'notDeepEqual', notDeepEqual);
371 }
372}
373
374assert.notDeepStrictEqual = notDeepStrictEqual;
375export function notDeepStrictEqual(actual, expected, message) {
376 if (_deepEqual(actual, expected, true)) {
377 fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
378 }
379}
380
381
382// 9. The strict equality assertion tests strict equality, as determined by ===.
383// assert.strictEqual(actual, expected, message_opt);
384assert.strictEqual = strictEqual;
385export function strictEqual(actual, expected, message) {
386 if (actual !== expected) {
387 fail(actual, expected, message, '===', strictEqual);
388 }
389}
390
391// 10. The strict non-equality assertion tests for strict inequality, as
392// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
393assert.notStrictEqual = notStrictEqual;
394export function notStrictEqual(actual, expected, message) {
395 if (actual === expected) {
396 fail(actual, expected, message, '!==', notStrictEqual);
397 }
398}
399
400function expectedException(actual, expected) {
401 if (!actual || !expected) {
402 return false;
403 }
404
405 if (Object.prototype.toString.call(expected) == '[object RegExp]') {
406 return expected.test(actual);
407 }
408
409 try {
410 if (actual instanceof expected) {
411 return true;
412 }
413 } catch (e) {
414 // Ignore. The instanceof check doesn't work for arrow functions.
415 }
416
417 if (Error.isPrototypeOf(expected)) {
418 return false;
419 }
420
421 return expected.call({}, actual) === true;
422}
423
424function _tryBlock(block) {
425 var error;
426 try {
427 block();
428 } catch (e) {
429 error = e;
430 }
431 return error;
432}
433
434function _throws(shouldThrow, block, expected, message) {
435 var actual;
436
437 if (typeof block !== 'function') {
438 throw new TypeError('"block" argument must be a function');
439 }
440
441 if (typeof expected === 'string') {
442 message = expected;
443 expected = null;
444 }
445
446 actual = _tryBlock(block);
447
448 message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
449 (message ? ' ' + message : '.');
450
451 if (shouldThrow && !actual) {
452 fail(actual, expected, 'Missing expected exception' + message);
453 }
454
455 var userProvidedMessage = typeof message === 'string';
456 var isUnwantedException = !shouldThrow && isError(actual);
457 var isUnexpectedException = !shouldThrow && actual && !expected;
458
459 if ((isUnwantedException &&
460 userProvidedMessage &&
461 expectedException(actual, expected)) ||
462 isUnexpectedException) {
463 fail(actual, expected, 'Got unwanted exception' + message);
464 }
465
466 if ((shouldThrow && actual && expected &&
467 !expectedException(actual, expected)) || (!shouldThrow && actual)) {
468 throw actual;
469 }
470}
471
472// 11. Expected to throw an error:
473// assert.throws(block, Error_opt, message_opt);
474assert.throws = throws;
475export function throws(block, /*optional*/error, /*optional*/message) {
476 _throws(true, block, error, message);
477}
478
479// EXTENSION! This is annoying to write outside this module.
480assert.doesNotThrow = doesNotThrow;
481export function doesNotThrow(block, /*optional*/error, /*optional*/message) {
482 _throws(false, block, error, message);
483}
484
485assert.ifError = ifError;
486export function ifError(err) {
487 if (err) throw err;
488}