From 4ec916bd45a03264bffd368f5a31d47869bb8499 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 5 Nov 2017 19:09:52 -0500 Subject: [PATCH 01/27] Rethink Acceptance Testing --- text/0268-acceptance-testing-refactor.md | 224 +++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 text/0268-acceptance-testing-refactor.md diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md new file mode 100644 index 0000000000..82d5983330 --- /dev/null +++ b/text/0268-acceptance-testing-refactor.md @@ -0,0 +1,224 @@ +- Start Date: 2017-11-05 +- RFC PR: [emberjs/rfcs#268](https://github.com/emberjs/rfcs/pull/268) +- Ember Issue: (leave this empty) + +# Summary + +The testing story in Ember today is better than it ever has been. It is now +possible to test individual component/template combos, register your own mock +components/services/etc, build complex acceptance tests, and almost anything else +you would like. + +Unfortunately, there is a massive disparity between different types of tests. +In acceptance tests, you use well designed global helpers to deal with async +related interactions; whereas in integration and unit tests you are forced to +manually deal with this asynchrony. The goal of this RFC is to unify the +concepts amongst the various types of test and provide a single common +structure to tests. + + +# Motivation + +Usage of rendering tests is becoming more and more common, but these tests +often still include manual event delegation (`this.$('.foo').click()` for +example), and assumes most (if not all) interactions are synchronous. This is +a major issue due to the fact that the vast majority of interactions will +actually be asynchronous. There have been a few recent additions to +`ember-test-helpers` that have made dealing with asynchrony better (namely +[emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md) +but forcing users to manually manage all interaction based async is a recipe +for disaster. + +Acceptance tests allow users to handle asynchrony with ease, but they rely on +global helpers that automatically wrap a single global promise which makes +testing of interleaved asynchronous things more difficult. There are a number +of limitations in acceptance tests as compared to integration tests (cannot +mock and/or stub services, cannot look up services to setup test context, etc). + +We need a single unified way to teach and understand testing in Ember that +leverages all the things we learned with the original acceptance testing +helpers that were introduced in Ember 1.0.0. Instead of inventing our own +syntax for dealing with the async (`andThen`) we should use new language +features such as `async` / `await`. + +# Detailed design + +The goal of this RFC is to introduce new system for acceptance tests that follows in the footsteps of +[emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md) +and continues to enhance the system created in that RFC to share the same structure and helper system. + +This new system for acceptance tests will be implemented in the +[ember-test-helpers](https://github.com/emberjs/ember-test-helpers/) library so +that we can iterate faster while supporting multiple Ember versions +independently and easily support multiple testing frameworks build on top of +the primitives in `ember-test-helpers`. Ultimately, the existing [ember-testing](https://github.com/emberjs/ember.js/tree/master/packages/ember-testing) system +will be deprecated but that deprecation will be added well after the new system has been +released and adopted by the community. + +Lets take a look at a basic example (lifted from [the guides](https://guides.emberjs.com/v2.16.0/testing/acceptance/)): + +```js +// **** 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 { setupAcceptanceTest } from 'ember-qunit'; +import { visit, fillIn, click } from 'ember-test-helpers'; + +module('Acceptance | login', function(hooks) { + setupAcceptanceTest(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(find('ul.posts li')[0].textContent, 'My new post'); + }); +}); +``` + +As you can see, this proposal is unifies on Qunit's nested module syntax following +in emberjs/rfcs#232's footsteps. + +## New APIs Proposed + +The following new methods will be exposed from `ember-qunit`: + +```ts +declare module 'ember-qunit' { + // ...snip... + export function setupAcceptanceTest(hooks: QUnitModuleHooks): void; +} +``` + +### `setupAcceptanceTest` + +This function will: + +* invoke `ember-test-helper`s `setupContext` with the tests context (which does the following): + * create an owner object and set it on the test context (e.g. `this.owner`) + * setup `this.set`, `this.setProperties`, `this.get`, and `this.getProperties` to + the test context + * setup `this.pauseTest` and `this.resumeTest` methods to allow easy pausing/resuming + of tests +* add routing related helpers + * setup `this.visit` method to visit the given url + * setup getter for `this.currentRouteName` which returns the current route name + * setup getter for `this.currentURL` which returns the current URL +* add DOM interaction helpers (heavily influenced by @cibernox's lovely addon [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers)) + * setup a getter for `this.element` which returns the DOM element representing + the root element + * if `jQuery` is present in the application sets up `this.$` method to run + jQuery selectors rooted to `this.element` + * setup `this.click` as an async helper to click on the specified selector + * setup `this.tap` as an async helper to tap on the specified selector + * setup `this.triggerKeyEvent` as an async helper to trigger a `KeyEvent` on the specified selector + * setup `this.triggerEvent` as an async helper to trigger an event on the specified selector + * setup `this.fillIn` as an async helper to enter text on the specified selector + * setup `this.waitUntil` as an async helper returning a promise which resolves when the provided callback returns a truthy value + * setup `this.focus` as an async helper which focuses the specified element + * setup `this.blur` as an async helper which unfocuses the specified element + +### `setupRenderingTest` + +The `setupRenderingTest` function proposed in +[emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md) +(and implemented in +[ember-qunit](https://github.com/emberjs/ember-qunit)@3.0.0) will be modified to add the same DOM interaction helpers: + +* setup a getter for `this.element` which returns the DOM element representing + the root element +* if `jQuery` is present in the application sets up `this.$` method to run + jQuery selectors rooted to `this.element` +* setup `this.click` as an async helper to click on the specified selector +* setup `this.tap` as an async helper to tap on the specified selector +* setup `this.triggerKeyEvent` as an async helper to trigger a `KeyEvent` on the specified selector +* setup `this.triggerEvent` as an async helper to trigger an event on the specified selector +* setup `this.fillIn` as an async helper to enter text on the specified selector +* setup `this.waitUntil` as an async helper returning a promise which resolves when the provided callback returns a truthy value +* setup `this.focus` as an async helper which focuses the specified element +* setup `this.blur` as an async helper which unfocuses the specified element + +Once implemented, `setupRenderingTest` and `setupAcceptanceTest` will diverge from each other in very few ways. + +### Importable helpers + +Since the design of this system relies on both the test helpers being applied +to the test context **and** the usage of `async` / `await`, a few importable +helpers are being introduced to help avoid extra noise (e.g. "rightward shift") +in tests. + +This means that users will be able to use either of the following interchangably: + +```js +// ***** importable helper ***** +import { click } from 'ember-test-helpers'; + +// ...snip... +test('does something', async function(assert) { + // ...snip... + await click('.selector-here'); + // ...snip... +}); + +// ***** test context helper ***** + +// ...snip... +test('does something', async function(assert) { + // ...snip... + await this.click('.selector-here'); + // ...snip... +}); +``` + +## Changes from Current System + +Here is a brief list of the more important but possibly understated changes +being proposed here: + +* The global test helpers that exist now, will no longer be present (e.g. + `click`, `visit`, etc) and instead will be available on the test context as + well as importable helpers. +* `this.owner` will now be present and allow (for the first time 🎉) overriding + items in the container/registry. + +## Migration + +It is quite important that both the existing acceptance testing system, and the +newly proposed system can co-exist together. This means that new tests can be generated +in the new style while existing tests remain untouched. + +However, it is quite likely that +[ember-qunit-codemod](https://github.com/rwjblue/ember-qunit-codemod) will be +able to accurately rewrite acceptance tests into the new format. + +# How We Teach This + +This change requires updates to the API documentation of `ember-qunit` and the +main Ember guides' testing section. The changes are largely intended to reduce +confusion, making it easier to teach and understand testing in Ember. + +# Drawbacks + +* This is a relatively large set of changes that are arguably not needed (things mostly work today). +* One of the major pains in upgrading larger applications to newer Ember versions, is updating their tests to follow "new" patterns. This RFC introduces yet another "new" thing (and proposes to deprecate the old thing), and could therefore be considered "just more churn". + +# Alternatives + +* The primary alternative to this would be to do nothing... + +# Unresolved questions + +TBD? From f779b71cbe32688d5080efbdd2e890f719948427 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 5 Nov 2017 19:19:23 -0500 Subject: [PATCH 02/27] Tweaks/corrections. --- text/0268-acceptance-testing-refactor.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 82d5983330..ed0bfa3164 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -20,7 +20,7 @@ structure to tests. # Motivation Usage of rendering tests is becoming more and more common, but these tests -often still include manual event delegation (`this.$('.foo').click()` for +often include manual event delegation (`this.$('.foo').click()` for example), and assumes most (if not all) interactions are synchronous. This is a major issue due to the fact that the vast majority of interactions will actually be asynchronous. There have been a few recent additions to @@ -193,14 +193,17 @@ being proposed here: well as importable helpers. * `this.owner` will now be present and allow (for the first time 🎉) overriding items in the container/registry. +* The new system will leverage the `Ember.Application` / `Ember.ApplicationInstance` split so that + we can avoid creating an `Ember.Application` instance per-test, and instead leverage the same system + that FastBoot itself uses to avoid running initializers for each acceptance test. ## Migration -It is quite important that both the existing acceptance testing system, and the +It is important that both the existing acceptance testing system, and the newly proposed system can co-exist together. This means that new tests can be generated in the new style while existing tests remain untouched. -However, it is quite likely that +However, it is likely that [ember-qunit-codemod](https://github.com/rwjblue/ember-qunit-codemod) will be able to accurately rewrite acceptance tests into the new format. @@ -213,12 +216,8 @@ confusion, making it easier to teach and understand testing in Ember. # Drawbacks * This is a relatively large set of changes that are arguably not needed (things mostly work today). -* One of the major pains in upgrading larger applications to newer Ember versions, is updating their tests to follow "new" patterns. This RFC introduces yet another "new" thing (and proposes to deprecate the old thing), and could therefore be considered "just more churn". +* One of the major hurdles in upgrading larger applications to newer Ember versions, is updating their tests to follow "new" patterns. This RFC introduces yet another "new" thing (and proposes to deprecate the old thing), and could therefore be considered "just more churn". # Alternatives * The primary alternative to this would be to do nothing... - -# Unresolved questions - -TBD? From 3ee1064dc344919f2a727e0176cbbb5b1778c5a7 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 5 Nov 2017 19:21:41 -0500 Subject: [PATCH 03/27] Tweak alternative. --- text/0268-acceptance-testing-refactor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index ed0bfa3164..5e0e58c6c1 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -220,4 +220,4 @@ confusion, making it easier to teach and understand testing in Ember. # Alternatives -* The primary alternative to this would be to do nothing... +* Do nothing? From cdbaecbf196a4f9108cf16117687a1f4314e2ba1 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 10:13:22 -0500 Subject: [PATCH 04/27] Fix typo in intro of detailed design. --- text/0268-acceptance-testing-refactor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 5e0e58c6c1..1598f5fd90 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -89,7 +89,7 @@ module('Acceptance | login', function(hooks) { }); ``` -As you can see, this proposal is unifies on Qunit's nested module syntax following +As you can see, this proposal unifies on Qunit's nested module syntax following in emberjs/rfcs#232's footsteps. ## New APIs Proposed From 3c577911adb30dd1c746b0ca5dd11f573ce315ef Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 10:14:44 -0500 Subject: [PATCH 05/27] Better document the DOM Helpers in the detailed design. --- text/0268-acceptance-testing-refactor.md | 116 +++++++++++++++++++---- 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 1598f5fd90..f1407a8b03 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -103,6 +103,84 @@ declare module 'ember-qunit' { } ``` +### DOM Interaction Helpers + +New native DOM interaction helpers will be added to both `setupRenderingTest` +and (proposed below) `setupAcceptanceTest`. The implementation for these +helpers has been iterated on and is quite stable in the +[ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers) +addon. + +The helpers will be migrated to `ember-test-helpers` and eventually +(once "the dust settles") `ember-native-dom-helpers` will be able to reexport +the versions from `ember-test-helpers` directly (which means apps that have +already adopted will have very minimal changes to make). + +The specific DOM helpers to be added are: + +``` +interface DOMInteractionHelpers { + /** + Clicks on the specified selector. + */ + click(selector: string | HTMLElement): Promise; + + /** + Taps on the specified selector. + */ + tap(selector: string | HTMLElement): Promise; + + /** + Triggers a keyboad event on the specified selector. + */ + triggerKeyEvent( + selector: string | HTMLElement, + eventType: 'keydown' | 'keypress' | 'keyup', + keyCode: string, + modifiers?: { + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false + } + ): Promise; + + /** + Triggers an event on the specified selector. + */ + triggerEvent( + selector: string | HTMLElement, + eventType: string, + eventOptions: any + ): Promise; + + /** + Fill in the specified selector's `value` property with the provided text. + */ + fillIn(selector: string | HTMLElement, text: string): Promise; + + /** + Focus the specified selector. + */ + focus(selector: string | HTMLElement): Promise; + + /** + Unfocus the specified selector. + */ + blur(selector: string | HTMLElement): Promise; + + /** + Returns a promise which resolves when the provided callback returns a truthy value. + */ + waitUntil(() => boolean): Promise; + + /** + Returns a promise which resolves when the provided selector (and count) becomes present. + */ + waitFor(selector: string, count?: number): Promise; +} +``` + ### `setupAcceptanceTest` This function will: @@ -119,37 +197,39 @@ This function will: * setup getter for `this.currentURL` which returns the current URL * add DOM interaction helpers (heavily influenced by @cibernox's lovely addon [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers)) * setup a getter for `this.element` which returns the DOM element representing - the root element + the root element * if `jQuery` is present in the application sets up `this.$` method to run jQuery selectors rooted to `this.element` - * setup `this.click` as an async helper to click on the specified selector - * setup `this.tap` as an async helper to tap on the specified selector - * setup `this.triggerKeyEvent` as an async helper to trigger a `KeyEvent` on the specified selector - * setup `this.triggerEvent` as an async helper to trigger an event on the specified selector - * setup `this.fillIn` as an async helper to enter text on the specified selector - * setup `this.waitUntil` as an async helper returning a promise which resolves when the provided callback returns a truthy value - * setup `this.focus` as an async helper which focuses the specified element - * setup `this.blur` as an async helper which unfocuses the specified element + * setup `this.click` helper method + * setup `this.tap` helper method + * setup `this.triggerKeyEvent` helper method + * setup `this.triggerEvent` helper method + * setup `this.fillIn` helper method + * setup `this.focus` helper method + * setup `this.blur` helper method + * setup `this.waitUntil` helper method + * setup `this.waitFor` helper method ### `setupRenderingTest` The `setupRenderingTest` function proposed in [emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md) (and implemented in -[ember-qunit](https://github.com/emberjs/ember-qunit)@3.0.0) will be modified to add the same DOM interaction helpers: +[ember-qunit](https://github.com/emberjs/ember-qunit)@3.0.0) will be modified to add the same DOM interaction helpers mentioned above: * setup a getter for `this.element` which returns the DOM element representing the root element * if `jQuery` is present in the application sets up `this.$` method to run jQuery selectors rooted to `this.element` -* setup `this.click` as an async helper to click on the specified selector -* setup `this.tap` as an async helper to tap on the specified selector -* setup `this.triggerKeyEvent` as an async helper to trigger a `KeyEvent` on the specified selector -* setup `this.triggerEvent` as an async helper to trigger an event on the specified selector -* setup `this.fillIn` as an async helper to enter text on the specified selector -* setup `this.waitUntil` as an async helper returning a promise which resolves when the provided callback returns a truthy value -* setup `this.focus` as an async helper which focuses the specified element -* setup `this.blur` as an async helper which unfocuses the specified element +* setup `this.click` helper method +* setup `this.tap` helper method +* setup `this.triggerKeyEvent` helper method +* setup `this.triggerEvent` helper method +* setup `this.fillIn` helper method +* setup `this.focus` helper method +* setup `this.blur` helper method +* setup `this.waitUntil` helper method +* setup `this.waitFor` helper method Once implemented, `setupRenderingTest` and `setupAcceptanceTest` will diverge from each other in very few ways. From 5e6c1bd2e34db47d6d5c1785c64be19a2493cdac Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 10:15:14 -0500 Subject: [PATCH 06/27] Clarify that `root element` meant the applications root element. --- text/0268-acceptance-testing-refactor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index f1407a8b03..3d9240f000 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -197,7 +197,7 @@ This function will: * setup getter for `this.currentURL` which returns the current URL * add DOM interaction helpers (heavily influenced by @cibernox's lovely addon [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers)) * setup a getter for `this.element` which returns the DOM element representing - the root element + the applications root element * if `jQuery` is present in the application sets up `this.$` method to run jQuery selectors rooted to `this.element` * setup `this.click` helper method From 12f4c7b09e728ad6276824e45c6ba71584a84e26 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 10:15:34 -0500 Subject: [PATCH 07/27] Remove `this.$` helper. --- text/0268-acceptance-testing-refactor.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 3d9240f000..a0201a3322 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -198,8 +198,6 @@ This function will: * add DOM interaction helpers (heavily influenced by @cibernox's lovely addon [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers)) * setup a getter for `this.element` which returns the DOM element representing the applications root element - * if `jQuery` is present in the application sets up `this.$` method to run - jQuery selectors rooted to `this.element` * setup `this.click` helper method * setup `this.tap` helper method * setup `this.triggerKeyEvent` helper method @@ -217,10 +215,6 @@ The `setupRenderingTest` function proposed in (and implemented in [ember-qunit](https://github.com/emberjs/ember-qunit)@3.0.0) will be modified to add the same DOM interaction helpers mentioned above: -* setup a getter for `this.element` which returns the DOM element representing - the root element -* if `jQuery` is present in the application sets up `this.$` method to run - jQuery selectors rooted to `this.element` * setup `this.click` helper method * setup `this.tap` helper method * setup `this.triggerKeyEvent` helper method From 4bb68572760b76d94b19809d0da84d186e05ec8b Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 10:21:06 -0500 Subject: [PATCH 08/27] Clarify the reasoning for both helper types. --- text/0268-acceptance-testing-refactor.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index a0201a3322..9b700ddf1e 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -232,7 +232,13 @@ Once implemented, `setupRenderingTest` and `setupAcceptanceTest` will diverge fr Since the design of this system relies on both the test helpers being applied to the test context **and** the usage of `async` / `await`, a few importable helpers are being introduced to help avoid extra noise (e.g. "rightward shift") -in tests. +in tests. In most cases the imported helpers will be used, but should be +considered to "de-sugar" into using the local methods on the test context. + +Having both mechanisms allow us to have both a clear and concise API in the +simple case (by reducing rightward shift, and clarifying _where_ a given helper +method is coming from), but still have the available helpers be discoverable +while debugging. This means that users will be able to use either of the following interchangably: From a6950d91b6a4c0479c908639cfe5bfd6171c9a1a Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 10:34:16 -0500 Subject: [PATCH 09/27] Add alternative about leaving ember-native-dom-helpers. --- text/0268-acceptance-testing-refactor.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 9b700ddf1e..e721132af0 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -301,3 +301,4 @@ confusion, making it easier to teach and understand testing in Ember. # Alternatives * Do nothing? +* Make `ember-native-dom-helpers` a default addon (removing the need for DOM interaction helpers proposed here). From f7656ea3f625aa188d80dbf736fbd10b0d8c36a2 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 11:56:56 -0500 Subject: [PATCH 10/27] Remove reference to `this.set` / `this.setProperties` / etc. --- text/0268-acceptance-testing-refactor.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index e721132af0..a8950ecbff 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -187,8 +187,6 @@ This function will: * invoke `ember-test-helper`s `setupContext` with the tests context (which does the following): * create an owner object and set it on the test context (e.g. `this.owner`) - * setup `this.set`, `this.setProperties`, `this.get`, and `this.getProperties` to - the test context * setup `this.pauseTest` and `this.resumeTest` methods to allow easy pausing/resuming of tests * add routing related helpers From 8975fb98dffaa629383da608f80061d7da423615 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 12:07:49 -0500 Subject: [PATCH 11/27] Remove public API suggestion for DOM interaction methods. No longer publicly expose two systems for the same thing, all in on imports... --- text/0268-acceptance-testing-refactor.md | 94 ++++++++---------------- 1 file changed, 30 insertions(+), 64 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index a8950ecbff..cfffcda338 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -119,21 +119,23 @@ already adopted will have very minimal changes to make). The specific DOM helpers to be added are: ``` -interface DOMInteractionHelpers { +declare module 'ember-test-helpers' { + // ...snip existing exports... + /** Clicks on the specified selector. */ - click(selector: string | HTMLElement): Promise; + export function click(selector: string | HTMLElement): Promise; /** Taps on the specified selector. */ - tap(selector: string | HTMLElement): Promise; + export function tap(selector: string | HTMLElement): Promise; /** Triggers a keyboad event on the specified selector. */ - triggerKeyEvent( + export function triggerKeyEvent( selector: string | HTMLElement, eventType: 'keydown' | 'keypress' | 'keyup', keyCode: string, @@ -148,7 +150,7 @@ interface DOMInteractionHelpers { /** Triggers an event on the specified selector. */ - triggerEvent( + export function triggerEvent( selector: string | HTMLElement, eventType: string, eventOptions: any @@ -157,27 +159,27 @@ interface DOMInteractionHelpers { /** Fill in the specified selector's `value` property with the provided text. */ - fillIn(selector: string | HTMLElement, text: string): Promise; + export function fillIn(selector: string | HTMLElement, text: string): Promise; /** Focus the specified selector. */ - focus(selector: string | HTMLElement): Promise; + export function focus(selector: string | HTMLElement): Promise; /** Unfocus the specified selector. */ - blur(selector: string | HTMLElement): Promise; + export function blur(selector: string | HTMLElement): Promise; /** Returns a promise which resolves when the provided callback returns a truthy value. */ - waitUntil(() => boolean): Promise; + export function waitUntil(() => boolean): Promise; /** Returns a promise which resolves when the provided selector (and count) becomes present. */ - waitFor(selector: string, count?: number): Promise; + export function waitFor(selector: string, count?: number): Promise; } ``` @@ -196,15 +198,15 @@ This function will: * add DOM interaction helpers (heavily influenced by @cibernox's lovely addon [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers)) * setup a getter for `this.element` which returns the DOM element representing the applications root element - * setup `this.click` helper method - * setup `this.tap` helper method - * setup `this.triggerKeyEvent` helper method - * setup `this.triggerEvent` helper method - * setup `this.fillIn` helper method - * setup `this.focus` helper method - * setup `this.blur` helper method - * setup `this.waitUntil` helper method - * setup `this.waitFor` helper method + * setup importable `click` helper method + * setup importable `tap` helper method + * setup importable `triggerKeyEvent` helper method + * setup importable `triggerEvent` helper method + * setup importable `fillIn` helper method + * setup importable `focus` helper method + * setup importable `blur` helper method + * setup importable `waitUntil` helper method + * setup importable `waitFor` helper method ### `setupRenderingTest` @@ -213,54 +215,18 @@ The `setupRenderingTest` function proposed in (and implemented in [ember-qunit](https://github.com/emberjs/ember-qunit)@3.0.0) will be modified to add the same DOM interaction helpers mentioned above: -* setup `this.click` helper method -* setup `this.tap` helper method -* setup `this.triggerKeyEvent` helper method -* setup `this.triggerEvent` helper method -* setup `this.fillIn` helper method -* setup `this.focus` helper method -* setup `this.blur` helper method -* setup `this.waitUntil` helper method -* setup `this.waitFor` helper method +* setup importable `click` helper method +* setup importable `tap` helper method +* setup importable `triggerKeyEvent` helper method +* setup importable `triggerEvent` helper method +* setup importable `fillIn` helper method +* setup importable `focus` helper method +* setup importable `blur` helper method +* setup importable `waitUntil` helper method +* setup importable `waitFor` helper method Once implemented, `setupRenderingTest` and `setupAcceptanceTest` will diverge from each other in very few ways. -### Importable helpers - -Since the design of this system relies on both the test helpers being applied -to the test context **and** the usage of `async` / `await`, a few importable -helpers are being introduced to help avoid extra noise (e.g. "rightward shift") -in tests. In most cases the imported helpers will be used, but should be -considered to "de-sugar" into using the local methods on the test context. - -Having both mechanisms allow us to have both a clear and concise API in the -simple case (by reducing rightward shift, and clarifying _where_ a given helper -method is coming from), but still have the available helpers be discoverable -while debugging. - -This means that users will be able to use either of the following interchangably: - -```js -// ***** importable helper ***** -import { click } from 'ember-test-helpers'; - -// ...snip... -test('does something', async function(assert) { - // ...snip... - await click('.selector-here'); - // ...snip... -}); - -// ***** test context helper ***** - -// ...snip... -test('does something', async function(assert) { - // ...snip... - await this.click('.selector-here'); - // ...snip... -}); -``` - ## Changes from Current System Here is a brief list of the more important but possibly understated changes From 7ee7132da898e41e044de854c5fa7e8facf23578 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 14:45:57 -0500 Subject: [PATCH 12/27] Remove more `this.foo` references. --- text/0268-acceptance-testing-refactor.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index cfffcda338..229bc13629 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -192,9 +192,9 @@ This function will: * setup `this.pauseTest` and `this.resumeTest` methods to allow easy pausing/resuming of tests * add routing related helpers - * setup `this.visit` method to visit the given url - * setup getter for `this.currentRouteName` which returns the current route name - * setup getter for `this.currentURL` which returns the current URL + * setup importable `visit` method to visit the given url + * setup importable `currentRouteName` method which returns the current route name + * setup importable `currentURL` method which returns the current URL * add DOM interaction helpers (heavily influenced by @cibernox's lovely addon [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers)) * setup a getter for `this.element` which returns the DOM element representing the applications root element From 1209ed3db7a8396409d00a3740aff09b928a2ac4 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 6 Nov 2017 14:47:30 -0500 Subject: [PATCH 13/27] Add blurb about removing implicit promise chaining. --- text/0268-acceptance-testing-refactor.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 229bc13629..94c5de599d 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -237,9 +237,13 @@ being proposed here: well as importable helpers. * `this.owner` will now be present and allow (for the first time 🎉) overriding items in the container/registry. -* The new system will leverage the `Ember.Application` / `Ember.ApplicationInstance` split so that - we can avoid creating an `Ember.Application` instance per-test, and instead leverage the same system - that FastBoot itself uses to avoid running initializers for each acceptance test. +* The new system will leverage the `Ember.Application` / + `Ember.ApplicationInstance` split so that we can avoid creating an + `Ember.Application` instance per-test, and instead leverage the same system + that FastBoot itself uses to avoid running initializers for each acceptance + test. +* Implicit promise chaining will no longer be present. If your test needs to + wait for a given promise, it should use `await`. ## Migration From b05ed2c529302bef263eb19ec84a3892104a4793 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 8 Nov 2017 11:39:01 -0500 Subject: [PATCH 14/27] Tweak summary prose for clarity and purpose. --- text/0268-acceptance-testing-refactor.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 94c5de599d..4bfbed2a9e 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -12,10 +12,13 @@ you would like. Unfortunately, there is a massive disparity between different types of tests. In acceptance tests, you use well designed global helpers to deal with async related interactions; whereas in integration and unit tests you are forced to -manually deal with this asynchrony. The goal of this RFC is to unify the -concepts amongst the various types of test and provide a single common -structure to tests. - +manually deal with this asynchrony. +[emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md) +introduced us to QUnit's nested modules API, made integration and unit testing +modular, and greatly simplified the concepts needed to learn how to write unit +and integration tests. The goal of this RFC is to leverage what we have learned +in prior RFCs and apply that knowledge to acceptance testing. Once this RFC has +been implemented all test types in Ember will have a unified cohesive structure. # Motivation @@ -25,7 +28,7 @@ example), and assumes most (if not all) interactions are synchronous. This is a major issue due to the fact that the vast majority of interactions will actually be asynchronous. There have been a few recent additions to `ember-test-helpers` that have made dealing with asynchrony better (namely -[emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md) +[emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md)) but forcing users to manually manage all interaction based async is a recipe for disaster. From ebfdbe15f0ac75661226354b7c2789dea5a504e6 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 8 Nov 2017 11:51:52 -0500 Subject: [PATCH 15/27] Migrate to use @ember/test-helpers. --- text/0268-acceptance-testing-refactor.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 4bfbed2a9e..6ae68571fd 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -27,7 +27,7 @@ often include manual event delegation (`this.$('.foo').click()` for example), and assumes most (if not all) interactions are synchronous. This is a major issue due to the fact that the vast majority of interactions will actually be asynchronous. There have been a few recent additions to -`ember-test-helpers` that have made dealing with asynchrony better (namely +`@ember/test-helpers` that have made dealing with asynchrony better (namely [emberjs/rfcs#232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md)) but forcing users to manually manage all interaction based async is a recipe for disaster. @@ -51,10 +51,10 @@ The goal of this RFC is to introduce new system for acceptance tests that follow and continues to enhance the system created in that RFC to share the same structure and helper system. This new system for acceptance tests will be implemented in the -[ember-test-helpers](https://github.com/emberjs/ember-test-helpers/) library so +[@ember/test-helpers](https://github.com/emberjs/ember-test-helpers/) library so that we can iterate faster while supporting multiple Ember versions independently and easily support multiple testing frameworks build on top of -the primitives in `ember-test-helpers`. Ultimately, the existing [ember-testing](https://github.com/emberjs/ember.js/tree/master/packages/ember-testing) system +the primitives in `@ember/test-helpers`. Ultimately, the existing [ember-testing](https://github.com/emberjs/ember.js/tree/master/packages/ember-testing) system will be deprecated but that deprecation will be added well after the new system has been released and adopted by the community. @@ -77,7 +77,7 @@ test('should add new post', function(assert) { // **** after **** import { module, test } from 'qunit'; import { setupAcceptanceTest } from 'ember-qunit'; -import { visit, fillIn, click } from 'ember-test-helpers'; +import { visit, fillIn, click } from '@ember/test-helpers'; module('Acceptance | login', function(hooks) { setupAcceptanceTest(hooks); @@ -114,15 +114,15 @@ helpers has been iterated on and is quite stable in the [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers) addon. -The helpers will be migrated to `ember-test-helpers` and eventually +The helpers will be migrated to `@ember/test-helpers` and eventually (once "the dust settles") `ember-native-dom-helpers` will be able to reexport -the versions from `ember-test-helpers` directly (which means apps that have +the versions from `@ember/test-helpers` directly (which means apps that have already adopted will have very minimal changes to make). The specific DOM helpers to be added are: ``` -declare module 'ember-test-helpers' { +declare module '@ember/test-helpers' { // ...snip existing exports... /** From 39da814db7ac1103a980782ea90142f6ccb860fb Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 8 Nov 2017 12:03:08 -0500 Subject: [PATCH 16/27] Remove wrapping `declare module` statement. --- text/0268-acceptance-testing-refactor.md | 122 +++++++++++------------ 1 file changed, 59 insertions(+), 63 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 6ae68571fd..571834cf8f 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -119,71 +119,67 @@ The helpers will be migrated to `@ember/test-helpers` and eventually the versions from `@ember/test-helpers` directly (which means apps that have already adopted will have very minimal changes to make). -The specific DOM helpers to be added are: +The specific DOM helpers to be added to the `@ember/test-helpers` module are: ``` -declare module '@ember/test-helpers' { - // ...snip existing exports... - - /** - Clicks on the specified selector. - */ - export function click(selector: string | HTMLElement): Promise; - - /** - Taps on the specified selector. - */ - export function tap(selector: string | HTMLElement): Promise; - - /** - Triggers a keyboad event on the specified selector. - */ - export function triggerKeyEvent( - selector: string | HTMLElement, - eventType: 'keydown' | 'keypress' | 'keyup', - keyCode: string, - modifiers?: { - ctrlKey: false, - altKey: false, - shiftKey: false, - metaKey: false - } - ): Promise; - - /** - Triggers an event on the specified selector. - */ - export function triggerEvent( - selector: string | HTMLElement, - eventType: string, - eventOptions: any - ): Promise; - - /** - Fill in the specified selector's `value` property with the provided text. - */ - export function fillIn(selector: string | HTMLElement, text: string): Promise; - - /** - Focus the specified selector. - */ - export function focus(selector: string | HTMLElement): Promise; - - /** - Unfocus the specified selector. - */ - export function blur(selector: string | HTMLElement): Promise; - - /** - Returns a promise which resolves when the provided callback returns a truthy value. - */ - export function waitUntil(() => boolean): Promise; - - /** - Returns a promise which resolves when the provided selector (and count) becomes present. - */ - export function waitFor(selector: string, count?: number): Promise; -} +/** + Clicks on the specified selector. +*/ +export function click(selector: string | HTMLElement): Promise; + +/** + Taps on the specified selector. +*/ +export function tap(selector: string | HTMLElement): Promise; + +/** + Triggers a keyboad event on the specified selector. +*/ +export function triggerKeyEvent( + selector: string | HTMLElement, + eventType: 'keydown' | 'keypress' | 'keyup', + keyCode: string, + modifiers?: { + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false + } +): Promise; + +/** + Triggers an event on the specified selector. +*/ +export function triggerEvent( + selector: string | HTMLElement, + eventType: string, + eventOptions: any +): Promise; + +/** + Fill in the specified selector's `value` property with the provided text. +*/ +export function fillIn(selector: string | HTMLElement, text: string): Promise; + +/** + Focus the specified selector. +*/ +export function focus(selector: string | HTMLElement): Promise; + +/** + Unfocus the specified selector. +*/ +export function blur(selector: string | HTMLElement): Promise; + +/** + Returns a promise which resolves when the provided callback returns a truthy value. +*/ +export function waitUntil(() => boolean): Promise; + +/** + Returns a promise which resolves when the provided selector (and count) becomes present. +*/ +export function waitFor(selector: string, count?: number): Promise; ``` ### `setupAcceptanceTest` From 57792c273ec1aa2fe40a249a952068b96426d774 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Thu, 9 Nov 2017 09:37:16 -0500 Subject: [PATCH 17/27] Add mention of removing default `tests/helpers/*.js`. --- text/0268-acceptance-testing-refactor.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 571834cf8f..cb2c4ac7be 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -243,6 +243,13 @@ being proposed here: test. * Implicit promise chaining will no longer be present. If your test needs to wait for a given promise, it should use `await`. +* The test helpers that are included by a new default ember-cli app will be no + longer needed and will be removed from the new application blueprint. This + includes: + * `tests/helpers/resolver.js` + * `tests/helpers/start-app.js` + * `tests/helpers/destroy-app.js` + * `tests/helpers/module-for-acceptance.js` ## Migration From 1676701cdf56548d73bc5e5bbdb5ecbc63269a6a Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 13:28:09 -0500 Subject: [PATCH 18/27] Correct the options to `waitFor` and `waitUntil`. Based on feedback from cibernox... --- text/0268-acceptance-testing-refactor.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index cb2c4ac7be..4b2d83c43e 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -174,12 +174,12 @@ export function blur(selector: string | HTMLElement): Promise; /** Returns a promise which resolves when the provided callback returns a truthy value. */ -export function waitUntil(() => boolean): Promise; +export function waitUntil(() => boolean, { timeout = 1000 }): Promise; /** Returns a promise which resolves when the provided selector (and count) becomes present. */ -export function waitFor(selector: string, count?: number): Promise; +export function waitFor(selector: string, { count?: number, timeout = 1000 }): Promise; ``` ### `setupAcceptanceTest` From ef325f4e2cd18d679fb79476e1c7c5b8b9fc5967 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 13:53:42 -0500 Subject: [PATCH 19/27] Add example of addon supporting both APIs. --- text/0268-acceptance-testing-refactor.md | 69 ++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 4b2d83c43e..8c0454d3d4 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -251,6 +251,75 @@ being proposed here: * `tests/helpers/destroy-app.js` * `tests/helpers/module-for-acceptance.js` +## Examples + +### Test Helper + +Assuming the following input: + +```js +import Ember from 'ember'; + +export function withFeature(app, featureName) { + let featuresService = app.__container__.lookup('service:features'); + featuresService.enable(featureName); +} + +Ember.Test.registerHelper('withFeature', withFeature); +``` + +In order for an addon to support both the existing acceptance testing system, and the new system it could replace that helper with the following: + +```js +import { registerAsyncHelper } from '@ember/test'; + +export function enableFeature(owner, featureName) { + let featuresService = this.owner.lookup('service:features'); + featuresService.enable(featureName); +} + +export default function setupFeatures(hooks, featureName) { + hooks.beforeEach(function() { + setupFeature(this.owner, featureName); + }) +} + +registerAsyncHelper('withFeature', function(app, featureName) { + setupFeature(app.__container__, featureName); +}); +``` + +This allows both the prior API (without modification) and the following: + +```js +// Option 1: +import { module, test } from 'qunit'; +import { setupAcceptanceTest } from 'ember-qunit'; +import { setupFeature } from 'addon-name-here/test-support'; + +module('asdf', function(hooks) { + setupAcceptanceTest(hooks); + setupFeature(hooks, 'feature-name-here'); + + test(...); +}); + +// Option 2: +import { module, test } from 'qunit'; +import { setupAcceptanceTest } from 'ember-qunit'; +import { enableFeature } from 'addon-name-here/test-support'; + +module('asdf', function(hooks) { + setupAcceptanceTest(hooks); + + test('awesome test title here', function(assert) { + enableFeature(this.owner, 'feature-name-here'); + + // ...snip... + }); +}); +``` + ## Migration It is important that both the existing acceptance testing system, and the From 6e0975c3d70922371a3ed5779e62e51aa5682c14 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 14:20:23 -0500 Subject: [PATCH 20/27] Remove reference to `find` in example. --- text/0268-acceptance-testing-refactor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 8c0454d3d4..7cb65002e0 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -87,7 +87,7 @@ module('Acceptance | login', function(hooks) { await fillIn('input.title', 'My new post'); await click('button.submit'); - assert.equal(find('ul.posts li')[0].textContent, 'My new post'); + assert.equal(this.element.querySelectorAll('ul.posts li')[0].textContent, 'My new post'); }); }); ``` From b487cb4d1de968f83177fd86a273c215f72d3463 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 15:03:15 -0500 Subject: [PATCH 21/27] Add example demonstrating factory overrides. --- text/0268-acceptance-testing-refactor.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 7cb65002e0..5d1893daee 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -320,6 +320,28 @@ module('asdf', function(hooks) { }); ``` +### Registering Factory Overrides + +Overriding a factory is generally done to allow the test to have more control +over the thing being tested. This is sometimes used to prevent side effects +that are not related to the test (i.e. to prevent network calls), other times +it is used to allow the test to inject some known state to make asserting the +results much easier. + +It is currently possible to register custom factories in integration and unit +tests, but not in acceptance tests (without using private API's that is). + +As of [emberjs/rfcs#232](https://github.com/emberjs/rfcs/pull/232) the +integration/unit test API for this registration is: + +```js +this.owner.register('service:stripe', MockService); +``` + +This RFC will allow this invocation syntax to work in all test types +(acceptance, integration, and unit). + + ## Migration It is important that both the existing acceptance testing system, and the From 8858b09efa01fc2f39a6fb3a62eda9ee19bf4ecb Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 15:11:39 -0500 Subject: [PATCH 22/27] Add more details about waiting for the result of `click` et al --- text/0268-acceptance-testing-refactor.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index 5d1893daee..b3f479dd26 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -242,7 +242,8 @@ being proposed here: that FastBoot itself uses to avoid running initializers for each acceptance test. * Implicit promise chaining will no longer be present. If your test needs to - wait for a given promise, it should use `await`. + wait for a given promise, it should use `await` (which will wait for the + system to "settle" in similar semantics to today's `wait()` helper). * The test helpers that are included by a new default ember-cli app will be no longer needed and will be removed from the new application blueprint. This includes: From 0f55cd5b99a9554f549833ef6b1e75d28b69790c Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 15:21:29 -0500 Subject: [PATCH 23/27] Fix typos in test helper example. --- text/0268-acceptance-testing-refactor.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index b3f479dd26..a74e0557b9 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -275,18 +275,18 @@ In order for an addon to support both the existing acceptance testing system, an import { registerAsyncHelper } from '@ember/test'; export function enableFeature(owner, featureName) { - let featuresService = this.owner.lookup('service:features'); + let featuresService = owner.lookup('service:features'); featuresService.enable(featureName); } -export default function setupFeatures(hooks, featureName) { +export default function setupFeature(hooks, featureName) { hooks.beforeEach(function() { - setupFeature(this.owner, featureName); + enableFeature(this.owner, featureName); }) } registerAsyncHelper('withFeature', function(app, featureName) { - setupFeature(app.__container__, featureName); + enableFeature(app.__container__, featureName); }); ``` From 8247efb8de7baac4be5460aa5da145446a1a1299 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Fri, 10 Nov 2017 15:27:00 -0500 Subject: [PATCH 24/27] Remove extraneous option for test helpers. --- text/0268-acceptance-testing-refactor.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index a74e0557b9..b7d176caa6 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -279,12 +279,6 @@ export function enableFeature(owner, featureName) { featuresService.enable(featureName); } -export default function setupFeature(hooks, featureName) { - hooks.beforeEach(function() { - enableFeature(this.owner, featureName); - }) -} - registerAsyncHelper('withFeature', function(app, featureName) { enableFeature(app.__container__, featureName); }); @@ -293,18 +287,6 @@ registerAsyncHelper('withFeature', function(app, featureName) { This allows both the prior API (without modification) and the following: ```js -// Option 1: -import { module, test } from 'qunit'; -import { setupAcceptanceTest } from 'ember-qunit'; -import { setupFeature } from 'addon-name-here/test-support'; - -module('asdf', function(hooks) { - setupAcceptanceTest(hooks); - setupFeature(hooks, 'feature-name-here'); - - test(...); -}); - // Option 2: import { module, test } from 'qunit'; import { setupAcceptanceTest } from 'ember-qunit'; From cbe88eb044ddd28fa0a19f2f56ad1de95f052e92 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sat, 11 Nov 2017 15:00:21 -0500 Subject: [PATCH 25/27] Update typings for `waitFor` and `waitUntil`. --- text/0268-acceptance-testing-refactor.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index b7d176caa6..a8eac1ee53 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -174,12 +174,12 @@ export function blur(selector: string | HTMLElement): Promise; /** Returns a promise which resolves when the provided callback returns a truthy value. */ -export function waitUntil(() => boolean, { timeout = 1000 }): Promise; +export function waitUntil(Function: Promise, { timeout = 1000 }): Promise; /** Returns a promise which resolves when the provided selector (and count) becomes present. */ -export function waitFor(selector: string, { count?: number, timeout = 1000 }): Promise; +export function waitFor(selector: string, { count?: number, timeout = 1000 }): Promise; ``` ### `setupAcceptanceTest` From 6370fa8513309e4e7005701cb3d566a095d4d4f4 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 15 Nov 2017 16:32:19 -0500 Subject: [PATCH 26/27] Add type for code snippet. --- text/0268-acceptance-testing-refactor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index a8eac1ee53..e9a65dc49d 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -121,7 +121,7 @@ already adopted will have very minimal changes to make). The specific DOM helpers to be added to the `@ember/test-helpers` module are: -``` +```ts /** Clicks on the specified selector. */ From f2b608b3535bb909631c451450cbd7310eeb8f13 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Wed, 15 Nov 2017 16:38:32 -0500 Subject: [PATCH 27/27] Rename import to `setupApplicationTest`. --- text/0268-acceptance-testing-refactor.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/text/0268-acceptance-testing-refactor.md b/text/0268-acceptance-testing-refactor.md index e9a65dc49d..a700a4e51b 100644 --- a/text/0268-acceptance-testing-refactor.md +++ b/text/0268-acceptance-testing-refactor.md @@ -76,11 +76,11 @@ test('should add new post', function(assert) { // **** after **** import { module, test } from 'qunit'; -import { setupAcceptanceTest } from 'ember-qunit'; +import { setupApplicationTest } from 'ember-qunit'; import { visit, fillIn, click } from '@ember/test-helpers'; module('Acceptance | login', function(hooks) { - setupAcceptanceTest(hooks); + setupApplicationTest(hooks); test('should add new post', async function(assert) { await visit('/posts/new'); @@ -102,14 +102,14 @@ The following new methods will be exposed from `ember-qunit`: ```ts declare module 'ember-qunit' { // ...snip... - export function setupAcceptanceTest(hooks: QUnitModuleHooks): void; + export function setupApplicationTest(hooks: QUnitModuleHooks): void; } ``` ### DOM Interaction Helpers New native DOM interaction helpers will be added to both `setupRenderingTest` -and (proposed below) `setupAcceptanceTest`. The implementation for these +and (proposed below) `setupApplicationTest`. The implementation for these helpers has been iterated on and is quite stable in the [ember-native-dom-helpers](https://github.com/cibernox/ember-native-dom-helpers) addon. @@ -182,7 +182,7 @@ export function waitUntil(Function: Promise, { timeout = 1000 }): Promise< export function waitFor(selector: string, { count?: number, timeout = 1000 }): Promise; ``` -### `setupAcceptanceTest` +### `setupApplicationTest` This function will: @@ -224,7 +224,7 @@ The `setupRenderingTest` function proposed in * setup importable `waitUntil` helper method * setup importable `waitFor` helper method -Once implemented, `setupRenderingTest` and `setupAcceptanceTest` will diverge from each other in very few ways. +Once implemented, `setupRenderingTest` and `setupApplicationTest` will diverge from each other in very few ways. ## Changes from Current System @@ -289,11 +289,11 @@ This allows both the prior API (without modification) and the following: ```js // Option 2: import { module, test } from 'qunit'; -import { setupAcceptanceTest } from 'ember-qunit'; +import { setupApplicationTest } from 'ember-qunit'; import { enableFeature } from 'addon-name-here/test-support'; module('asdf', function(hooks) { - setupAcceptanceTest(hooks); + setupApplicationTest(hooks); test('awesome test title here', function(assert) { enableFeature(this.owner, 'feature-name-here');