The Next Generation of Testing

@mikoscz
Michał Staśkiewicz


Old fashion
New kids on the block
Migration
Agenda
Old fashion way
moduleFor()
moduleForModel()
moduleForComponent()
moduleForAcceptance()
?
Terrible asynchronous syntax
andThen()
andThen()
andThen()
andThen()
:<
andThen()
import { test } from 'qunit';
import moduleForAcceptance from 'some-app/tests/helpers/module-for-acceptance';
moduleForAcceptance('Acceptance | users');
test('should add new uesr', function(assert) {
  visit('/users/new');
  fillIn('input.email', 'm.staskiewicz@selleo.com');
  click('button.submit');
  andThen(() => assert.equal(find('ul.users li:first').text(), 'm.staskiewicz@selleo.com'));
});ECMAScript 2017 FTW!
(async/await syntax)
import { test } from 'qunit';
import moduleForAcceptance from 'some-app/tests/helpers/module-for-acceptance';
moduleForAcceptance('Acceptance | users');
test('should add new uesr', async function(assert) {
  await visit('/users/new');
  await fillIn('input.email', 'm.staskiewicz@selleo.com');
  await click('button.submit');
  assert.equal(find('ul.users li:first').text(), 'm.staskiewicz@selleo.com');
});jQuery :<
import { test } from 'qunit';
import moduleForAcceptance from 'some-app/tests/helpers/module-for-acceptance';
moduleForAcceptance('Acceptance | users');
test('should add new uesr', async function(assert) {
  await visit('/users/new');
  await fillIn('input.email', 'm.staskiewicz@selleo.com');
  await click('button.submit');
  assert.equal(find('ul.users li:first').text(), 'm.staskiewicz@selleo.com');
});jQuery :<
await click('button.submit');
assert.equal(find('ul.users li:first').text(), 'm.staskiewicz@selleo.com');Super
Awesome
Speed
Beautifull
Lovely
The world without jQuery <3
import { click, find } from 'ember-native-dom-helpers';
await click('button.submit');
assert.equal(find('ul.users li:first').textContent, 'm.staskiewicz@selleo.com');ember install ember-native-dom-helpers
RFC #232
"Add new QUnit testing API"
module()
setupTest()
setupRenderingTest()
RFC #268
// old
moduleForAcceptance()
// new
module()
setupAcceptanceTest()Plain QUnit tests
import { module, test } from 'qunit';
module('relativeDate', function(hooks) {
  test('format relative dates correctly', function() {
    assert.equal(relativeDate('2018/03/25 19:40:10'), 'just now');
  });
});Container tests
- Test with access to the container(Services, Routes, Controllers)
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Service | events-counter', function(hooks) {
  setupTest(hooks);
  test('it counts events', function(assert) {
    const service = this.owner.lookup('service:events-counter');
    service.addEvent('first');
    service.addEvent('second');
    assert.equal(service.get('eventsCount'), 2);
  });
});Rendering tests
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, click } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Component | counter', function(hooks) {
  setupRenderingTest(hooks);
  test('it counts clicks', async function(assert) {
    this.set('count', 0);
    await render(hbs`{{click-counter value=value ...}}`);
    assert.equal(this.element.textContent, '0 clicks');
    await click('.counter');
    assert.equal(this.element.textContent, '1 clicks');
  });
});Acceptance tests
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, fillIn, click } from '@ember/test-helpers';
module('Acceptance | users', function(hooks) {
  setupApplicationTest(hooks);
  test('should add new user', async function(assert) {
    await visit('/users/new');
    await fillIn('input.email', 'm.staskiewicz@selleo.com');
    await click('button.submit');
    const email = this.element.querySelector('ul.users li:first').textContent;
    assert.equal(email, 'm.staskiewicz@selleo.com');
  });
});Cool!
But how to use it?
ember install
ember-cli-qunit 4.2.0 <(works from ember 2.4.x <)
Migration
1. async/await syntax
2. ember-native-dom-helpers
(ember-native-dom-helpers-codemod)
3. moduleFor() -> setupTest()
(ember-qunit-codemod)
4. (at)ember/test-helpers
(ember-test-helpers-codemod)
@ -> (at) awesome font without at sing :'<
Helpful stuff
Loading state
test('shows loading spinner after submitting', async function(assert) {
  await visit('/comments/new');
  await fillIn('input.comment', 'Hello there');
  const promise = click('.submit');
  await waitFor('.loading-spinner');
  assert.ok(find('.spinner'));
  await promise;
  assert.ok(find('.some-success-notify'));
});Custom Test Helpers
old registerAsyncHelper()
export async function createAccount(email) {
  await fillIn('#email', email);
  await click('button.submit');
}Test Selectors
// template.hbs
<h1>{{title}}</h1>
<input class="title-field">
// test.js
await fillIn('.title-field', 'Hello from field');
const title = this.element.querySelector('h1').textContent;
assert.equal(title, 'Hello from field');// template.hbs
<h1 data-test-title>{{title}}</h1>
<input class="title-field" data-test-title-field>
// test.js
await fillIn('[data-test-title-field]', 'Hello from field');
const title = this.element.querySelector('[data-test-title').textContent;
assert.equal(title, 'Hello from field');ember install ember-test-selectors
Awesome!
Now make it readable
const title = this.element.querySelector('[data-test-title').textContent;
assert.equal(title, 'Hello from field');assert.dom('[data-test-title]').hasText('Hello from field');qunit-dom
qunit -dom
assert.dom('h1').exists();
assert.dom('h1').hasClass('title');
assert.dom('h1').hasText('Welcome to Ember, John Doe!');
assert.dom('input').isFocused();
assert.dom('input').hasValue(/.+ Doe/);
assert.dom('input').hasAttribute('type', 'text');sources:
The Next Generation of Testing in Ember.js by Tobias Bieniek
ember-cli-qunit
qunit-dom
EmberConf 2018 presentations
Thanks!
and keep testing your code!

The Next Generation of Testing in Ember.js
By Michał Staśkiewicz
The Next Generation of Testing in Ember.js
- 933
 
   
   
  