Testing Engines with ember-qunit >= 3.4


#1

When testing an Ember Engine, we want to run acceptance tests with the dummy app, but unit and integration tests with the engine itself. We found a solution, and I wanted to share it for others and to see if there’s a better way.

We want most tests to use the engine’s resolve so that this.lookup('component:my-button') finds the engine’s component (from the addon/ directory):

// tests/test-helper.js
import { start } from 'ember-qunit';
import { setResolver } from 'ember-test-helpers';
import engineResolverFor from 'ember-engines/test-support/engine-resolver-for';
 
setResolver(engineResolverFor('my-engine-name'));
 
start();

But for acceptance tests, we want to set up the dummy application so that we have a full application to run, like so:

import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, currentURL } from '@ember/test-helpers';

module('basic acceptance test', function(hooks) {
  setupApplicationTest(hooks);

  test('can visit /', async function(assert) {
    await visit('/');
    assert.equal(currentURL(), '/');
  });
});

Because we never called setApplication (as described in the ember-qunit readme), this will fail. But once we call setApplication, it will override the setResolver call and all unit and integration tests will fail. So we came up with a custom “setup” function that uses setupApplicationTest under the hood:

// tests/helpers/dummy.js
import Application from '../../app';
import config from '../../config/environment';
import { setApplication } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
 
export function setupDummyApplicationTest({ beforeEach, afterEach }, options) {
  const hooks = {
    beforeEach(fn) {
      return beforeEach(function(...args) {
        setApplication(Application.create(config.APP));
        return fn.apply(this, args);
      });
    },
 
    afterEach(fn) {
      return afterEach(function(...args) {
        setApplication(null);
        return fn.apply(this, args);
      });
    }
  };
 
  setupApplicationTest(hooks, options);
}

So we can fix the above example by swapping setupApplicationTest with setupDummyApplicationTest. And calling setApplication(null) in afterEach() allows the next test to use the engine’s resolver as specified in tests/test-helper.js.

Are there are any downsides to this approach? Or: is there a better pattern we should be using?