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.
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
- var format = require('util').format;
3
- var stripAnsi = require('strip-ansi');
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
- function TapReporter() {
15
- if (!(this instanceof TapReporter)) {
16
- return new TapReporter();
14
+ class TapReporter {
15
+ constructor() {
16
+ this.i = 0;
17
17
  }
18
-
19
- this.i = 0;
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
- var title = stripAnsi(test.title);
41
-
42
- if (test.error) {
43
- output = [
44
- '# ' + title,
45
- format('not ok %d - %s', ++this.i, title),
46
- ' ---',
47
- ' operator: ' + test.error.operator,
48
- ' expected: ' + test.error.expected,
49
- ' actual: ' + test.error.actual,
50
- ' at: ' + getSourceFromStack(test.error.stack, 1),
51
- ' ...'
52
- ];
53
- } else {
54
- output = [
55
- '# ' + title,
56
- format('%s %d - %s %s', passed, ++this.i, title, directive).trim()
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
- return output.join('\n');
61
- };
62
-
63
- TapReporter.prototype.unhandledError = function (err) {
64
- var output = [
65
- '# ' + err.message,
66
- format('not ok %d - %s', ++this.i, err.message)
67
- ];
68
- // AvaErrors don't have stack traces.
69
- if (err.type !== 'exception' || err.name !== 'AvaError') {
70
- output.push(
71
- ' ---',
72
- ' name: ' + err.name,
73
- ' at: ' + getSourceFromStack(err.stack, 1),
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
- return output.join('\n');
79
- };
80
+ if (runStatus.skipCount > 0) {
81
+ output.push(`# skip ${runStatus.skipCount}`);
82
+ }
80
83
 
81
- TapReporter.prototype.finish = function (runStatus) {
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
- if (runStatus.skipCount > 0) {
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
- output.push('# fail ' + (runStatus.failCount + runStatus.rejectionCount + runStatus.exceptionCount), '');
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;
@@ -1,130 +1,157 @@
1
1
  'use strict';
2
- var prettyMs = require('pretty-ms');
3
- var figures = require('figures');
4
- var chalk = require('chalk');
5
- var plur = require('plur');
6
- var repeating = require('repeating');
7
- var colors = require('../colors');
8
-
9
- Object.keys(colors).forEach(function (key) {
10
- colors[key].enabled = true;
11
- });
12
-
13
- function VerboseReporter() {
14
- if (!(this instanceof VerboseReporter)) {
15
- return new VerboseReporter();
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
- if (test.todo) {
31
- return ' ' + colors.todo('- ' + test.title);
32
- } else if (test.skip) {
33
- return ' ' + colors.skip('- ' + test.title);
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
- if (test.failing) {
37
- return ' ' + colors.error(figures.tick) + ' ' + colors.error(test.title);
38
- }
54
+ const types = {
55
+ rejection: 'Unhandled Rejection',
56
+ exception: 'Uncaught Exception'
57
+ };
39
58
 
40
- if (runStatus.fileCount === 1 && runStatus.testCount === 1 && test.title === '[anonymous]') {
41
- return undefined;
42
- }
59
+ let output = colors.error(types[err.type] + ':', err.file) + '\n';
43
60
 
44
- // display duration only over a threshold
45
- var threshold = 100;
46
- var duration = test.duration > threshold ? colors.duration(' (' + prettyMs(test.duration) + ')') : '';
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
- return ' ' + colors.pass(figures.tick) + ' ' + test.title + duration;
49
- };
67
+ output += '\n';
50
68
 
51
- VerboseReporter.prototype.unhandledError = function (err) {
52
- if (err.type === 'exception' && err.name === 'AvaError') {
53
- return colors.error(' ' + figures.cross + ' ' + err.message);
69
+ return output;
54
70
  }
55
-
56
- var types = {
57
- rejection: 'Unhandled Rejection',
58
- exception: 'Uncaught Exception'
59
- };
60
-
61
- var output = colors.error(types[err.type] + ':', err.file) + '\n';
62
-
63
- if (err.stack) {
64
- output += ' ' + colors.stack(err.stack) + '\n';
65
- } else {
66
- output += ' ' + colors.stack(JSON.stringify(err)) + '\n';
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
- output += '\n';
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
- var i = 0;
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
- if (runStatus.failCount > 0) {
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
- return output + '\n';
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;