Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d765dc2

Browse files
author
vdemedes
committedDec 22, 2015
add TAP support
1 parent b02e5ec commit d765dc2

File tree

6 files changed

+199
-9
lines changed

6 files changed

+199
-9
lines changed
 

‎cli.js

+29-8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var updateNotifier = require('update-notifier');
2323
var chalk = require('chalk');
2424
var Promise = require('bluebird');
2525
var log = require('./lib/logger');
26+
var tap = require('./lib/tap');
2627
var Api = require('./api');
2728

2829
// Bluebird specific
@@ -37,6 +38,7 @@ var cli = meow([
3738
' --fail-fast Stop after first test failure',
3839
' --serial Run tests serially',
3940
' --require Module to preload (Can be repeated)',
41+
' --tap Generate TAP output',
4042
'',
4143
'Examples',
4244
' ava',
@@ -54,7 +56,8 @@ var cli = meow([
5456
],
5557
boolean: [
5658
'fail-fast',
57-
'serial'
59+
'serial',
60+
'tap'
5861
]
5962
});
6063

@@ -65,7 +68,11 @@ if (cli.flags.init) {
6568
return;
6669
}
6770

68-
log.write();
71+
if (cli.flags.tap) {
72+
console.log(tap.start());
73+
} else {
74+
log.write();
75+
}
6976

7077
var api = new Api(cli.input, {
7178
failFast: cli.flags.failFast,
@@ -74,6 +81,11 @@ var api = new Api(cli.input, {
7481
});
7582

7683
api.on('test', function (test) {
84+
if (cli.flags.tap) {
85+
console.log(tap.test(test));
86+
return;
87+
}
88+
7789
if (test.error) {
7890
log.error(test.title, chalk.red(test.error.message));
7991
} else {
@@ -87,17 +99,26 @@ api.on('test', function (test) {
8799
});
88100

89101
api.on('error', function (data) {
102+
if (cli.flags.tap) {
103+
console.log(tap.unhandledError(data));
104+
return;
105+
}
106+
90107
log.unhandledError(data.type, data.file, data);
91108
});
92109

93110
api.run()
94111
.then(function () {
95-
log.write();
96-
log.report(api.passCount, api.failCount, api.rejectionCount, api.exceptionCount);
97-
log.write();
98-
99-
if (api.failCount > 0) {
100-
log.errors(api.errors);
112+
if (cli.flags.tap) {
113+
console.log(tap.finish(api.passCount, api.failCount, api.rejectionCount, api.exceptionCount));
114+
} else {
115+
log.write();
116+
log.report(api.passCount, api.failCount, api.rejectionCount, api.exceptionCount);
117+
log.write();
118+
119+
if (api.failCount > 0) {
120+
log.errors(api.errors);
121+
}
101122
}
102123

103124
process.stdout.write('');

‎lib/tap.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict';
2+
var format = require('util').format;
3+
4+
// Parses stack trace and extracts original function name, file name and line.
5+
function getSourceFromStack(stack, index) {
6+
return stack
7+
.split('\n')
8+
.slice(index, index + 1)
9+
.join('')
10+
.replace(/^\s+at /, '');
11+
}
12+
13+
exports.start = function () {
14+
return 'TAP version 13';
15+
};
16+
17+
var i = 0;
18+
19+
exports.test = function (test) {
20+
var output;
21+
22+
if (test.error) {
23+
output = [
24+
'# ' + test.title,
25+
format('not ok %d - %s', ++i, test.error.message),
26+
' ---',
27+
' operator: ' + test.error.operator,
28+
' expected: ' + test.error.expected,
29+
' actual: ' + test.error.actual,
30+
' at: ' + getSourceFromStack(test.error.stack, 3),
31+
' ...'
32+
];
33+
} else {
34+
output = [
35+
'# ' + test.title,
36+
format('ok %d - %s', ++i, test.title)
37+
];
38+
}
39+
40+
return output.join('\n');
41+
};
42+
43+
exports.unhandledError = function (err) {
44+
var output = [
45+
'# ' + err.message,
46+
format('not ok %d - %s', ++i, err.message),
47+
' ---',
48+
' name: ' + err.name,
49+
' at: ' + getSourceFromStack(err.stack, 1),
50+
' ...'
51+
];
52+
53+
return output.join('\n');
54+
};
55+
56+
exports.finish = function (passCount, failCount, rejectionCount, exceptionCount) {
57+
var output = [
58+
'',
59+
'1..' + (passCount + failCount),
60+
'# tests ' + (passCount + failCount),
61+
'# pass ' + passCount,
62+
'# fail ' + (failCount + rejectionCount + exceptionCount),
63+
''
64+
];
65+
66+
return output.join('\n');
67+
};

‎media/tap-output.png

14.8 KB
Loading

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@
7474
"generators",
7575
"yield",
7676
"observable",
77-
"observables"
77+
"observables",
78+
"tap"
7879
],
7980
"dependencies": {
8081
"arr-flatten": "^1.0.1",

‎readme.md

+12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Even though JavaScript is single-threaded, IO in Node.js can happen in parallel
3333
- [Async function support](#async-function-support)
3434
- [Observable support](#observable-support)
3535
- [Enhanced asserts](#enhanced-asserts)
36+
- [Optional TAP output](#optional-tap-output)
3637

3738

3839
## Test syntax
@@ -105,6 +106,7 @@ $ ava --help
105106
--fail-fast Stop after first test failure
106107
--serial Run tests serially
107108
--require Module to preload (Can be repeated)
109+
--tap Generate TAP output
108110
109111
Examples
110112
ava
@@ -456,6 +458,16 @@ test.cb(t => {
456458
});
457459
```
458460

461+
### Optional TAP output
462+
463+
AVA can generate TAP output via `--tap` option for use with any [TAP reporter](https://github.com/sindresorhus/awesome-tap#reporters).
464+
465+
```
466+
$ ava --tap | tap-nyan
467+
```
468+
469+
<img src="media/tap-output.png" width="398">
470+
459471

460472
## API
461473

‎test/tap.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
'use strict';
2+
var test = require('tap').test;
3+
var tap = require('../lib/tap');
4+
5+
test('start', function (t) {
6+
t.is(tap.start(), 'TAP version 13');
7+
t.end();
8+
});
9+
10+
test('passing test', function (t) {
11+
var actualOutput = tap.test({
12+
title: 'passing'
13+
});
14+
15+
var expectedOutput = [
16+
'# passing',
17+
'ok 1 - passing'
18+
].join('\n');
19+
20+
t.is(actualOutput, expectedOutput);
21+
t.end();
22+
});
23+
24+
test('failing test', function (t) {
25+
var actualOutput = tap.test({
26+
title: 'failing',
27+
error: {
28+
message: 'false == true',
29+
operator: '==',
30+
expected: true,
31+
actual: false,
32+
stack: ['', '', '', ' at Test.fn (test.js:1:2)'].join('\n')
33+
}
34+
});
35+
36+
var expectedOutput = [
37+
'# failing',
38+
'not ok 2 - false == true',
39+
' ---',
40+
' operator: ==',
41+
' expected: true',
42+
' actual: false',
43+
' at: Test.fn (test.js:1:2)',
44+
' ...'
45+
].join('\n');
46+
47+
t.is(actualOutput, expectedOutput);
48+
t.end();
49+
});
50+
51+
test('unhandled error', function (t) {
52+
var actualOutput = tap.unhandledError({
53+
message: 'unhandled',
54+
name: 'TypeError',
55+
stack: ['', ' at Test.fn (test.js:1:2)'].join('\n')
56+
});
57+
58+
var expectedOutput = [
59+
'# unhandled',
60+
'not ok 3 - unhandled',
61+
' ---',
62+
' name: TypeError',
63+
' at: Test.fn (test.js:1:2)',
64+
' ...'
65+
].join('\n');
66+
67+
t.is(actualOutput, expectedOutput);
68+
t.end();
69+
});
70+
71+
test('results', function (t) {
72+
var passCount = 1;
73+
var failCount = 2;
74+
var rejectionCount = 3;
75+
var exceptionCount = 4;
76+
77+
var actualOutput = tap.finish(passCount, failCount, rejectionCount, exceptionCount);
78+
var expectedOutput = [
79+
'',
80+
'1..' + (passCount + failCount),
81+
'# tests ' + (passCount + failCount),
82+
'# pass ' + passCount,
83+
'# fail ' + (failCount + rejectionCount + exceptionCount),
84+
''
85+
].join('\n');
86+
87+
t.is(actualOutput, expectedOutput);
88+
t.end();
89+
});

0 commit comments

Comments
 (0)
Please sign in to comment.