mocha-api-errors
v1.0.2
Published
Print full API responses in your Mocha tests when you get an unexpected responses.
Downloads
51
Readme
mocha-api-errors
Print full API responses in your Mocha tests when you get an unexpected response.
Developed at the Media Engineering Institute (HEIG-VD).
Installation
$> npm install mocha-api-errors
Usage
It can be quite annoying to write assertions on HTTP responses in tests, because you get so little information from the assertion error:
expect(res.status, 'res.status').to.equal(200);
// AssertionError: expected 400 to equal 200
//
// res.status
// + expected - actual
//
// -400
// +200
//
// at Context.it (spec/index.spec.js:12:20)
Okay, the server responded with the HTTP 400 Bad Request status code, but you have no idea why. It would be great to know what was the response from the server. Should you add code to your tests to print it if an error occurs? Should you write a complex custom Mocha matcher for HTTP responses?
Run Mocha with the mocha-api-errors reporter, and it will include the HTTP response in the error's stack trace so that you will see it if any assertion fails:
$> mocha --reporter mocha-api-errors spec/**/*.js
You also need to attach the offending HTTP response to the test's res
property. Here's an example with
supertest:
const supertest = require('supertest');
const app = require('./my-express-app');
it('should work', async function() {
const res = this.test.res = await supertest(app).get('/test');
expect(res.status, 'res.status').to.equal(200);
});
Here's the output you might get with this configuration. Note the HTTP response shown before the stack trace:
// AssertionError: expected 400 to equal 200
//
// res.status
// + expected - actual
//
// -400
// +200
//
// HTTP/1.1 400 Bad Request
// x-powered-by: Express
// content-type: application/json; charset=utf-8
// content-length: 13
// etag: W/"d-pedE0BZFQNM7HX6mFsKPL6l+dUo"
// date: Tue, 28 Nov 2017 08:58:02 GMT
// connection: close
//
// {
// "why": "because"
// }
// at Context.it (spec/index.spec.js:12:20)
Now you know exactly what the problem is (provided that your server is kind enough to give you that information).
Creating a custom reporter
The mocha-api-errors reporter extends Mocha's spec reporter, but you can extend any other reporter by using its extend
function:
const mocha = require('mocha');
const MochaApiErrorsReporter = require('mocha-api-errors');
// Extend any existing reporter with API error enrichment:
const CustomReporter = MochaApiErrorsReporter.extend(mocha.reporters.Dot);
This assumes that you extend Mocha's base reporter, which adds test failures to
the this.failures
array in the reporter.
Configuration
The following options can be passed as the second argument to extend
:
const CustomReporter = MochaApiErrorsReporter.extend(mocha.reporters.Dot, { /* options... */ });
responseProperty
- The name of the test property where the HTTP response is expected. Defaults tores
.getResponse(test, err)
- A function that should return the HTTP response of a test when an error occurs. It will be called with the reporter as context (this
), and with the test and error as arguments (the same arguments as Mocha'sfail
runner event). It defaults to simply returning the test property defined by theresponseProperty
option.getError
- A function that should return the error to enrich when an error occurs in a test. It will be called with the reporter as context (this
), and with the test and error as arguments (the same arguments as Mocha'sfail
runner event). It defaults to returning theerr
property of the last failure (taken from thethis.failures
array of the base reporter).
Using a custom reporter programmatically
To use your custom reporter without publishing it as a package, you might need to run Mocha programmatically:
const Mocha = require('mocha');
const fs = require('fs');
const path = require('path');
// Instantiate a Mocha instance with your custom reporter.
const mocha = new Mocha({
reporter: require('./custom-reporter')
});
const testDir = 'some/dir/test'
// Add each .js file to the mocha instance.
fs.readdirSync(testDir).filter(function(file){
// Only keep the .js files.
return file.substr(-3) === '.js';
}).forEach(function(file){
mocha.addFile(
path.join(testDir, file)
);
});
// Run the tests.
mocha.run(function(failures){
process.on('exit', function () {
// Exit with non-zero status if there were failures.
process.exit(failures);
});
});