vitest 0.0.33 → 0.0.34

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
@@ -1,10 +1,18 @@
1
- # vitest
2
-
3
- [![NPM version](https://img.shields.io/npm/v/vitest?color=a1b858&label=)](https://www.npmjs.com/package/vitest)
1
+ <p align="center">
2
+ <img src="https://user-images.githubusercontent.com/11247099/145112184-a9ff6727-661c-439d-9ada-963124a281f7.png" height="200">
3
+ </p>
4
4
 
5
+ <h1 align="center">
6
+ Vitest
7
+ </h1>
8
+ <p align="center">
5
9
  A blazing fast unit test framework powered by Vite.
10
+ <p>
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/vitest"><img src="https://img.shields.io/npm/v/vitest?color=a1b858&label="></a>
13
+ <p>
6
14
 
7
- > **This project is currently in closed beta exclusively for Sponsors.**<br>
15
+ > 💖 **This project is currently in closed beta exclusively for Sponsors.**<br>
8
16
  > Become a Sponsor of [@patak-js](https://github.com/sponsors/patak-js) or [@antfu](https://github.com/sponsors/antfu) to access the source code and issues tracker.
9
17
 
10
18
  > ⚠️ **DISCLAIMER**: Vitest is still in development and not stable yet. It's not recommended to use it in production.
@@ -15,17 +23,19 @@ A blazing fast unit test framework powered by Vite.
15
23
 
16
24
  ## Features
17
25
 
18
- - [Vite](https://vitejs.dev/)'s config, transformers, resolvers, and plugins.
26
+ - [Vite](https://vitejs.dev/)'s config, transformers, resolvers, and plugins. Use the same setup from your app!
19
27
  - [Jest Snapshot](https://jestjs.io/docs/snapshot-testing)
20
28
  - [Chai](https://www.chaijs.com/) built-in for assertions, with [jest-expect](https://jestjs.io/docs/expect) compatible APIs.
29
+ - [Smart watch mode](#watch-mode), just like HMR for tests!
30
+ - [Code coverage](#coverage)
21
31
  - [Sinon](https://sinonjs.org/) built-in for mocking
22
- - [JSDOM](https://github.com/jsdom/jsdom) built-in built-in for DOM mocking
32
+ - [JSDOM](https://github.com/jsdom/jsdom) built-in for DOM and browser API mocking
23
33
  - Components testing ([Vue example](./test/vue), [React example](./test/react))
24
34
  - Async suite / test, top level await
25
35
  - ESM friendly
26
36
  - Out-of-box TypeScript / JSX support
27
37
  - Suite and Test filtering (skip, only, todo)
28
- - [Test coverage](#coverage)
38
+ - Concurrent Tests
29
39
 
30
40
  ```ts
31
41
  import { it, describe, expect, assert } from 'vitest'
@@ -229,6 +239,39 @@ describe('suite', () => {
229
239
  })
230
240
  ```
231
241
 
242
+ ### Running tests concurrently
243
+
244
+ Use `.concurrent` in consecutive tests to run them in parallel
245
+
246
+ ```ts
247
+ // The two tasks marked with concurrent will be run in parallel
248
+ describe('suite', () => {
249
+ it('serial task', () => {
250
+ assert.equal(Math.sqrt(4), 3)
251
+ })
252
+ it.concurrent('concurrent task 1', () => {
253
+ assert.equal(Math.sqrt(4), 3)
254
+ })
255
+ it.concurrent('concurrent task 2', () => {
256
+ assert.equal(Math.sqrt(4), 3)
257
+ })
258
+ })
259
+ ```
260
+
261
+ You can also use `.skip`, `.only`, and `.todo` with concurrent tasks. All the following combinations are valid:
262
+ ```js
263
+ it.concurrent(...)
264
+
265
+ it.skip.concurrent(...)
266
+ it.concurrent.skip(...)
267
+
268
+ it.only.concurrent(...)
269
+ it.concurrent.only(...)
270
+
271
+ it.todo.concurrent(...)
272
+ it.concurrent.todo(...)
273
+ ```
274
+
232
275
  ## Sponsors
233
276
 
234
277
  <p align="center">
@@ -1,3 +1,4 @@
1
1
  export declare const defaultIncludes: string[];
2
2
  export declare const defaultExcludes: string[];
3
3
  export declare const globalApis: string[];
4
+ export declare const defaultConcurrentTimeout = 5000;
package/dist/constants.js CHANGED
@@ -21,3 +21,4 @@ export const globalApis = [
21
21
  'beforeEach',
22
22
  'afterEach',
23
23
  ];
24
+ export const defaultConcurrentTimeout = 5000;
package/dist/node/node.js CHANGED
@@ -68,8 +68,10 @@ const stubRequests = {
68
68
  createHotContext() {
69
69
  return {
70
70
  accept: () => { },
71
+ prune: () => { },
71
72
  };
72
73
  },
74
+ updateStyle() { },
73
75
  },
74
76
  };
75
77
  async function transform(server, id) {
package/dist/run/index.js CHANGED
@@ -98,8 +98,15 @@ export async function runSuite(suite, ctx) {
98
98
  else {
99
99
  try {
100
100
  await callHook(suite, 'beforeAll', [suite]);
101
- for (const t of suite.tasks)
102
- await runTask(t, ctx);
101
+ for (const taskGroup of partitionTasks(suite.tasks)) {
102
+ if (taskGroup[0].concurrent) {
103
+ await Promise.all(taskGroup.map(t => runTask(t, ctx)));
104
+ }
105
+ else {
106
+ for (const t of taskGroup)
107
+ await runTask(t, ctx);
108
+ }
109
+ }
103
110
  await callHook(suite, 'afterAll', [suite]);
104
111
  }
105
112
  catch (e) {
@@ -110,6 +117,25 @@ export async function runSuite(suite, ctx) {
110
117
  }
111
118
  await ((_b = reporter.onSuiteEnd) === null || _b === void 0 ? void 0 : _b.call(reporter, suite, ctx));
112
119
  }
120
+ /**
121
+ * Partition consecutive serial and concurrent tasks in groups
122
+ */
123
+ function partitionTasks(tasks) {
124
+ let taskGroup = [];
125
+ const groupedTasks = [];
126
+ for (const task of tasks) {
127
+ if (taskGroup.length === 0 || !!task.concurrent === !!taskGroup[0].concurrent) {
128
+ taskGroup.push(task);
129
+ }
130
+ else {
131
+ groupedTasks.push(taskGroup);
132
+ taskGroup = [task];
133
+ }
134
+ }
135
+ if (taskGroup.length > 0)
136
+ groupedTasks.push(taskGroup);
137
+ return groupedTasks;
138
+ }
113
139
  export async function runFile(file, ctx) {
114
140
  var _a, _b;
115
141
  const { reporter } = ctx;
package/dist/suite.d.ts CHANGED
@@ -2,9 +2,24 @@ import { SuiteCollector, TestFactory, TestFunction, Suite } from './types';
2
2
  export declare const defaultSuite: SuiteCollector;
3
3
  export declare const test: {
4
4
  (name: string, fn: TestFunction): void;
5
- skip(name: string, fn: TestFunction): void;
6
- only(name: string, fn: TestFunction): void;
7
- todo(name: string): void;
5
+ concurrent: {
6
+ (name: string, fn: TestFunction, timeout?: number | undefined): void;
7
+ skip(name: string, fn: TestFunction, timeout?: number | undefined): void;
8
+ only(name: string, fn: TestFunction, timeout?: number | undefined): void;
9
+ todo(name: string): void;
10
+ };
11
+ skip: {
12
+ (name: string, fn: TestFunction): void;
13
+ concurrent(name: string, fn: TestFunction, timeout?: number | undefined): void;
14
+ };
15
+ only: {
16
+ (name: string, fn: TestFunction): void;
17
+ concurrent(name: string, fn: TestFunction, timeout?: number | undefined): void;
18
+ };
19
+ todo: {
20
+ (name: string): void;
21
+ concurrent(name: string): void;
22
+ };
8
23
  };
9
24
  export declare function suite(suiteName: string, factory?: TestFactory): SuiteCollector;
10
25
  export declare namespace suite {
@@ -15,9 +30,24 @@ export declare namespace suite {
15
30
  export declare const describe: typeof suite;
16
31
  export declare const it: {
17
32
  (name: string, fn: TestFunction): void;
18
- skip(name: string, fn: TestFunction): void;
19
- only(name: string, fn: TestFunction): void;
20
- todo(name: string): void;
33
+ concurrent: {
34
+ (name: string, fn: TestFunction, timeout?: number | undefined): void;
35
+ skip(name: string, fn: TestFunction, timeout?: number | undefined): void;
36
+ only(name: string, fn: TestFunction, timeout?: number | undefined): void;
37
+ todo(name: string): void;
38
+ };
39
+ skip: {
40
+ (name: string, fn: TestFunction): void;
41
+ concurrent(name: string, fn: TestFunction, timeout?: number | undefined): void;
42
+ };
43
+ only: {
44
+ (name: string, fn: TestFunction): void;
45
+ concurrent(name: string, fn: TestFunction, timeout?: number | undefined): void;
46
+ };
47
+ todo: {
48
+ (name: string): void;
49
+ concurrent(name: string): void;
50
+ };
21
51
  };
22
52
  export declare const beforeAll: (fn: Suite['hooks']['beforeAll'][0]) => void;
23
53
  export declare const afterAll: (fn: Suite['hooks']['afterAll'][0]) => void;
package/dist/suite.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { context } from './context';
2
+ import { defaultConcurrentTimeout } from './constants';
2
3
  export const defaultSuite = suite('');
3
4
  function getCurrentSuite() {
4
5
  return context.currentSuite || defaultSuite;
@@ -16,6 +17,16 @@ function createSuiteCollector(name, factory = () => { }, mode) {
16
17
  afterEach: [],
17
18
  },
18
19
  };
20
+ const test = createTestCollector((name, fn, mode, concurrent) => {
21
+ queue.push({
22
+ name,
23
+ mode,
24
+ concurrent,
25
+ suite: {},
26
+ state: (mode !== 'run' && mode !== 'only') ? mode : undefined,
27
+ fn,
28
+ });
29
+ });
19
30
  const collector = {
20
31
  name,
21
32
  mode,
@@ -27,21 +38,6 @@ function createSuiteCollector(name, factory = () => { }, mode) {
27
38
  function addHook(name, ...fn) {
28
39
  suiteBase.hooks[name].push(...fn);
29
40
  }
30
- function collectTask(name, fn, mode) {
31
- queue.push({
32
- name,
33
- mode,
34
- suite: {},
35
- state: (mode !== 'run' && mode !== 'only') ? mode : undefined,
36
- fn,
37
- });
38
- }
39
- function test(name, fn) {
40
- collectTask(name, fn, 'run');
41
- }
42
- test.skip = (name, fn) => collectTask(name, fn, 'skip');
43
- test.only = (name, fn) => collectTask(name, fn, 'only');
44
- test.todo = (name) => collectTask(name, () => { }, 'todo');
45
41
  function clear() {
46
42
  queue.length = 0;
47
43
  factoryQueue.length = 0;
@@ -64,11 +60,66 @@ function createSuiteCollector(name, factory = () => { }, mode) {
64
60
  context.suites.push(collector);
65
61
  return collector;
66
62
  }
63
+ function createConcurrentOptions(timeout) {
64
+ return { timeout: timeout !== null && timeout !== void 0 ? timeout : defaultConcurrentTimeout };
65
+ }
66
+ function createTestCollector(collectTask) {
67
+ function test(name, fn) {
68
+ collectTask(name, fn, 'run');
69
+ }
70
+ test.concurrent = concurrent;
71
+ test.skip = skip;
72
+ test.only = only;
73
+ test.todo = todo;
74
+ function concurrent(name, fn, timeout) {
75
+ collectTask(name, fn, 'run', createConcurrentOptions(timeout));
76
+ }
77
+ concurrent.skip = (name, fn, timeout) => collectTask(name, fn, 'skip', createConcurrentOptions(timeout));
78
+ concurrent.only = (name, fn, timeout) => collectTask(name, fn, 'only', createConcurrentOptions(timeout));
79
+ concurrent.todo = todo;
80
+ function skip(name, fn) {
81
+ collectTask(name, fn, 'skip');
82
+ }
83
+ skip.concurrent = concurrent.skip;
84
+ function only(name, fn) {
85
+ collectTask(name, fn, 'only');
86
+ }
87
+ only.concurrent = concurrent.only;
88
+ function todo(name) {
89
+ collectTask(name, () => { }, 'todo');
90
+ }
91
+ todo.concurrent = todo;
92
+ return test;
93
+ }
67
94
  // apis
68
- export const test = (name, fn) => getCurrentSuite().test(name, fn);
69
- test.skip = (name, fn) => getCurrentSuite().test.skip(name, fn);
70
- test.only = (name, fn) => getCurrentSuite().test.only(name, fn);
71
- test.todo = (name) => getCurrentSuite().test.todo(name);
95
+ export const test = (function () {
96
+ function test(name, fn) {
97
+ return getCurrentSuite().test(name, fn);
98
+ }
99
+ function concurrent(name, fn, timeout) {
100
+ return getCurrentSuite().test.concurrent(name, fn, timeout);
101
+ }
102
+ concurrent.skip = (name, fn, timeout) => getCurrentSuite().test.concurrent.skip(name, fn, timeout);
103
+ concurrent.only = (name, fn, timeout) => getCurrentSuite().test.concurrent.only(name, fn, timeout);
104
+ concurrent.todo = (name) => getCurrentSuite().test.concurrent.todo(name);
105
+ function skip(name, fn) {
106
+ return getCurrentSuite().test.skip(name, fn);
107
+ }
108
+ skip.concurrent = (name, fn, timeout) => getCurrentSuite().test.skip.concurrent(name, fn, timeout);
109
+ function only(name, fn) {
110
+ return getCurrentSuite().test.only(name, fn);
111
+ }
112
+ only.concurrent = (name, fn, timeout) => getCurrentSuite().test.only.concurrent(name, fn, timeout);
113
+ function todo(name) {
114
+ return getCurrentSuite().test.todo(name);
115
+ }
116
+ todo.concurrent = (name) => getCurrentSuite().test.todo.concurrent(name);
117
+ test.concurrent = concurrent;
118
+ test.skip = skip;
119
+ test.only = only;
120
+ test.todo = todo;
121
+ return test;
122
+ })();
72
123
  export function suite(suiteName, factory) {
73
124
  return createSuiteCollector(suiteName, factory, 'run');
74
125
  }
package/dist/types.d.ts CHANGED
@@ -64,9 +64,13 @@ export interface ResolvedConfig extends Required<UserOptions> {
64
64
  }
65
65
  export declare type RunMode = 'run' | 'skip' | 'only' | 'todo';
66
66
  export declare type TaskState = RunMode | 'pass' | 'fail';
67
+ export interface ConcurrentOptions {
68
+ timeout: number;
69
+ }
67
70
  export interface Task {
68
71
  name: string;
69
72
  mode: RunMode;
73
+ concurrent?: ConcurrentOptions;
70
74
  suite: Suite;
71
75
  fn: () => Awaitable<void>;
72
76
  file?: File;
@@ -74,11 +78,30 @@ export interface Task {
74
78
  error?: unknown;
75
79
  }
76
80
  export declare type TestFunction = () => Awaitable<void>;
81
+ interface ConcurrentCollector {
82
+ (name: string, fn: TestFunction, timeout?: number): void;
83
+ only: (name: string, fn: TestFunction, timeout?: number) => void;
84
+ skip: (name: string, fn: TestFunction, timeout?: number) => void;
85
+ todo: (name: string) => void;
86
+ }
87
+ interface OnlyCollector {
88
+ (name: string, fn: TestFunction): void;
89
+ concurrent: (name: string, fn: TestFunction, timeout?: number) => void;
90
+ }
91
+ interface SkipCollector {
92
+ (name: string, fn: TestFunction): void;
93
+ concurrent: (name: string, fn: TestFunction, timeout?: number) => void;
94
+ }
95
+ interface TodoCollector {
96
+ (name: string): void;
97
+ concurrent: (name: string) => void;
98
+ }
77
99
  export interface TestCollector {
78
100
  (name: string, fn: TestFunction): void;
79
- only: (name: string, fn: TestFunction) => void;
80
- skip: (name: string, fn: TestFunction) => void;
81
- todo: (name: string) => void;
101
+ concurrent: ConcurrentCollector;
102
+ only: OnlyCollector;
103
+ skip: SkipCollector;
104
+ todo: TodoCollector;
82
105
  }
83
106
  export declare type HookListener<T extends any[]> = (...args: T) => Awaitable<void>;
84
107
  export interface Suite {
@@ -136,3 +159,4 @@ export interface Reporter {
136
159
  onWatcherStart?: (ctx: RunnerContext) => Awaitable<void>;
137
160
  onWatcherRerun?: (files: string[], trigger: string, ctx: RunnerContext) => Awaitable<void>;
138
161
  }
162
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "A blazing fast unit test framework powered by Vite",
5
5
  "keywords": [
6
6
  "vite",