@jsenv/test 1.0.0 → 1.0.2
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/README.md +314 -0
- package/dist/jsenv_test.js +3 -1
- package/package.json +2 -2
- package/src/runtime_browsers/using_playwright.js +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# @jsenv/test [](https://www.npmjs.com/package/@jsenv/test)
|
|
2
|
+
|
|
3
|
+
Executing test files in web browsers and/or Node.js.
|
|
4
|
+
This tool enforce test files to be written as **standard** files, without any sort of complexity.
|
|
5
|
+
|
|
6
|
+
# 1. Writing tests on web browsers
|
|
7
|
+
|
|
8
|
+
This section demonstrates how to write a test that will be executed in a web browser.
|
|
9
|
+
|
|
10
|
+
The function that will be tested is inside "add.js" file:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
export const add = (a, b) => a + b
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The demonstration uses the following file structure:
|
|
17
|
+
|
|
18
|
+
<pre>
|
|
19
|
+
project/
|
|
20
|
+
src/
|
|
21
|
+
<strong>add.js</strong>
|
|
22
|
+
index.html
|
|
23
|
+
package.json
|
|
24
|
+
</pre>
|
|
25
|
+
|
|
26
|
+
At the end of the demo, the file structure will be like this:
|
|
27
|
+
|
|
28
|
+
<pre>
|
|
29
|
+
project/
|
|
30
|
+
scripts/
|
|
31
|
+
<strong>dev.mjs</strong>
|
|
32
|
+
<strong>test.mjs</strong>
|
|
33
|
+
src/
|
|
34
|
+
add.js
|
|
35
|
+
<strong>add.test.html</strong>
|
|
36
|
+
index.html
|
|
37
|
+
package.json
|
|
38
|
+
</pre>
|
|
39
|
+
|
|
40
|
+
## 1.1 Writing the test file
|
|
41
|
+
|
|
42
|
+
*src/add.test.html*
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<!DOCTYPE html>
|
|
46
|
+
<html>
|
|
47
|
+
<head>
|
|
48
|
+
<title>Title</title>
|
|
49
|
+
<meta charset="utf-8" />
|
|
50
|
+
<link rel="icon" href="data:," />
|
|
51
|
+
</head>
|
|
52
|
+
|
|
53
|
+
<body>
|
|
54
|
+
<script type="module">
|
|
55
|
+
import { add } from "./add.js"
|
|
56
|
+
|
|
57
|
+
const actual = add(1, 2)
|
|
58
|
+
const expected = 3
|
|
59
|
+
if (actual !== expected) {
|
|
60
|
+
throw new Error(`add(1,2) should return 3, got ${actual}`)
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 1.2 Executing the test file
|
|
68
|
+
|
|
69
|
+
*scripts/dev.mjs*: will start a web server that is needed to executed "add.test.html" in a browser.
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
import { startDevServer } from "@jsenv/core"
|
|
73
|
+
|
|
74
|
+
await startDevServer({
|
|
75
|
+
sourceDirectoryUrl: new URL("../src/", import.meta.url),
|
|
76
|
+
port: 3456,
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
*scripts/test.mjs*: will start a web browser and use it to execute all test files.
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import { executeTestPlan, chromium } from "@jsenv/test"
|
|
84
|
+
|
|
85
|
+
await executeTestPlan({
|
|
86
|
+
rootDirectoryUrl: new URL("../", import.meta.url),
|
|
87
|
+
testPlan: {
|
|
88
|
+
"./src/**/*.test.html": {
|
|
89
|
+
chromium: {
|
|
90
|
+
runtime: chromium()
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
webServer: {
|
|
95
|
+
origin: "http://localhost:3456",
|
|
96
|
+
rootDirectoryUrl: new URL("../src/", import.meta.url),
|
|
97
|
+
moduleUrl: new URL("./dev.mjs", import.meta.url),
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Command to install dependencies:
|
|
103
|
+
|
|
104
|
+
```console
|
|
105
|
+
npm i --save-dev @jsenv/core
|
|
106
|
+
npm i --save-dev @jsenv/test
|
|
107
|
+
npm i --save-dev playwright
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
☝️ Playwright is used by `@jsenv/test` to start a web browser, see [playwright website](https://github.com/microsoft/playwright)<sup>↗</sup>.
|
|
111
|
+
|
|
112
|
+
Command to execute tests:
|
|
113
|
+
|
|
114
|
+
```console
|
|
115
|
+
node ./scripts/test.mjs
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 1.3 Executing on more browsers
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
import {
|
|
122
|
+
executeTestPlan,
|
|
123
|
+
chromium,
|
|
124
|
+
firefox,
|
|
125
|
+
webkit,
|
|
126
|
+
} from "@jsenv/test"
|
|
127
|
+
|
|
128
|
+
await executeTestPlan({
|
|
129
|
+
rootDirectoryUrl: new URL("../", import.meta.url),
|
|
130
|
+
testPlan: {
|
|
131
|
+
"./src/**/*.test.html": {
|
|
132
|
+
chromium: {
|
|
133
|
+
runtime: chromium()
|
|
134
|
+
},
|
|
135
|
+
firefox: {
|
|
136
|
+
runtime: firefox()
|
|
137
|
+
},
|
|
138
|
+
webkit: {
|
|
139
|
+
runtime: webkit()
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
webServer: {
|
|
144
|
+
origin: "http://localhost:3456",
|
|
145
|
+
rootDirectoryUrl: new URL("../src/", import.meta.url),
|
|
146
|
+
moduleUrl: new URL("./dev.mjs", import.meta.url),
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 2. Writing tests on Node.js
|
|
152
|
+
|
|
153
|
+
This section demonstrates how to write a test that will be executed in Node.js.
|
|
154
|
+
|
|
155
|
+
The function that will be tested is inside "add.js" file:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
export const add = (a, b) => a + b
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The demonstration uses the following file structure:
|
|
162
|
+
|
|
163
|
+
<pre>
|
|
164
|
+
project/
|
|
165
|
+
src/
|
|
166
|
+
<strong>add.js</strong>
|
|
167
|
+
package.json
|
|
168
|
+
</pre>
|
|
169
|
+
|
|
170
|
+
At the end of the demo, the file structure will be like this:
|
|
171
|
+
|
|
172
|
+
<pre>
|
|
173
|
+
project/
|
|
174
|
+
scripts/
|
|
175
|
+
<strong>test.mjs</strong>
|
|
176
|
+
src/
|
|
177
|
+
add.js
|
|
178
|
+
tests/
|
|
179
|
+
<strong>add.test.mjs</strong>
|
|
180
|
+
package.json
|
|
181
|
+
</pre>
|
|
182
|
+
|
|
183
|
+
## 2.1 Writing the test file
|
|
184
|
+
|
|
185
|
+
*add.test.mjs*
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
import { add } from "./add.js"
|
|
189
|
+
|
|
190
|
+
const actual = add(1, 2)
|
|
191
|
+
const expected = 3
|
|
192
|
+
if (actual !== expected) {
|
|
193
|
+
throw new Error(`add(1,2) should return 3, got ${actual}`)
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 2.2 Executing the test file
|
|
198
|
+
|
|
199
|
+
*scripts/test.mjs*
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
import { executeTestPlan, nodeWorkerThread } from "@jsenv/test"
|
|
203
|
+
|
|
204
|
+
await executeTestPlan({
|
|
205
|
+
rootDirectoryUrl: new URL("../", import.meta.url),
|
|
206
|
+
testPlan: {
|
|
207
|
+
"./tests/**/*.test.mjs": {
|
|
208
|
+
node: {
|
|
209
|
+
runtime: nodeWorkerThread()
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Command to install dependencies:
|
|
217
|
+
|
|
218
|
+
```console
|
|
219
|
+
npm i --save-dev @jsenv/test
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Command to execute tests:
|
|
223
|
+
|
|
224
|
+
```console
|
|
225
|
+
node ./scripts/test.mjs
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## 3. Assertion library
|
|
229
|
+
|
|
230
|
+
To have a basic example, the part of the code comparing `actual` and `expected` was done without an assertion library.
|
|
231
|
+
In pratice a test would likely use one. The diff below shows how the assertion can be written using [@jsenv/assert](../assert). Note that any other assertion library would work.
|
|
232
|
+
|
|
233
|
+
```diff
|
|
234
|
+
+ import { assert } from "@jsenv/assert"
|
|
235
|
+
import { add } from "./add.js"
|
|
236
|
+
|
|
237
|
+
const actual = add(1, 2)
|
|
238
|
+
const expected = 3
|
|
239
|
+
- if (actual !== expected) {
|
|
240
|
+
- throw new Error(`add(1,2) should return 3, got ${actual}`)
|
|
241
|
+
- }
|
|
242
|
+
+ assert({ actual, expected })
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 4. API
|
|
246
|
+
|
|
247
|
+
## 4.1 executeTestPlan
|
|
248
|
+
|
|
249
|
+
```js
|
|
250
|
+
import { executeTestPlan } from "@jsenv/test"
|
|
251
|
+
|
|
252
|
+
const report = await executeTestPlan({
|
|
253
|
+
keepRunning: false, // true would keep process alive and all browsers opened even when tests are done
|
|
254
|
+
coverageEnabled: false, // collect code coverage while executing tests
|
|
255
|
+
})
|
|
256
|
+
report // contains many information about test executions
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## 4.2 chromium/firefox/webkit
|
|
260
|
+
|
|
261
|
+
Params can be used to configure how the browser runtime is started
|
|
262
|
+
|
|
263
|
+
```js
|
|
264
|
+
chromium({
|
|
265
|
+
headful: true // browser UI would be displayed while running tests
|
|
266
|
+
})
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## 4.3 nodeWorkerThread/nodeChildProcess
|
|
270
|
+
|
|
271
|
+
Params can be used to configure how node child process or node worker thread is started.
|
|
272
|
+
Both runtime share the same arguments.
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
import {
|
|
276
|
+
nodeWorkerThread,
|
|
277
|
+
nodeChildProcess
|
|
278
|
+
} from "@jsenv/test"
|
|
279
|
+
|
|
280
|
+
nodeWorkerThread({
|
|
281
|
+
commandLineOptions: [], // see https://nodejs.org/api/cli.html#options
|
|
282
|
+
env: null // will be written on process.env, see https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback
|
|
283
|
+
importMap: null, // can be used to override import resolution (redirect to other files during test)
|
|
284
|
+
})
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## 4.4 Allocated time
|
|
288
|
+
|
|
289
|
+
Each file is given 30s to execute.
|
|
290
|
+
If this duration is exceeded the browser tab (or node process/worker thread) is closed and execution is considered as failed.
|
|
291
|
+
This duration can be configured as shown below:
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
import {
|
|
295
|
+
executeTestPlan,
|
|
296
|
+
nodeWorkerThread
|
|
297
|
+
} from "@jsenv/test"
|
|
298
|
+
|
|
299
|
+
await executeTestPlan({
|
|
300
|
+
rootDirectoryUrl: new URL("../", import.meta.url),
|
|
301
|
+
testPlan: {
|
|
302
|
+
"./tests/**/*.test.mjs": {
|
|
303
|
+
node: {
|
|
304
|
+
runtime: nodeWorkerThread(),
|
|
305
|
+
allocatedMs: 60_000
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
})
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
☝️ Code above changes the default allocated time to 60s.
|
|
313
|
+
|
|
314
|
+
|
package/dist/jsenv_test.js
CHANGED
|
@@ -2081,6 +2081,8 @@ ansiEscapes.clearTerminal = isWindows ? `${ansiEscapes.eraseScreen}${ESC}0f`
|
|
|
2081
2081
|
// 3. Moves cursor to the top-left position
|
|
2082
2082
|
// More info: https://www.real-world-systems.com/docs/ANSIcode.html
|
|
2083
2083
|
: `${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
|
|
2084
|
+
ansiEscapes.enterAlternativeScreen = ESC + '?1049h';
|
|
2085
|
+
ansiEscapes.exitAlternativeScreen = ESC + '?1049l';
|
|
2084
2086
|
ansiEscapes.beep = BEL;
|
|
2085
2087
|
ansiEscapes.link = (text, url) => [OSC, '8', SEP, SEP, url, BEL, text, OSC, '8', SEP, SEP, BEL].join('');
|
|
2086
2088
|
ansiEscapes.image = (buffer, options = {}) => {
|
|
@@ -4503,7 +4505,7 @@ const createRuntimeUsingPlaywright = ({
|
|
|
4503
4505
|
stopOnExit: true,
|
|
4504
4506
|
playwrightLaunchOptions: {
|
|
4505
4507
|
...playwrightLaunchOptions,
|
|
4506
|
-
headless: !headful
|
|
4508
|
+
headless: headful === undefined ? !keepRunning : !headful
|
|
4507
4509
|
}
|
|
4508
4510
|
});
|
|
4509
4511
|
if (browser._initializer.version) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/test",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"playwright": "1.x"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@jsenv/core": "35.0.
|
|
36
|
+
"@jsenv/core": "35.0.1",
|
|
37
37
|
"@jsenv/abort": "4.2.4",
|
|
38
38
|
"@jsenv/ast": "3.0.6",
|
|
39
39
|
"@jsenv/filesystem": "4.2.3",
|
|
@@ -83,7 +83,7 @@ export const createRuntimeUsingPlaywright = ({
|
|
|
83
83
|
stopOnExit: true,
|
|
84
84
|
playwrightLaunchOptions: {
|
|
85
85
|
...playwrightLaunchOptions,
|
|
86
|
-
headless: !headful,
|
|
86
|
+
headless: headful === undefined ? !keepRunning : !headful,
|
|
87
87
|
},
|
|
88
88
|
})
|
|
89
89
|
if (browser._initializer.version) {
|