ember-qunit
Version:
QUnit helpers for testing Ember.js applications
310 lines (224 loc) • 10.2 kB
Markdown
Migration Guide
==============================================================================
Migrating to native TypeScript support in v6.1.0
------------------------------------------------------------------------------
The types for the QUnit `TestContext` provided by the `ember-qunit` and `@ember/test-helpers` types on DefinitelyTyped made a choice to prioritize convenience over robustness when it came to what methods and values were available on `this` in any given test: they made *all* methods availabe regardless of what your setup actually involved. For example, this totally invalid code would have passed the type checker:
```ts
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { hbs } from 'ember-cli-htmlbars';
module('bad times', function (hooks) {
setupTest(hooks);
test('this will not *run* correctly', async function (assert) {
await this.render(hbs`<p>whoopsie</p>`);
});
})
```
To resolve this, you need to explicitly specify what `this` is for different kinds of tests:
```ts
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import type { RenderingTextContext } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('better times', function (hooks) {
setupTest(hooks);
test(
'this will not *run* correctly',
async function (this: RenderingTextContext, assert) {
await this.render(hbs`<p>whoopsie</p>`);
}
);
})
```
While annoying, this is accurate and prevents the annoying mismatch. Combined with support for using local scope with `<template>` (see [Ember RFC 0785][rfc-0785]), available since v2.8 of `@ember/test-helpers`, the need to specify the `this` will go away entirely over time.
[rfc-0785]: https://rfcs.emberjs.com/id/0785-remove-set-get-in-tests
To use these public types, you also will need to add `@glimmer/interfaces` and `@glimmer/reference` to your `devDependencies`, since of `@ember/test-helpers` uses them (indirectly) in its public APIs, and `ember-qunit` uses `@ember/test-helpers` in turn.
Upgrading from v4.x to v5.0.0
------------------------------------------------------------------------------
`ember-qunit` had a few major changes that affects apps when migrating from v4.x to v5:
* Require the application to have a `qunit` and `@ember/test-helpers` dependency of some sort
* Require the QUnit and `@ember/test-helpers` DOM fixtures to be added to the applications `tests/index.html`
* Require the application to have `ember-auto-import`
* Dropped support for usage of `ember-test-helpers` imports
* Dropped support for `moduleFor*` APIs
* Drop support for older Node versions (8, 9, 11, 13)
* Remove re-exports of QUnit functions from `ember-qunit`
* Drop support for usage with Ember older than 3.8
### `qunit` and `@ember/test-helpers` dependencies
Older versions of `ember-qunit` directly depended on `qunit` and
`@ember/test-helpers`. In v5, this relationship was changed and now
`ember-qunit` has `qunit` and `@ember/test-helpers` (v2) as peer dependencies.
In order to accomodate this change, in your application, you can run:
```sh
# npm users
npm install --save-dev qunit "@ember/test-helpers"
# yarn users
yarn add --dev qunit "@ember/test-helpers"
```
### DOM fixtures
In v5 `ember-qunit` moved from automatically providing the testing DOM fixtures to requiring that
the host application provide them itself.
In order to accomodate this change in your application add the following
snippet to your `tests/index.html` just after your `{{content-for
"test-body"}}` entry:
```html
<div id="qunit"></div>
<div id="qunit-fixture">
<div id="ember-testing-container">
<div id="ember-testing"></div>
</div>
</div>
```
### QUnit DOM
If you use QUnit DOM, you may encounter the error message `assert.dom is not a function` when you run tests.
To address this issue, import and run QUnit DOM's `setup` function in your `test-helper.js` file:
```javascript
// tests/test-helper.js
import * as QUnit from 'qunit';
import { setup } from 'qunit-dom';
//...
setup(QUnit.assert);
setApplication(Application.create(config.APP));
start();
//...
```
**Note**: Only make this change when you've updated your version of `ember-qunit` to a `5.x.x` version. Doing so pre-emptively will result in errors trying to import `setup`.
### Remove `ember-test-helpers` modules
For a long time `@ember/test-helpers` re-exported all of its modules under the `ember-test-helpers` namespace,
in v5 of `ember-qunit` (which requires `@ember/test-helpers@2.0.0`) those re-exports are removed.
For the most part, you can migrate any `ember-test-helpers` imports to `@ember/test-helpers`.
### Migrating from `moduleFor*` APIs
This section provides instruction for upgrading your test suite from the
[Legacy APIs](legacy.md) to Ember's latest testing APIs based on RFCs
[232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md)
and
[268](https://github.com/emberjs/rfcs/blob/master/text/0268-acceptance-testing-refactor.md).
For the complete introduction to the new testing APIs, please read the
latest [Ember Guides](https://guides.emberjs.com/release/testing/). The
following examples will give you an overview how to migrate your existing Ember
QUnit based test suite.
#### Unit tests
Before:
```javascript
import { test, moduleFor } from 'ember-qunit';
moduleFor('controller:sidebar', 'SidebarController', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});
```
After:
```javascript
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('SidebarController', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('exists', function(assert) {
let controller = this.owner.lookup('controller:sidebar');
assert.ok(controller);
});
});
```
##### Migration steps
* Use `module` and `test` imported from `qunit` directly
* Use `setupTest()` instead of `moduleFor()`
* Use the Owner object given by `this.owner` directly instead of `this.subject()`
You can use the
[ember-qunit-codemod](https://github.com/rwjblue/ember-qunit-codemod)
to update your test code automatically.
#### Component tests
Before:
```javascript
import { test, moduleForComponent } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('GravatarImageComponent', {
integration: true
});
test('it renders', function(assert) {
this.render(hbs`{{gravatar-image}}`);
assert.equal(this.$('img').length, 1);
});
```
After:
```javascript
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('GravatarImageComponent', function(hooks) {
setupRenderingTest(hooks);
test('renders', async function(assert) {
await render(hbs`{{gravatar-image}}`);
assert.ok(this.element.querySelector('img'));
});
});
```
##### Migration steps
* Use `module` and `test` imported from `qunit` directly
* Use `setupRenderingTest()` instead of `moduleForComponent()`
* Render using the `render()` helper from `@ember/test-helpers` instead of
`this.render()`
* `render()` is now always an async call, so use `async`/`await` to wait for it
to complete
* Use `this.element` to get access to the rendered DOM
* Do not use jQuery for DOM interaction, instead use the
[DOM Interaction Helpers](https://github.com/emberjs/ember-test-helpers/blob/master/API.md#dom-interaction-helpers)
from `@ember/test-helpers`
You can use the
[ember-qunit-codemod](https://github.com/rwjblue/ember-qunit-codemod)
to update your test setup code automatically.
For migrating to the DOM interaction helpers, you can use the
[ember-test-helpers-codemod](https://github.com/simonihmig/ember-test-helpers-codemod)
to automatically convert all or most of it.
#### Acceptance tests
Before:
```javascript
import { test } from 'qunit';
import moduleForAcceptance from 'app/tests/helpers/module-for-acceptance';
moduleForAcceptance('basic acceptance test');
test('can visit /', function() {
visit('/');
andThen(() => {
assert.equal(currentURL(), '/');
});
});
```
After:
```javascript
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, currentURL } from '@ember/test-helpers';
module('basic acceptance test', function(hooks) {
setupApplicationTest(hooks);
test('can visit /', async function(assert) {
await visit('/');
assert.equal(currentURL(), '/');
});
});
```
##### Migration steps
* Use `module` and `test` imported from `qunit` directly
* Use `setupApplicationTest()` instead of `moduleForAcceptance()` or `beforeEach`/`afterEach` hooks for setting up the
application
* Use the [Routing Helpers](https://github.com/emberjs/ember-test-helpers/blob/master/API.md#routing-helpers)
from `@ember/test-helpers` instead of the global helpers, e.g. `visit`
* Do not use the "global" test helpers for DOM interaction, instead use the
[DOM Interaction Helpers](https://github.com/emberjs/ember-test-helpers/blob/master/API.md#dom-interaction-helpers)
from `@ember/test-helpers`
* use `async`/`await` to wait for asynchronous operations like `visit()` or
`click()`
* use `this.element` to get access to the rendered DOM
You can use the
[ember-qunit-codemod](https://github.com/rwjblue/ember-qunit-codemod)
to update your test setup code automatically.
For migrating from the global test helpers to those proved by
`@ember/test-helpers`, you can use the
[ember-test-helpers-codemod](https://github.com/simonihmig/ember-test-helpers-codemod)
to assist you with that task.
###### Caveats
* As of ember-cli-qunit@4.1.0 / ember-qunit@3.0.0, `Ember.testing` is only set tor `true` during the test run. Previously it was always set to `true`. For more information see https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/no-ember-testing-in-module-scope.md