1.0.2 • Published 6 years ago

mocha-api-errors v1.0.2

Weekly downloads
3
License
MIT
Repository
github
Last release
6 years ago

mocha-api-errors

Print full API responses in your Mocha tests when you get an unexpected response.

npm version Dependency Status Build Status Coverage Status License

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 to res.
  • 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's fail runner event). It defaults to simply returning the test property defined by the responseProperty 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's fail runner event). It defaults to returning the err property of the last failure (taken from the this.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);
  });
});