1 | function createCommonjsModule(fn, module) {
|
2 | return module = { exports: {} }, fn(module, module.exports), module.exports;
|
3 | }
|
4 |
|
5 | var keys = createCommonjsModule(function (module, exports) {
|
6 | exports = module.exports = typeof Object.keys === 'function'
|
7 | ? Object.keys : shim;
|
8 |
|
9 | exports.shim = shim;
|
10 | function shim (obj) {
|
11 | var keys = [];
|
12 | for (var key in obj) keys.push(key);
|
13 | return keys;
|
14 | }
|
15 | });
|
16 |
|
17 | var keys_1 = keys.shim;
|
18 |
|
19 | var is_arguments = createCommonjsModule(function (module, exports) {
|
20 | var supportsArgumentsClass = (function(){
|
21 | return Object.prototype.toString.call(arguments)
|
22 | })() == '[object Arguments]';
|
23 |
|
24 | exports = module.exports = supportsArgumentsClass ? supported : unsupported;
|
25 |
|
26 | exports.supported = supported;
|
27 | function supported(object) {
|
28 | return Object.prototype.toString.call(object) == '[object Arguments]';
|
29 | }
|
30 |
|
31 | exports.unsupported = unsupported;
|
32 | function unsupported(object){
|
33 | return object &&
|
34 | typeof object == 'object' &&
|
35 | typeof object.length == 'number' &&
|
36 | Object.prototype.hasOwnProperty.call(object, 'callee') &&
|
37 | !Object.prototype.propertyIsEnumerable.call(object, 'callee') ||
|
38 | false;
|
39 | }
|
40 | });
|
41 |
|
42 | var is_arguments_1 = is_arguments.supported;
|
43 | var is_arguments_2 = is_arguments.unsupported;
|
44 |
|
45 | var deepEqual_1 = createCommonjsModule(function (module) {
|
46 | var pSlice = Array.prototype.slice;
|
47 |
|
48 |
|
49 |
|
50 | var deepEqual = module.exports = function (actual, expected, opts) {
|
51 | if (!opts) opts = {};
|
52 |
|
53 | if (actual === expected) {
|
54 | return true;
|
55 |
|
56 | } else if (actual instanceof Date && expected instanceof Date) {
|
57 | return actual.getTime() === expected.getTime();
|
58 |
|
59 |
|
60 |
|
61 | } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') {
|
62 | return opts.strict ? actual === expected : actual == expected;
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 | } else {
|
71 | return objEquiv(actual, expected, opts);
|
72 | }
|
73 | };
|
74 |
|
75 | function isUndefinedOrNull(value) {
|
76 | return value === null || value === undefined;
|
77 | }
|
78 |
|
79 | function isBuffer (x) {
|
80 | if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
|
81 | if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
|
82 | return false;
|
83 | }
|
84 | if (x.length > 0 && typeof x[0] !== 'number') return false;
|
85 | return true;
|
86 | }
|
87 |
|
88 | function objEquiv(a, b, opts) {
|
89 | var i, key;
|
90 | if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
91 | return false;
|
92 |
|
93 | if (a.prototype !== b.prototype) return false;
|
94 |
|
95 |
|
96 | if (is_arguments(a)) {
|
97 | if (!is_arguments(b)) {
|
98 | return false;
|
99 | }
|
100 | a = pSlice.call(a);
|
101 | b = pSlice.call(b);
|
102 | return deepEqual(a, b, opts);
|
103 | }
|
104 | if (isBuffer(a)) {
|
105 | if (!isBuffer(b)) {
|
106 | return false;
|
107 | }
|
108 | if (a.length !== b.length) return false;
|
109 | for (i = 0; i < a.length; i++) {
|
110 | if (a[i] !== b[i]) return false;
|
111 | }
|
112 | return true;
|
113 | }
|
114 | try {
|
115 | var ka = keys(a),
|
116 | kb = keys(b);
|
117 | } catch (e) {
|
118 | return false;
|
119 | }
|
120 |
|
121 |
|
122 | if (ka.length != kb.length)
|
123 | return false;
|
124 |
|
125 | ka.sort();
|
126 | kb.sort();
|
127 |
|
128 | for (i = ka.length - 1; i >= 0; i--) {
|
129 | if (ka[i] != kb[i])
|
130 | return false;
|
131 | }
|
132 |
|
133 |
|
134 | for (i = ka.length - 1; i >= 0; i--) {
|
135 | key = ka[i];
|
136 | if (!deepEqual(a[key], b[key], opts)) return false;
|
137 | }
|
138 | return typeof a === typeof b;
|
139 | }
|
140 | });
|
141 |
|
142 | const getAssertionLocation = () => {
|
143 | const err = new Error();
|
144 | const stack = (err.stack || '').split('\n');
|
145 | return (stack[3] || '').trim().replace(/^at/i, '');
|
146 | };
|
147 |
|
148 | const assertMethodHook = fn => function (...args) {
|
149 | const assertResult = fn(...args);
|
150 |
|
151 | if (assertResult.pass === false) {
|
152 | assertResult.at = getAssertionLocation();
|
153 | }
|
154 |
|
155 | this.collect(assertResult);
|
156 | return assertResult;
|
157 | };
|
158 |
|
159 | const Assertion = {
|
160 | ok: assertMethodHook((val, description = 'should be truthy') => ({
|
161 | pass: Boolean(val),
|
162 | actual: val,
|
163 | expected: true,
|
164 | description,
|
165 | operator: 'ok'
|
166 | })),
|
167 | deepEqual: assertMethodHook((actual, expected, description = 'should be equivalent') => ({
|
168 | pass: deepEqual_1(actual, expected),
|
169 | actual,
|
170 | expected,
|
171 | description,
|
172 | operator: 'deepEqual'
|
173 | })),
|
174 | equal: assertMethodHook((actual, expected, description = 'should be equal') => ({
|
175 | pass: actual === expected,
|
176 | actual,
|
177 | expected,
|
178 | description,
|
179 | operator: 'equal'
|
180 | })),
|
181 | notOk: assertMethodHook((val, description = 'should not be truthy') => ({
|
182 | pass: !val,
|
183 | expected: false,
|
184 | actual: val,
|
185 | description,
|
186 | operator: 'notOk'
|
187 | })),
|
188 | notDeepEqual: assertMethodHook((actual, expected, description = 'should not be equivalent') => ({
|
189 | pass: !deepEqual_1(actual, expected),
|
190 | actual,
|
191 | expected,
|
192 | description,
|
193 | operator: 'notDeepEqual'
|
194 | })),
|
195 | notEqual: assertMethodHook((actual, expected, description = 'should not be equal') => ({
|
196 | pass: actual !== expected,
|
197 | actual,
|
198 | expected,
|
199 | description,
|
200 | operator: 'notEqual'
|
201 | })),
|
202 | throws: assertMethodHook((func, expected, description) => {
|
203 | let caught;
|
204 | let pass;
|
205 | let actual;
|
206 | if (typeof expected === 'string') {
|
207 | [expected, description] = [description, expected];
|
208 | }
|
209 | try {
|
210 | func();
|
211 | } catch (err) {
|
212 | caught = {error: err};
|
213 | }
|
214 | pass = caught !== undefined;
|
215 | actual = caught && caught.error;
|
216 | if (expected instanceof RegExp) {
|
217 | pass = expected.test(actual) || expected.test(actual && actual.message);
|
218 | expected = String(expected);
|
219 | } else if (typeof expected === 'function' && caught) {
|
220 | pass = actual instanceof expected;
|
221 | actual = actual.constructor;
|
222 | }
|
223 | return {
|
224 | pass,
|
225 | expected,
|
226 | actual,
|
227 | operator: 'throws',
|
228 | description: description || 'should throw'
|
229 | };
|
230 | }),
|
231 | doesNotThrow: assertMethodHook((func, expected, description) => {
|
232 | let caught;
|
233 | if (typeof expected === 'string') {
|
234 | [expected, description] = [description, expected];
|
235 | }
|
236 | try {
|
237 | func();
|
238 | } catch (err) {
|
239 | caught = {error: err};
|
240 | }
|
241 | return {
|
242 | pass: caught === undefined,
|
243 | expected: 'no thrown error',
|
244 | actual: caught && caught.error,
|
245 | operator: 'doesNotThrow',
|
246 | description: description || 'should not throw'
|
247 | };
|
248 | }),
|
249 | fail: assertMethodHook((description = 'fail called') => ({
|
250 | pass: false,
|
251 | actual: 'fail called',
|
252 | expected: 'fail not called',
|
253 | description,
|
254 | operator: 'fail'
|
255 | }))
|
256 | };
|
257 |
|
258 | var assert = (collect, test) => Object.assign(
|
259 | Object.create(Assertion, {collect: {value: collect}}), {
|
260 | async test(description, spec) {
|
261 |
|
262 | return test(description, spec).task;
|
263 | }
|
264 | });
|
265 |
|
266 | const tester = (collect, {offset = 0} = {}) => (description, spec) => {
|
267 | const buffer = [{type: 'title', data: description, offset}];
|
268 | const result = {count: 0, pass: true, description, spec};
|
269 | let done = false;
|
270 |
|
271 | const createAssertion = item => {
|
272 | result.pass = result.pass && item.pass;
|
273 | return {type: 'assert', data: item, offset};
|
274 | };
|
275 |
|
276 | const collector = item => {
|
277 | result.count++;
|
278 | item.id = result.count;
|
279 | if (item[Symbol.asyncIterator] === undefined) {
|
280 |
|
281 | buffer.push(createAssertion(item));
|
282 | } else {
|
283 |
|
284 | buffer.push(item);
|
285 | }
|
286 | };
|
287 |
|
288 | const handleDelegate = async delegate => {
|
289 | const {value, done} = await delegate.next();
|
290 |
|
291 |
|
292 | if (done === true) {
|
293 | const {executionTime, pass, description} = value;
|
294 | const subTestAssertion = Object.assign(createAssertion({
|
295 | pass,
|
296 | description,
|
297 | id: delegate.id,
|
298 | executionTime
|
299 | }), {type: 'testAssert'});
|
300 | buffer.shift();
|
301 | buffer.unshift(subTestAssertion);
|
302 | return instance.next();
|
303 | }
|
304 | return {value, done};
|
305 | };
|
306 |
|
307 | const subTest = tester(collector, {offset: offset + 1});
|
308 |
|
309 | const start = Date.now();
|
310 |
|
311 | const assertFn = assert(collector, subTest);
|
312 | const task = new Promise(resolve => resolve(spec(assertFn)))
|
313 | .then(() => {
|
314 |
|
315 | result.executionTime = Date.now() - start;
|
316 | buffer.push({type: 'plan', data: {start: 1, end: result.count}, offset});
|
317 | buffer.push({type: 'time', data: result.executionTime, offset});
|
318 | done = true;
|
319 | return result;
|
320 | })
|
321 | .catch(err => {
|
322 |
|
323 | buffer.push({type: 'assert', data: {pass: false, description}});
|
324 | buffer.push({type: 'comment', data: 'Unhandled exception'});
|
325 | buffer.push({type: 'bailout', data: err, offset});
|
326 | done = true;
|
327 | });
|
328 |
|
329 | const instance = {
|
330 | test: subTest,
|
331 | task,
|
332 | [Symbol.asyncIterator]() {
|
333 | return this;
|
334 | },
|
335 | async next() {
|
336 | if (buffer.length === 0) {
|
337 | if (done === true) {
|
338 | return {done: true, value: result};
|
339 | }
|
340 |
|
341 | await task;
|
342 | return this.next();
|
343 | }
|
344 |
|
345 | const next = buffer[0];
|
346 |
|
347 |
|
348 | if (next[Symbol.asyncIterator] !== undefined) {
|
349 | return handleDelegate(next);
|
350 | }
|
351 |
|
352 | return {value: buffer.shift(), done: false};
|
353 | }
|
354 | };
|
355 |
|
356 |
|
357 | collect(instance);
|
358 |
|
359 | return instance;
|
360 | };
|
361 |
|
362 | const print = (message, offset = 0) => {
|
363 | console.log(message.padStart(message.length + (offset * 4)));
|
364 | };
|
365 |
|
366 | const toYaml = print => (obj, offset = 0) => {
|
367 | for (const [prop, value] of Object.entries(obj)) {
|
368 | print(`${prop}: ${JSON.stringify(value)}`, offset + 0.5);
|
369 | }
|
370 | };
|
371 |
|
372 | const tap = print => {
|
373 | const yaml = toYaml(print);
|
374 | return {
|
375 | version(version = 13) {
|
376 | print(`TAP version ${version}`);
|
377 | },
|
378 | title(value, offset = 0) {
|
379 | const message = offset > 0 ? `Subtest: ${value}` : value;
|
380 | this.comment(message, offset);
|
381 | },
|
382 | assert(value, offset = 0) {
|
383 | const {pass, description, id, executionTime, expected = '', actual = '', at = '', operator = ''} = value;
|
384 | const label = pass === true ? 'ok' : 'not ok';
|
385 | print(`${label} ${id} - ${description}${executionTime ? ` # time=${executionTime}ms` : ''}`, offset);
|
386 | if (pass === false && value.operator) {
|
387 | print('---', offset + 0.5);
|
388 | yaml({expected, actual, at, operator}, offset);
|
389 | print('...', offset + 0.5);
|
390 | }
|
391 | },
|
392 | plan(value, offset = 0) {
|
393 | print(`1..${value.end}`, offset);
|
394 | },
|
395 | time(value, offset = 0) {
|
396 | this.comment(`time=${value}ms`, offset);
|
397 | },
|
398 | comment(value, offset = 0) {
|
399 | print(`# ${value}`, offset);
|
400 | },
|
401 | bailout(value = 'Unhandled exception') {
|
402 | print(`Bail out! ${value}`);
|
403 | },
|
404 | testAssert(value, offset = 0) {
|
405 | return this.assert(value, offset);
|
406 | }
|
407 | };
|
408 | };
|
409 |
|
410 | var tap$1 = (printFn = print) => {
|
411 | const reporter = tap(printFn);
|
412 | return (toPrint = {}) => {
|
413 | const {data, type, offset = 0} = toPrint;
|
414 | if (typeof reporter[type] === 'function') {
|
415 | reporter[type](data, offset);
|
416 | }
|
417 |
|
418 | };
|
419 | };
|
420 |
|
421 |
|
422 |
|
423 |
|
424 | const asyncIterator = behavior => Object.assign({
|
425 | [Symbol.asyncIterator]() {
|
426 | return this;
|
427 | }
|
428 | }, behavior);
|
429 |
|
430 | const filter = predicate => iterator => asyncIterator({
|
431 | async next() {
|
432 | const {done, value} = await iterator.next();
|
433 |
|
434 | if (done === true) {
|
435 | return {done};
|
436 | }
|
437 |
|
438 | if (!predicate(value)) {
|
439 | return this.next();
|
440 | }
|
441 |
|
442 | return {done, value};
|
443 | }
|
444 | });
|
445 |
|
446 | const map = mapFn => iterator => asyncIterator({
|
447 | [Symbol.asyncIterator]() {
|
448 | return this;
|
449 | },
|
450 | async next() {
|
451 | const {done, value} = await iterator.next();
|
452 | if (done === true) {
|
453 | return {done};
|
454 | }
|
455 | return {done, value: mapFn(value)};
|
456 | }
|
457 | });
|
458 |
|
459 | const stream = asyncIterator => Object.assign(asyncIterator, {
|
460 | map(fn) {
|
461 | return stream(map(fn)(asyncIterator));
|
462 | },
|
463 | filter(fn) {
|
464 | return stream(filter(fn)(asyncIterator));
|
465 | }
|
466 | });
|
467 |
|
468 | const combine = (...iterators) => {
|
469 | const [...pending] = iterators;
|
470 | let current = pending.shift();
|
471 |
|
472 | return asyncIterator({
|
473 | async next() {
|
474 | if (current === undefined) {
|
475 | return {done: true};
|
476 | }
|
477 |
|
478 | const {done, value} = await current.next();
|
479 |
|
480 | if (done === true) {
|
481 | current = pending.shift();
|
482 | return this.next();
|
483 | }
|
484 |
|
485 | return {done, value};
|
486 | }
|
487 | });
|
488 | };
|
489 |
|
490 | let flatten = true;
|
491 | const tests = [];
|
492 | const test = tester(t => tests.push(t));
|
493 |
|
494 |
|
495 | const subTest = (test('Root', () => {})).test;
|
496 | test.test = (description, spec) => {
|
497 | flatten = false;
|
498 | return subTest(description, spec);
|
499 | };
|
500 |
|
501 | const start = async ({reporter = tap$1()} = {}) => {
|
502 | let count = 0;
|
503 | let failure = 0;
|
504 | reporter({type: 'version', data: 13});
|
505 |
|
506 |
|
507 | await tests[0].next();
|
508 |
|
509 | let outputStream = stream(combine(...tests));
|
510 | outputStream = flatten ? outputStream
|
511 | .filter(({type}) => type !== 'testAssert')
|
512 | .map(item => Object.assign(item, {offset: 0})) :
|
513 | outputStream;
|
514 |
|
515 | const filterOutAtRootLevel = ['plan', 'time'];
|
516 | outputStream = outputStream
|
517 | .filter(item => item.offset > 0 || !filterOutAtRootLevel.includes(item.type))
|
518 | .map(item => {
|
519 | if (item.offset > 0 || (item.type !== 'assert' && item.type !== 'testAssert')) {
|
520 | return item;
|
521 | }
|
522 |
|
523 | count++;
|
524 | item.data.id = count;
|
525 | failure += item.data.pass ? 0 : 1;
|
526 | return item;
|
527 | });
|
528 |
|
529 |
|
530 | while (true) {
|
531 | const {done, value} = await outputStream.next();
|
532 |
|
533 | if (done === true) {
|
534 | break;
|
535 | }
|
536 |
|
537 | reporter(value);
|
538 |
|
539 | if (value.type === 'bailout') {
|
540 | throw value.data;
|
541 | }
|
542 | }
|
543 |
|
544 | reporter({type: 'plan', data: {start: 1, end: count}});
|
545 | reporter({type: 'comment', data: failure > 0 ? `failed ${failure} of ${count} tests` : 'ok'});
|
546 | };
|
547 |
|
548 |
|
549 | if (typeof window === 'undefined') {
|
550 | setTimeout(start, 0);
|
551 | } else {
|
552 | window.addEventListener('load', start);
|
553 | }
|
554 |
|
555 | export default test;
|
556 |
|