nole 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +514 -294
- package/bin/nole.js +145 -110
- package/dist/cjs/const.js +45 -0
- package/dist/cjs/core.js +61 -0
- package/dist/cjs/dynamic.js +56 -0
- package/dist/cjs/handle/after-each-hooks.js +29 -0
- package/dist/cjs/handle/after-hooks.js +27 -0
- package/dist/cjs/handle/before-each-hooks.js +29 -0
- package/dist/cjs/handle/before-hooks.js +37 -0
- package/dist/cjs/handle/cleanup-hooks.js +37 -0
- package/dist/cjs/handle/specs.js +52 -0
- package/dist/cjs/index.js +14 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/run.js +216 -0
- package/dist/cjs/symbol.js +6 -0
- package/dist/cjs/test-wrap.js +33 -0
- package/dist/cjs/utils/executor.js +23 -0
- package/dist/cjs/utils/time_difference.js +26 -0
- package/dist/cjs/utils/time_factor.js +31 -0
- package/dist/core.d.ts +3 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +2 -2
- package/dist/dynamic.d.ts +2 -0
- package/dist/dynamic.d.ts.map +1 -1
- package/dist/dynamic.js +16 -1
- package/dist/handle/before-hooks.d.ts.map +1 -1
- package/dist/handle/before-hooks.js +12 -2
- package/dist/handle/specs.d.ts.map +1 -1
- package/dist/handle/specs.js +12 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +16 -7
- package/dist/symbol.d.ts +1 -0
- package/dist/symbol.d.ts.map +1 -1
- package/dist/symbol.js +3 -2
- package/dist/test-wrap.d.ts +1 -0
- package/dist/test-wrap.d.ts.map +1 -1
- package/dist/test-wrap.js +1 -1
- package/dist/utils/time_difference.d.ts.map +1 -1
- package/package.json +68 -57
- package/dist/utils/executor.test.d.ts +0 -8
- package/dist/utils/executor.test.d.ts.map +0 -1
- package/dist/utils/executor.test.js +0 -22
- package/dist/utils/time_difference.test.d.ts +0 -6
- package/dist/utils/time_difference.test.d.ts.map +0 -1
- package/dist/utils/time_difference.test.js +0 -11
- package/dist/utils/time_factor.test.d.ts +0 -6
- package/dist/utils/time_factor.test.d.ts.map +0 -1
- package/dist/utils/time_factor.test.js +0 -27
- package/src/const.ts +0 -11
- package/src/core.ts +0 -89
- package/src/dynamic.ts +0 -53
- package/src/handle/after-each-hooks.ts +0 -41
- package/src/handle/after-hooks.ts +0 -38
- package/src/handle/before-each-hooks.ts +0 -40
- package/src/handle/before-hooks.ts +0 -39
- package/src/handle/cleanup-hooks.ts +0 -55
- package/src/handle/specs.ts +0 -68
- package/src/index.ts +0 -3
- package/src/run.ts +0 -259
- package/src/symbol.ts +0 -1
- package/src/test-wrap.ts +0 -48
- package/src/utils/executor.test.ts +0 -24
- package/src/utils/executor.ts +0 -22
- package/src/utils/time_difference.test.ts +0 -11
- package/src/utils/time_difference.ts +0 -26
- package/src/utils/time_factor.test.ts +0 -28
- package/src/utils/time_factor.ts +0 -33
- package/test/basic.test.ts +0 -23
- package/test/before.test.ts +0 -41
- package/test/clean-up.test.ts +0 -48
- package/test/dynamic-skip.test.ts +0 -6
- package/test/dynamic.test.ts +0 -28
- package/test/extend.test.ts +0 -43
- package/test/hook.test.ts +0 -26
- package/test/multi-dependency.test.ts +0 -43
- package/test/multiple-uppercased-chars.test.ts +0 -20
- package/test/skip-all.test.ts +0 -10
- package/test/tsconfig.json +0 -24
- package/test/turkish-chars.test.ts +0 -20
- package/tsconfig.json +0 -16
package/README.md
CHANGED
|
@@ -1,294 +1,514 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
# Nole
|
|
4
|
-
|
|
5
|
-
Nole is a testing platform just like mocha..
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
> -
|
|
207
|
-
> -
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# Nole
|
|
4
|
+
|
|
5
|
+
Nole is a testing platform just like mocha.. Feels simple, works really well.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// test/queue.test.ts
|
|
9
|
+
import { Test } from "nole";
|
|
10
|
+
|
|
11
|
+
export class QueueTest extends Test() {
|
|
12
|
+
queue!: Queue;
|
|
13
|
+
|
|
14
|
+
createInstance() {
|
|
15
|
+
this.queue = new Queue();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
push() {
|
|
19
|
+
this.queue.push(10);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async pipe() {
|
|
23
|
+
await this.queue.pipe(somewhere);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
$ nole ./test/**/*.test.ts
|
|
30
|
+
(ok) 0.09 ms QueueTest.createInstance()
|
|
31
|
+
(ok) 0.11 ms QueueTest.push()
|
|
32
|
+
(ok) 1.09 ms QueueTest.pipe()
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Skip
|
|
36
|
+
|
|
37
|
+
You can skip tests. Make sure method name starts with skip
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
// test/queue.test.ts
|
|
41
|
+
import { Test } from "nole";
|
|
42
|
+
|
|
43
|
+
export class QueueTest extends Test() {
|
|
44
|
+
skip_Push() {
|
|
45
|
+
this.queue.push(10);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
$ nole ./**/test/*.test.ts
|
|
52
|
+
(skip) QueueTest.skip_Push() {marked as skipped}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// test/queue.test.ts
|
|
57
|
+
import { Test } from "nole";
|
|
58
|
+
|
|
59
|
+
export class QueueTest extends Test({
|
|
60
|
+
skip: "no need",
|
|
61
|
+
}) {
|
|
62
|
+
push() {
|
|
63
|
+
this.queue.push(10);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
$ nole ./**/test/*.test.ts
|
|
70
|
+
(skip) QueueTest.skip_Push() {no need}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Dynamic Skip
|
|
74
|
+
|
|
75
|
+
Sometimes you only know at runtime whether a test should run. Call `skipTest()`
|
|
76
|
+
inside a spec to skip just that spec.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// test/queue.test.ts
|
|
80
|
+
import { Test, skipTest } from "nole";
|
|
81
|
+
|
|
82
|
+
export class QueueTest extends Test() {
|
|
83
|
+
push() {
|
|
84
|
+
if (!process.env.QUEUE_URL) {
|
|
85
|
+
skipTest("QUEUE_URL is not set");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.queue.push(10);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
$ nole ./test/**/*.test.ts
|
|
95
|
+
(dskip) QueueTest.push() {QUEUE_URL is not set}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Skipping the whole class
|
|
99
|
+
|
|
100
|
+
Use `skipClass()` to dynamically skip every remaining spec of the class. This is
|
|
101
|
+
handy inside the `before` hook, so an unmet precondition skips the entire class
|
|
102
|
+
instead of failing.
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
// test/queue.test.ts
|
|
106
|
+
import { Test, skipClass } from "nole";
|
|
107
|
+
|
|
108
|
+
export class QueueTest extends Test() {
|
|
109
|
+
async before() {
|
|
110
|
+
if (!process.env.QUEUE_URL) {
|
|
111
|
+
skipClass("QUEUE_URL is not set");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
push() {
|
|
116
|
+
this.queue.push(10);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async pipe() {
|
|
120
|
+
await this.queue.pipe(somewhere);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
$ nole ./test/**/*.test.ts
|
|
127
|
+
(dskip) QueueTest:before() {QUEUE_URL is not set}
|
|
128
|
+
(dskip) QueueTest.push()
|
|
129
|
+
↳ skip came from :before
|
|
130
|
+
(dskip) QueueTest.pipe()
|
|
131
|
+
↳ skip came from :before
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> You can also call `skipClass()` from a spec — every spec that hasn't run yet
|
|
135
|
+
> will be skipped, and the report shows where the skip came from.
|
|
136
|
+
>
|
|
137
|
+
> `skipClass()` can only be used inside specs and the `before` hook. Hooks
|
|
138
|
+
> cannot be skipped — calling `skipTest()` inside `before` is an error; you
|
|
139
|
+
> probably meant `skipClass()`.
|
|
140
|
+
|
|
141
|
+
## Internal functions
|
|
142
|
+
|
|
143
|
+
Nole treats every method as a spec by default. If you need a plain helper method
|
|
144
|
+
that Nole should not run as a spec, prefix its name with `_`.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
// test/queue.test.ts
|
|
148
|
+
import { Test } from "nole";
|
|
149
|
+
|
|
150
|
+
export class QueueTest extends Test() {
|
|
151
|
+
async _connect() {
|
|
152
|
+
// not a spec, just a helper you call yourself
|
|
153
|
+
return new Connection("...");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async push() {
|
|
157
|
+
const conn = await this._connect();
|
|
158
|
+
conn.push(10);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
$ nole ./test/**/*.test.ts
|
|
165
|
+
(ok) 0.11 ms QueueTest.push()
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
> The prefix is configurable via the `SPEC_SKIP_PREFIX` environment variable
|
|
169
|
+
> (defaults to `_`).
|
|
170
|
+
|
|
171
|
+
## Dependencies
|
|
172
|
+
|
|
173
|
+
You can include other tests and wait them to complete.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// test/database.test.ts
|
|
177
|
+
import { Test } from "nole";
|
|
178
|
+
|
|
179
|
+
export class Database extends Test() {
|
|
180
|
+
connection!: any;
|
|
181
|
+
|
|
182
|
+
async connect() {
|
|
183
|
+
connection = new Connection("...");
|
|
184
|
+
|
|
185
|
+
await connection.connect();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
// test/other.test.ts
|
|
192
|
+
import { Test } from "nole";
|
|
193
|
+
import { Database } from "./database.test";
|
|
194
|
+
|
|
195
|
+
export class Other extends Test({
|
|
196
|
+
dependencies: {
|
|
197
|
+
database: () => Database,
|
|
198
|
+
},
|
|
199
|
+
}) {
|
|
200
|
+
async DoThings() {
|
|
201
|
+
await this.database.connection.doStuff();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
> - All dependencies will be waited until done
|
|
207
|
+
> - If dependencies cannot resolve, it will occurr an error after the available tests done.
|
|
208
|
+
|
|
209
|
+
## Wait other tests
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
// test/redis.test.ts
|
|
213
|
+
import { Test } from "nole";
|
|
214
|
+
|
|
215
|
+
export class A extends Test() {
|
|
216
|
+
async doThings() {}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export class B extends Test({ before: () => [A] }) {
|
|
220
|
+
async doThings() {}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Hook
|
|
225
|
+
|
|
226
|
+
Hooks will help you to develop helper methods.
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
// test/hook.test.ts
|
|
230
|
+
import { Test } from "nole";
|
|
231
|
+
|
|
232
|
+
export class HookTest {
|
|
233
|
+
value!: number;
|
|
234
|
+
|
|
235
|
+
async beforeEach() {
|
|
236
|
+
this.value = Math.random();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
validateNumber() {
|
|
240
|
+
if (this.value > 0.5) {
|
|
241
|
+
throw new Error("Should not be higher than 0.5");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Dynamic Tests
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
// test/dynamic.test.ts
|
|
251
|
+
import { Test, addTest } from "nole";
|
|
252
|
+
|
|
253
|
+
// not exported, nole cannot auto-bind this class
|
|
254
|
+
class DynamicTest extends Test() {
|
|
255
|
+
test() {}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// adds it anyway
|
|
259
|
+
addTest(() => DynamicTest);
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
// test/dynamic2.test.ts
|
|
264
|
+
import { Test, addTest } from "nole";
|
|
265
|
+
|
|
266
|
+
if (something) {
|
|
267
|
+
addTest(
|
|
268
|
+
() =>
|
|
269
|
+
class Special extends Test() {
|
|
270
|
+
check() {}
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
// test/dynamic3.test.ts
|
|
278
|
+
import { Test, addTest } from "nole";
|
|
279
|
+
|
|
280
|
+
export class DeepTest extends Test() {
|
|
281
|
+
check() {
|
|
282
|
+
if (something) {
|
|
283
|
+
addTest(() => class Wololo extends Test() {});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Test cleanup
|
|
290
|
+
|
|
291
|
+
There is a special hook that can be used to capture test finishing stage.
|
|
292
|
+
|
|
293
|
+
> **Lifecycle:**
|
|
294
|
+
>
|
|
295
|
+
> - (class) Before
|
|
296
|
+
> - - (method) BeforeEach
|
|
297
|
+
> - - (method) Spec
|
|
298
|
+
> - - (method) AfterEach
|
|
299
|
+
> - (class) After
|
|
300
|
+
> - (class) CleanUp \*called after dependency execution
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
// test/database-with-cleanup.test.ts
|
|
304
|
+
import { Test } from "nole";
|
|
305
|
+
|
|
306
|
+
export class DatabaseWithCleanup extends Test() {
|
|
307
|
+
connection!: any;
|
|
308
|
+
|
|
309
|
+
async connect() {
|
|
310
|
+
this.connection = new Connection("...");
|
|
311
|
+
|
|
312
|
+
await connection.connect();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async cleanUp() {
|
|
316
|
+
this.connection.close();
|
|
317
|
+
console.log("Connection closed!");
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
// test/other.test.ts
|
|
324
|
+
import { Test } from "nole";
|
|
325
|
+
import { Database } from "./database.test";
|
|
326
|
+
|
|
327
|
+
export class Other extends Test({
|
|
328
|
+
dependencies: {
|
|
329
|
+
database: () => DatabaseWithCleanup,
|
|
330
|
+
},
|
|
331
|
+
}) {
|
|
332
|
+
async doThings() {
|
|
333
|
+
await this.database.connection.doStuff();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
$ nole ./test/**/*.test.ts
|
|
340
|
+
(ok) 0.09 ms DatabaseWithCleanup.connect()
|
|
341
|
+
(ok) 0.11 ms Other.doThings()
|
|
342
|
+
Connection closed!
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Test extending
|
|
346
|
+
|
|
347
|
+
If they are classes we should be able to extend them right
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
// test/extending.test.ts
|
|
351
|
+
import { Test } from "nole";
|
|
352
|
+
|
|
353
|
+
// Simple is not exported, so nole wont handle it
|
|
354
|
+
class Simple extends Test() {
|
|
355
|
+
value = 1;
|
|
356
|
+
|
|
357
|
+
check() {
|
|
358
|
+
if (this.value !== 1) {
|
|
359
|
+
// yeah it should be 1 anyway
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export class Complex extends Simple {
|
|
365
|
+
check() {
|
|
366
|
+
if (this.value > 0) {
|
|
367
|
+
// maybe it is more than just 1?
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
super.check(); // or
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export class MoreComplex extends Simple {
|
|
375
|
+
moreSpecs() {
|
|
376
|
+
// mooree
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
$ nole ./test/**/*.test.ts
|
|
383
|
+
(ok) 0.09 ms Complex.check()
|
|
384
|
+
(ok) 0.11 ms MoreComplex.check()
|
|
385
|
+
(ok) 0.11 ms MoreComplex.moreSpecs()
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Execution order
|
|
389
|
+
|
|
390
|
+
Inherited specs run parent-first, so a child can rely on the state left behind
|
|
391
|
+
by its ancestors.
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
// test/inheritance.test.ts
|
|
395
|
+
import * as assert from "assert";
|
|
396
|
+
import { Test } from "nole";
|
|
397
|
+
|
|
398
|
+
export class GrandparentTest extends Test() {
|
|
399
|
+
variable = 1;
|
|
400
|
+
|
|
401
|
+
async doesSomething() {
|
|
402
|
+
assert.equal(this.variable, 1);
|
|
403
|
+
this.variable = 2;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export class FatherTest extends GrandparentTest {
|
|
408
|
+
async doesSomethingElse() {
|
|
409
|
+
assert.equal(this.variable, 2);
|
|
410
|
+
this.variable = 3;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export class ChildTest extends FatherTest {
|
|
415
|
+
async doesMoreStuff() {
|
|
416
|
+
assert.equal(this.variable, 3);
|
|
417
|
+
this.variable = 4;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
$ nole ./test/**/*.test.ts
|
|
424
|
+
(ok) 0.09 ms ChildTest.doesSomething()
|
|
425
|
+
(ok) 0.10 ms ChildTest.doesSomethingElse()
|
|
426
|
+
(ok) 0.11 ms ChildTest.doesMoreStuff()
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Inheriting behavior
|
|
430
|
+
|
|
431
|
+
Skips and hooks are inherited too. A `skipClass()` defined on a base class skips
|
|
432
|
+
every subclass that reaches it, and an overridden hook can call `super` to keep
|
|
433
|
+
the parent's setup.
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
// test/inheritance.test.ts
|
|
437
|
+
import { Test, skipClass } from "nole";
|
|
438
|
+
|
|
439
|
+
// not exported, only used as a base
|
|
440
|
+
class CompanyTest extends Test() {
|
|
441
|
+
async noWorkingAllowed() {
|
|
442
|
+
skipClass("no working allowed");
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export class EmployeeTest extends CompanyTest {
|
|
447
|
+
async work() {
|
|
448
|
+
// never runs, the class is skipped
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
class HookInitialTest extends Test() {
|
|
453
|
+
variable = 1;
|
|
454
|
+
|
|
455
|
+
before() {
|
|
456
|
+
this.variable = 2;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
test() {
|
|
460
|
+
assert.equal(this.variable, 2);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export class HookOverrideTest extends HookInitialTest {
|
|
465
|
+
before() {
|
|
466
|
+
super.before(); // keep the parent's setup
|
|
467
|
+
this.variable = 10;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
test() {
|
|
471
|
+
assert.equal(this.variable, 10);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## CommonJS support
|
|
477
|
+
|
|
478
|
+
Nole ships both an ESM and a CommonJS build, wired up through the package
|
|
479
|
+
`exports` map. Use whichever your project speaks — `import` gets the ESM build,
|
|
480
|
+
`require` gets the CommonJS one:
|
|
481
|
+
|
|
482
|
+
```js
|
|
483
|
+
import { Test } from "nole"; // ESM
|
|
484
|
+
const { Test } = require("nole"); // CommonJS
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
You don't even need TypeScript. A plain CommonJS `.js` test file works:
|
|
488
|
+
|
|
489
|
+
```js
|
|
490
|
+
// test/commonjs/require.test.js
|
|
491
|
+
const { Test } = require("nole");
|
|
492
|
+
|
|
493
|
+
exports.CommonJSTest = class CommonJSTest extends Test() {
|
|
494
|
+
async check() {
|
|
495
|
+
console.log("It works from CommonJS");
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
When discovering tests, nole loads each file with the loader that matches its own
|
|
501
|
+
module format: ESM files via `import()`, CommonJS files via `require()`. The
|
|
502
|
+
format is decided the same way Node decides it — `.mts`/`.cts` win by extension,
|
|
503
|
+
otherwise the nearest `package.json` `type` field is used. So ESM and CommonJS
|
|
504
|
+
test files can even live side by side in one run:
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
$ nole './test/**/*.test.{ts,js}'
|
|
508
|
+
(ok) 0.11 ms QueueTest.push()
|
|
509
|
+
(ok) 0.58 ms CommonJSTest.check()
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
> Quote your globs (`'./test/**/*.test.{ts,js}'`) so nole expands them itself
|
|
513
|
+
> instead of relying on the shell — this keeps discovery consistent across
|
|
514
|
+
> environments.
|