DOES IT
WORK

ALL TOGETHER

https://upload.wikimedia.org/wikipedia/commons/0/07/HTS_Systems_UPS_Ground_shipments.jpg
https://twitter.com/gdinwiddie/status/690726656449839104

ACCEPTANCE

tests in SPA

WHAT
HOW
EXAMPLE

WHAT
HOW
EXAMPLE

Pieces work together (routing, components, services, server comunication)

Acceptance

Integration

Unit

Acceptance

Unit

Integration

Testing Triangle

SPA Testing

WHAT
HOW
EXAMPLE

Mirage

Mock
Test Helpers
ember-simple-auth

Page
Object

ES8

WHAT
HOW

EXAMPLE

Pieces work together (routing, components, services, server comunication)

// tests/acceptance/mail-logs-test.js
import { describe, it, beforeEach, afterEach } from 'mocha';
import { expect } from 'chai';
import { before, after } from 'cl-app/tests/helpers/module-for-acceptance-authenticated';

describe('Acceptance | mail logs', function() {
  it('/mail-logs works', async function() {
    beforeEach(before);
    afterEach(after);


    // LISTING


    // ADD


    // EDIT

  });
});


// tests/helpers/module-for-acceptance-authenticated.js

import startApp from 'cl-app/tests/helpers/start-app';
import destroyApp from 'cl-app/tests/helpers/destroy-app';
import { authenticateSession } from 'cl-app/tests/helpers/ember-simple-auth';

const sessionData = {
  idToken: 1
};

let application;

export function before() {
  application = startApp();
  authenticateSession(application, sessionData);
}

export function after() {
  destroyApp(application);
}
// tests/acceptance/mail-logs-test.js
// ...

describe('Acceptance | mail logs', function() {
  it('/mail-logs works', async function() {
    // ...


    // LISTING
    expect(currentURL()).to.equal('/mail-logs');
    expect(page.mailLogCount).to.equal(10);


    // ADD


    // EDIT

  });
});


// tests/acceptance/mail-logs-test.js
// ...
import page from 'cl-app/tests/pages/mail-logs';

describe('Acceptance | mail logs', function() {
  it('/mail-logs works', async function() {
    // ...
    server.createList('mailLog', 10);

    await page.visit();

    // LISTING
    expect(currentURL()).to.equal('/mail-logs');
    expect(page.mailLogCount).to.equal(10);


    // ADD


    // EDIT

  });
});


// tests/pages/mail-logs.js

import {
  clickable,
  count,
  create,
  fillable,
  text,
  visitable
} from 'ember-cli-page-object';

const rows = 'tbody > tr';

export default create({
  visit: visitable('/mail-logs'),

  mailLogCount: count(rows),
});
// tests/acceptance/mail-logs-test.js
// ...

describe('Acceptance | mail logs', function() {
  it('/mail-logs works', async function() {
    // ...
    // LISTING
    // ...
    server.create('category', { name: 'office' });
    server.create('company', { name: 'selleo inc.' });

    // ADD
    await page
      .formNew()
      .fillExternalNumber('200-212-123')
      .selectCompany('selleo')
      .selectCategory('office')
      .submit();

    expect(page.mailLogCount).to.equal(11);
    expect(page.onMailLog(10).text).to.include('200-212-123');
    expect(server.db.mailLogs[10].externalNumber).to.equal('200-212-123');


    // EDIT

  });
});


import { clickable, count, create, fillable, text, visitable } from 'ember-cli-page-object';

const newForm = '.card-header';
const rows = 'tbody > tr';
const expandedRow = `${rows}.lt-expanded-row`;

export default create({
  // ...

  formNew() {
    return this._form(newForm);
  },

  _form(scope) {
    return create({
      scope,
      fillExternalNumber: fillable('input', { at: 1 }),
      fillCompany: fillable('input', { at: 2 }),
      fillCategory: fillable('input', { at: 4 }),
      clickFirstSuggestion: clickable('.md-autocomplete-suggestions li', { resetScope: true }),
      selectCompany(company) {
        return this.fillCompany(company).clickFirstSuggestion();
      },
      selectCategory(category) {
        return this.fillCategory(category).clickFirstSuggestion();
      },

      submit: clickable('button')
    });
  }
});
import { describe, it, beforeEach, afterEach } from 'mocha';
import { expect } from 'chai';
import { before, after } from 'cl-app/tests/helpers/module-for-acceptance-authenticated';
import page from 'cl-app/tests/pages/mail-logs';

describe('Acceptance | mail logs', function() {
  this.timeout(7000);
  beforeEach(before);
  afterEach(after);

  it('/mail-logs works', async function() {
    server.create('category', { name: 'office' });
    server.create('company', { name: 'selleo inc.' });
    server.createList('mailLog', 10);

    await page.visit();

    // LISTING
    expect(currentURL()).to.equal('/mail-logs');
    expect(page.mailLogCount).to.equal(10);

    // ADD
    await page.formNew()
      .fillExternalNumber('200-212-123')
      .selectCompany('selleo')
      .selectCategory('office')
      .submit();

    expect(page.mailLogCount).to.equal(11);
    expect(page.onMailLog(10).text).to.include('200-212-123');
    expect(server.db.mailLogs[10].externalNumber).to.equal('200-212-123');

    // EDIT
    await page.onMailLog(1).click()
      .formEdit()
      .fillExternalNumber('300-323-234')
      .submit();

    expect(page.onMailLog(1).text).to.include('300-323-234');
    expect(server.db.mailLogs[1].externalNumber).to.equal('300-323-234');
  });
});

https://twitter.com/gdinwiddie/status/690726656449839104

Mirage

Mock
Test Helpers
ember-simple-auth

Page
Object

ES8

# config/application.rb
require_relative 'boot'

# require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
# require "active_job/railtie"
require "active_record/railtie"
# require "action_controller/railtie"
# require "action_mailer/railtie"
# require "action_view/railtie"
# require "action_cable/engine"
# require "sprockets/railtie"
# require "rails/test_unit/railtie"


# app/controllers/application_controller.rb
class ApplicationController < JSONAPI::ResourceControllerMetal
  include Knock::Authenticable

  before_action :authenticate_user

  # it's for knock only, and this is very naive implementation of head method
  def head(type, options = {}) ... end
end

Acceptance Testing JavaScript Apps

By Michał Czyż

Acceptance Testing JavaScript Apps

HaXorZ

  • 1,286