vitest 0.0.72 → 0.0.76
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.gh.md +10 -276
- package/dist/cli.js +114 -50
- package/dist/entry.js +93 -22
- package/dist/{error-fb6ff2e6.js → error-1df12c37.js} +47 -31
- package/dist/{global-e40b54d6.js → global-784f167d.js} +2 -2
- package/dist/index-bf952d9c.js +33 -0
- package/dist/index.d.ts +39 -15
- package/dist/index.js +2 -2
- package/dist/{suite-819c135e.js → suite-1bc54c1b.js} +41 -40
- package/dist/worker.js +1 -0
- package/package.json +3 -2
- package/dist/index-e37648e9.js +0 -31
package/README.gh.md
CHANGED
|
@@ -11,6 +11,14 @@ A blazing fast unit test framework powered by Vite.
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="https://www.npmjs.com/package/vitest"><img src="https://img.shields.io/npm/v/vitest?color=a1b858&label="></a>
|
|
13
13
|
<p>
|
|
14
|
+
<h2 align="center">
|
|
15
|
+
<a href="https://preview.vitest.dev">Open the Docs</a>
|
|
16
|
+
</h2>
|
|
17
|
+
<h3 align="center">
|
|
18
|
+
<a href=https://discord.com/invite/2zYZNngd7y"><i>Get involved!</i></a>
|
|
19
|
+
</h3>
|
|
20
|
+
<br>
|
|
21
|
+
<br>
|
|
14
22
|
|
|
15
23
|
> 💖 **This project is currently in closed beta exclusively for Sponsors.**<br>
|
|
16
24
|
> Become a Sponsor of [@patak-dev](https://github.com/sponsors/patak-dev) or [@antfu](https://github.com/sponsors/antfu) to access the source code and issues tracker.
|
|
@@ -19,7 +27,8 @@ A blazing fast unit test framework powered by Vite.
|
|
|
19
27
|
|
|
20
28
|
> Vitest requires Vite v2.7 and Node v16
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
|
|
31
|
+
Switch to Vitest by following the [Getting Started Guide](https://preview.vitest.dev/guide) or learn [why we are building a new test runner](https://preview.vitest.dev/guide).
|
|
23
32
|
|
|
24
33
|
## Features
|
|
25
34
|
|
|
@@ -74,281 +83,6 @@ $ npx vitest
|
|
|
74
83
|
- [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)
|
|
75
84
|
- [vitesse-lite](https://github.com/antfu/vitesse-lite)
|
|
76
85
|
|
|
77
|
-
## Configuration
|
|
78
|
-
|
|
79
|
-
`vitest` will read your root `vite.config.ts` when it present to match with the plugins and setup as your Vite app. If you want to it to have a different configuration for testing, you could either:
|
|
80
|
-
|
|
81
|
-
- Create `vitest.config.ts`, which will have the higher priority
|
|
82
|
-
- Pass `--config` option to CLI, e.g. `vitest --config ./path/to/vitest.config.ts`
|
|
83
|
-
- Use `process.env.VITEST` to conditionally apply different configuration in `vite.config.ts`
|
|
84
|
-
|
|
85
|
-
To configure `vitest` itself, add `test` property in your Vite config
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
|
-
// vite.config.ts
|
|
89
|
-
import { defineConfig } from 'vite'
|
|
90
|
-
|
|
91
|
-
export default defineConfig({
|
|
92
|
-
test: {
|
|
93
|
-
// ...
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Global APIs
|
|
99
|
-
|
|
100
|
-
By default, `vitest` does not provide global APIs for explicitness. If you prefer to use the APIs globally like Jest, you can pass the `--global` option to CLI or add `global: true` in the config.
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
// vite.config.ts
|
|
104
|
-
import { defineConfig } from 'vite'
|
|
105
|
-
|
|
106
|
-
export default defineConfig({
|
|
107
|
-
test: {
|
|
108
|
-
global: true
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
To get TypeScript working with the global APIs, add `vitest/global` to the `types` filed in your `tsconfig.json`
|
|
114
|
-
|
|
115
|
-
```jsonc
|
|
116
|
-
// tsconfig.json
|
|
117
|
-
{
|
|
118
|
-
"compilerOptions": {
|
|
119
|
-
"types": [
|
|
120
|
-
"vitest/global"
|
|
121
|
-
]
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
If you are already using [`unplugin-auto-import`](https://github.com/antfu/unplugin-vue-components) in your project, you can also use it directly for auto importing those APIs.
|
|
127
|
-
|
|
128
|
-
```ts
|
|
129
|
-
// vite.config.ts
|
|
130
|
-
import { defineConfig } from 'vite'
|
|
131
|
-
import AutoImport from 'unplugin-auto-import/vite'
|
|
132
|
-
|
|
133
|
-
export default defineConfig({
|
|
134
|
-
plugins: [
|
|
135
|
-
AutoImport({
|
|
136
|
-
imports: ['vitest'],
|
|
137
|
-
dts: true // generate TypeScript declaration
|
|
138
|
-
})
|
|
139
|
-
]
|
|
140
|
-
})
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Browser Mocking
|
|
144
|
-
|
|
145
|
-
Vitest supports both [happy-dom](https://github.com/capricorn86/happy-dom) or [jsdom](https://github.com/jsdom/jsdom) for mocking DOM and browser APIs. They don't come with Vitest, you might need to install them:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
$ npm i -D happy-dom
|
|
149
|
-
# or
|
|
150
|
-
$ npm i -D jsdom
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
After that, change the `environment` option in your config file:
|
|
154
|
-
|
|
155
|
-
```ts
|
|
156
|
-
// vite.config.ts
|
|
157
|
-
import { defineConfig } from 'vite'
|
|
158
|
-
|
|
159
|
-
export default defineConfig({
|
|
160
|
-
test: {
|
|
161
|
-
environment: 'happy-dom' // or 'jsdom', 'node'
|
|
162
|
-
}
|
|
163
|
-
})
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Watch Mode
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
$ vitest -w
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
Vitest smartly searches the module graph and only rerun the related tests (just like how HMR works in Vite!).
|
|
173
|
-
|
|
174
|
-
## Coverage
|
|
175
|
-
|
|
176
|
-
Vitest works perfectly with [c8](https://github.com/bcoe/c8)
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
$ npm i -D c8
|
|
180
|
-
$ c8 vitest
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
```json
|
|
184
|
-
{
|
|
185
|
-
"scripts": {
|
|
186
|
-
"test": "vitest",
|
|
187
|
-
"coverage": "c8 vitest"
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
For convenience, we also provide a shorthand for passing `--coverage` option to CLI, which will wrap the process with `c8` for you. Note when using the shorthand, you will lose the ability to pass additional options to `c8`.
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
$ vitest --coverage
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
For more configuration available, please refer to [c8](https://github.com/bcoe/c8)'s documentation.
|
|
199
|
-
|
|
200
|
-
## Filtering
|
|
201
|
-
|
|
202
|
-
### CLI
|
|
203
|
-
|
|
204
|
-
You can use CLI to filter test files my name:
|
|
205
|
-
|
|
206
|
-
```bash
|
|
207
|
-
$ vitest basic
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
Will only execute test files that contain `basic`, e.g.
|
|
211
|
-
|
|
212
|
-
```
|
|
213
|
-
basic.test.ts
|
|
214
|
-
basic-foo.test.ts
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Specifying a Timeout
|
|
218
|
-
|
|
219
|
-
You can optionally pass a timeout in milliseconds as third argument to tests. The default is 5 seconds.
|
|
220
|
-
|
|
221
|
-
```ts
|
|
222
|
-
test('name', async() => { ... }, 1000)
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
Hooks also can receive a timeout, with the same 5 seconds default.
|
|
226
|
-
|
|
227
|
-
```ts
|
|
228
|
-
beforeAll( async() => { ... }, 1000)
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Skipping suites and tests
|
|
232
|
-
|
|
233
|
-
Use `.skip` to avoid running certain suites or tests
|
|
234
|
-
|
|
235
|
-
```ts
|
|
236
|
-
describe.skip('skipped suite', () => {
|
|
237
|
-
it('test', () => {
|
|
238
|
-
// Suite skipped, no error
|
|
239
|
-
assert.equal(Math.sqrt(4), 3)
|
|
240
|
-
})
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
describe('suite', () => {
|
|
244
|
-
it.skip('skipped test', () => {
|
|
245
|
-
// Test skipped, no error
|
|
246
|
-
assert.equal(Math.sqrt(4), 3)
|
|
247
|
-
})
|
|
248
|
-
})
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### Selecting suites and tests to run
|
|
252
|
-
|
|
253
|
-
Use `.only` to only run certain suites or tests
|
|
254
|
-
|
|
255
|
-
```ts
|
|
256
|
-
// Only this suite (and others marked with only) are run
|
|
257
|
-
describe.only('suite', () => {
|
|
258
|
-
it('test', () => {
|
|
259
|
-
assert.equal(Math.sqrt(4), 3)
|
|
260
|
-
})
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
describe('another suite', () => {
|
|
264
|
-
it('skipped test', () => {
|
|
265
|
-
// Test skipped, as tests are running in Only mode
|
|
266
|
-
assert.equal(Math.sqrt(4), 3)
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
it.only('test', () => {
|
|
270
|
-
// Only this test (and others marked with only) are run
|
|
271
|
-
assert.equal(Math.sqrt(4), 2)
|
|
272
|
-
})
|
|
273
|
-
})
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Unimplemented suites and tests
|
|
277
|
-
|
|
278
|
-
Use `.todo` to stub suites and tests that should be implemented
|
|
279
|
-
|
|
280
|
-
```ts
|
|
281
|
-
// An entry will be shown in the report for this suite
|
|
282
|
-
describe.todo('unimplemented suite')
|
|
283
|
-
|
|
284
|
-
// An entry will be shown in the report for this test
|
|
285
|
-
describe('suite', () => {
|
|
286
|
-
it.todo('unimplemented test')
|
|
287
|
-
})
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
### Running tests concurrently
|
|
291
|
-
|
|
292
|
-
Use `.concurrent` in consecutive tests to run them in parallel
|
|
293
|
-
|
|
294
|
-
```ts
|
|
295
|
-
// The two tests marked with concurrent will be run in parallel
|
|
296
|
-
describe('suite', () => {
|
|
297
|
-
it('serial test', () => {
|
|
298
|
-
assert.equal(Math.sqrt(4), 3)
|
|
299
|
-
})
|
|
300
|
-
it.concurrent('concurrent test 1', () => {
|
|
301
|
-
assert.equal(Math.sqrt(4), 3)
|
|
302
|
-
})
|
|
303
|
-
it.concurrent('concurrent test 2', () => {
|
|
304
|
-
assert.equal(Math.sqrt(4), 3)
|
|
305
|
-
})
|
|
306
|
-
})
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
If you use `.concurrent` in a suite, every tests in it will be run in parallel
|
|
310
|
-
```ts
|
|
311
|
-
// The two tests marked with concurrent will be run in parallel
|
|
312
|
-
describe.concurrent('suite', () => {
|
|
313
|
-
it('concurrent test 1', () => {
|
|
314
|
-
assert.equal(Math.sqrt(4), 3)
|
|
315
|
-
})
|
|
316
|
-
it('concurrent test 2', () => {
|
|
317
|
-
assert.equal(Math.sqrt(4), 3)
|
|
318
|
-
})
|
|
319
|
-
// No effect, same as not using .concurrent
|
|
320
|
-
it.concurrent('concurrent test 3', () => {
|
|
321
|
-
assert.equal(Math.sqrt(4), 3)
|
|
322
|
-
})
|
|
323
|
-
})
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
You can also use `.skip`, `.only`, and `.todo` with concurrent suite and tests. All the following combinations are valid:
|
|
327
|
-
```js
|
|
328
|
-
describe.concurrent(...)
|
|
329
|
-
|
|
330
|
-
describe.skip.concurrent(...)
|
|
331
|
-
describe.concurrent.skip(...)
|
|
332
|
-
|
|
333
|
-
describe.only.concurrent(...)
|
|
334
|
-
describe.concurrent.only(...)
|
|
335
|
-
|
|
336
|
-
describe.todo.concurrent(...)
|
|
337
|
-
describe.concurrent.todo(...)
|
|
338
|
-
|
|
339
|
-
it.concurrent(...)
|
|
340
|
-
|
|
341
|
-
it.skip.concurrent(...)
|
|
342
|
-
it.concurrent.skip(...)
|
|
343
|
-
|
|
344
|
-
it.only.concurrent(...)
|
|
345
|
-
it.concurrent.only(...)
|
|
346
|
-
|
|
347
|
-
it.todo.concurrent(...)
|
|
348
|
-
it.concurrent.todo(...)
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
|
|
352
86
|
## Sponsors
|
|
353
87
|
|
|
354
88
|
<p align="center">
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import require$$2, { EventEmitter } from 'events';
|
|
2
|
-
import { s as stringWidth, a as ansiStyles, b as stripAnsi, c as sliceAnsi, d as c, F as F_POINTER, e as F_DOWN, f as
|
|
2
|
+
import { s as stringWidth, a as ansiStyles, b as stripAnsi, c as sliceAnsi, d as c, F as F_POINTER, e as F_DOWN, f as F_LONG_DASH, g as F_DOWN_RIGHT, h as F_DOT, i as F_CHECK, j as F_CROSS, k as cliTruncate, l as F_RIGHT, p as printError } from './error-1df12c37.js';
|
|
3
3
|
import { performance } from 'perf_hooks';
|
|
4
4
|
import path, { isAbsolute, relative, dirname, basename, resolve } from 'path';
|
|
5
5
|
import { g as getNames, s as slash, a as getTests, b as getSuites, t as toArray, h as hasFailed } from './utils-9dcc4050.js';
|
|
@@ -632,7 +632,7 @@ const cac = (name = "") => new CAC(name);
|
|
|
632
632
|
|
|
633
633
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
634
634
|
|
|
635
|
-
var version = "0.0.
|
|
635
|
+
var version = "0.0.76";
|
|
636
636
|
|
|
637
637
|
const ESC = '\u001B[';
|
|
638
638
|
const OSC = '\u001B]';
|
|
@@ -1451,6 +1451,24 @@ const spinnerMap = new WeakMap();
|
|
|
1451
1451
|
const outputMap = new WeakMap();
|
|
1452
1452
|
const pointer = c.yellow(F_POINTER);
|
|
1453
1453
|
const skipped = c.yellow(F_DOWN);
|
|
1454
|
+
function divider(text, left, right) {
|
|
1455
|
+
let length = process.stdout.columns;
|
|
1456
|
+
if (!length || isNaN(length))
|
|
1457
|
+
length = 10;
|
|
1458
|
+
if (text) {
|
|
1459
|
+
const textLength = stripAnsi(text).length;
|
|
1460
|
+
if (left == null && right != null) {
|
|
1461
|
+
left = length - textLength - right;
|
|
1462
|
+
} else {
|
|
1463
|
+
left = left ?? Math.floor((length - textLength) / 2);
|
|
1464
|
+
right = length - textLength - left;
|
|
1465
|
+
}
|
|
1466
|
+
left = Math.max(0, left);
|
|
1467
|
+
right = Math.max(0, right);
|
|
1468
|
+
return `${F_LONG_DASH.repeat(left)}${text}${F_LONG_DASH.repeat(right)}`;
|
|
1469
|
+
}
|
|
1470
|
+
return F_LONG_DASH.repeat(length);
|
|
1471
|
+
}
|
|
1454
1472
|
function formatTestPath(root, path) {
|
|
1455
1473
|
var _a;
|
|
1456
1474
|
if (isAbsolute(path))
|
|
@@ -1573,7 +1591,8 @@ function renderTree(tasks, level = 0) {
|
|
|
1573
1591
|
const createRenderer = (_tasks) => {
|
|
1574
1592
|
let tasks = _tasks;
|
|
1575
1593
|
let timer;
|
|
1576
|
-
const
|
|
1594
|
+
const stdout = process.stdout;
|
|
1595
|
+
const log = createLogUpdate(stdout);
|
|
1577
1596
|
function update() {
|
|
1578
1597
|
log(renderTree(tasks));
|
|
1579
1598
|
}
|
|
@@ -1595,13 +1614,17 @@ const createRenderer = (_tasks) => {
|
|
|
1595
1614
|
timer = void 0;
|
|
1596
1615
|
}
|
|
1597
1616
|
log.clear();
|
|
1598
|
-
|
|
1617
|
+
stdout.write(`${renderTree(tasks)}
|
|
1618
|
+
`);
|
|
1599
1619
|
return this;
|
|
1620
|
+
},
|
|
1621
|
+
clear() {
|
|
1622
|
+
log.clear();
|
|
1600
1623
|
}
|
|
1601
1624
|
};
|
|
1602
1625
|
};
|
|
1603
1626
|
function getFullName(task) {
|
|
1604
|
-
return getNames(task).join(c.
|
|
1627
|
+
return getNames(task).join(c.dim(" > "));
|
|
1605
1628
|
}
|
|
1606
1629
|
const spinnerFrames = process.platform === "win32" ? ["-", "\\", "|", "/"] : ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1607
1630
|
function elegantSpinner() {
|
|
@@ -1618,11 +1641,23 @@ class DefaultReporter {
|
|
|
1618
1641
|
this.ctx = ctx;
|
|
1619
1642
|
this.start = 0;
|
|
1620
1643
|
this.end = 0;
|
|
1644
|
+
this.console = globalThis.console;
|
|
1645
|
+
this.isFirstWatchRun = true;
|
|
1621
1646
|
const mode = ctx.config.watch ? c.yellow(" DEV ") : c.cyan(" RUN ");
|
|
1622
|
-
|
|
1647
|
+
this.log(`${c.inverse(c.bold(mode))} ${c.gray(this.ctx.config.root)}
|
|
1623
1648
|
`);
|
|
1624
1649
|
this.start = performance.now();
|
|
1625
1650
|
}
|
|
1651
|
+
log(...args) {
|
|
1652
|
+
if (this.ctx.config.silent)
|
|
1653
|
+
return;
|
|
1654
|
+
this.console.log(...args);
|
|
1655
|
+
}
|
|
1656
|
+
error(...args) {
|
|
1657
|
+
if (this.ctx.config.silent)
|
|
1658
|
+
return;
|
|
1659
|
+
this.console.error(...args);
|
|
1660
|
+
}
|
|
1626
1661
|
relative(path) {
|
|
1627
1662
|
return relative(this.ctx.config.root, path);
|
|
1628
1663
|
}
|
|
@@ -1641,16 +1676,16 @@ class DefaultReporter {
|
|
|
1641
1676
|
return;
|
|
1642
1677
|
const task = this.ctx.state.idMap[pack[0]];
|
|
1643
1678
|
if (task.type === "test" && ((_a = task.result) == null ? void 0 : _a.state) && ((_b = task.result) == null ? void 0 : _b.state) !== "run") {
|
|
1644
|
-
|
|
1679
|
+
this.log(` ${getStateSymbol(task)} ${getFullName(task)}`);
|
|
1645
1680
|
if (task.result.state === "fail")
|
|
1646
|
-
|
|
1681
|
+
this.log(c.red(` ${F_RIGHT} ${(_c = task.result.error) == null ? void 0 : _c.message}`));
|
|
1647
1682
|
}
|
|
1648
1683
|
}
|
|
1649
1684
|
async onFinished(files = this.ctx.state.getFiles()) {
|
|
1650
1685
|
var _a, _b;
|
|
1651
1686
|
this.end = performance.now();
|
|
1652
1687
|
await this.stopListRender();
|
|
1653
|
-
|
|
1688
|
+
this.log();
|
|
1654
1689
|
const suites = getSuites(files);
|
|
1655
1690
|
const tests = getTests(files);
|
|
1656
1691
|
const failedSuites = suites.filter((i) => {
|
|
@@ -1661,24 +1696,27 @@ class DefaultReporter {
|
|
|
1661
1696
|
var _a2;
|
|
1662
1697
|
return ((_a2 = i.result) == null ? void 0 : _a2.state) === "fail";
|
|
1663
1698
|
});
|
|
1699
|
+
const failedTotal = failedSuites.length + failedTests.length;
|
|
1700
|
+
let current = 1;
|
|
1701
|
+
const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
|
|
1702
|
+
`);
|
|
1664
1703
|
if (failedSuites.length) {
|
|
1665
|
-
|
|
1666
|
-
|
|
1704
|
+
this.error(c.red(divider(c.bold(c.inverse(` Failed Suites ${failedSuites.length} `)))));
|
|
1705
|
+
this.error();
|
|
1667
1706
|
for (const suite of failedSuites) {
|
|
1668
|
-
|
|
1707
|
+
this.error(c.red(`
|
|
1669
1708
|
- ${getFullName(suite)}`));
|
|
1670
1709
|
await printError((_a = suite.result) == null ? void 0 : _a.error);
|
|
1671
|
-
|
|
1710
|
+
errorDivider();
|
|
1672
1711
|
}
|
|
1673
1712
|
}
|
|
1674
1713
|
if (failedTests.length) {
|
|
1675
|
-
|
|
1676
|
-
|
|
1714
|
+
this.error(c.red(divider(c.bold(c.inverse(` Failed Tests ${failedTests.length} `)))));
|
|
1715
|
+
this.error();
|
|
1677
1716
|
for (const test of failedTests) {
|
|
1678
|
-
|
|
1679
|
-
${c.inverse(" FAIL ")}`)} ${getFullName(test)}`);
|
|
1717
|
+
this.error(`${c.red(c.bold(c.inverse(" FAIL ")))} ${getFullName(test)}`);
|
|
1680
1718
|
await printError((_b = test.result) == null ? void 0 : _b.error);
|
|
1681
|
-
|
|
1719
|
+
errorDivider();
|
|
1682
1720
|
}
|
|
1683
1721
|
}
|
|
1684
1722
|
const executionTime = this.end - this.start;
|
|
@@ -1694,17 +1732,17 @@ ${c.inverse(" FAIL ")}`)} ${getFullName(test)}`);
|
|
|
1694
1732
|
};
|
|
1695
1733
|
const snapshotOutput = renderSnapshotSummary(this.ctx.config.root, this.ctx.snapshot.summary);
|
|
1696
1734
|
if (snapshotOutput.length) {
|
|
1697
|
-
|
|
1735
|
+
this.log(snapshotOutput.map((t, i) => i === 0 ? `${padTitle("Snapshots")} ${t}` : `${padTitle("")} ${t}`).join("\n"));
|
|
1698
1736
|
if (snapshotOutput.length > 1)
|
|
1699
|
-
|
|
1737
|
+
this.log();
|
|
1700
1738
|
}
|
|
1701
|
-
|
|
1702
|
-
|
|
1739
|
+
this.log(padTitle("Test Files"), getStateString(files));
|
|
1740
|
+
this.log(padTitle("Tests"), getStateString(tests));
|
|
1703
1741
|
if (this.watchFilters)
|
|
1704
|
-
|
|
1742
|
+
this.log(padTitle("Time"), time(threadTime));
|
|
1705
1743
|
else
|
|
1706
|
-
|
|
1707
|
-
|
|
1744
|
+
this.log(padTitle("Time"), time(executionTime) + c.gray(` (in thread ${time(threadTime)}, ${(executionTime / threadTime * 100).toFixed(2)}%)`));
|
|
1745
|
+
this.log();
|
|
1708
1746
|
}
|
|
1709
1747
|
async onWatcherStart() {
|
|
1710
1748
|
await this.stopListRender();
|
|
@@ -1713,24 +1751,36 @@ ${c.inverse(" FAIL ")}`)} ${getFullName(test)}`);
|
|
|
1713
1751
|
return ((_a = i.result) == null ? void 0 : _a.state) === "fail";
|
|
1714
1752
|
});
|
|
1715
1753
|
if (failed.length)
|
|
1716
|
-
|
|
1754
|
+
this.log(`
|
|
1717
1755
|
${c.bold(c.inverse(c.red(" FAIL ")))}${c.red(` ${failed.length} tests failed. Watching for file changes...`)}`);
|
|
1718
1756
|
else
|
|
1719
|
-
|
|
1757
|
+
this.log(`
|
|
1720
1758
|
${c.bold(c.inverse(c.green(" PASS ")))}${c.green(" Waiting for file changes...")}`);
|
|
1759
|
+
if (this.isFirstWatchRun) {
|
|
1760
|
+
this.isFirstWatchRun = false;
|
|
1761
|
+
this.log(c.gray("press any key to exit..."));
|
|
1762
|
+
}
|
|
1721
1763
|
}
|
|
1722
1764
|
async onWatcherRerun(files, trigger) {
|
|
1723
1765
|
await this.stopListRender();
|
|
1724
1766
|
this.watchFilters = files;
|
|
1725
|
-
console.clear();
|
|
1726
|
-
|
|
1767
|
+
this.console.clear();
|
|
1768
|
+
this.log(c.blue("Re-running tests...") + c.dim(` [ ${this.relative(trigger)} ]
|
|
1727
1769
|
`));
|
|
1728
1770
|
}
|
|
1729
1771
|
async stopListRender() {
|
|
1730
1772
|
var _a;
|
|
1731
1773
|
(_a = this.renderer) == null ? void 0 : _a.stop();
|
|
1732
1774
|
this.renderer = void 0;
|
|
1733
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
1775
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1776
|
+
}
|
|
1777
|
+
onUserConsoleLog(log) {
|
|
1778
|
+
var _a;
|
|
1779
|
+
(_a = this.renderer) == null ? void 0 : _a.clear();
|
|
1780
|
+
const task = log.taskId ? this.ctx.state.idMap[log.taskId] : void 0;
|
|
1781
|
+
this.log(c.gray(log.type + c.dim(` | ${task ? getFullName(task) : "unknown test"}`)));
|
|
1782
|
+
process[log.type].write(`${log.content}
|
|
1783
|
+
`);
|
|
1734
1784
|
}
|
|
1735
1785
|
}
|
|
1736
1786
|
|
|
@@ -2126,6 +2176,7 @@ async function initViteServer(options = {}) {
|
|
|
2126
2176
|
resolved.maxThreads = parseInt(process.env.VITEST_MAX_THREADS);
|
|
2127
2177
|
if (process.env.VITEST_MIN_THREADS)
|
|
2128
2178
|
resolved.minThreads = parseInt(process.env.VITEST_MIN_THREADS);
|
|
2179
|
+
resolved.setupFiles = Array.from(resolved.setupFiles || []).map((i) => resolve(root, i));
|
|
2129
2180
|
return {
|
|
2130
2181
|
server,
|
|
2131
2182
|
config: resolved
|
|
@@ -2172,7 +2223,8 @@ function createFakePool(ctx) {
|
|
|
2172
2223
|
}
|
|
2173
2224
|
function createWorkerPool(ctx) {
|
|
2174
2225
|
const options = {
|
|
2175
|
-
filename: workerPath
|
|
2226
|
+
filename: workerPath,
|
|
2227
|
+
useAtomics: false
|
|
2176
2228
|
};
|
|
2177
2229
|
if (ctx.config.maxThreads != null)
|
|
2178
2230
|
options.maxThreads = ctx.config.maxThreads;
|
|
@@ -2203,7 +2255,7 @@ function createChannel(ctx) {
|
|
|
2203
2255
|
const port = channel.port2;
|
|
2204
2256
|
const workerPort = channel.port1;
|
|
2205
2257
|
port.on("message", async ({ id, method, args = [] }) => {
|
|
2206
|
-
var _a, _b, _c, _d;
|
|
2258
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2207
2259
|
async function send(fn) {
|
|
2208
2260
|
try {
|
|
2209
2261
|
port.postMessage({ id, result: await fn() });
|
|
@@ -2224,6 +2276,9 @@ function createChannel(ctx) {
|
|
|
2224
2276
|
ctx.state.updateTasks([args[0]]);
|
|
2225
2277
|
(_d = (_c = ctx.reporter).onTaskUpdate) == null ? void 0 : _d.call(_c, args[0]);
|
|
2226
2278
|
return;
|
|
2279
|
+
case "log":
|
|
2280
|
+
(_f = (_e = ctx.reporter).onUserConsoleLog) == null ? void 0 : _f.call(_e, args[0]);
|
|
2281
|
+
return;
|
|
2227
2282
|
}
|
|
2228
2283
|
console.error("Unhandled message", method, args);
|
|
2229
2284
|
});
|
|
@@ -2255,6 +2310,7 @@ async function startWatcher(ctx, pool) {
|
|
|
2255
2310
|
let timer;
|
|
2256
2311
|
const changedTests = new Set();
|
|
2257
2312
|
const seen = new Set();
|
|
2313
|
+
let isFirstRun = true;
|
|
2258
2314
|
let promise;
|
|
2259
2315
|
server.watcher.on("change", (id) => {
|
|
2260
2316
|
id = slash(id);
|
|
@@ -2286,6 +2342,7 @@ async function startWatcher(ctx, pool) {
|
|
|
2286
2342
|
seen.clear();
|
|
2287
2343
|
return;
|
|
2288
2344
|
}
|
|
2345
|
+
isFirstRun = false;
|
|
2289
2346
|
ctx.state.getFiles().forEach((file) => {
|
|
2290
2347
|
var _a2;
|
|
2291
2348
|
if (((_a2 = file.result) == null ? void 0 : _a2.state) === "fail")
|
|
@@ -2295,7 +2352,9 @@ async function startWatcher(ctx, pool) {
|
|
|
2295
2352
|
const tests = Array.from(changedTests);
|
|
2296
2353
|
changedTests.clear();
|
|
2297
2354
|
seen.clear();
|
|
2298
|
-
promise = start(tests, id, invalidates)
|
|
2355
|
+
promise = start(tests, id, invalidates).then(() => {
|
|
2356
|
+
promise = void 0;
|
|
2357
|
+
});
|
|
2299
2358
|
await promise;
|
|
2300
2359
|
}, WATCHER_DEBOUNCE);
|
|
2301
2360
|
}
|
|
@@ -2306,8 +2365,18 @@ async function startWatcher(ctx, pool) {
|
|
|
2306
2365
|
await ((_b = reporter.onFinished) == null ? void 0 : _b.call(reporter, ctx.state.getFiles(tests)));
|
|
2307
2366
|
await ((_c = reporter.onWatcherStart) == null ? void 0 : _c.call(reporter));
|
|
2308
2367
|
}
|
|
2309
|
-
if (process.stdin.isTTY)
|
|
2310
|
-
|
|
2368
|
+
if (process.stdin.isTTY) {
|
|
2369
|
+
readline.emitKeypressEvents(process.stdin);
|
|
2370
|
+
process.stdin.setRawMode(true);
|
|
2371
|
+
process.stdin.on("keypress", (str) => {
|
|
2372
|
+
if (str === "" || str === "")
|
|
2373
|
+
process.exit();
|
|
2374
|
+
if (promise)
|
|
2375
|
+
return;
|
|
2376
|
+
if (isFirstRun)
|
|
2377
|
+
process.exit();
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2311
2380
|
await new Promise(() => {
|
|
2312
2381
|
});
|
|
2313
2382
|
}
|
|
@@ -2328,16 +2397,6 @@ function getAffectedTests(ctx, id, set = new Set(), seen = new Set()) {
|
|
|
2328
2397
|
}
|
|
2329
2398
|
return set;
|
|
2330
2399
|
}
|
|
2331
|
-
function listenToKeybard() {
|
|
2332
|
-
readline.emitKeypressEvents(process.stdin);
|
|
2333
|
-
process.stdin.setRawMode(true);
|
|
2334
|
-
process.stdin.on("keypress", (str, key) => {
|
|
2335
|
-
if (str === "" || str === "")
|
|
2336
|
-
process.exit();
|
|
2337
|
-
if (str === "\r")
|
|
2338
|
-
process.exit();
|
|
2339
|
-
});
|
|
2340
|
-
}
|
|
2341
2400
|
|
|
2342
2401
|
async function start(ctx) {
|
|
2343
2402
|
var _a, _b;
|
|
@@ -2414,7 +2473,7 @@ var __spreadValues = (a, b) => {
|
|
|
2414
2473
|
};
|
|
2415
2474
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
2416
2475
|
const cli = cac("vitest");
|
|
2417
|
-
cli.version(version).option("-r, --root <path>", "root path").option("-c, --config <path>", "path to config file").option("-u, --update", "update snapshot").option("--global", "inject apis globally").option("--dom", "mock browser api with happy-dom").option("--environment <env>", "runner environment", {
|
|
2476
|
+
cli.version(version).option("-r, --root <path>", "root path").option("-c, --config <path>", "path to config file").option("-u, --update", "update snapshot").option("-w, --watch", "watch mode").option("--threads", "enabled threads", { default: true }).option("--silent", "silent").option("--global", "inject apis globally").option("--dom", "mock browser api with happy-dom").option("--environment <env>", "runner environment", {
|
|
2418
2477
|
default: "node"
|
|
2419
2478
|
}).help();
|
|
2420
2479
|
cli.command("run [...filters]").action(run);
|
|
@@ -2423,20 +2482,25 @@ cli.command("dev [...filters]").action(dev);
|
|
|
2423
2482
|
cli.command("[...filters]").action(dev);
|
|
2424
2483
|
cli.parse();
|
|
2425
2484
|
async function dev(cliFilters, argv) {
|
|
2426
|
-
argv.watch
|
|
2485
|
+
if (argv.watch == null)
|
|
2486
|
+
argv.watch = !process.env.CI && !process.env.NODE_V8_COVERAGE;
|
|
2427
2487
|
await run(cliFilters, argv);
|
|
2428
2488
|
}
|
|
2429
2489
|
async function run(cliFilters, argv) {
|
|
2430
2490
|
process.env.VITEST = "true";
|
|
2431
|
-
|
|
2432
|
-
|
|
2491
|
+
process.env.NODE_ENV = "test";
|
|
2492
|
+
if (!argv.silent) {
|
|
2493
|
+
console.log(c.magenta(c.bold("\nVitest is in closed beta exclusively for Sponsors")));
|
|
2494
|
+
console.log(c.yellow("Learn more at https://vitest.dev\n"));
|
|
2495
|
+
}
|
|
2433
2496
|
const { config, server } = await initViteServer(__spreadProps(__spreadValues({}, argv), { cliFilters }));
|
|
2434
2497
|
const ctx = process.__vitest__ = {
|
|
2435
2498
|
server,
|
|
2436
2499
|
config,
|
|
2437
2500
|
state: new StateManager(),
|
|
2438
2501
|
snapshot: new SnapshotManager(config),
|
|
2439
|
-
reporter: config.reporter
|
|
2502
|
+
reporter: config.reporter,
|
|
2503
|
+
console: globalThis.console
|
|
2440
2504
|
};
|
|
2441
2505
|
ctx.reporter = ctx.reporter || new DefaultReporter(ctx);
|
|
2442
2506
|
try {
|