Skip to content

Commit d41d10b

Browse files
committedDec 3, 2020
Wraps assert functions, updating stack trace of generated errors
1 parent 30b7210 commit d41d10b

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed
 

Diff for: ‎lib/test.js

+27-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ Test.prototype.serverAddress = function(app, path) {
6464
return protocol + '://127.0.0.1:' + port + path;
6565
};
6666

67+
/**
68+
* Wraps an assert function into another.
69+
* The wrapper function edit the stack trace of any assertion error, prepending a more useful stack to it.
70+
*
71+
* @param {Function} assertFn
72+
* @returns {Function} wrapped assert function
73+
*/
74+
75+
function wrapAssertFn(assertFn) {
76+
var savedStack = new Error().stack.split('\n').slice(3);
77+
78+
return function(res) {
79+
var badStack;
80+
var err = assertFn(res);
81+
if (err && err.stack) {
82+
badStack = err.stack.replace(err.message, '').split('\n').slice(1);
83+
err.stack = [err.message, savedStack, '----', badStack].flat().join('\n');
84+
}
85+
return err;
86+
};
87+
}
88+
6789
/**
6890
* Expectations:
6991
*
@@ -83,30 +105,30 @@ Test.prototype.serverAddress = function(app, path) {
83105
Test.prototype.expect = function(a, b, c) {
84106
// callback
85107
if (typeof a === 'function') {
86-
this._asserts.push(a);
108+
this._asserts.push(wrapAssertFn(a));
87109
return this;
88110
}
89111
if (typeof b === 'function') this.end(b);
90112
if (typeof c === 'function') this.end(c);
91113

92114
// status
93115
if (typeof a === 'number') {
94-
this._asserts.push(this._assertStatus.bind(this, a));
116+
this._asserts.push(wrapAssertFn(this._assertStatus.bind(this, a)));
95117
// body
96118
if (typeof b !== 'function' && arguments.length > 1) {
97-
this._asserts.push(this._assertBody.bind(this, b));
119+
this._asserts.push(wrapAssertFn(this._assertBody.bind(this, b)));
98120
}
99121
return this;
100122
}
101123

102124
// header field
103125
if (typeof b === 'string' || typeof b === 'number' || b instanceof RegExp) {
104-
this._asserts.push(this._assertHeader.bind(this, { name: '' + a, value: b }));
126+
this._asserts.push(wrapAssertFn(this._assertHeader.bind(this, { name: '' + a, value: b })));
105127
return this;
106128
}
107129

108130
// body
109-
this._asserts.push(this._assertBody.bind(this, a));
131+
this._asserts.push(wrapAssertFn(this._assertBody.bind(this, a)));
110132

111133
return this;
112134
};

Diff for: ‎test/supertest.js

+22
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ describe('request(app)', function () {
359359
.expect(404)
360360
.end(function (err, res) {
361361
err.message.should.equal('expected 404 "Not Found", got 200 "OK"');
362+
err.stack.should.match(/test\/supertest.js:/);
362363
done();
363364
});
364365
});
@@ -419,6 +420,7 @@ describe('request(app)', function () {
419420
.expect(200, '')
420421
.end(function (err, res) {
421422
err.message.should.equal('expected \'\' response body, got \'foo\'');
423+
err.stack.should.match(/test\/supertest.js:/);
422424
done();
423425
});
424426
});
@@ -440,6 +442,7 @@ describe('request(app)', function () {
440442
.expect('hey')
441443
.end(function (err, res) {
442444
err.message.should.equal('expected \'hey\' response body, got \'{"foo":"bar"}\'');
445+
err.stack.should.match(/test\/supertest.js:/);
443446
done();
444447
});
445448
});
@@ -459,6 +462,7 @@ describe('request(app)', function () {
459462
.expect('hey')
460463
.end(function (err, res) {
461464
err.message.should.equal('expected 200 "OK", got 500 "Internal Server Error"');
465+
err.stack.should.match(/test\/supertest.js:/);
462466
done();
463467
});
464468
});
@@ -491,6 +495,7 @@ describe('request(app)', function () {
491495
.expect({ foo: 'baz' })
492496
.end(function (err, res) {
493497
err.message.should.equal('expected { foo: \'baz\' } response body, got { foo: \'bar\' }');
498+
err.stack.should.match(/test\/supertest.js:/);
494499

495500
request(app)
496501
.get('/')
@@ -522,6 +527,7 @@ describe('request(app)', function () {
522527
.expect({ stringValue: 'foo', numberValue: 3, nestedObject: { innerString: 5 } })
523528
.end(function (err, res) {
524529
err.message.should.equal('expected {\n stringValue: \'foo\',\n numberValue: 3,\n nestedObject: { innerString: 5 }\n} response body, got {\n stringValue: \'foo\',\n numberValue: 3,\n nestedObject: { innerString: \'5\' }\n}'); // eslint-disable-line max-len
530+
err.stack.should.match(/test\/supertest.js:/);
525531

526532
request(app)
527533
.get('/')
@@ -542,6 +548,7 @@ describe('request(app)', function () {
542548
.expect(/^bar/)
543549
.end(function (err, res) {
544550
err.message.should.equal('expected body \'foobar\' to match /^bar/');
551+
err.stack.should.match(/test\/supertest.js:/);
545552
done();
546553
});
547554
});
@@ -560,6 +567,7 @@ describe('request(app)', function () {
560567
.expect('hey tj')
561568
.end(function (err, res) {
562569
err.message.should.equal("expected 'hey' response body, got 'hey tj'");
570+
err.stack.should.match(/test\/supertest.js:/);
563571
done();
564572
});
565573
});
@@ -592,6 +600,7 @@ describe('request(app)', function () {
592600
.expect('Content-Foo', 'bar')
593601
.end(function (err, res) {
594602
err.message.should.equal('expected "Content-Foo" header field');
603+
err.stack.should.match(/test\/supertest.js:/);
595604
done();
596605
});
597606
});
@@ -609,6 +618,7 @@ describe('request(app)', function () {
609618
.end(function (err, res) {
610619
err.message.should.equal('expected "Content-Type" of "text/html", '
611620
+ 'got "application/json; charset=utf-8"');
621+
err.stack.should.match(/test\/supertest.js:/);
612622
done();
613623
});
614624
});
@@ -640,6 +650,7 @@ describe('request(app)', function () {
640650
.end(function (err) {
641651
err.message.should.equal('expected "Content-Type" matching /^application/, '
642652
+ 'got "text/html; charset=utf-8"');
653+
err.stack.should.match(/test\/supertest.js:/);
643654
done();
644655
});
645656
});
@@ -656,6 +667,7 @@ describe('request(app)', function () {
656667
.expect('Content-Length', 4)
657668
.end(function (err) {
658669
err.message.should.equal('expected "Content-Length" of "4", got "3"');
670+
err.stack.should.match(/test\/supertest.js:/);
659671
done();
660672
});
661673
});
@@ -682,6 +694,7 @@ describe('request(app)', function () {
682694
})
683695
.end(function (err) {
684696
err.message.should.equal('failed');
697+
err.stack.should.match(/test\/supertest.js:/);
685698
done();
686699
});
687700
});
@@ -707,6 +720,7 @@ describe('request(app)', function () {
707720
})
708721
.end(function (err) {
709722
err.message.should.equal('some descriptive error');
723+
err.stack.should.match(/test\/supertest.js:/);
710724
(err instanceof Error).should.be.true;
711725
done();
712726
});
@@ -747,6 +761,7 @@ describe('request(app)', function () {
747761
.expect('Content-Type', /json/)
748762
.end(function (err) {
749763
err.message.should.match(/Content-Type/);
764+
err.stack.should.match(/test\/supertest.js:/);
750765
done();
751766
});
752767
});
@@ -790,6 +805,7 @@ describe('request(app)', function () {
790805
.end(function (err) {
791806
err.message.should.equal('expected "Content-Type" matching /bloop/, '
792807
+ 'got "text/html; charset=utf-8"');
808+
err.stack.should.match(/test\/supertest.js:/);
793809
done();
794810
});
795811
});
@@ -808,6 +824,7 @@ describe('request(app)', function () {
808824
.end(function (err) {
809825
err.message.should.equal('expected "Content-Type" matching /bloop/, '
810826
+ 'got "text/html; charset=utf-8"');
827+
err.stack.should.match(/test\/supertest.js:/);
811828
done();
812829
});
813830
});
@@ -826,6 +843,7 @@ describe('request(app)', function () {
826843
.end(function (err) {
827844
err.message.should.equal('expected "Content-Type" matching /bloop/, '
828845
+ 'got "text/html; charset=utf-8"');
846+
err.stack.should.match(/test\/supertest.js:/);
829847
done();
830848
});
831849
});
@@ -984,6 +1002,7 @@ describe('assert ordering by call order', function () {
9841002
.end(function (err, res) {
9851003
err.message.should.equal('expected \'hey\' response body, '
9861004
+ 'got \'{"message":"something went wrong"}\'');
1005+
err.stack.should.match(/test\/supertest.js:/);
9871006
done();
9881007
});
9891008
});
@@ -1003,6 +1022,7 @@ describe('assert ordering by call order', function () {
10031022
.expect('hey')
10041023
.end(function (err, res) {
10051024
err.message.should.equal('expected 200 "OK", got 500 "Internal Server Error"');
1025+
err.stack.should.match(/test\/supertest.js:/);
10061026
done();
10071027
});
10081028
});
@@ -1023,6 +1043,7 @@ describe('assert ordering by call order', function () {
10231043
.end(function (err, res) {
10241044
err.message.should.equal('expected "content-type" matching /html/, '
10251045
+ 'got "application/json; charset=utf-8"');
1046+
err.stack.should.match(/test\/supertest.js:/);
10261047
done();
10271048
});
10281049
});
@@ -1195,6 +1216,7 @@ describe('request.get(url).query(vals) works as expected', function () {
11951216
.end(function (err, res) {
11961217
err.should.be.an.instanceof(Error);
11971218
err.message.should.match(/Nock: Disallowed net connect/);
1219+
err.stack.should.match(/test\/supertest.js:/);
11981220
done();
11991221
});
12001222

0 commit comments

Comments
 (0)
Please sign in to comment.