|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 'use strict'; |
|
6 |
|
7 module.metadata = { |
|
8 'stability': 'unstable' |
|
9 }; |
|
10 |
|
11 const { defer } = require('../core/promise'); |
|
12 const { setInterval, clearInterval } = require('../timers'); |
|
13 |
|
14 function getTestNames (exports) |
|
15 Object.keys(exports).filter(name => /^test/.test(name)) |
|
16 |
|
17 function isTestAsync (fn) fn.length > 1 |
|
18 function isHelperAsync (fn) fn.length > 2 |
|
19 |
|
20 /* |
|
21 * Takes an `exports` object of a test file and a function `beforeFn` |
|
22 * to be run before each test. `beforeFn` is called with a `name` string |
|
23 * as the first argument of the test name, and may specify a second |
|
24 * argument function `done` to indicate that this function should |
|
25 * resolve asynchronously |
|
26 */ |
|
27 function before (exports, beforeFn) { |
|
28 getTestNames(exports).map(name => { |
|
29 let testFn = exports[name]; |
|
30 if (!isTestAsync(testFn) && !isHelperAsync(beforeFn)) { |
|
31 exports[name] = function (assert) { |
|
32 beforeFn(name, assert); |
|
33 testFn(assert); |
|
34 }; |
|
35 } |
|
36 else if (isTestAsync(testFn) && !isHelperAsync(beforeFn)) { |
|
37 exports[name] = function (assert, done) { |
|
38 beforeFn(name, assert); |
|
39 testFn(assert, done); |
|
40 }; |
|
41 } |
|
42 else if (!isTestAsync(testFn) && isHelperAsync(beforeFn)) { |
|
43 exports[name] = function (assert, done) { |
|
44 beforeFn(name, assert, () => { |
|
45 testFn(assert); |
|
46 done(); |
|
47 }); |
|
48 }; |
|
49 } else if (isTestAsync(testFn) && isHelperAsync(beforeFn)) { |
|
50 exports[name] = function (assert, done) { |
|
51 beforeFn(name, assert, () => { |
|
52 testFn(assert, done); |
|
53 }); |
|
54 }; |
|
55 } |
|
56 }); |
|
57 } |
|
58 exports.before = before; |
|
59 |
|
60 /* |
|
61 * Takes an `exports` object of a test file and a function `afterFn` |
|
62 * to be run after each test. `afterFn` is called with a `name` string |
|
63 * as the first argument of the test name, and may specify a second |
|
64 * argument function `done` to indicate that this function should |
|
65 * resolve asynchronously |
|
66 */ |
|
67 function after (exports, afterFn) { |
|
68 getTestNames(exports).map(name => { |
|
69 let testFn = exports[name]; |
|
70 if (!isTestAsync(testFn) && !isHelperAsync(afterFn)) { |
|
71 exports[name] = function (assert) { |
|
72 testFn(assert); |
|
73 afterFn(name, assert); |
|
74 }; |
|
75 } |
|
76 else if (isTestAsync(testFn) && !isHelperAsync(afterFn)) { |
|
77 exports[name] = function (assert, done) { |
|
78 testFn(assert, () => { |
|
79 afterFn(name, assert); |
|
80 done(); |
|
81 }); |
|
82 }; |
|
83 } |
|
84 else if (!isTestAsync(testFn) && isHelperAsync(afterFn)) { |
|
85 exports[name] = function (assert, done) { |
|
86 testFn(assert); |
|
87 afterFn(name, assert, done); |
|
88 }; |
|
89 } else if (isTestAsync(testFn) && isHelperAsync(afterFn)) { |
|
90 exports[name] = function (assert, done) { |
|
91 testFn(assert, () => { |
|
92 afterFn(name, assert, done); |
|
93 }); |
|
94 }; |
|
95 } |
|
96 }); |
|
97 } |
|
98 exports.after = after; |
|
99 |
|
100 function waitUntil (predicate, delay) { |
|
101 let { promise, resolve } = defer(); |
|
102 let interval = setInterval(() => { |
|
103 if (!predicate()) return; |
|
104 clearInterval(interval); |
|
105 resolve(); |
|
106 }, delay || 10); |
|
107 return promise; |
|
108 } |
|
109 exports.waitUntil = waitUntil; |