Manual Reference Source Test

Build Status Coverage Status semantic-release Documentation Greenkeeper badge PRs Welcome

Fetch-mock-fixtures (FMF)

While most of mockers for fetch are only meant to intercept and define the next response content, FMF goes far beyond and offers a wide range of tools for testing js apps.

What is featured :

For instance, with FMF, you can do such things to quickly configure two fixtures in a mocha test (that will obviously succeed) :

import Server from 'fetch-mock-fixtures';

const server = new Server();

describe('Headers test', function() {
  before(() => server.start()) // Start intercepting fetch calls
  after(() => server.stop()) // Restore to normal behavior

  it('should use json headers', async function() {
    server
      .when // or .on
        .header('content-type').equal(/json/) // use a regexp here to avoid writing full header
        .respond.with.preset('200')
      .fallback.to.preset('400')

    let response = await fetch('/', {
      headers: {'content-type': 'application/json'}
    });

    response.status.should.equal(200);
  })
})

How FMF can ease API outgoing requests unit tests ?

FMF enables really quick response configuration that allows testing the outgoing request to set up different responses (see above example). You only have to check a response property (like status) instead of manually parsing request built by your app to validate it.

Furthermore, you can use the before and after hooks or body as a callback to alter response on very precise expectations.

How FMF can ease functional tests ?

In real life, scripts are often sending multiple requests to do their job. FMF removes the pain of handling multiple responses by easing their management. Let's see this example with a two steps authentication login. A bit verbose for what is actually doing but it aims to illustrate things :

import Server from 'fetch-mock-fixtures';

const server = new Server();

// Define on-the-fly fixtures to handle login tests
server
  .verbose(true) // Enable console login for each request/response/error
  .when
      .pathname.equal('/login')
      .method.equal('POST')
      .body('json').equal(body => body.username === 'foo')
    .respond.with
      .preset(401)
  .when
      .pathname.equal('/session')
      .method.equal('POST')
      .body('json').equal(token => body.authToken === '123')
    .respond.with
      .preset('json')
      .body({success: true, sessionToken: '456'})
  .fallback.to
    .preset(403)

describe('Login test suite', function() {
  before(() => server.start())
  after(() => server.stop())

  it('should login', async function() {
    await triggerTheLoginLogic('foo');
    await sendTheTokenLogic('123');
    logged.should.be.true;
  })

  it('should fail login on username', async function() {
    await triggerTheLoginLogic('bar');
    logged.should.be.false;
  })

  it('should fail login on token', async function() {
    await triggerTheLoginLogic('foo');
    await sendTheTokenLogic('hacked!');
    logged.should.be.false;
  })
})

We're not only sending back data to the app but also checking outgoing requests at the same time because the answer will only be sent if calling the right url with the right method and the right data. with and to are only optional sugars to improve human readability.

Last not least, you can easily deploy url-based routing to use your "real" data inside each tests instead of providing fake data and get rid of on-the-fly fixtures (see dynamic fixtures examples).

When to use FMF ?

At any time :smile:

Nevertheless, FMF will truly give its best with any testing framework (Mocha, Jasmine, Junit...) that allows to automate operations between each tests like start, stop or reset the server.

Installation

Installation can easily be done through NPM or Yarn. Sinon is required by FMF to stub fetch but is not included in the bundle. It must be installed as well if not already present.

npm install sinon fetch-mock-fixtures --save-dev

yarn add sinon fetch-mock-fixtures --dev

FMF should be installed as a dev dependency. It is not meant to be used as an in-app offline mode feature.

Note : FMF is built upon Promise, Proxy and fetch API (Request, Headers, Response) that are available in all modern browsers. If you intend to run tests on older browsers (IE) or versions, you may need to polyfill them. Here's some available tools you can use :

Full documentation and API reference

Please pay visit to the docs pages.

Bugs and improvements

Any bugs and issues can be filed on the github repository.

You are free and very welcome to fork the project and submit any PR to fix or improve FMF.

I'm especially interested for good will who wish to improve query matcher processors to provide more tools to evaluate query and choose the right response.

Changelog