Skip to content

Commit eb925e7

Browse files
committed
Docs: Add "Sharing hooks" example to Test lifecycle
Ref https://stackoverflow.com/a/79571790/319266
1 parent 1af1cb4 commit eb925e7

File tree

2 files changed

+78
-44
lines changed

2 files changed

+78
-44
lines changed

docs/api/QUnit/module.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ A hook callback may be an async function, or return a Promise or other then-able
160160
```js
161161
QUnit.module('Database connection', function (hooks) {
162162
hooks.before(async function () {
163-
await MyDb.connect();
163+
this.conn = await MyDb.createConnection().open();
164164
});
165165

166166
hooks.after(async function () {
167-
await MyDb.disconnect();
167+
await this.conn.close();
168168
});
169169

170170
// define tests...

docs/lifecycle.md

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,14 @@ QUnit.module('Foo', function (hooks) {
115115
### Example: Async hook callback
116116

117117
```js
118-
QUnit.module('Database connection', function (hooks) {
118+
QUnit.module('Database', function (hooks) {
119119
hooks.before(async function () {
120-
await MyDb.connect();
120+
this.conn = MyDb.createConnection();
121+
await this.conn.open();
121122
});
122123

123124
hooks.after(async function () {
124-
await MyDb.disconnect();
125+
await this.conn.close();
125126
});
126127

127128
// define tests...
@@ -131,32 +132,59 @@ QUnit.module('Database connection', function (hooks) {
131132
You can also define async hooks without modern async-await syntax, by returning a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or other "then"-able object:
132133

133134
```js
134-
QUnit.module('Database connection', {
135+
QUnit.module('Database', {
135136
before: function () {
136-
return new Promise(function (resolve, reject) {
137-
MyDb.connect(function (err) {
138-
if (err) {
139-
reject(err);
140-
} else {
141-
resolve();
142-
}
143-
});
144-
});
137+
this.conn = MyDb.createConnection();
138+
return this.conn.open();
145139
},
146140
after: function () {
147-
return new Promise(function (resolve, reject) {
148-
MyDb.disconnect(function (err) {
149-
if (err) {
150-
reject(err);
151-
} else {
152-
resolve();
153-
}
154-
});
155-
});
141+
return this.conn.close();
156142
}
157143
});
158144
```
159145

146+
### Example: Sharing hooks
147+
148+
If you have multiple components that extend or call the same feature, you may find yourself wanting to reuse a set of mocks, test fixtures, or utility functions across different QUnit modules.
149+
150+
You can do this by providing a set of re-usable hooks, which you can effectively "merge" into your module.
151+
152+
If your setup only needs to run once, consider placing it in a [bootstrap script](./api/config/index.md) instead, along any other configuration.
153+
154+
If your setup should run for all test modules, use a global [`QUnit.hooks`](./api/QUnit/hooks.md) which applies automatically without any per-module setup.
155+
156+
```js
157+
export function setupFruit (hooks) {
158+
hooks.before(function () {
159+
this.fruit = new Fruit('Apple');
160+
});
161+
hooks.afterEach(function () {
162+
this.fruit.detach();
163+
this.fruit.clean();
164+
});
165+
}
166+
```
167+
168+
```js
169+
import { setupFruit } from './setup.fruit.js';
170+
171+
QUnit.module('Painting', function (hooks) {
172+
setupFruit(hooks);
173+
174+
hooks.beforeEach(function () {
175+
this.canvas = new Painting();
176+
});
177+
178+
QUnit.test('The Son of Man', function (assert) {
179+
const face = new Face();
180+
this.canvas.append(face);
181+
this.canvas.append(this.fruit);
182+
183+
assert.equal(this.canvas.getVisibility(face), 'obscured');
184+
});
185+
});
186+
```
187+
160188
## Test context
161189

162190
Each test starts with a fresh copy of the test context as provided by the module. This is generally an empty object. The test context is available as `this` inside the [`QUnit.test()`](./api/QUnit/test.md) function and hook callbacks.
@@ -167,8 +195,12 @@ The `before` hook has access to the base object that tests and child modules inh
167195

168196
```js
169197
QUnit.module('Maker', function (hooks) {
198+
hooks.before(function () {
199+
this.inventory = 'ABCDEFG';
200+
});
201+
170202
hooks.beforeEach(function () {
171-
this.parts = ['A', 'B'];
203+
this.parts = [this.inventory[0], this.inventory[1]];
172204
});
173205

174206
QUnit.test('make alphabet', function (assert) {
@@ -186,10 +218,12 @@ QUnit.module('Maker', function (hooks) {
186218
If you use arrow functions, beware that the `this` test context is not reachable from inside an arrow function. JavaScript does have a built-in lexical scope that you can use in a similar way. This works the same as a text context for simple cases (i.e. you assign all variables together in `beforeEach`).
187219

188220
```js
189-
QUnit.module('Machine Maker', function (hooks) {
221+
QUnit.module('Maker', function (hooks) {
222+
const inventory = 'ABCDEFG';
223+
190224
let parts;
191225
hooks.beforeEach(function () {
192-
parts = ['A', 'B'];
226+
parts = [inventory[0], inventory[1]];
193227
});
194228

195229
QUnit.test('make alphabet', function (assert) {
@@ -236,30 +270,30 @@ QUnit.test('make good music', function (assert) {
236270
This is functionally equivalent to:
237271

238272
```js
239-
QUnit.module('example', {
240-
before () {
273+
QUnit.module('example', function (hooks) {
274+
hooks.before(function () {
241275
this.inventory = 'ABCDEFG';
242276
this.makeParts = function (a, b) {
243277
return [this.inventory[a], this.inventory[b]];
244278
};
245-
},
246-
beforeEach () {
279+
});
280+
hooks.beforeEach(function () {
247281
this.parts = this.makeParts(0, 1);
248-
}
249-
});
282+
});
250283

251-
QUnit.test('make alphabet', function (assert) {
252-
this.parts.push('C');
253-
assert.equal(this.parts.join(''), 'ABC');
254-
});
284+
QUnit.test('make alphabet', function (assert) {
285+
this.parts.push('C');
286+
assert.equal(this.parts.join(''), 'ABC');
287+
});
255288

256-
QUnit.test('make music', function (assert) {
257-
this.parts.push('B', 'A');
258-
assert.equal(this.parts.join(''), 'ABBA');
259-
});
289+
QUnit.test('make music', function (assert) {
290+
this.parts.push('B', 'A');
291+
assert.equal(this.parts.join(''), 'ABBA');
292+
});
260293

261-
QUnit.test('make good music', function (assert) {
262-
var x = this.makeParts(1, 1).join('');
263-
assert.equal(x, 'BB', 'The King of the Blues');
294+
QUnit.test('make good music', function (assert) {
295+
var x = this.makeParts(1, 1).join('');
296+
assert.equal(x, 'BB', 'The King of the Blues');
297+
});
264298
});
265299
```

0 commit comments

Comments
 (0)