Skip to content

Commit

Permalink
Wraps assert functions, updating stack trace of generated errors
Browse files Browse the repository at this point in the history
  • Loading branch information
jpbochi committed Dec 3, 2020
1 parent 30b7210 commit d41d10b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
32 changes: 27 additions & 5 deletions lib/test.js
Expand Up @@ -64,6 +64,28 @@ Test.prototype.serverAddress = function(app, path) {
return protocol + '://127.0.0.1:' + port + path;
};

/**
* Wraps an assert function into another.
* The wrapper function edit the stack trace of any assertion error, prepending a more useful stack to it.
*
* @param {Function} assertFn
* @returns {Function} wrapped assert function
*/

function wrapAssertFn(assertFn) {
var savedStack = new Error().stack.split('\n').slice(3);

return function(res) {
var badStack;
var err = assertFn(res);
if (err && err.stack) {
badStack = err.stack.replace(err.message, '').split('\n').slice(1);
err.stack = [err.message, savedStack, '----', badStack].flat().join('\n');
}
return err;
};
}

/**
* Expectations:
*
Expand All @@ -83,30 +105,30 @@ Test.prototype.serverAddress = function(app, path) {
Test.prototype.expect = function(a, b, c) {
// callback
if (typeof a === 'function') {
this._asserts.push(a);
this._asserts.push(wrapAssertFn(a));
return this;
}
if (typeof b === 'function') this.end(b);
if (typeof c === 'function') this.end(c);

// status
if (typeof a === 'number') {
this._asserts.push(this._assertStatus.bind(this, a));
this._asserts.push(wrapAssertFn(this._assertStatus.bind(this, a)));
// body
if (typeof b !== 'function' && arguments.length > 1) {
this._asserts.push(this._assertBody.bind(this, b));
this._asserts.push(wrapAssertFn(this._assertBody.bind(this, b)));
}
return this;
}

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

// body
this._asserts.push(this._assertBody.bind(this, a));
this._asserts.push(wrapAssertFn(this._assertBody.bind(this, a)));

return this;
};
Expand Down
22 changes: 22 additions & 0 deletions test/supertest.js
Expand Up @@ -359,6 +359,7 @@ describe('request(app)', function () {
.expect(404)
.end(function (err, res) {
err.message.should.equal('expected 404 "Not Found", got 200 "OK"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -419,6 +420,7 @@ describe('request(app)', function () {
.expect(200, '')
.end(function (err, res) {
err.message.should.equal('expected \'\' response body, got \'foo\'');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -440,6 +442,7 @@ describe('request(app)', function () {
.expect('hey')
.end(function (err, res) {
err.message.should.equal('expected \'hey\' response body, got \'{"foo":"bar"}\'');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -459,6 +462,7 @@ describe('request(app)', function () {
.expect('hey')
.end(function (err, res) {
err.message.should.equal('expected 200 "OK", got 500 "Internal Server Error"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -491,6 +495,7 @@ describe('request(app)', function () {
.expect({ foo: 'baz' })
.end(function (err, res) {
err.message.should.equal('expected { foo: \'baz\' } response body, got { foo: \'bar\' }');
err.stack.should.match(/test\/supertest.js:/);

request(app)
.get('/')
Expand Down Expand Up @@ -522,6 +527,7 @@ describe('request(app)', function () {
.expect({ stringValue: 'foo', numberValue: 3, nestedObject: { innerString: 5 } })
.end(function (err, res) {
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
err.stack.should.match(/test\/supertest.js:/);

request(app)
.get('/')
Expand All @@ -542,6 +548,7 @@ describe('request(app)', function () {
.expect(/^bar/)
.end(function (err, res) {
err.message.should.equal('expected body \'foobar\' to match /^bar/');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -560,6 +567,7 @@ describe('request(app)', function () {
.expect('hey tj')
.end(function (err, res) {
err.message.should.equal("expected 'hey' response body, got 'hey tj'");
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -592,6 +600,7 @@ describe('request(app)', function () {
.expect('Content-Foo', 'bar')
.end(function (err, res) {
err.message.should.equal('expected "Content-Foo" header field');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -609,6 +618,7 @@ describe('request(app)', function () {
.end(function (err, res) {
err.message.should.equal('expected "Content-Type" of "text/html", '
+ 'got "application/json; charset=utf-8"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -640,6 +650,7 @@ describe('request(app)', function () {
.end(function (err) {
err.message.should.equal('expected "Content-Type" matching /^application/, '
+ 'got "text/html; charset=utf-8"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -656,6 +667,7 @@ describe('request(app)', function () {
.expect('Content-Length', 4)
.end(function (err) {
err.message.should.equal('expected "Content-Length" of "4", got "3"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -682,6 +694,7 @@ describe('request(app)', function () {
})
.end(function (err) {
err.message.should.equal('failed');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -707,6 +720,7 @@ describe('request(app)', function () {
})
.end(function (err) {
err.message.should.equal('some descriptive error');
err.stack.should.match(/test\/supertest.js:/);
(err instanceof Error).should.be.true;
done();
});
Expand Down Expand Up @@ -747,6 +761,7 @@ describe('request(app)', function () {
.expect('Content-Type', /json/)
.end(function (err) {
err.message.should.match(/Content-Type/);
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -790,6 +805,7 @@ describe('request(app)', function () {
.end(function (err) {
err.message.should.equal('expected "Content-Type" matching /bloop/, '
+ 'got "text/html; charset=utf-8"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -808,6 +824,7 @@ describe('request(app)', function () {
.end(function (err) {
err.message.should.equal('expected "Content-Type" matching /bloop/, '
+ 'got "text/html; charset=utf-8"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -826,6 +843,7 @@ describe('request(app)', function () {
.end(function (err) {
err.message.should.equal('expected "Content-Type" matching /bloop/, '
+ 'got "text/html; charset=utf-8"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -984,6 +1002,7 @@ describe('assert ordering by call order', function () {
.end(function (err, res) {
err.message.should.equal('expected \'hey\' response body, '
+ 'got \'{"message":"something went wrong"}\'');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -1003,6 +1022,7 @@ describe('assert ordering by call order', function () {
.expect('hey')
.end(function (err, res) {
err.message.should.equal('expected 200 "OK", got 500 "Internal Server Error"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand All @@ -1023,6 +1043,7 @@ describe('assert ordering by call order', function () {
.end(function (err, res) {
err.message.should.equal('expected "content-type" matching /html/, '
+ 'got "application/json; charset=utf-8"');
err.stack.should.match(/test\/supertest.js:/);
done();
});
});
Expand Down Expand Up @@ -1195,6 +1216,7 @@ describe('request.get(url).query(vals) works as expected', function () {
.end(function (err, res) {
err.should.be.an.instanceof(Error);
err.message.should.match(/Nock: Disallowed net connect/);
err.stack.should.match(/test\/supertest.js:/);
done();
});

Expand Down

0 comments on commit d41d10b

Please sign in to comment.