Skip to content

Commit

Permalink
update(testing): upd. acc. test code examples (emberjs/ember.js#15933)
Browse files Browse the repository at this point in the history
This updates the acceptance testing section including its code examples
according to the new Ember Qunit Pattern proposed through RFC#268.
  • Loading branch information
jayjayjpg committed Feb 12, 2018
1 parent 12749fc commit c1151a7
Showing 1 changed file with 53 additions and 57 deletions.
110 changes: 53 additions & 57 deletions source/testing/acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,46 @@ ember g acceptance-test login
This generates this file:

```tests/acceptance/login-test.js
import { test } from 'qunit';
import moduleForAcceptance from 'my-app/tests/helpers/module-for-acceptance';
import { module, test } from 'qunit';
import { visit } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';

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

test('visiting /login', function(assert) {
visit('/login');

andThen(function() {
test('visiting /login', async function(assert) {
await visit('/login');
assert.equal(currentURL(), '/login');
});
});
```

`moduleForAcceptance` deals with application setup and teardown. The last few lines, within
the function `test`, contain an example test.
`module` allows you to scope your tests: Any test setup that is done inside of this scope will
apply to all test cases contained in this module.
Scoping your tests with `module` also allows you to execute your tests independently from other tests.
For example, to only run your tests from your `login` module, run `ember test --module='Acceptance | login'`.
`setupApplicationTest` deals with application setup and teardown.
The `test` function contains an example test.

Almost every test has a pattern of visiting a route, interacting with the page
(using the helpers), and checking for expected changes in the DOM.

For example:

```tests/acceptance/new-post-appears-first-test.js
import { test } from 'qunit';
import moduleForAcceptance from 'my-app/tests/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'));
import { module, test } from 'qunit';
import { click, fillIn, visit } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';

module('Acceptance | posts', 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.querySelector('ul.posts li').textContent, 'My new post');
});
});
```

Expand Down Expand Up @@ -74,10 +81,7 @@ types of helpers: **asynchronous** and **synchronous**.
Asynchronous helpers are "aware" of (and wait for) asynchronous behavior within
your application, making it much easier to write deterministic tests.

Also, these helpers register themselves in the order that you call them and will
be run in a chain; each one is only called after the previous one finishes. You can rest assured, therefore, that the order you call them in will also
be their execution order, and that the previous helper has finished before the
next one starts.
Some of these handy helpers are:

* [`click(selector)`][1]
- Clicks an element and triggers any actions triggered by the element's `click`
Expand All @@ -96,6 +100,32 @@ next one starts.
- Visits the given route and returns a promise that fulfills when all resulting
async behavior is complete.

You can find the full list of helpers in the [API Documentation of ember-test-helpers](https://github.com/emberjs/ember-test-helpers/blob/master/API.md).

The asynchronous test helpers from `@ember/test-helpers` are meant to be used together with the [ES2017 feature async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) to write easy-to-read tests which
deal with asynchronous behavior as follows:

Mark the callback passed to the `test` function as asynchronous using the `async` keyword:

```tests/acceptance/new-post-appears-first-test.js
test('should add new post', async function(assert) {

});
```
Before making an assertion, wait for the execution of each asynchronous helper to finish with the `await` keyword:

```tests/acceptance/new-post-appears-first-test.js
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.querySelector('ul.posts li').textContent, 'My new post');
});
```

Once we `await` the execution of the asynchronous helpers this way, we will ensure that all subsequent assertions are always made **after** the
previous steps in the test have completed.

### Synchronous Helpers

Synchronous helpers are performed immediately when triggered.
Expand All @@ -112,40 +142,6 @@ Synchronous helpers are performed immediately when triggered.
conflicts with the test framework's reporter, and this is done by default
if the context is not specified.

### Wait Helpers

The `andThen` helper will wait for all preceding asynchronous helpers to
complete prior to progressing forward. Let's take a look at the following
example.

```tests/acceptance/new-post-appears-first-test.js
import { test } from 'qunit';
import moduleForAcceptance from 'my-app/tests/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'));
});
```

First we visit the new posts URL "/posts/new", enter the text "My new post"
into an input control with the CSS class "title", and click on a button whose
class is "submit".

We then make a call to the `andThen` helper which will wait for the preceding
asynchronous test helpers to complete (specifically, `andThen` will only be
called **after** the new posts URL was visited, the text filled in and the
submit button was clicked, **and** the browser has returned from doing whatever
those actions required). Note `andThen` has a single argument of the function
that contains the code to execute after the other test helpers have finished.

In the `andThen` helper, we finally make our call to `assert.equal` which makes an
assertion that the text found in the first li of the ul whose class is "posts"
is equal to "My new post".

[1]: http://emberjs.com/api/classes/Ember.Test.html#method_click
[2]: http://emberjs.com/api/classes/Ember.Test.html#method_fillIn
Expand Down

0 comments on commit c1151a7

Please sign in to comment.