ava 0.16.0 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.js +297 -265
- package/cli.js +15 -179
- package/index.js +5 -98
- package/index.js.flow +201 -0
- package/lib/assert.js +87 -53
- package/lib/ava-error.js +4 -8
- package/lib/ava-files.js +282 -0
- package/lib/babel-config.js +35 -73
- package/lib/beautify-stack.js +17 -16
- package/lib/caching-precompiler.js +72 -87
- package/lib/cli.js +181 -0
- package/lib/code-excerpt.js +57 -0
- package/lib/colors.js +6 -2
- package/lib/concurrent.js +62 -75
- package/lib/enhance-assert.js +57 -49
- package/lib/extract-stack.js +10 -0
- package/lib/fork.js +67 -68
- package/lib/format-assert-error.js +72 -0
- package/lib/globals.js +3 -8
- package/lib/hook.js +15 -20
- package/lib/logger.js +59 -82
- package/lib/main.js +90 -0
- package/lib/prefix-title.js +21 -0
- package/lib/process-adapter.js +108 -0
- package/lib/reporters/mini.js +260 -257
- package/lib/reporters/tap.js +80 -85
- package/lib/reporters/verbose.js +142 -115
- package/lib/run-status.js +110 -152
- package/lib/runner.js +125 -137
- package/lib/sequence.js +68 -84
- package/lib/serialize-error.js +68 -4
- package/lib/snapshot-state.js +30 -0
- package/lib/test-collection.js +144 -156
- package/lib/test-worker.js +45 -95
- package/lib/test.js +289 -318
- package/lib/throws-helper.js +9 -9
- package/lib/validate-test.js +48 -0
- package/lib/watcher.js +258 -297
- package/package.json +63 -53
- package/profile.js +68 -55
- package/readme.md +215 -101
- package/types/generated.d.ts +848 -228
- package/types/make.js +54 -23
- package/lib/send.js +0 -16
package/lib/reporters/tap.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const format = require('util').format;
|
|
3
|
+
const stripAnsi = require('strip-ansi');
|
|
4
4
|
|
|
5
|
-
// Parses stack trace and extracts original function name, file name and line
|
|
5
|
+
// Parses stack trace and extracts original function name, file name and line
|
|
6
6
|
function getSourceFromStack(stack, index) {
|
|
7
7
|
return stack
|
|
8
8
|
.split('\n')
|
|
@@ -11,94 +11,89 @@ function getSourceFromStack(stack, index) {
|
|
|
11
11
|
.replace(/^\s+ /, '');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
class TapReporter {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.i = 0;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
module.exports = TapReporter;
|
|
23
|
-
|
|
24
|
-
TapReporter.prototype.start = function () {
|
|
25
|
-
return 'TAP version 13';
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
TapReporter.prototype.test = function (test) {
|
|
29
|
-
var output;
|
|
30
|
-
|
|
31
|
-
var directive = '';
|
|
32
|
-
var passed = test.todo ? 'not ok' : 'ok';
|
|
33
|
-
|
|
34
|
-
if (test.todo) {
|
|
35
|
-
directive = '# TODO';
|
|
36
|
-
} else if (test.skip) {
|
|
37
|
-
directive = '# SKIP';
|
|
18
|
+
start() {
|
|
19
|
+
return 'TAP version 13';
|
|
38
20
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'
|
|
47
|
-
|
|
48
|
-
'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
21
|
+
test(test) {
|
|
22
|
+
let output;
|
|
23
|
+
|
|
24
|
+
let directive = '';
|
|
25
|
+
const passed = test.todo ? 'not ok' : 'ok';
|
|
26
|
+
|
|
27
|
+
if (test.todo) {
|
|
28
|
+
directive = '# TODO';
|
|
29
|
+
} else if (test.skip) {
|
|
30
|
+
directive = '# SKIP';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const title = stripAnsi(test.title);
|
|
34
|
+
|
|
35
|
+
if (test.error) {
|
|
36
|
+
output = [
|
|
37
|
+
'# ' + title,
|
|
38
|
+
format('not ok %d - %s', ++this.i, title),
|
|
39
|
+
' ---',
|
|
40
|
+
' operator: ' + test.error.operator,
|
|
41
|
+
' expected: ' + test.error.expected,
|
|
42
|
+
' actual: ' + test.error.actual,
|
|
43
|
+
' at: ' + getSourceFromStack(test.error.stack, 1),
|
|
44
|
+
' ...'
|
|
45
|
+
];
|
|
46
|
+
} else {
|
|
47
|
+
output = [
|
|
48
|
+
`# ${title}`,
|
|
49
|
+
format('%s %d - %s %s', passed, ++this.i, title, directive).trim()
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return output.join('\n');
|
|
58
54
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
);
|
|
55
|
+
unhandledError(err) {
|
|
56
|
+
const output = [
|
|
57
|
+
`# ${err.message}`,
|
|
58
|
+
format('not ok %d - %s', ++this.i, err.message)
|
|
59
|
+
];
|
|
60
|
+
// AvaErrors don't have stack traces
|
|
61
|
+
if (err.type !== 'exception' || err.name !== 'AvaError') {
|
|
62
|
+
output.push(
|
|
63
|
+
' ---',
|
|
64
|
+
' name: ' + err.name,
|
|
65
|
+
' at: ' + getSourceFromStack(err.stack, 1),
|
|
66
|
+
' ...'
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return output.join('\n');
|
|
76
71
|
}
|
|
72
|
+
finish(runStatus) {
|
|
73
|
+
const output = [
|
|
74
|
+
'',
|
|
75
|
+
'1..' + (runStatus.passCount + runStatus.failCount + runStatus.skipCount),
|
|
76
|
+
'# tests ' + (runStatus.passCount + runStatus.failCount + runStatus.skipCount),
|
|
77
|
+
'# pass ' + runStatus.passCount
|
|
78
|
+
];
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
+
if (runStatus.skipCount > 0) {
|
|
81
|
+
output.push(`# skip ${runStatus.skipCount}`);
|
|
82
|
+
}
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
var output = [
|
|
83
|
-
'',
|
|
84
|
-
'1..' + (runStatus.passCount + runStatus.failCount + runStatus.skipCount),
|
|
85
|
-
'# tests ' + (runStatus.passCount + runStatus.failCount + runStatus.skipCount),
|
|
86
|
-
'# pass ' + runStatus.passCount
|
|
87
|
-
];
|
|
84
|
+
output.push('# fail ' + (runStatus.failCount + runStatus.rejectionCount + runStatus.exceptionCount), '');
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
output.push('# skip ' + runStatus.skipCount);
|
|
86
|
+
return output.join('\n');
|
|
91
87
|
}
|
|
88
|
+
write(str) {
|
|
89
|
+
console.log(str);
|
|
90
|
+
}
|
|
91
|
+
stdout(data) {
|
|
92
|
+
process.stderr.write(data);
|
|
93
|
+
}
|
|
94
|
+
stderr(data) {
|
|
95
|
+
this.stdout(data);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
92
98
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return output.join('\n');
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
TapReporter.prototype.write = function (str) {
|
|
99
|
-
console.log(str);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
TapReporter.prototype.stdout = TapReporter.prototype.stderr = function (data) {
|
|
103
|
-
process.stderr.write(data);
|
|
104
|
-
};
|
|
99
|
+
module.exports = TapReporter;
|
package/lib/reporters/verbose.js
CHANGED
|
@@ -1,130 +1,157 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
const indentString = require('indent-string');
|
|
3
|
+
const prettyMs = require('pretty-ms');
|
|
4
|
+
const figures = require('figures');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const plur = require('plur');
|
|
7
|
+
const formatAssertError = require('../format-assert-error');
|
|
8
|
+
const extractStack = require('../extract-stack');
|
|
9
|
+
const codeExcerpt = require('../code-excerpt');
|
|
10
|
+
const colors = require('../colors');
|
|
11
|
+
|
|
12
|
+
class VerboseReporter {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = Object.assign({}, options);
|
|
15
|
+
|
|
16
|
+
chalk.enabled = this.options.color;
|
|
17
|
+
for (const key of Object.keys(colors)) {
|
|
18
|
+
colors[key].enabled = this.options.color;
|
|
19
|
+
}
|
|
16
20
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
module.exports = VerboseReporter;
|
|
20
|
-
|
|
21
|
-
VerboseReporter.prototype.start = function () {
|
|
22
|
-
return '';
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
VerboseReporter.prototype.test = function (test, runStatus) {
|
|
26
|
-
if (test.error) {
|
|
27
|
-
return ' ' + colors.error(figures.cross) + ' ' + test.title + ' ' + colors.error(test.error.message);
|
|
21
|
+
start() {
|
|
22
|
+
return '';
|
|
28
23
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
test(test, runStatus) {
|
|
25
|
+
if (test.error) {
|
|
26
|
+
return ' ' + colors.error(figures.cross) + ' ' + test.title + ' ' + colors.error(test.error.message);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (test.todo) {
|
|
30
|
+
return ' ' + colors.todo('- ' + test.title);
|
|
31
|
+
} else if (test.skip) {
|
|
32
|
+
return ' ' + colors.skip('- ' + test.title);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (test.failing) {
|
|
36
|
+
return ' ' + colors.error(figures.tick) + ' ' + colors.error(test.title);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (runStatus.fileCount === 1 && runStatus.testCount === 1 && test.title === '[anonymous]') {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Display duration only over a threshold
|
|
44
|
+
const threshold = 100;
|
|
45
|
+
const duration = test.duration > threshold ? colors.duration(' (' + prettyMs(test.duration) + ')') : '';
|
|
46
|
+
|
|
47
|
+
return ' ' + colors.pass(figures.tick) + ' ' + test.title + duration;
|
|
34
48
|
}
|
|
49
|
+
unhandledError(err) {
|
|
50
|
+
if (err.type === 'exception' && err.name === 'AvaError') {
|
|
51
|
+
return colors.error(' ' + figures.cross + ' ' + err.message);
|
|
52
|
+
}
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
const types = {
|
|
55
|
+
rejection: 'Unhandled Rejection',
|
|
56
|
+
exception: 'Uncaught Exception'
|
|
57
|
+
};
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
59
|
+
let output = colors.error(types[err.type] + ':', err.file) + '\n';
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
61
|
+
if (err.stack) {
|
|
62
|
+
output += ' ' + colors.stack(err.stack) + '\n';
|
|
63
|
+
} else {
|
|
64
|
+
output += ' ' + colors.stack(JSON.stringify(err)) + '\n';
|
|
65
|
+
}
|
|
47
66
|
|
|
48
|
-
|
|
49
|
-
};
|
|
67
|
+
output += '\n';
|
|
50
68
|
|
|
51
|
-
|
|
52
|
-
if (err.type === 'exception' && err.name === 'AvaError') {
|
|
53
|
-
return colors.error(' ' + figures.cross + ' ' + err.message);
|
|
69
|
+
return output;
|
|
54
70
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
finish(runStatus) {
|
|
72
|
+
let output = '\n';
|
|
73
|
+
|
|
74
|
+
const lines = [
|
|
75
|
+
runStatus.failCount > 0 ?
|
|
76
|
+
' ' + colors.error(runStatus.failCount, plur('test', runStatus.failCount), 'failed') :
|
|
77
|
+
' ' + colors.pass(runStatus.passCount, plur('test', runStatus.passCount), 'passed'),
|
|
78
|
+
runStatus.knownFailureCount > 0 ? ' ' + colors.error(runStatus.knownFailureCount, plur('known failure', runStatus.knownFailureCount)) : '',
|
|
79
|
+
runStatus.skipCount > 0 ? ' ' + colors.skip(runStatus.skipCount, plur('test', runStatus.skipCount), 'skipped') : '',
|
|
80
|
+
runStatus.todoCount > 0 ? ' ' + colors.todo(runStatus.todoCount, plur('test', runStatus.todoCount), 'todo') : '',
|
|
81
|
+
runStatus.rejectionCount > 0 ? ' ' + colors.error(runStatus.rejectionCount, 'unhandled', plur('rejection', runStatus.rejectionCount)) : '',
|
|
82
|
+
runStatus.exceptionCount > 0 ? ' ' + colors.error(runStatus.exceptionCount, 'uncaught', plur('exception', runStatus.exceptionCount)) : '',
|
|
83
|
+
runStatus.previousFailCount > 0 ? ' ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun') : ''
|
|
84
|
+
].filter(Boolean);
|
|
85
|
+
|
|
86
|
+
if (lines.length > 0) {
|
|
87
|
+
lines[0] += ' ' + chalk.gray.dim('[' + new Date().toLocaleTimeString('en-US', {hour12: false}) + ']');
|
|
88
|
+
output += lines.join('\n');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (runStatus.knownFailureCount > 0) {
|
|
92
|
+
runStatus.knownFailures.forEach(test => {
|
|
93
|
+
output += '\n\n\n ' + colors.error(test.title);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (runStatus.failCount > 0) {
|
|
98
|
+
runStatus.tests.forEach((test, index) => {
|
|
99
|
+
if (!test.error) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const beforeSpacing = index === 0 ? '\n\n' : '\n\n\n\n';
|
|
104
|
+
output += beforeSpacing + ' ' + colors.title(test.title) + '\n';
|
|
105
|
+
if (test.error.source) {
|
|
106
|
+
output += ' ' + colors.errorSource(test.error.source.file + ':' + test.error.source.line) + '\n';
|
|
107
|
+
|
|
108
|
+
const excerpt = codeExcerpt(test.error.source, {maxWidth: process.stdout.columns});
|
|
109
|
+
if (excerpt) {
|
|
110
|
+
output += '\n' + indentString(excerpt, 2) + '\n';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (test.error.showOutput) {
|
|
115
|
+
output += '\n' + indentString(formatAssertError(test.error), 2);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// `.trim()` is needed, because default `err.message` is ' ' (see lib/assert.js)
|
|
119
|
+
if (test.error.message.trim()) {
|
|
120
|
+
output += '\n' + indentString(test.error.message, 2) + '\n';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (test.error.stack) {
|
|
124
|
+
const extracted = extractStack(test.error.stack);
|
|
125
|
+
if (extracted.includes('\n')) {
|
|
126
|
+
output += '\n' + indentString(colors.errorStack(extracted), 2);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (runStatus.failFastEnabled === true && runStatus.remainingCount > 0 && runStatus.failCount > 0) {
|
|
133
|
+
const remaining = 'At least ' + runStatus.remainingCount + ' ' + plur('test was', 'tests were', runStatus.remainingCount) + ' skipped.';
|
|
134
|
+
output += '\n\n\n ' + colors.information('`--fail-fast` is on. ' + remaining);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (runStatus.hasExclusive === true && runStatus.remainingCount > 0) {
|
|
138
|
+
output += '\n\n\n ' + colors.information('The .only() modifier is used in some tests.', runStatus.remainingCount, plur('test', runStatus.remainingCount), plur('was', 'were', runStatus.remainingCount), 'not run');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return output + '\n';
|
|
67
142
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return output;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
VerboseReporter.prototype.finish = function (runStatus) {
|
|
75
|
-
var output = '\n';
|
|
76
|
-
|
|
77
|
-
var lines = [
|
|
78
|
-
runStatus.failCount > 0 ?
|
|
79
|
-
' ' + colors.error(runStatus.failCount, plur('test', runStatus.failCount), 'failed') :
|
|
80
|
-
' ' + colors.pass(runStatus.passCount, plur('test', runStatus.passCount), 'passed'),
|
|
81
|
-
runStatus.knownFailureCount > 0 ? ' ' + colors.error(runStatus.knownFailureCount, plur('known failure', runStatus.knownFailureCount)) : '',
|
|
82
|
-
runStatus.skipCount > 0 ? ' ' + colors.skip(runStatus.skipCount, plur('test', runStatus.skipCount), 'skipped') : '',
|
|
83
|
-
runStatus.todoCount > 0 ? ' ' + colors.todo(runStatus.todoCount, plur('test', runStatus.todoCount), 'todo') : '',
|
|
84
|
-
runStatus.rejectionCount > 0 ? ' ' + colors.error(runStatus.rejectionCount, 'unhandled', plur('rejection', runStatus.rejectionCount)) : '',
|
|
85
|
-
runStatus.exceptionCount > 0 ? ' ' + colors.error(runStatus.exceptionCount, 'uncaught', plur('exception', runStatus.exceptionCount)) : '',
|
|
86
|
-
runStatus.previousFailCount > 0 ? ' ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun') : ''
|
|
87
|
-
].filter(Boolean);
|
|
88
|
-
|
|
89
|
-
if (lines.length > 0) {
|
|
90
|
-
lines[0] += ' ' + chalk.gray.dim('[' + new Date().toLocaleTimeString('en-US', {hour12: false}) + ']');
|
|
91
|
-
output += lines.join('\n');
|
|
143
|
+
section() {
|
|
144
|
+
return chalk.gray.dim('\u2500'.repeat(process.stdout.columns || 80));
|
|
92
145
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (runStatus.knownFailureCount > 0) {
|
|
97
|
-
runStatus.knownFailures.forEach(function (test) {
|
|
98
|
-
i++;
|
|
99
|
-
output += '\n\n\n ' + colors.error(i + '.', test.title);
|
|
100
|
-
});
|
|
146
|
+
write(str) {
|
|
147
|
+
console.error(str);
|
|
101
148
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
runStatus.tests.forEach(function (test) {
|
|
105
|
-
if (!(test.error && test.error.message)) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
i++;
|
|
110
|
-
|
|
111
|
-
output += '\n\n\n ' + colors.error(i + '.', test.title) + '\n';
|
|
112
|
-
var stack = test.error.stack ? test.error.stack.trimRight() : '';
|
|
113
|
-
output += ' ' + colors.stack(stack);
|
|
114
|
-
});
|
|
149
|
+
stdout(data) {
|
|
150
|
+
process.stderr.write(data);
|
|
115
151
|
}
|
|
152
|
+
stderr(data) {
|
|
153
|
+
process.stderr.write(data);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
116
156
|
|
|
117
|
-
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
VerboseReporter.prototype.section = function () {
|
|
121
|
-
return chalk.gray.dim(repeating('\u2500', process.stdout.columns || 80));
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
VerboseReporter.prototype.write = function (str) {
|
|
125
|
-
console.error(str);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
VerboseReporter.prototype.stdout = VerboseReporter.prototype.stderr = function (data) {
|
|
129
|
-
process.stderr.write(data);
|
|
130
|
-
};
|
|
157
|
+
module.exports = VerboseReporter;
|