We will review how to install and use Ember Mirage, a Ember CLI Addon that allows you to mock server requests and response and provides a fixture strategy.

Installation

You can get more information in Mirage installation page, but you can use:

ember install ember-cli-mirage

This will setup a mirage folder which contains the following subfolders:

  • models: they represent a mirage-base model (don’t confuse with ember-data models), and they are use to understand what kind of attributes and relations they have between them.
  • fixtures: You can insert here raw endpoint data, is the faster way to start populating some data.
  • factories: A smart way to create endpoint data, allows you to define dynamic logic.
  • scenarios: Use this to change your development data without affecting your tests.
  • serializers: You can use to change the format of the server response.

Setup the code

We are going to focus on creating some sort of dummy login feature, the objective is to be able to mock using Mirage 2 scenarios, the first one is the scenario when the login is valid, in which case we should redirect to the index route. Otherwise we will show an authentication error.

We will use the help of a service and a component, they look pretty much like this:

// app/services/session.js
export default Service.extend({
    user: null,

    isLoggedIn: computed.bool('user'),
    isLoginError: false,

    login: function(username) {
        return this.$.post('http://localhost:8080/api/v1/user/login', {username} ).then((data) => {
            if (!data.error) {
                this.set('user', data.user);
            }
        }).catch(() => {
            this.set('isLoginError', true);
        });
    },
});

Note that as today, mirage does not support fetch by default, issue 983, now lets define our first integration test:

Create the user model

We can do this with the following command:

ember g mirage-model user

Create user factory

We need some user to test against, for that we can create a simple fixture like this one:

// mirage/factories/users.js
import { Factory } from 'ember-cli-mirage';

export default Factory.extend({
    id: 1,
    name: 'Rastikko'
});


Handle mirage Response

Now we need to create the Route Handler to handle both cases, the one that the user is not authorized (anything but the already created user), or the success case:

// mirage/config.js
this.post('/users/login', (schema, request) => {
    const name = JSON.parse(request.requestBody).name;
    if (name !== 'Rastikko') {
        return new Mirage.Response(401, {}, {message: 'Unauthorized'});
    }
    return schema.users.findBy({name});
});

Create the acceptance tests

Considering we have the component logic ready to display some sort of element with an error selector if the service returns an error or redirect to the index route if it went through, we can create an acceptance test like this:

import { test } from 'qunit';

import moduleForAcceptance from 'erudite-battles-client/tests/helpers/module-for-acceptance';

moduleForAcceptance('Acceptance | login');

test('visiting /login', function(assert) {
  server.create('user');
  visit('/users/create');

  andThen(function() {
    assert.equal(currentURL(), '/users/create');
    fillIn('input.login-input', 'Faker');
    click('button.login-btn');
    // little hack to ensure rerender
    visit('/users/create');
    andThen(function() {
        assert.equal(find('div.alert-danger').text().trim(), 'User not found.');
    });
  });
});