UNPKG

4.61 kBJavaScriptView Raw
1'use strict';
2
3var colors = require('colors');
4var sprintf = require('util').format;
5
6function onRun() {
7 if (this.node.skip) {
8 this.state.testsSkipped++;
9
10 this.out({
11 format: [ '%s▹ %s', this.indent, this.node.description.underline ],
12 colors: [ 'yellow' ]
13 });
14 } else {
15 this.state.testsRun++;
16
17 this.out('%s▸ %s', this.indent, this.node.description.underline);
18
19 if (this.config.profile)
20 this.runTime = process.hrTime();
21 }
22}
23
24function writeTimeFrom(out, from, subject) {
25 var diff = process.hrTime(from);
26 out({
27 format: [ '%s ◎ %s took %dms %dμs\n', subject, diff[0], diff[1] ],
28 colors: [ 'italic', 'grey' ]
29 });
30}
31
32function onNodeDone() {
33 this.out('');
34
35 if (this.config.profile && !this.isEmpty)
36 writeTimeFrom(this.out, this.runTime, 'test');
37}
38
39function onTreeDone() {
40 if (this.config.profile && this.hasChildTests)
41 writeTimeFrom(this.out, this.runTime, 'test node and subtree');
42
43 if(this.isEmpty && !this.node.skip)
44 this.out({
45 format: [ '%s This test has no content.\n', this.indent ],
46 colors: [ 'yellow', 'italic' ]
47 });
48}
49
50function onChildTest(node) {
51 this.isEmpty = false;
52 this.hasChildTests = true;
53 var writer = new Writer(this.config, this.state, node, this.indentCount + 1);
54 writer.listen();
55}
56
57function onAssertOk(text) {
58 this.isEmpty = false;
59 this.state.assertionsRun++;
60
61 this.out({
62 format: [ '%s ✔ %s', this.indent, text || 'ok' ],
63 colors: [ 'green' ]
64 });
65}
66
67function onAssertNotOk(text) {
68 this.isEmpty = false;
69 this.state.assertionsRun++;
70 this.state.assertionsFailed++;
71
72 if (!this.testFailed) {
73 this.testFailed = true;
74 this.state.testsFailed++;
75 }
76
77 this.out({
78 format: [ '%s ✘ %s', this.indent, text || 'not ok' ],
79 colors: [ 'red', 'bold' ]
80 });
81}
82
83function onComment(args) {
84 this.out({
85 format: ['%s ✳ %s', this.indent, sprintf.apply(null, args)],
86 colors: [ 'grey' ]
87 })
88}
89
90function getIndent(count) {
91 var str = '';
92 for (var i = 0; i < count; i++)
93 str += ' ';
94
95 return str;
96}
97
98function Writer(config, state, node, indentCount) {
99 this.config = config || {};
100
101 this.state = state;
102 this.node = node;
103
104 this.indentCount = indentCount;
105 this.indent = getIndent(indentCount);
106}
107
108Writer.prototype.isEmpty = true;
109
110Writer.prototype.listen = function () {
111 this.node.once('run', onRun.bind(this));
112 this.node.once('nodeDone', onNodeDone.bind(this));
113 this.node.once('treeDone', onTreeDone.bind(this));
114 this.node.on('childTest', onChildTest.bind(this));
115 this.node.on('assertOk', onAssertOk.bind(this));
116 this.node.on('assertNotOk', onAssertNotOk.bind(this));
117 this.node.on('comment', onComment.bind(this));
118};
119
120Writer.prototype.out = function (format) {
121 if (arguments.length === 1 && typeof format === 'object') {
122 format = arguments[0].format;
123 var colors = arguments[0].colors;
124 } else if (arguments.length > 1) {
125 format = [];
126 Array.prototype.push.apply(format, arguments);
127 }
128
129 var str = Array.isArray(format) ? sprintf.apply(null, format) : format;
130
131 if (colors && !this.config.noColors)
132 str = colors.reduce(function (str, c) { return str[c]; }, str);
133
134 (this.config.out || console.log)(str);
135};
136
137module.exports = function (runner, config) {
138 var state = {
139 testsRun: 0,
140 assertionsRun: 0,
141 testsFailed: 0,
142 assertionsFailed: 0,
143 testsSkipped: 0
144 };
145
146 var out = config && config.out || console.log;
147
148 runner.on('file', function(filePath){
149 out(filePath.cyan);
150 out('');
151 });
152
153 runner.on('test', function (node) {
154 var writer = new Writer(config, state, node, 0);
155 writer.listen();
156 });
157
158 runner.on('done', function () {
159 function numStr(num, str) {
160 var format = '%d %s';
161 if (num !== 1) format += 's';
162
163 return sprintf(format, num, str);
164 }
165
166 var skippedStr = state.testsSkipped ? sprintf('(%s skipped)', numStr(state.testsSkipped, 'test')).yellow : '';
167
168 out('# Summary');
169 if (!state.testsFailed && !state.assertionsFailed) {
170 var passStr = sprintf(
171 '✔ Pass: %s, %s',
172 numStr(state.testsRun, 'test'),
173 numStr(state.assertionsRun, 'assertion'));
174
175 out(' %s %s', passStr.green, skippedStr);
176 } else {
177 out(sprintf(
178 ' ✘ Fail: %s, %s',
179 numStr(state.testsFailed, 'test'),
180 numStr(state.assertionsFailed, 'assertion'))
181 .red.bold);
182
183 var allRanStr = sprintf(
184 '- %s, %s ran.',
185 numStr(state.testsRun, 'test'),
186 numStr(state.assertionsRun, 'assertion'));
187
188 out(' %s %s', allRanStr.grey, skippedStr);
189 }
190 });
191};
\No newline at end of file