vitest 0.0.25 → 0.0.29
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 +18 -1
- package/dist/index.d.ts +5 -3
- package/dist/integrations/chai/jest-expect.js +15 -3
- package/dist/integrations/chai/setup.js +2 -0
- package/dist/node/cli.js +35 -10
- package/dist/node/entry.js +2 -1
- package/dist/node/node.d.ts +1 -1
- package/dist/node/node.js +31 -4
- package/dist/reporters/default.d.ts +4 -1
- package/dist/reporters/default.js +16 -3
- package/dist/run/index.js +2 -3
- package/dist/types.d.ts +9 -1
- package/package.json +13 -4
package/README.gh.md
CHANGED
|
@@ -9,6 +9,8 @@ A blazing fast unit test framework powered by Vite.
|
|
|
9
9
|
|
|
10
10
|
> ⚠️ **DISCLAIMER**: Vitest is still in development and not stable yet. It's not recommended to use it in production.
|
|
11
11
|
|
|
12
|
+
> Vitest requires Vite v2.7.0 or above
|
|
13
|
+
|
|
12
14
|
## Features
|
|
13
15
|
|
|
14
16
|
- [Vite](https://vitejs.dev/)'s config, transformers, resolvers, and plugins.
|
|
@@ -114,10 +116,25 @@ export default defineConfig({
|
|
|
114
116
|
$ vitest -w
|
|
115
117
|
```
|
|
116
118
|
|
|
117
|
-
Vitest
|
|
119
|
+
Vitest smartly searches the module graph and only rerun the related tests (just like how HMR works in Vite!).
|
|
118
120
|
|
|
119
121
|
## Filtering
|
|
120
122
|
|
|
123
|
+
### CLI
|
|
124
|
+
|
|
125
|
+
You can use CLI to filter test files my name:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
$ vitest basic
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Will only execute test files that contain `basic`, e.g.
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
basic.test.ts
|
|
135
|
+
basic-foo.test.ts
|
|
136
|
+
```
|
|
137
|
+
|
|
121
138
|
### Skipping suites and tasks
|
|
122
139
|
|
|
123
140
|
Use `.skip` to avoid running certain suites or tests
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ declare global {
|
|
|
19
19
|
toEqual(expected: any): void;
|
|
20
20
|
toStrictEqual(expected: any): void;
|
|
21
21
|
toBe(expected: any): void;
|
|
22
|
+
toMatch(expected: string | RegExp): void;
|
|
23
|
+
toMatchObject(expected: any): void;
|
|
22
24
|
toContain(item: any): void;
|
|
23
25
|
toBeTruthy(): void;
|
|
24
26
|
toBeFalsy(): void;
|
|
@@ -27,10 +29,10 @@ declare global {
|
|
|
27
29
|
toBeNull(): void;
|
|
28
30
|
toBeDefined(): void;
|
|
29
31
|
toBeInstanceOf(c: any): void;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
toBeCalled(): void;
|
|
32
|
+
toHaveBeenCalledTimes(n: number): void;
|
|
33
|
+
toHaveBeenCalledOnce(): void;
|
|
33
34
|
toHaveBeenCalled(): void;
|
|
35
|
+
toHaveBeenCalledWith(...args: any[]): void;
|
|
34
36
|
}
|
|
35
37
|
interface ExpectStatic {
|
|
36
38
|
addSnapshotSerializer: import('pretty-format').Plugin;
|
|
@@ -12,6 +12,15 @@ export function JestChaiExpect() {
|
|
|
12
12
|
utils.addMethod(proto, 'toBe', function (expected) {
|
|
13
13
|
return this.equal(expected);
|
|
14
14
|
});
|
|
15
|
+
utils.addMethod(proto, 'toMatchObject', function (expected) {
|
|
16
|
+
return this.containSubset(expected);
|
|
17
|
+
});
|
|
18
|
+
utils.addMethod(proto, 'toMatch', function (expected) {
|
|
19
|
+
if (typeof expected === 'string')
|
|
20
|
+
return this.include(expected);
|
|
21
|
+
else
|
|
22
|
+
return this.match(expected);
|
|
23
|
+
});
|
|
15
24
|
utils.addMethod(proto, 'toContain', function (item) {
|
|
16
25
|
return this.contain(item);
|
|
17
26
|
});
|
|
@@ -39,17 +48,20 @@ export function JestChaiExpect() {
|
|
|
39
48
|
return this.instanceOf(obj);
|
|
40
49
|
});
|
|
41
50
|
// mock
|
|
42
|
-
utils.addMethod(proto, '
|
|
51
|
+
utils.addMethod(proto, 'toHaveBeenCalledTimes', function (number) {
|
|
43
52
|
return this.callCount(number);
|
|
44
53
|
});
|
|
45
|
-
utils.addMethod(proto, '
|
|
54
|
+
utils.addMethod(proto, 'toHaveBeenCalledOnce', function () {
|
|
46
55
|
return this.callCount(1);
|
|
47
56
|
});
|
|
48
|
-
utils.addMethod(proto, '
|
|
57
|
+
utils.addMethod(proto, 'toHaveBeenCalled', function () {
|
|
49
58
|
return this.called;
|
|
50
59
|
});
|
|
51
60
|
utils.addMethod(proto, 'toHaveBeenCalled', function () {
|
|
52
61
|
return this.called;
|
|
53
62
|
});
|
|
63
|
+
utils.addMethod(proto, 'toHaveBeenCalledWith', function (...args) {
|
|
64
|
+
return this.calledWith(...args);
|
|
65
|
+
});
|
|
54
66
|
};
|
|
55
67
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import chai from 'chai';
|
|
2
2
|
import SinonChai from 'sinon-chai';
|
|
3
|
+
import Subset from 'chai-subset';
|
|
3
4
|
import { JestChaiExpect } from './jest-expect';
|
|
4
5
|
import { SnapshotPlugin } from './snapshot';
|
|
5
6
|
export async function setupChai(config) {
|
|
6
7
|
chai.use(SinonChai);
|
|
7
8
|
chai.use(JestChaiExpect());
|
|
9
|
+
chai.use(Subset);
|
|
8
10
|
chai.use(await SnapshotPlugin(config));
|
|
9
11
|
}
|
package/dist/node/cli.js
CHANGED
|
@@ -19,13 +19,18 @@ sade('vitest [filter]', true)
|
|
|
19
19
|
.option('--global', 'inject apis globally', false)
|
|
20
20
|
.option('--dev', 'dev mode', false)
|
|
21
21
|
.option('--jsdom', 'mock browser api using JSDOM', false)
|
|
22
|
-
.action(async (filters,
|
|
22
|
+
.action(async (filters, argv) => {
|
|
23
23
|
process.env.VITEST = 'true';
|
|
24
|
+
const defaultInline = [
|
|
25
|
+
'vue',
|
|
26
|
+
'@vue',
|
|
27
|
+
];
|
|
24
28
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
|
-
const root = resolve(
|
|
26
|
-
const configPath =
|
|
27
|
-
? resolve(root,
|
|
29
|
+
const root = resolve(argv.root || process.cwd());
|
|
30
|
+
const configPath = argv.config
|
|
31
|
+
? resolve(root, argv.config)
|
|
28
32
|
: await findUp(['vitest.config.ts', 'vitest.config.js', 'vitest.config.mjs', 'vite.config.ts', 'vite.config.js', 'vite.config.mjs'], { cwd: root });
|
|
33
|
+
const options = argv;
|
|
29
34
|
options.config = configPath;
|
|
30
35
|
options.root = root;
|
|
31
36
|
options.filters = filters
|
|
@@ -39,7 +44,7 @@ sade('vitest [filter]', true)
|
|
|
39
44
|
await startViteNode({
|
|
40
45
|
root,
|
|
41
46
|
files: [
|
|
42
|
-
resolve(__dirname,
|
|
47
|
+
resolve(__dirname, argv.dev ? '../../src/node/entry.ts' : './entry.js'),
|
|
43
48
|
],
|
|
44
49
|
config: configPath,
|
|
45
50
|
defaultConfig: {
|
|
@@ -49,11 +54,31 @@ sade('vitest [filter]', true)
|
|
|
49
54
|
],
|
|
50
55
|
},
|
|
51
56
|
},
|
|
52
|
-
shouldExternalize(id) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
shouldExternalize(id, server) {
|
|
58
|
+
var _a, _b, _c, _d;
|
|
59
|
+
const inline = ['vitest', ...defaultInline, ...((_b = (_a = server.config.test) === null || _a === void 0 ? void 0 : _a.deps) === null || _b === void 0 ? void 0 : _b.inline) || []];
|
|
60
|
+
const external = ((_d = (_c = server.config.test) === null || _c === void 0 ? void 0 : _c.deps) === null || _d === void 0 ? void 0 : _d.external) || [];
|
|
61
|
+
for (const ex of inline) {
|
|
62
|
+
if (typeof ex === 'string') {
|
|
63
|
+
if (id.includes(`/node_modules/${ex}/`))
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
if (ex.test(id))
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const ex of external) {
|
|
72
|
+
if (typeof ex === 'string') {
|
|
73
|
+
if (id.includes(`/node_modules/${ex}/`))
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (ex.test(id))
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return id.includes('/node_modules/');
|
|
57
82
|
},
|
|
58
83
|
});
|
|
59
84
|
})
|
package/dist/node/entry.js
CHANGED
|
@@ -3,4 +3,5 @@ if (!process.__vite_node__ || !process.__vitest__)
|
|
|
3
3
|
throw new Error('Vitest can only run in vite-node environment, please use the CLI to start the process');
|
|
4
4
|
const inlineOptions = process.__vite_node__.server.config.test || {};
|
|
5
5
|
const cliOptions = process.__vitest__.options || {};
|
|
6
|
-
|
|
6
|
+
const options = Object.assign(Object.assign({}, cliOptions), inlineOptions);
|
|
7
|
+
await run(options);
|
package/dist/node/node.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface ViteNodeOptions {
|
|
|
15
15
|
root: string;
|
|
16
16
|
files: string[];
|
|
17
17
|
_?: string[];
|
|
18
|
-
shouldExternalize?: (file: string) => boolean;
|
|
18
|
+
shouldExternalize?: (file: string, server: ViteDevServer) => boolean;
|
|
19
19
|
config?: string;
|
|
20
20
|
defaultConfig?: InlineConfig;
|
|
21
21
|
}
|
package/dist/node/node.js
CHANGED
|
@@ -42,6 +42,8 @@ function normalizeId(id) {
|
|
|
42
42
|
id = `\0${id.slice('/@id/__x00__'.length)}`;
|
|
43
43
|
if (id && id.startsWith('/@id/'))
|
|
44
44
|
id = id.slice('/@id/'.length);
|
|
45
|
+
if (id.startsWith('__vite-browser-external:'))
|
|
46
|
+
id = id.slice('__vite-browser-external:'.length);
|
|
45
47
|
return id;
|
|
46
48
|
}
|
|
47
49
|
function toFilePath(id, server) {
|
|
@@ -58,6 +60,29 @@ function toFilePath(id, server) {
|
|
|
58
60
|
absolute = `/${absolute}`;
|
|
59
61
|
return absolute;
|
|
60
62
|
}
|
|
63
|
+
const stubRequests = {
|
|
64
|
+
'/@vite/client': {
|
|
65
|
+
injectQuery: (id) => id,
|
|
66
|
+
createHotContext() {
|
|
67
|
+
return {
|
|
68
|
+
accept: () => { },
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
async function transform(server, id) {
|
|
74
|
+
if (id.match(/\.(?:[cm]?[jt]sx?|json)$/)) {
|
|
75
|
+
return await server.transformRequest(id, { ssr: true });
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// for components like Vue, we want to use the client side
|
|
79
|
+
// plugins but then covert the code to be consumed by the server
|
|
80
|
+
const result = await server.transformRequest(id);
|
|
81
|
+
if (!result)
|
|
82
|
+
return undefined;
|
|
83
|
+
return await server.ssrTransform(result.code, result.map, id);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
61
86
|
async function execute(files, server, options) {
|
|
62
87
|
const result = [];
|
|
63
88
|
for (const file of files)
|
|
@@ -74,7 +99,9 @@ async function execute(files, server, options) {
|
|
|
74
99
|
}
|
|
75
100
|
return cachedRequest(dep, callstack);
|
|
76
101
|
};
|
|
77
|
-
|
|
102
|
+
if (id in stubRequests)
|
|
103
|
+
return stubRequests[id];
|
|
104
|
+
const result = await transform(server, id);
|
|
78
105
|
if (!result)
|
|
79
106
|
throw new Error(`failed to load ${id}`);
|
|
80
107
|
const url = pathToFileURL(fsPath);
|
|
@@ -97,11 +124,11 @@ async function execute(files, server, options) {
|
|
|
97
124
|
return exports;
|
|
98
125
|
}
|
|
99
126
|
async function cachedRequest(rawId, callstack) {
|
|
100
|
-
if (builtinModules.includes(rawId))
|
|
101
|
-
return import(rawId);
|
|
102
127
|
const id = normalizeId(rawId);
|
|
128
|
+
if (builtinModules.includes(id))
|
|
129
|
+
return import(id);
|
|
103
130
|
const fsPath = toFilePath(id, server);
|
|
104
|
-
if (options.shouldExternalize(fsPath))
|
|
131
|
+
if (options.shouldExternalize(fsPath, server))
|
|
105
132
|
return import(fsPath);
|
|
106
133
|
if (__pendingModules__.has(fsPath))
|
|
107
134
|
return __pendingModules__.get(fsPath);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Listr from 'listr';
|
|
2
|
-
import { File, Reporter, RunnerContext, Task } from '../types';
|
|
2
|
+
import { File, Reporter, RunnerContext, Task, ResolvedConfig } from '../types';
|
|
3
3
|
interface TaskPromise {
|
|
4
4
|
promise: Promise<void>;
|
|
5
5
|
resolve: () => void;
|
|
@@ -11,6 +11,9 @@ export declare class DefaultReporter implements Reporter {
|
|
|
11
11
|
listr: Listr | null;
|
|
12
12
|
listrPromise: Promise<void> | null;
|
|
13
13
|
taskMap: Map<Task, TaskPromise>;
|
|
14
|
+
cwd: string;
|
|
15
|
+
relative(path: string): string;
|
|
16
|
+
onStart(config: ResolvedConfig): void;
|
|
14
17
|
onCollected(files: File[]): void;
|
|
15
18
|
onTaskEnd(task: Task): void;
|
|
16
19
|
onFinished(ctx: RunnerContext): Promise<void>;
|
|
@@ -11,6 +11,14 @@ export class DefaultReporter {
|
|
|
11
11
|
this.listr = null;
|
|
12
12
|
this.listrPromise = null;
|
|
13
13
|
this.taskMap = new Map();
|
|
14
|
+
this.cwd = process.cwd();
|
|
15
|
+
}
|
|
16
|
+
relative(path) {
|
|
17
|
+
return relative(this.cwd, path);
|
|
18
|
+
}
|
|
19
|
+
onStart(config) {
|
|
20
|
+
this.cwd = config.root;
|
|
21
|
+
console.log(c.green(`Running tests under ${c.gray(this.cwd)}\n`));
|
|
14
22
|
}
|
|
15
23
|
onCollected(files) {
|
|
16
24
|
this.start = performance.now();
|
|
@@ -41,9 +49,14 @@ export class DefaultReporter {
|
|
|
41
49
|
};
|
|
42
50
|
this.listr = new Listr(files.map((file) => {
|
|
43
51
|
return {
|
|
44
|
-
title: relative(
|
|
52
|
+
title: this.relative(file.filepath),
|
|
45
53
|
task: () => {
|
|
46
|
-
|
|
54
|
+
if (file.error)
|
|
55
|
+
throw file.error;
|
|
56
|
+
const suites = file.suites.filter(i => i.tasks.length);
|
|
57
|
+
if (!suites.length)
|
|
58
|
+
throw new Error('No tasks found');
|
|
59
|
+
return new Listr(suites.flatMap((suite) => {
|
|
47
60
|
if (!suite.name)
|
|
48
61
|
return createTasksListr(suite.tasks);
|
|
49
62
|
return [{
|
|
@@ -122,7 +135,7 @@ export class DefaultReporter {
|
|
|
122
135
|
async onWatcherRerun(files, trigger) {
|
|
123
136
|
await this.listrPromise;
|
|
124
137
|
console.clear();
|
|
125
|
-
console.log(c.blue('Re-running tests...') + c.dim(` [ ${relative(
|
|
138
|
+
console.log(c.blue('Re-running tests...') + c.dim(` [ ${this.relative(trigger)} ]\n`));
|
|
126
139
|
}
|
|
127
140
|
// TODO:
|
|
128
141
|
onSnapshotUpdate() {
|
package/dist/run/index.js
CHANGED
|
@@ -98,9 +98,8 @@ export async function runSuite(suite, ctx) {
|
|
|
98
98
|
else {
|
|
99
99
|
try {
|
|
100
100
|
await callHook(suite, 'beforeAll', [suite]);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// await runTask(t, ctx)
|
|
101
|
+
for (const t of suite.tasks)
|
|
102
|
+
await runTask(t, ctx);
|
|
104
103
|
await callHook(suite, 'afterAll', [suite]);
|
|
105
104
|
}
|
|
106
105
|
catch (e) {
|
package/dist/types.d.ts
CHANGED
|
@@ -11,6 +11,13 @@ export interface UserOptions {
|
|
|
11
11
|
* @default ['**\/node_modules\/**']
|
|
12
12
|
*/
|
|
13
13
|
excludes?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Handling for dependencies inlining or externalizing
|
|
16
|
+
*/
|
|
17
|
+
deps?: {
|
|
18
|
+
external?: (string | RegExp)[];
|
|
19
|
+
inline?: (string | RegExp)[];
|
|
20
|
+
};
|
|
14
21
|
/**
|
|
15
22
|
* Register apis globally
|
|
16
23
|
*
|
|
@@ -52,6 +59,7 @@ export interface UserOptions {
|
|
|
52
59
|
}
|
|
53
60
|
export interface ResolvedConfig extends Required<UserOptions> {
|
|
54
61
|
filters?: string[];
|
|
62
|
+
config?: string;
|
|
55
63
|
}
|
|
56
64
|
export declare type RunMode = 'run' | 'skip' | 'only' | 'todo';
|
|
57
65
|
export declare type TaskState = RunMode | 'pass' | 'fail';
|
|
@@ -114,7 +122,7 @@ export interface GlobalContext {
|
|
|
114
122
|
currentSuite: SuiteCollector | null;
|
|
115
123
|
}
|
|
116
124
|
export interface Reporter {
|
|
117
|
-
onStart?: (
|
|
125
|
+
onStart?: (config: ResolvedConfig) => Awaitable<void>;
|
|
118
126
|
onCollected?: (files: File[], ctx: RunnerContext) => Awaitable<void>;
|
|
119
127
|
onFinished?: (ctx: RunnerContext) => Awaitable<void>;
|
|
120
128
|
onSuiteBegin?: (suite: Suite, ctx: RunnerContext) => Awaitable<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.29",
|
|
4
4
|
"description": "A blazing fast unit test framework powered by Vite",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
@@ -44,8 +44,9 @@
|
|
|
44
44
|
"lint": "eslint \"{src,test}/**/*.ts\"",
|
|
45
45
|
"prepublishOnly": "nr build",
|
|
46
46
|
"release": "bumpp --commit --push --tag && esmo scripts/publish.ts",
|
|
47
|
-
"test": "
|
|
48
|
-
"test:
|
|
47
|
+
"test": "run-s test:*",
|
|
48
|
+
"test:core": "node bin/vitest.mjs --dev -r test/core",
|
|
49
|
+
"test:vue": "node bin/vitest.mjs --dev -r test/vue",
|
|
49
50
|
"watch": "tsc -p src/tsconfig.json --watch"
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
"@types/chai": "^4.2.22",
|
|
54
55
|
"@types/sinon-chai": "^3.2.6",
|
|
55
56
|
"chai": "^4.3.4",
|
|
57
|
+
"chai-subset": "^1.6.0",
|
|
56
58
|
"fast-glob": "^3.2.7",
|
|
57
59
|
"find-up": "^6.2.0",
|
|
58
60
|
"jest-snapshot": "^27.4.2",
|
|
@@ -64,19 +66,26 @@
|
|
|
64
66
|
"sinon": "^12.0.1",
|
|
65
67
|
"sinon-chai": "^3.7.0"
|
|
66
68
|
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"vite": "^2.7.0"
|
|
71
|
+
},
|
|
67
72
|
"devDependencies": {
|
|
68
73
|
"@antfu/eslint-config": "^0.12.1",
|
|
69
74
|
"@antfu/ni": "^0.11.0",
|
|
75
|
+
"@types/chai-subset": "^1.3.3",
|
|
70
76
|
"@types/jsdom": "^16.2.13",
|
|
71
77
|
"@types/listr": "^0.14.4",
|
|
72
78
|
"@types/node": "^16.11.11",
|
|
73
79
|
"@types/sade": "^1.7.3",
|
|
74
80
|
"@types/sinon": "^10.0.6",
|
|
81
|
+
"@vitejs/plugin-vue": "^1.10.1",
|
|
75
82
|
"bumpp": "^7.1.1",
|
|
76
83
|
"eslint": "^8.4.0",
|
|
77
84
|
"esno": "^0.12.1",
|
|
85
|
+
"npm-run-all": "^4.1.5",
|
|
78
86
|
"rimraf": "^3.0.2",
|
|
79
87
|
"typescript": "^4.5.2",
|
|
80
|
-
"vite": "^2.
|
|
88
|
+
"vite": "^2.7.0",
|
|
89
|
+
"vue": "^3.2.24"
|
|
81
90
|
}
|
|
82
91
|
}
|