Ember Testing

Improvements 🚀 

12/07/2017

Alex Alvarez

  •      @alexalvarez_dev
  •      @alexander-alvarez
  •      @alexander-alvarez 

Full-Stack Developer in NYC

Here to talk to you about....

Testing in Ember

RFC 232 & RFC 268

moduleForComponent(/* */);

moduleForAcceptance(/* */);

moduleForModel(/* */);
// moduleForModel
// moduleForComponent(/* unit test */)
setupTest(hooks);

// moduleForComponent(/* integration test */)
setupRenderingTest(hooks);

// moduleForAcceptance
setupApplicationTest(hooks);


Integration Test

// **** before ****

import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('x-foo', {
  integration: true
});

test('renders', function(assert) {
  assert.expect(1);

  this.render(hbs`{{pretty-color name="red"}}`);

  assert.equal(this.$('.color-name').text(), 'red');
});

// **** after ****

import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

module('x-foo', function(hooks) {
  setupRenderingTest(hooks);

  test('renders', async function(assert) {
    assert.expect(1);

    await this.render(hbs`{{pretty-color name="red"}}`);

    assert.equal(this.$('.color-name').text(), 'red');
  });
});

Component Unit Test

// **** before ****

import { moduleForComponent, test } from 'ember-qunit';

moduleForComponent('x-foo', {
  unit: true
});

test('computes properly', function(assert) {
  assert.expect(1);

  let subject = this.subject({
    name: 'something'
  });

  let result = subject.get('someCP');
  assert.equal(result, 'expected value');
});

// **** after ****

import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('x-foo', function(hooks) {
  setupTest(hooks);

  test('computed properly', function(assert) {
    assert.expect(1);

    let Factory = this.owner.factoryFor('component:x-foo');
    let subject = Factory.create({
      name: 'something'
    });

    let result = subject.get('someCP');
    assert.equal(result, 'expected value');
  });
});

Service Test

// **** before ****

import { moduleFor, test } from 'ember-qunit';

moduleFor('service:flash', 'Unit | Service | Flash', {
  unit: true
});

test('should allow messages to be queued', function (assert) {
  assert.expect(4);
  
  let subject = this.subject();
  
  subject.show('some message here');
  
  let messages = subject.messages;
  
  assert.deepEqual(messages, [
    'some message here'
  ]);
});

// **** after ****
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Service | Flash', function(hooks) {
  setupTest(hooks);
  
  test('should allow messages to be queued', function (assert) {
    assert.expect(4);
  
    let subject = this.owner.lookup('service:flash');
  
    subject.show('some message here');
  
    let messages = subject.messages;
  
    assert.deepEqual(messages, [
      'some message here'
    ]);
  });
});

Acceptance Test

(RFC 268 still being implemented)

// **** before ****
import { test } from 'qunit';
import moduleForAcceptance from '../helpers/module-for-acceptance';

moduleForAcceptance('Acceptance | posts');

test('should add new post', function(assert) {
  visit('/posts/new');
  fillIn('input.title', 'My new post');
  click('button.submit');
  andThen(() => assert.equal(find('ul.posts li:first').text(), 'My new post'));
});

// **** after ****
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, fillIn, click } from '@ember/test-helpers';

module('Acceptance | login', function(hooks) {
  setupApplicationTest(hooks);

  test('should add new post', async function(assert) {
    await visit('/posts/new');
    await fillIn('input.title', 'My new post');
    await click('button.submit');

    assert.equal(this.element.querySelectorAll('ul.posts li')[0].textContent, 'My new post');
  });
});

Why?

  • Eliminate confusion around `moduleFor*`
    • Clarifying what comes from `qunit` vs `ember-qunit`
  • Enable use of QUnit 2.0 features (nested modules anyone?)
  • Class vs. function based 
    • is-a -> has-a
    • "I need a rendering context"
    • "I need an application"

 

 

What does an "integration test" even mean?

Cool... How do I use it?

ember install ember-cli-qunit@^4.1.1

And start using it.

jscodeshift -t https://rawgit.com/rwjblue/ember-qunit-codemod/master/ember-qunit-codemod.js ./tests

And should have all* your tests passing in the new style.

But

* Please open up bugs if edge cases are discovered https://github.com/rwjblue/ember-qunit-codemod

codemod

But...

But the blueprints & guides don't recommend this

 

Yet...

Quest Issue ( A day Ago)

pollyfill for those not on Ember 2.17+

Similar push needed for ember-data blueprints

Thanks to

@rwjblue

@tbieniek

& anyone helping to push testing along

Ember Testing

By Alex Alvarez

Ember Testing

Updates to APIs leveraging QUnit, RFC 232 and 268

  • 437