+2
-0
@@ -10,2 +10,4 @@ #!/usr/bin/env node | ||
| process.env.VITEST = 'true' | ||
| const argv = minimist(process.argv.slice(2), { | ||
@@ -12,0 +14,0 @@ alias: { |
+1
-1
@@ -25,5 +25,5 @@ var _a; | ||
| const testOptions = viteConfig.test || {}; | ||
| await run(Object.assign(Object.assign({}, testOptions), { updateSnapshot: argv.update, rootDir: argv.root || process.cwd() })); | ||
| await run(Object.assign(Object.assign({}, testOptions), { server, updateSnapshot: argv.update, rootDir: argv.root || process.cwd(), nameFilters: argv._ })); | ||
| function help() { | ||
| log('Help: finish help'); | ||
| } |
+1
-1
@@ -8,2 +8,2 @@ import sinon from 'sinon'; | ||
| export { sinon }; | ||
| export declare const mock: sinon.SinonMockStatic, spy: sinon.SinonSpyStatic; | ||
| export declare const mock: sinon.SinonMockStatic, spy: sinon.SinonSpyStatic, stub: sinon.SinonStubStatic; |
+1
-1
@@ -8,2 +8,2 @@ import sinon from 'sinon'; | ||
| export { sinon }; | ||
| export const { mock, spy } = sinon; | ||
| export const { mock, spy, stub } = sinon; |
@@ -51,9 +51,9 @@ import { relative } from 'path'; | ||
| (_a = task.__ora) === null || _a === void 0 ? void 0 : _a.stop(); | ||
| if (task.status === 'pass') { | ||
| if (task.state === 'pass') { | ||
| this.log(`${c.green(CHECK + task.name)}`); | ||
| } | ||
| else if (task.status === 'skip') { | ||
| else if (task.state === 'skip') { | ||
| this.log(c.dim(c.yellow(`${DOT + task.name} (skipped)`))); | ||
| } | ||
| else if (task.status === 'todo') { | ||
| else if (task.state === 'todo') { | ||
| this.log(c.dim(`${DOT + task.name} (todo)`)); | ||
@@ -71,6 +71,7 @@ } | ||
| const tasks = files.reduce((acc, file) => acc.concat(file.suites.flatMap(i => i.tasks)), []); | ||
| const passed = tasks.filter(i => i.status === 'pass'); | ||
| const failed = tasks.filter(i => i.status === 'fail'); | ||
| const skipped = tasks.filter(i => i.status === 'skip'); | ||
| const todo = tasks.filter(i => i.status === 'todo'); | ||
| const runable = tasks.filter(i => i.state === 'pass' || i.state === 'fail'); | ||
| const passed = tasks.filter(i => i.state === 'pass'); | ||
| const failed = tasks.filter(i => i.state === 'fail'); | ||
| const skipped = tasks.filter(i => i.state === 'skip'); | ||
| const todo = tasks.filter(i => i.state === 'todo'); | ||
| this.indent = 0; | ||
@@ -94,5 +95,5 @@ if (failedFiles.length) { | ||
| } | ||
| this.log(c.green(`Passed ${passed.length} / ${tasks.length}`)); | ||
| this.log(c.green(`Passed ${passed.length} / ${runable.length}`)); | ||
| if (failed.length) | ||
| this.log(c.red(`Failed ${failed.length} / ${tasks.length}`)); | ||
| this.log(c.red(`Failed ${failed.length} / ${runable.length}`)); | ||
| if (skipped.length) | ||
@@ -99,0 +100,0 @@ this.log(c.yellow(`Skipped ${skipped.length}`)); |
+3
-3
@@ -1,5 +0,5 @@ | ||
| import { File, Options, Task, RunnerContext } from './types'; | ||
| import { File, Config, Task, RunnerContext } from './types'; | ||
| export declare function runTask(task: Task, ctx: RunnerContext): Promise<void>; | ||
| export declare function collectFiles(files: string[]): Promise<File[]>; | ||
| export declare function collectFiles(paths: string[]): Promise<File[]>; | ||
| export declare function runFile(file: File, ctx: RunnerContext): Promise<void>; | ||
| export declare function run(options?: Options): Promise<void>; | ||
| export declare function run(config: Config): Promise<void>; |
+47
-31
@@ -14,25 +14,19 @@ import chai from 'chai'; | ||
| await ((_a = reporter.onTaskBegin) === null || _a === void 0 ? void 0 : _a.call(reporter, task, ctx)); | ||
| await beforeEachHook.fire(task); | ||
| if (task.suite.mode === 'skip' || task.mode === 'skip') { | ||
| task.status = 'skip'; | ||
| } | ||
| else if (task.suite.mode === 'todo' || task.mode === 'todo') { | ||
| task.status = 'todo'; | ||
| } | ||
| else { | ||
| if (task.mode === 'run') { | ||
| await beforeEachHook.fire(task); | ||
| try { | ||
| await task.fn(); | ||
| task.status = 'pass'; | ||
| task.state = 'pass'; | ||
| } | ||
| catch (e) { | ||
| task.status = 'fail'; | ||
| task.state = 'fail'; | ||
| task.error = e; | ||
| } | ||
| await afterEachHook.fire(task); | ||
| } | ||
| await afterEachHook.fire(task); | ||
| await ((_b = reporter.onTaskEnd) === null || _b === void 0 ? void 0 : _b.call(reporter, task, ctx)); | ||
| } | ||
| export async function collectFiles(files) { | ||
| const result = []; | ||
| for (const filepath of files) { | ||
| export async function collectFiles(paths) { | ||
| const files = []; | ||
| for (const filepath of paths) { | ||
| const file = { | ||
@@ -58,9 +52,33 @@ filepath, | ||
| } | ||
| result.push(file); | ||
| files.push(file); | ||
| } | ||
| return result; | ||
| const allSuites = files.reduce((suites, file) => suites.concat(file.suites), []); | ||
| interpretOnlyMode(allSuites); | ||
| allSuites.forEach((i) => { | ||
| if (i.mode === 'skip') | ||
| i.tasks.forEach(t => t.mode === 'run' && (t.state = 'skip')); | ||
| else | ||
| interpretOnlyMode(i.tasks); | ||
| }); | ||
| return files; | ||
| } | ||
| /** | ||
| * If any items been marked as `only`, mark all other items as `skip`. | ||
| */ | ||
| function interpretOnlyMode(items) { | ||
| if (items.some(i => i.mode === 'only')) { | ||
| items.forEach((i) => { | ||
| if (i.mode === 'run') | ||
| i.mode = 'skip'; | ||
| else if (i.mode === 'only') | ||
| i.mode = 'run'; | ||
| }); | ||
| } | ||
| } | ||
| export async function runFile(file, ctx) { | ||
| var _a, _b, _c, _d; | ||
| const { reporter } = ctx; | ||
| const runableSuites = file.suites.filter(i => i.mode === 'run'); | ||
| if (runableSuites.length === 0) | ||
| return; | ||
| await ((_a = reporter.onFileBegin) === null || _a === void 0 ? void 0 : _a.call(reporter, file, ctx)); | ||
@@ -79,17 +97,19 @@ await beforeFileHook.fire(file); | ||
| } | ||
| export async function run(options = {}) { | ||
| var _a, _b, _c; | ||
| const { rootDir = process.cwd() } = options; | ||
| export async function run(config) { | ||
| var _a, _b, _c, _d; | ||
| const { rootDir = process.cwd() } = config; | ||
| // setup chai | ||
| chai.use(await SnapshotPlugin({ | ||
| rootDir, | ||
| update: options.updateSnapshot, | ||
| update: config.updateSnapshot, | ||
| })); | ||
| chai.use(SinonChai); | ||
| // collect files | ||
| const paths = await fg(options.includes || defaultIncludes, { | ||
| let paths = await fg(config.includes || defaultIncludes, { | ||
| absolute: true, | ||
| cwd: options.rootDir, | ||
| ignore: options.excludes || defaultExcludes, | ||
| cwd: config.rootDir, | ||
| ignore: config.excludes || defaultExcludes, | ||
| }); | ||
| if ((_a = config.nameFilters) === null || _a === void 0 ? void 0 : _a.length) | ||
| paths = paths.filter(i => config.nameFilters.some(f => i.includes(f))); | ||
| if (!paths.length) { | ||
@@ -101,11 +121,10 @@ console.error('No test files found'); | ||
| const reporter = new DefaultReporter(); | ||
| await ((_a = reporter.onStart) === null || _a === void 0 ? void 0 : _a.call(reporter, options)); | ||
| await ((_b = reporter.onStart) === null || _b === void 0 ? void 0 : _b.call(reporter, config)); | ||
| const files = await collectFiles(paths); | ||
| const ctx = { | ||
| files, | ||
| mode: isOnlyMode(files) ? 'only' : 'all', | ||
| userOptions: options, | ||
| config, | ||
| reporter, | ||
| }; | ||
| await ((_b = reporter.onCollected) === null || _b === void 0 ? void 0 : _b.call(reporter, ctx)); | ||
| await ((_c = reporter.onCollected) === null || _c === void 0 ? void 0 : _c.call(reporter, ctx)); | ||
| await beforeAllHook.fire(); | ||
@@ -115,6 +134,3 @@ for (const file of files) | ||
| await afterAllHook.fire(); | ||
| await ((_c = reporter.onFinished) === null || _c === void 0 ? void 0 : _c.call(reporter, ctx)); | ||
| await ((_d = reporter.onFinished) === null || _d === void 0 ? void 0 : _d.call(reporter, ctx)); | ||
| } | ||
| function isOnlyMode(files) { | ||
| return !!files.find(file => file.suites.find(suite => suite.mode === 'only' || suite.tasks.find(t => t.mode === 'only'))); | ||
| } |
+1
-1
@@ -25,3 +25,3 @@ import { context } from './context'; | ||
| suite: {}, | ||
| status: 'init', | ||
| state: mode !== 'run' ? mode : undefined, | ||
| fn, | ||
@@ -28,0 +28,0 @@ }); |
+9
-6
@@ -0,1 +1,2 @@ | ||
| import { ViteDevServer } from 'vite'; | ||
| export declare type Awaitable<T> = Promise<T> | T; | ||
@@ -6,8 +7,11 @@ export interface UserOptions { | ||
| } | ||
| export interface Options extends UserOptions { | ||
| export interface Config extends UserOptions { | ||
| rootDir?: string; | ||
| updateSnapshot?: boolean; | ||
| nameFilters?: string[]; | ||
| server: ViteDevServer; | ||
| watch?: boolean; | ||
| } | ||
| export declare type RunMode = 'run' | 'skip' | 'only' | 'todo'; | ||
| export declare type TaskStatus = 'init' | 'pass' | 'fail' | 'skip' | 'todo'; | ||
| export declare type TaskState = RunMode | 'pass' | 'fail'; | ||
| export interface Task { | ||
@@ -19,3 +23,3 @@ name: string; | ||
| file?: File; | ||
| status: TaskStatus; | ||
| state?: TaskState; | ||
| error?: unknown; | ||
@@ -52,4 +56,3 @@ } | ||
| files: File[]; | ||
| mode: 'all' | 'only'; | ||
| userOptions: Options; | ||
| config: Config; | ||
| reporter: Reporter; | ||
@@ -62,3 +65,3 @@ } | ||
| export interface Reporter { | ||
| onStart: (userOptions: Options) => Awaitable<void>; | ||
| onStart: (userOptions: Config) => Awaitable<void>; | ||
| onCollected: (ctx: RunnerContext) => Awaitable<void>; | ||
@@ -65,0 +68,0 @@ onFinished: (ctx: RunnerContext) => Awaitable<void>; |
+0
-1
@@ -1,2 +0,1 @@ | ||
| /* eslint-disable no-use-before-define */ | ||
| export {}; |
+10
-11
| { | ||
| "name": "vitest", | ||
| "version": "0.0.11", | ||
| "version": "0.0.12", | ||
| "type": "module", | ||
@@ -35,11 +35,2 @@ "description": "", | ||
| }, | ||
| "scripts": { | ||
| "build": "tsc", | ||
| "watch": "tsc --watch", | ||
| "lint": "eslint \"{src,test}/**/*.ts\"", | ||
| "prepublishOnly": "nr build", | ||
| "release": "bumpp --commit --push --tag && pnpm publish", | ||
| "test": "node bin/vitest.mjs --dev", | ||
| "test:update": "nr test -u" | ||
| }, | ||
| "devDependencies": { | ||
@@ -72,3 +63,11 @@ "@antfu/eslint-config": "^0.11.1", | ||
| "vite-node": "^0.1.10" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsc", | ||
| "watch": "tsc --watch", | ||
| "lint": "eslint \"{src,test}/**/*.ts\"", | ||
| "release": "bumpp --commit --push --tag && pnpm publish", | ||
| "test": "node bin/vitest.mjs --dev", | ||
| "test:update": "nr test -u" | ||
| } | ||
| } | ||
| } |
+23
-0
@@ -40,2 +40,23 @@ # vitest | ||
| ## Configuration | ||
| `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: | ||
| - Create `vitest.config.ts`, which will have the higher priority | ||
| - Pass `--config` option to CLI, e.g. `vitest --config ./path/to/vitest.config.ts` | ||
| - Use `process.env.VITEST` to conditionally apply differnet configuration in `vite.config.ts` | ||
| To configure `vitest` itself, add `test` property in your Vite config | ||
| ```ts | ||
| // vite.config.ts | ||
| import { defineConfig } from 'vite' | ||
| export default defineConfig({ | ||
| test: { | ||
| // ... | ||
| } | ||
| }) | ||
| ``` | ||
| ## Filtering | ||
@@ -107,2 +128,3 @@ | ||
| - [x] Mock | ||
| - [ ] Global Mode & Types | ||
| - [ ] Parallel Executing | ||
@@ -112,2 +134,3 @@ - [ ] CLI Help | ||
| - [ ] Watch | ||
| - [ ] Source Map | ||
| - [ ] Coverage | ||
@@ -114,0 +137,0 @@ |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
43083
3.41%1010
2.02%146
18.7%3
50%