vitest 0.0.72 → 0.0.73

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 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
- [**Join the Discord!**](https://discord.com/invite/2zYZNngd7y)
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 F_DOWN_RIGHT, g as F_DOT, h as F_CHECK, i as F_CROSS, j as cliTruncate, k as F_RIGHT, p as printError } from './error-fb6ff2e6.js';
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_DOWN_RIGHT, g as F_DOT, h as F_CHECK, i as F_CROSS, j as cliTruncate, k as F_RIGHT, p as printError } from './error-5a04e54b.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.72";
635
+ var version = "0.0.73";
636
636
 
637
637
  const ESC = '\u001B[';
638
638
  const OSC = '\u001B]';
@@ -1441,7 +1441,7 @@ function createLogUpdate(stream, {showCursor = false} = {}) {
1441
1441
  return render;
1442
1442
  }
1443
1443
 
1444
- createLogUpdate(process$2.stdout);
1444
+ const logUpdate = createLogUpdate(process$2.stdout);
1445
1445
 
1446
1446
  createLogUpdate(process$2.stderr);
1447
1447
 
@@ -1573,9 +1573,8 @@ function renderTree(tasks, level = 0) {
1573
1573
  const createRenderer = (_tasks) => {
1574
1574
  let tasks = _tasks;
1575
1575
  let timer;
1576
- const log = createLogUpdate(process.stdout);
1577
1576
  function update() {
1578
- log(renderTree(tasks));
1577
+ logUpdate(renderTree(tasks));
1579
1578
  }
1580
1579
  return {
1581
1580
  start() {
@@ -1594,9 +1593,12 @@ const createRenderer = (_tasks) => {
1594
1593
  clearInterval(timer);
1595
1594
  timer = void 0;
1596
1595
  }
1597
- log.clear();
1596
+ logUpdate.clear();
1598
1597
  console.log(renderTree(tasks));
1599
1598
  return this;
1599
+ },
1600
+ clear() {
1601
+ logUpdate.clear();
1600
1602
  }
1601
1603
  };
1602
1604
  };
@@ -1732,6 +1734,14 @@ ${c.bold(c.inverse(c.green(" PASS ")))}${c.green(" Waiting for file changes...")
1732
1734
  this.renderer = void 0;
1733
1735
  await new Promise((resolve) => setTimeout(resolve, 100));
1734
1736
  }
1737
+ onUserConsoleLog(log) {
1738
+ var _a;
1739
+ (_a = this.renderer) == null ? void 0 : _a.clear();
1740
+ const task = log.taskId ? this.ctx.state.idMap[log.taskId] : void 0;
1741
+ console.log(c.gray(`${log.type} | ${task ? c.dim(getFullName(task)) : "unknown test"}`));
1742
+ process[log.type].write(`${log.content}
1743
+ `);
1744
+ }
1735
1745
  }
1736
1746
 
1737
1747
  class SnapshotManager {
@@ -2172,7 +2182,8 @@ function createFakePool(ctx) {
2172
2182
  }
2173
2183
  function createWorkerPool(ctx) {
2174
2184
  const options = {
2175
- filename: workerPath
2185
+ filename: workerPath,
2186
+ useAtomics: false
2176
2187
  };
2177
2188
  if (ctx.config.maxThreads != null)
2178
2189
  options.maxThreads = ctx.config.maxThreads;
@@ -2203,7 +2214,7 @@ function createChannel(ctx) {
2203
2214
  const port = channel.port2;
2204
2215
  const workerPort = channel.port1;
2205
2216
  port.on("message", async ({ id, method, args = [] }) => {
2206
- var _a, _b, _c, _d;
2217
+ var _a, _b, _c, _d, _e, _f;
2207
2218
  async function send(fn) {
2208
2219
  try {
2209
2220
  port.postMessage({ id, result: await fn() });
@@ -2224,6 +2235,9 @@ function createChannel(ctx) {
2224
2235
  ctx.state.updateTasks([args[0]]);
2225
2236
  (_d = (_c = ctx.reporter).onTaskUpdate) == null ? void 0 : _d.call(_c, args[0]);
2226
2237
  return;
2238
+ case "log":
2239
+ (_f = (_e = ctx.reporter).onUserConsoleLog) == null ? void 0 : _f.call(_e, args[0]);
2240
+ return;
2227
2241
  }
2228
2242
  console.error("Unhandled message", method, args);
2229
2243
  });
package/dist/entry.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { Console } from 'console';
2
+ import { Writable } from 'stream';
1
3
  import { importModule } from 'local-pkg';
2
4
  import chai, { expect, util } from 'chai';
3
5
  import SinonChai from 'sinon-chai';
@@ -5,7 +7,7 @@ import Subset from 'chai-subset';
5
7
  import path, { basename } from 'path';
6
8
  import { g as getNames, i as interpretOnlyMode, p as partitionSuiteChildren, c as hasTests, h as hasFailed } from './utils-9dcc4050.js';
7
9
  import fs from 'fs';
8
- import { d as c$1, l as generateDiff } from './error-fb6ff2e6.js';
10
+ import { d as c$1, l as generateDiff } from './error-5a04e54b.js';
9
11
  import { performance } from 'perf_hooks';
10
12
  import { j as setHooks, c as createSuiteHooks, h as clearContext, d as defaultSuite, k as context, l as getHooks, m as getFn } from './suite-819c135e.js';
11
13
  import { n as nanoid } from './index-6427e0f2.js';
@@ -3473,6 +3475,9 @@ function JestChaiExpect() {
3473
3475
  def("toHaveLength", function(length) {
3474
3476
  return this.have.length(length);
3475
3477
  });
3478
+ def("toHaveProperty", function(...args) {
3479
+ return this.have.deep.nested.property(...args);
3480
+ });
3476
3481
  def("toBeCloseTo", function(number, numDigits = 2) {
3477
3482
  utils.expectTypes(this, ["number"]);
3478
3483
  return this.closeTo(number, numDigits);
@@ -3581,11 +3586,47 @@ async function setupChai() {
3581
3586
  installed = true;
3582
3587
  }
3583
3588
 
3589
+ let globalSetup = false;
3584
3590
  async function setupGlobalEnv(config) {
3591
+ if (globalSetup)
3592
+ return;
3593
+ globalSetup = true;
3594
+ setupConsoleLogSpy();
3585
3595
  await setupChai();
3586
3596
  if (config.global)
3587
3597
  (await import('./global-e40b54d6.js')).registerApiGlobally();
3588
3598
  }
3599
+ function setupConsoleLogSpy() {
3600
+ const stdout = new Writable({
3601
+ write(data, encoding, callback) {
3602
+ var _a;
3603
+ send("log", {
3604
+ type: "stdout",
3605
+ content: String(data),
3606
+ taskId: (_a = process.__vitest_worker__.current) == null ? void 0 : _a.id
3607
+ });
3608
+ callback();
3609
+ }
3610
+ });
3611
+ const stderr = new Writable({
3612
+ write(data, encoding, callback) {
3613
+ var _a;
3614
+ send("log", {
3615
+ type: "stderr",
3616
+ content: String(data),
3617
+ taskId: (_a = process.__vitest_worker__.current) == null ? void 0 : _a.id
3618
+ });
3619
+ callback();
3620
+ }
3621
+ });
3622
+ const newConsole = new Console({
3623
+ stdout,
3624
+ stderr,
3625
+ colorMode: true,
3626
+ groupIndentation: 2
3627
+ });
3628
+ globalThis.console = newConsole;
3629
+ }
3589
3630
  async function withEnv(name, fn) {
3590
3631
  const env = await environments[name].setup(globalThis);
3591
3632
  try {
@@ -3668,6 +3709,7 @@ async function runTest(test) {
3668
3709
  };
3669
3710
  updateTask(test);
3670
3711
  getSnapshotClient().setTest(test);
3712
+ process.__vitest_worker__.current = test;
3671
3713
  try {
3672
3714
  await callHook(test.suite, "beforeEach", [test, test.suite]);
3673
3715
  await getFn(test)();
@@ -3684,6 +3726,7 @@ async function runTest(test) {
3684
3726
  }
3685
3727
  getSnapshotClient().clearTest();
3686
3728
  test.result.end = performance.now();
3729
+ process.__vitest_worker__.current = void 0;
3687
3730
  updateTask(test);
3688
3731
  }
3689
3732
  async function runSuite(suite) {
@@ -1264,7 +1264,7 @@ async function printError(error) {
1264
1264
  }
1265
1265
  let codeFramePrinted = false;
1266
1266
  const stacks = parseStack(e.stack || e.stackStr || "");
1267
- const nearest = stacks.find((stack) => server.moduleGraph.getModuleById(stack.file));
1267
+ const nearest = stacks.find((stack) => !stack.file.includes("vitest/dist") && server.moduleGraph.getModuleById(stack.file));
1268
1268
  if (nearest) {
1269
1269
  const mod = server.moduleGraph.getModuleById(nearest.file);
1270
1270
  const transformResult = mod == null ? void 0 : mod.ssrTransformResult;
package/dist/index.d.ts CHANGED
@@ -150,6 +150,11 @@ interface VitestContext {
150
150
  snapshot: SnapshotManager;
151
151
  reporter: Reporter;
152
152
  }
153
+ interface UserConsoleLog {
154
+ content: string;
155
+ type: 'stdout' | 'stderr';
156
+ taskId?: string;
157
+ }
153
158
 
154
159
  declare type RunMode = 'run' | 'skip' | 'only' | 'todo';
155
160
  declare type TaskState = RunMode | 'pass' | 'fail';
@@ -239,6 +244,7 @@ interface Reporter {
239
244
  onTaskUpdate?: (pack: TaskResultPack) => Awaitable<void>;
240
245
  onWatcherStart?: () => Awaitable<void>;
241
246
  onWatcherRerun?: (files: string[], trigger: string) => Awaitable<void>;
247
+ onUserConsoleLog?: (log: UserConsoleLog) => Awaitable<void>;
242
248
  }
243
249
 
244
250
  declare type SnapshotData = Record<string, string>;
@@ -407,8 +413,8 @@ interface WorkerContext {
407
413
  invalidates?: string[];
408
414
  }
409
415
  interface RpcMap {
410
- workerReady: [[], void];
411
416
  fetch: [[id: string], TransformResult | null | undefined];
417
+ log: [[UserConsoleLog], void];
412
418
  onCollected: [[files: File[]], void];
413
419
  onFinished: [[], void];
414
420
  onTaskUpdate: [[pack: TaskResultPack], void];
@@ -527,6 +533,7 @@ declare global {
527
533
  config: ResolvedConfig;
528
534
  rpc: RpcCall;
529
535
  send: RpcSend;
536
+ current?: Test;
530
537
  };
531
538
  }
532
539
  }
@@ -572,6 +579,7 @@ declare global {
572
579
  toBeInstanceOf(c: any): void;
573
580
  toBeCalledTimes(n: number): void;
574
581
  toHaveLength(l: number): void;
582
+ toHaveProperty(p: string, value?: any): void;
575
583
  toBeCloseTo(number: number, numDigits?: number): void;
576
584
  toHaveBeenCalledTimes(n: number): void;
577
585
  toHaveBeenCalledOnce(): void;
@@ -599,4 +607,4 @@ declare global {
599
607
  }
600
608
  }
601
609
 
602
- export { Arrayable, Awaitable, CliOptions, ComputeMode, Environment, EnvironmentReturn, File, GlobalContext, HookListener, ModuleCache, Nullable, Reporter, ResolvedConfig, RpcCall, RpcMap, RpcPayload, RpcSend, RunMode, SnapshotData, SnapshotMatchOptions, SnapshotResult, SnapshotStateOptions, SnapshotSummary, SnapshotUpdateState, Suite, SuiteCollector, SuiteHooks, Task, TaskBase, TaskResult, TaskResultPack, TaskState, Test, TestCollector, TestFactory, TestFunction, UncheckedSnapshot, UserOptions, VitestContext, WorkerContext, afterAll, afterEach, beforeAll, beforeEach, clearContext, createSuiteHooks, defaultSuite, describe, it, mock, spy, stub, suite, test };
610
+ export { Arrayable, Awaitable, CliOptions, ComputeMode, Environment, EnvironmentReturn, File, GlobalContext, HookListener, ModuleCache, Nullable, Reporter, ResolvedConfig, RpcCall, RpcMap, RpcPayload, RpcSend, RunMode, SnapshotData, SnapshotMatchOptions, SnapshotResult, SnapshotStateOptions, SnapshotSummary, SnapshotUpdateState, Suite, SuiteCollector, SuiteHooks, Task, TaskBase, TaskResult, TaskResultPack, TaskState, Test, TestCollector, TestFactory, TestFunction, UncheckedSnapshot, UserConsoleLog, UserOptions, VitestContext, WorkerContext, afterAll, afterEach, beforeAll, beforeEach, clearContext, createSuiteHooks, defaultSuite, describe, it, mock, spy, stub, suite, test };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest",
3
- "version": "0.0.72",
3
+ "version": "0.0.73",
4
4
  "description": "A blazing fast unit test framework powered by Vite",
5
5
  "keywords": [
6
6
  "vite",
@@ -51,7 +51,8 @@
51
51
  "test": "node bin/vitest.mjs -r test/core",
52
52
  "test:all": "cross-env CI=true pnpm -r --stream --filter !vitest run test --",
53
53
  "test:ci": "cross-env CI=true pnpm -r --stream --filter !vitest --filter !@vitest/test-fails run test --",
54
- "typecheck": "tsc --noEmit && nr lint"
54
+ "typecheck": "tsc --noEmit && nr lint",
55
+ "ci": "ni && nr typecheck && nr lint && nr build && nr test:all"
55
56
  },
56
57
  "dependencies": {
57
58
  "@types/chai": "^4.3.0",