Ember-CLI with integration tests with .json files


#1

TL;DR How do I access .json files locally in test files for fixture data when running ember test from cli?

I have a ember cli application that is using a rails app as an API. These are two different repos. I am trying to set up a fixtures directory that will be identical between the two apps so we can ensure that changes will not break either side.

This is working in when I run tests from the /tests route because I have the fixtures directory in public assets and am using $.getJson to access the json in the tests. Ideally, I would be able to keep the files in the tests directory and access them locally when running ember test.

My current setup is:

json-fixture.js:

import Ember from "ember";

var JsonFixture = {
  load( test_module, path ) {
    return new Ember.RSVP.Promise(function (resolve, reject) {
      var url = `http://localhost:4200/assets/fixtures/${path}.json`;
      $.getJSON(url).done(function (data) {
        resolve(data);
      }).fail(function (request, status, error) {
        var handleFailure = function() {
          module(test_module);
          test("Data should have been loaded", function() {
            ok(false, `${request.responseText.trim()} in '${test_module}'`);
          });
        };
        reject(handleFailure);
      });
    });
  }
};

export default JsonFixture;

Then the test file can look like:

import Ember from 'ember';
import startApp from 'prohub/tests/helpers/start-app';
import Pretender from 'pretender';
import JsonFixture from 'prohub/tests/helpers/json-fixture';

var App,
    server,
    store,
    test_module = "Integration - Customers Page",
    path = "customers/index/default";

JsonFixture.load(test_module, path).then(function (customers_json) {

  var config = {
    setup: function() {
      App = startApp();
      authenticateSession();
      server = new Pretender(function() {
        this.get('/api/customers', function(request) {
          return [200, {"Content-Type": "application/json"}, JSON.stringify(customers_json)];
        });
        this.get('/api/customers/:id', function(request) {
          var customer = customers_json.customers.find(function(customer) {
            if (customer.id === parseInt(request.params.id, 10)) {
              return customer;
            }
          });

          return [200, {"Content-Type": "application/json"}, JSON.stringify({customer: customer})];
        });
      });
    },
    teardown: function() {
      Ember.run(App, 'destroy');
      server.shutdown();
    }
  };

  module(test_module, config);

  var customerName = function(n) {
    var customer = customers_json.customers[n - 1];
    return `${customer.first_name} ${customer.last_name}`;
  };

  test('Should allow navigation to the customers page from the landing page', function() {
    visit('/').then(function() {
      click('a:contains("Customers")').then(function() {
        equal(find('h3').text(), 'Customers');
      });
    });
  });

  test('Should list all customers', function() {
    visit('/customers').then(function() {
      equal(find(`a:contains("${customerName(1)}")`).length, 1);
      equal(find(`a:contains("${customerName(2)}")`).length, 1);
      equal(find(`a:contains("${customerName(3)}")`).length, 1);
      equal(find(`a:contains("${customerName(4)}")`).length, 1);
    });
  });

  test('Should be able to navigate to a customer page', function() {
    visit('/customers').then(function() {
      click(`a:contains("${customerName(1)}")`).then(function() {
        equal(find('h4').text(), customerName(1));
      });
    });
  });

  test('Should be able visit a customer page', function() {
    visit('/customers/' + customers_json.customers[0].id).then(function() {
      equal(find('h4').text(), customerName(1));
    });
  });
}, function (handleError) {
  handleError();
});

#2

The “best” way I found to fix this is to use symlinks from (your JSON folder) into (your app folder)/public, and fixup the URLs to load from, depending on the environment (in case the paths are different at test/dev/deploy time). It’s not pretty, but it works.

http mocks are almost the right answer, but those don’t work when running tests. https://github.com/ember-cli/ember-cli/issues/1763 is the issue for that, but the pull request that fixes it still needs work.