1 | 'use strict';
|
2 |
|
3 | var tape = require('../');
|
4 | var tap = require('tap');
|
5 | var concat = require('concat-stream');
|
6 | var tapParser = require('tap-parser');
|
7 | var yaml = require('js-yaml');
|
8 |
|
9 | tap.test('preserves stack trace with newlines', function (tt) {
|
10 | tt.plan(3);
|
11 |
|
12 | var test = tape.createHarness();
|
13 | var stream = test.createStream();
|
14 | var parser = stream.pipe(tapParser());
|
15 | var stackTrace = 'foo\n bar';
|
16 |
|
17 | parser.once('assert', function (data) {
|
18 | tt.deepEqual(data, {
|
19 | ok: false,
|
20 | id: 1,
|
21 | name: 'Error: Preserve stack',
|
22 | diag: {
|
23 | stack: stackTrace,
|
24 | operator: 'error',
|
25 | at: data.diag.at
|
26 | }
|
27 | });
|
28 | });
|
29 |
|
30 | stream.pipe(concat(function (body) {
|
31 | var strippedBody = stripAt(body.toString('utf8'));
|
32 | tt.deepEqual(strippedBody.split('\n'), [
|
33 | 'TAP version 13',
|
34 | '# multiline stack trace',
|
35 | 'not ok 1 Error: Preserve stack',
|
36 | ' ---',
|
37 | ' operator: error',
|
38 | ' stack: |-',
|
39 | ' foo',
|
40 | ' bar',
|
41 | ' ...',
|
42 | '',
|
43 | '1..1',
|
44 | '# tests 1',
|
45 | '# pass 0',
|
46 | '# fail 1',
|
47 | ''
|
48 | ]);
|
49 |
|
50 | tt.deepEqual(getDiag(strippedBody), {
|
51 | stack: stackTrace,
|
52 | operator: 'error'
|
53 | });
|
54 | }));
|
55 |
|
56 | test('multiline stack trace', function (t) {
|
57 | t.plan(1);
|
58 | var err = new Error('Preserve stack');
|
59 | err.stack = stackTrace;
|
60 | t.error(err);
|
61 | });
|
62 | });
|
63 |
|
64 | tap.test('parses function info from original stack', function (tt) {
|
65 | tt.plan(4);
|
66 |
|
67 | var test = tape.createHarness();
|
68 | test.createStream();
|
69 |
|
70 | test._results._watch = function (t) {
|
71 | t.on('result', function (res) {
|
72 | tt.equal('Test.testFunctionNameParsing', res.functionName);
|
73 | tt.match(res.file, /stackTrace.js/i);
|
74 | tt.ok(Number(res.line) > 0);
|
75 | tt.ok(Number(res.column) > 0);
|
76 | });
|
77 | };
|
78 |
|
79 | test('t.equal stack trace', function testFunctionNameParsing(t) {
|
80 | t.equal(true, false, 'true should be false');
|
81 | t.end();
|
82 | });
|
83 | });
|
84 |
|
85 | tap.test('parses function info from original stack for anonymous function', function (tt) {
|
86 | tt.plan(4);
|
87 |
|
88 | var test = tape.createHarness();
|
89 | test.createStream();
|
90 |
|
91 | test._results._watch = function (t) {
|
92 | t.on('result', function (res) {
|
93 | tt.equal('Test.<anonymous>', res.functionName);
|
94 | tt.match(res.file, /stackTrace.js/i);
|
95 | tt.ok(Number(res.line) > 0);
|
96 | tt.ok(Number(res.column) > 0);
|
97 | });
|
98 | };
|
99 |
|
100 | test('t.equal stack trace', function (t) {
|
101 | t.equal(true, false, 'true should be false');
|
102 | t.end();
|
103 | });
|
104 | });
|
105 |
|
106 | if (typeof Promise === 'function' && typeof Promise.resolve === 'function') {
|
107 |
|
108 | tap.test('parses function info from original stack for Promise scenario', function (tt) {
|
109 | tt.plan(4);
|
110 |
|
111 | var test = tape.createHarness();
|
112 | test.createStream();
|
113 |
|
114 | test._results._watch = function (t) {
|
115 | t.on('result', function (res) {
|
116 | tt.equal('onfulfilled', res.functionName);
|
117 | tt.match(res.file, /stackTrace.js/i);
|
118 | tt.ok(Number(res.line) > 0);
|
119 | tt.ok(Number(res.column) > 0);
|
120 | });
|
121 | };
|
122 |
|
123 | test('t.equal stack trace', function testFunctionNameParsing(t) {
|
124 | new Promise(function (resolve) {
|
125 | resolve();
|
126 | }).then(function onfulfilled() {
|
127 | t.equal(true, false, 'true should be false');
|
128 | t.end();
|
129 | });
|
130 | });
|
131 | });
|
132 |
|
133 | tap.test('parses function info from original stack for Promise scenario with anonymous function', function (tt) {
|
134 | tt.plan(4);
|
135 |
|
136 | var test = tape.createHarness();
|
137 | test.createStream();
|
138 |
|
139 | test._results._watch = function (t) {
|
140 | t.on('result', function (res) {
|
141 | tt.equal('<anonymous>', res.functionName);
|
142 | tt.match(res.file, /stackTrace.js/i);
|
143 | tt.ok(Number(res.line) > 0);
|
144 | tt.ok(Number(res.column) > 0);
|
145 | });
|
146 | };
|
147 |
|
148 | test('t.equal stack trace', function testFunctionNameParsing(t) {
|
149 | new Promise(function (resolve) {
|
150 | resolve();
|
151 | }).then(function () {
|
152 | t.equal(true, false, 'true should be false');
|
153 | t.end();
|
154 | });
|
155 | });
|
156 | });
|
157 |
|
158 | }
|
159 |
|
160 | tap.test('preserves stack trace for failed assertions', function (tt) {
|
161 | tt.plan(6);
|
162 |
|
163 | var test = tape.createHarness();
|
164 | var stream = test.createStream();
|
165 | var parser = stream.pipe(tapParser());
|
166 |
|
167 | var stack = '';
|
168 | parser.once('assert', function (data) {
|
169 | tt.equal(typeof data.diag.at, 'string');
|
170 | tt.equal(typeof data.diag.stack, 'string');
|
171 | var at = data.diag.at || '';
|
172 | stack = data.diag.stack || '';
|
173 | tt.ok((/^Error: true should be false(\n {4}at .+)+/).exec(stack), 'stack should be a stack');
|
174 | tt.deepEqual(data, {
|
175 | ok: false,
|
176 | id: 1,
|
177 | name: 'true should be false',
|
178 | diag: {
|
179 | at: at,
|
180 | stack: stack,
|
181 | operator: 'equal',
|
182 | expected: false,
|
183 | actual: true
|
184 | }
|
185 | });
|
186 | });
|
187 |
|
188 | stream.pipe(concat(function (body) {
|
189 | var strippedBody = stripAt(body.toString('utf8'));
|
190 | tt.deepEqual(strippedBody.split('\n'), [].concat(
|
191 | 'TAP version 13',
|
192 | '# t.equal stack trace',
|
193 | 'not ok 1 true should be false',
|
194 | ' ---',
|
195 | ' operator: equal',
|
196 | ' expected: false',
|
197 | ' actual: true',
|
198 | ' stack: |-',
|
199 | stack.split('\n').map(function (x) { return ' ' + x; }),
|
200 | ' ...',
|
201 | '',
|
202 | '1..1',
|
203 | '# tests 1',
|
204 | '# pass 0',
|
205 | '# fail 1',
|
206 | ''
|
207 | ));
|
208 |
|
209 | tt.deepEqual(getDiag(strippedBody), {
|
210 | stack: stack,
|
211 | operator: 'equal',
|
212 | expected: false,
|
213 | actual: true
|
214 | });
|
215 | }));
|
216 |
|
217 | test('t.equal stack trace', function (t) {
|
218 | t.plan(1);
|
219 | t.equal(true, false, 'true should be false');
|
220 | });
|
221 | });
|
222 |
|
223 | tap.test('preserves stack trace for failed assertions where actual===falsy', function (tt) {
|
224 | tt.plan(6);
|
225 |
|
226 | var test = tape.createHarness();
|
227 | var stream = test.createStream();
|
228 | var parser = stream.pipe(tapParser());
|
229 |
|
230 | var stack = '';
|
231 | parser.once('assert', function (data) {
|
232 | tt.equal(typeof data.diag.at, 'string');
|
233 | tt.equal(typeof data.diag.stack, 'string');
|
234 | var at = data.diag.at || '';
|
235 | stack = data.diag.stack || '';
|
236 | tt.ok((/^Error: false should be true(\n {4}at .+)+/).exec(stack), 'stack should be a stack');
|
237 | tt.deepEqual(data, {
|
238 | ok: false,
|
239 | id: 1,
|
240 | name: 'false should be true',
|
241 | diag: {
|
242 | at: at,
|
243 | stack: stack,
|
244 | operator: 'equal',
|
245 | expected: true,
|
246 | actual: false
|
247 | }
|
248 | });
|
249 | });
|
250 |
|
251 | stream.pipe(concat(function (body) {
|
252 | var strippedBody = stripAt(body.toString('utf8'));
|
253 | tt.deepEqual(strippedBody.split('\n'), [].concat(
|
254 | 'TAP version 13',
|
255 | '# t.equal stack trace',
|
256 | 'not ok 1 false should be true',
|
257 | ' ---',
|
258 | ' operator: equal',
|
259 | ' expected: true',
|
260 | ' actual: false',
|
261 | ' stack: |-',
|
262 | stack.split('\n').map(function (x) { return ' ' + x; }),
|
263 | ' ...',
|
264 | '',
|
265 | '1..1',
|
266 | '# tests 1',
|
267 | '# pass 0',
|
268 | '# fail 1',
|
269 | ''
|
270 | ));
|
271 |
|
272 | tt.deepEqual(getDiag(strippedBody), {
|
273 | stack: stack,
|
274 | operator: 'equal',
|
275 | expected: true,
|
276 | actual: false
|
277 | });
|
278 | }));
|
279 |
|
280 | test('t.equal stack trace', function (t) {
|
281 | t.plan(1);
|
282 | t.equal(false, true, 'false should be true');
|
283 | });
|
284 | });
|
285 |
|
286 | function getDiag(body) {
|
287 | var yamlStart = body.indexOf(' ---');
|
288 | var yamlEnd = body.indexOf(' ...\n');
|
289 | var diag = body.slice(yamlStart, yamlEnd).split('\n').map(function (line) {
|
290 | return line.slice(2);
|
291 | }).join('\n');
|
292 |
|
293 |
|
294 | var withStack = yaml.safeLoad(diag);
|
295 | delete withStack.at;
|
296 | return withStack;
|
297 | }
|
298 |
|
299 | function stripAt(body) {
|
300 | return body.replace(/^\s*at:\s+Test.*$\n/m, '');
|
301 | }
|