UNPKG

8.56 kBMarkdownView Raw
1
2Legacy Guide
3==============================================================================
4
5This document describes the use of `ember-qunit` with Ember's legacy testing
6APIs, which have been superseded by the newer testing system based on the RFCs
7[232](https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md)
8and
9[268](https://github.com/emberjs/rfcs/blob/master/text/0268-acceptance-testing-refactor.md).
10
11## Usage
12
13- [Component Integration Tests](#component-integration-tests)
14- [Component Unit Tests](#component-unit-tests)
15- [Other Tests](#other-tests)
16- [Ember Data Tests](#ember-data-tests)
17
18### Component Integration Tests
19
20```js
21import hbs from 'htmlbars-inline-precompile';
22import { test, moduleForComponent } from 'ember-qunit';
23
24moduleForComponent('x-foo', {
25 integration: true
26});
27
28test('it renders', function(assert) {
29 assert.expect(2);
30
31 // setup the outer context
32 this.set('value', 'cat');
33 this.on('action', function(result) {
34 assert.equal(result, 'bar', 'The correct result was returned');
35 });
36
37 // render the component
38 this.render(hbs`
39 {{ x-foo value=value action="result" }}
40 `);
41
42 assert.equal(this.$('div>.value').text(), 'cat', 'The component shows the correct value');
43
44 this.$('button').click();
45});
46```
47
48Component integration tests are the default mode for `moduleForComponent`. You can still explicitly activate them by passing `integration: true`.
49
50Integration tests have the advantage of testing your component as Ember would actually use them. It's helpful to think of this mode as simply testing the inputs and outputs of the component. These tests allow you interact with both the bound values that are passed into the component as well as its resulting actions.
51
52Component integration tests have the following features:
53- Your test context `this` acts as the outer context for the component. As a result, you can call `this.set` and `this.on` to setup values and event listeners that you can then have interact with the component.
54- You are required to render the component as a template, e.g. ``this.render(hbs`{{ your-component-name value=value action="updated" }}`)``. You can render other components as well as block content.
55- All of the normal Ember lifecycle hooks for a component are called (including the new ones from 1.13.x).
56- Testing the component's template is through `this.$()`.
57- You do not require dependencies through `needs:`. Doing so will force the test into unit mode.
58- You do not have direct access to the component instance. (`this.subject()` will raise an exception).
59
60### Component Unit Tests
61
62[Ember Guide](http://guides.emberjs.com/v1.13.0/testing/testing-components/)
63
64```js
65import { test, moduleForComponent } from 'ember-qunit';
66
67moduleForComponent('x-foo', {
68 unit: true,
69 needs: ['helper:pluralize-string']
70});
71
72// run a test
73test('it renders', function(assert) {
74 assert.expect(1);
75
76 // creates the component instance
77 var subject = this.subject();
78
79 // render the component on the page
80 this.render();
81 assert.equal(this.$('.foo').text(), 'bar');
82});
83```
84
85Unit tests used to be the default mode for component tests. To flag a test as a unit test, either specify `unit: true` or include `needs: []` in the callbacks object.
86
87Unit tests have the advantage of giving you direct access to the component instance so you can test its internals. Unit tests have the following features:
88
89- You have access to the component instance through `this.subject()`.
90- If you want to render the component's template, call either `this.render()` or `this.$()`.
91- Testing the component's template is through `this.$()`.
92- You are required to specify any dependencies other than the component's template in the `needs: []` option. This includes helpers, services, partials, and any other components (with their templates) that are referenced.
93- Unit tests do not call most of the Ember lifecycle hooks. `didInsertElement` and `willDestroyElement` will be called, but the remaining hooks introduced in Ember 1.13.x will not be.
94- There is no outer context for the component so testing things such as actions will require directly stubbing the actions on the component.
95
96### Other Tests
97
98[Controllers Guide](http://guides.emberjs.com/v1.13.0/testing/testing-controllers/)
99
100[Routes Guide](http://guides.emberjs.com/v1.13.0/testing/testing-routes/)
101
102```js
103import { test, moduleFor } from 'ember-qunit';
104
105moduleFor('controller:home');
106
107test('It can calculate the result', function(assert) {
108 assert.expect(1);
109
110 var subject = this.subject();
111
112 subject.set('value', 'foo');
113 assert.equal(subject.get('result'), 'bar');
114});
115```
116
117`moduleFor` works for any object you could look up with the Ember Resolver (service, routes, controllers, etc.).
118
119Note: Controllers / Routes do not have access to rendering. You will need to either use a component test or an acceptance test.
120
121### Ember Data Tests
122
123[Ember Guide](http://guides.emberjs.com/v1.13.0/testing/testing-models/)
124
125```js
126import { test, moduleForModel } from 'ember-qunit';
127
128moduleForModel('user', {
129 needs: ['model:child']
130});
131
132test('It can set its child', function(assert) {
133 assert.expect(1);
134 var subject = this.subject();
135
136 var child = subject.store.createRecord('child');
137 subject.get('children').pushObject(child);
138
139 assert.equal(subject.get('some-computed-value'), true);
140});
141```
142
143## Advanced Usage
144### Setting the resolver
145
146```js
147// if you don't have a custom resolver, do it like this:
148setResolver(Ember.DefaultResolver.create({ namespace: App }));
149
150// otherwise something like:
151import Resolver from './path/to/resolver';
152import { setResolver } from 'ember-qunit';
153setResolver(Resolver.create());
154```
155
156### Async Example
157
158Under the hood, if you use `Ember.RSVP.Promise`, ember-qunit will call
159QUnit's `start` and `stop` helpers to stop the test from tearing down
160and running other tests while your asynchronous code runs. ember-qunit
161also asserts that the promise gets fulfilled.
162
163In addition, you can also return promises in the test body:
164
165```js
166// If you return a promise from a test callback it becomes an asyncTest. This
167// is a key difference between ember-qunit and standard QUnit.
168test('async is awesome', function(assert) {
169 assert.expect(1);
170 var myThing = MyThing.create();
171 // myThing.exampleMethod() returns a promise
172 return myThing.exampleMethod().then(function() {
173 assert.ok(myThing.get('finished'));
174 });
175});
176```
177
178If an error is thrown in your promise or a promise
179within `test` becomes rejected, ember-qunit will fail the test.
180To assert that a promise should be rejected, you can "catch"
181the error and assert that you got there:
182
183```js
184test('sometimes async gets rejected', function(assert) {
185 assert.expect(1);
186 var myThing = MyThing.create()
187
188 return myThing.exampleMethod().then(function() {
189 assert.ok(false, "promise should not be fulfilled");
190 })['catch'](function(err) {
191 assert.equal(err.message, "User not Authorized");
192 });
193});
194```
195
196## Test Helpers
197
198### `moduleFor(fullName [, description [, callbacks]])`
199
200- `fullName`: (String) - The full name of the unit, ie
201 `controller:application`, `route:index`.
202
203- `description`: (String) optional - The description of the module
204
205- `callbacks`: (Object) optional
206 - QUnit callbacks (`beforeEach` and `afterEach`)
207 - ember-test-helpers callback (`subject`)
208 - `integration: true` or `unit: true` (default: `integration: true`)
209 - `needs` specify any dependencies the tested module will require.
210
211### `moduleForComponent(name, [description, callbacks])`
212
213- `name`: (String) - the short name of the component that you'd use in a
214 template, ie `x-foo`, `ic-tabs`, etc.
215
216- `description`: (String) optional - The description of the module
217
218- `callbacks`: (Object) optional
219 - QUnit callbacks (`beforeEach` and `afterEach`)
220 - ember-test-helpers callback (`subject`)
221 - `integration: true` or `unit: true` (default: `integration: true`)
222 - `needs` specify any dependencies the tested module will require. (Including this will force your test into unit mode).
223
224### `moduleForModel(name, [description, callbacks])`
225
226- `name`: (String) - the short name of the model you'd use in `store`
227 operations ie `user`, `assignmentGroup`, etc.
228
229- `description`: (String) optional - The description of the module
230
231- `callbacks`: (Object) optional
232 - QUnit callbacks (`beforeEach` and `afterEach`)
233 - ember-test-helpers callback (`subject`)
234 - `integration: true` or `unit: true` (default: `integration: true`)
235 - `needs` specify any dependencies the tested module will require.