vitest 0.0.16 → 0.0.20

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.md CHANGED
@@ -156,8 +156,8 @@ describe('suite', () => {
156
156
  - [x] Mock
157
157
  - [x] Global Mode & Types
158
158
  - [ ] Parallel Executing
159
- - [ ] CLI Help
160
- - [ ] JSDom
159
+ - [ ] CLI Help (Use yargs)
160
+ - [x] JSDom
161
161
  - [ ] Watch
162
162
  - [ ] Source Map
163
163
  - [ ] Coverage
package/dist/constants.js CHANGED
@@ -1,22 +1,23 @@
1
1
  export const defaultIncludes = ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'];
2
2
  export const defaultExcludes = ['**/node_modules/**', '**/dist/**'];
3
3
  export const globalApis = [
4
+ // suite
4
5
  'suite',
5
6
  'test',
6
7
  'describe',
7
8
  'it',
9
+ // chai
10
+ 'chai',
8
11
  'expect',
9
12
  'assert',
13
+ // sinon
14
+ 'sinon',
10
15
  'spy',
11
16
  'mock',
12
17
  'stub',
13
- 'sinon',
18
+ // hooks
14
19
  'beforeAll',
15
20
  'afterAll',
16
21
  'beforeEach',
17
22
  'afterEach',
18
- 'beforeFile',
19
- 'afterFile',
20
- 'beforeSuite',
21
- 'afterSuite',
22
23
  ];
package/dist/index.d.ts CHANGED
@@ -3,4 +3,29 @@ export * from './suite';
3
3
  export * from './config';
4
4
  export * from './integrations/chai';
5
5
  export * from './integrations/sinon';
6
- export { beforeAll, afterAll, beforeEach, afterEach, beforeFile, afterFile, beforeSuite, afterSuite } from './hooks';
6
+ declare global {
7
+ namespace Chai {
8
+ interface Assertion {
9
+ toMatchSnapshot(message?: string): Assertion;
10
+ matchSnapshot(message?: string): Assertion;
11
+ toEqual(expected: any): void;
12
+ toStrictEqual(expected: any): void;
13
+ toBe(expected: any): void;
14
+ toContain(item: any): void;
15
+ toBeTruthy(): void;
16
+ toBeFalsy(): void;
17
+ toBeNaN(): void;
18
+ toBeUndefined(): void;
19
+ toBeNull(): void;
20
+ toBeDefined(): void;
21
+ toBeInstanceOf(c: any): void;
22
+ toBeCalledTimes(n: number): void;
23
+ toBeCalledOnce(): void;
24
+ toBeCalled(): void;
25
+ toHaveBeenCalled(): void;
26
+ }
27
+ interface ExpectStatic {
28
+ addSnapshotSerializer: import('pretty-format').Plugin;
29
+ }
30
+ }
31
+ }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-namespace */
1
2
  export * from './types';
2
3
  export * from './suite';
3
4
  export * from './config';
4
5
  export * from './integrations/chai';
5
6
  export * from './integrations/sinon';
6
- export { beforeAll, afterAll, beforeEach, afterEach, beforeFile, afterFile, beforeSuite, afterSuite } from './hooks';
@@ -1,21 +1,2 @@
1
1
  import { ChaiPlugin } from './types';
2
2
  export declare function JestChaiExpect(): ChaiPlugin;
3
- declare global {
4
- namespace Chai {
5
- interface Assertion {
6
- toEqual(expected: any): void;
7
- toStrictEqual(expected: any): void;
8
- toBe(expected: any): void;
9
- toContain(item: any): void;
10
- toBeTruthy(): void;
11
- toBeFalsy(): void;
12
- toBeNaN(): void;
13
- toBeUndefined(): void;
14
- toBeNull(): void;
15
- toBeDefined(): void;
16
- }
17
- interface ExpectStatic {
18
- addSnapshotSerializer: import('pretty-format').Plugin;
19
- }
20
- }
21
- }
@@ -10,7 +10,7 @@ export function JestChaiExpect() {
10
10
  return this.equal(expected);
11
11
  });
12
12
  utils.addMethod(proto, 'toBe', function (expected) {
13
- return this.be(expected);
13
+ return this.equal(expected);
14
14
  });
15
15
  utils.addMethod(proto, 'toContain', function (item) {
16
16
  return this.contain(item);
@@ -19,7 +19,7 @@ export function JestChaiExpect() {
19
19
  const obj = utils.flag(this, 'object');
20
20
  this.assert(Boolean(obj), 'expected #{this} to be truthy', 'expected #{this} to not be truthy', obj);
21
21
  });
22
- utils.addMethod(proto, 'toFalsy', function () {
22
+ utils.addMethod(proto, 'toBeFalsy', function () {
23
23
  const obj = utils.flag(this, 'object');
24
24
  this.assert(!obj, 'expected #{this} to be falsy', 'expected #{this} to not be falsy', obj);
25
25
  });
@@ -35,5 +35,21 @@ export function JestChaiExpect() {
35
35
  utils.addMethod(proto, 'toBeDefined', function () {
36
36
  return this.not.be.undefined;
37
37
  });
38
+ utils.addMethod(proto, 'toBeInstanceOf', function (obj) {
39
+ return this.instanceOf(obj);
40
+ });
41
+ // mock
42
+ utils.addMethod(proto, 'toBeCalledTimes', function (number) {
43
+ return this.callCount(number);
44
+ });
45
+ utils.addMethod(proto, 'toBeCalledOnce', function () {
46
+ return this.callCount(1);
47
+ });
48
+ utils.addMethod(proto, 'toBeCalled', function () {
49
+ return this.called;
50
+ });
51
+ utils.addMethod(proto, 'toHaveBeenCalled', function () {
52
+ return this.called;
53
+ });
38
54
  };
39
55
  }
@@ -1,17 +1,8 @@
1
1
  import { ChaiPlugin } from '../types';
2
+ import { SnapshotManager } from './manager';
2
3
  export interface SnapshotOptions {
3
4
  rootDir: string;
4
5
  update?: boolean;
5
6
  }
7
+ export declare function getSnapshotManager(): SnapshotManager;
6
8
  export declare function SnapshotPlugin(options: SnapshotOptions): Promise<ChaiPlugin>;
7
- declare global {
8
- namespace Chai {
9
- interface Assertion {
10
- toMatchSnapshot(message?: string): Assertion;
11
- matchSnapshot(message?: string): Assertion;
12
- }
13
- interface ExpectStatic {
14
- addSnapshotSerializer: import('pretty-format').Plugin;
15
- }
16
- }
17
- }
@@ -1,8 +1,10 @@
1
1
  import Snap from 'jest-snapshot';
2
- import { afterAll, beforeEach } from '../../../hooks';
3
2
  import { SnapshotManager } from './manager';
4
3
  const { addSerializer } = Snap;
5
4
  let _manager;
5
+ export function getSnapshotManager() {
6
+ return _manager;
7
+ }
6
8
  export async function SnapshotPlugin(options) {
7
9
  const { rootDir } = options;
8
10
  _manager = new SnapshotManager({
@@ -14,18 +16,6 @@ export async function SnapshotPlugin(options) {
14
16
  rootDir,
15
17
  });
16
18
  return function (chai, utils) {
17
- beforeEach((task) => {
18
- var _a;
19
- _manager.setContext({
20
- file: ((_a = task.file) === null || _a === void 0 ? void 0 : _a.filepath) || task.name,
21
- title: task.name,
22
- fullTitle: [task.suite.name, task.name].filter(Boolean).join(' > '),
23
- });
24
- });
25
- afterAll(() => {
26
- _manager.saveSnap();
27
- _manager.report();
28
- });
29
19
  for (const key of ['matchSnapshot', 'toMatchSnapshot']) {
30
20
  utils.addMethod(chai.Assertion.prototype, key, function (message) {
31
21
  const expected = utils.flag(this, 'object');
@@ -1,5 +1,6 @@
1
1
  import type { SnapshotStateType, SnapshotResolver } from 'jest-snapshot';
2
2
  import type { SnapshotStateOptions } from 'jest-snapshot/build/State';
3
+ import { Task } from '../../../types';
3
4
  import { SnapshotSummary } from './utils/types';
4
5
  export interface Context {
5
6
  file: string;
@@ -20,6 +21,7 @@ export declare class SnapshotManager {
20
21
  snapshotResolver?: SnapshotResolver | null;
21
22
  });
22
23
  onFileChanged(): void;
24
+ setTask(task: Task): void;
23
25
  setContext(context: Context): void;
24
26
  assert(received: unknown, message: string): void;
25
27
  saveSnap(): void;
@@ -31,6 +31,14 @@ export class SnapshotManager {
31
31
  this.testFile = this.context.file;
32
32
  this.snapshotState = new SnapshotState(this.snapshotResolver.resolveSnapshotPath(this.testFile), this.snapshotOptions);
33
33
  }
34
+ setTask(task) {
35
+ var _a;
36
+ this.setContext({
37
+ file: ((_a = task.file) === null || _a === void 0 ? void 0 : _a.filepath) || task.name,
38
+ title: task.name,
39
+ fullTitle: [task.suite.name, task.name].filter(Boolean).join(' > '),
40
+ });
41
+ }
34
42
  setContext(context) {
35
43
  if (!context.title || !context.file)
36
44
  return;
@@ -1,4 +1,5 @@
1
1
  import { JSDOM } from 'jsdom';
2
+ import { KEYS } from './keys';
2
3
  export function setupJSDOM(global) {
3
4
  const dom = new JSDOM('<!DOCTYPE html>', {
4
5
  pretendToBeVisual: true,
@@ -6,7 +7,7 @@ export function setupJSDOM(global) {
6
7
  // TODO: options
7
8
  url: 'http://localhost:3000',
8
9
  });
9
- const keys = Object.getOwnPropertyNames(dom.window)
10
+ const keys = KEYS.concat(Object.getOwnPropertyNames(dom.window))
10
11
  .filter(k => !k.startsWith('_'))
11
12
  .filter(k => !(k in global));
12
13
  for (const key of keys)
@@ -0,0 +1 @@
1
+ export declare const KEYS: string[];
@@ -0,0 +1,187 @@
1
+ // SEE https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/interfaces.js
2
+ const LIVING_KEYS = [
3
+ 'DOMException',
4
+ 'NamedNodeMap',
5
+ 'Attr',
6
+ 'Node',
7
+ 'Element',
8
+ 'DocumentFragment',
9
+ 'HTMLDocument',
10
+ 'Document',
11
+ 'CharacterData',
12
+ 'Comment',
13
+ 'DocumentType',
14
+ 'DOMImplementation',
15
+ 'ProcessingInstruction',
16
+ 'Image',
17
+ 'Text',
18
+ 'Event',
19
+ 'CustomEvent',
20
+ 'MessageEvent',
21
+ 'ErrorEvent',
22
+ 'HashChangeEvent',
23
+ 'PopStateEvent',
24
+ 'UIEvent',
25
+ 'MouseEvent',
26
+ 'KeyboardEvent',
27
+ 'TouchEvent',
28
+ 'ProgressEvent',
29
+ 'EventTarget',
30
+ 'Location',
31
+ 'History',
32
+ 'HTMLElement',
33
+ 'HTMLAnchorElement',
34
+ 'HTMLAppletElement',
35
+ 'HTMLAreaElement',
36
+ 'HTMLAudioElement',
37
+ 'HTMLBaseElement',
38
+ 'HTMLBodyElement',
39
+ 'HTMLBRElement',
40
+ 'HTMLButtonElement',
41
+ 'HTMLCanvasElement',
42
+ 'HTMLDataElement',
43
+ 'HTMLDataListElement',
44
+ 'HTMLDialogElement',
45
+ 'HTMLDirectoryElement',
46
+ 'HTMLDivElement',
47
+ 'HTMLDListElement',
48
+ 'HTMLEmbedElement',
49
+ 'HTMLFieldSetElement',
50
+ 'HTMLFontElement',
51
+ 'HTMLFormElement',
52
+ 'HTMLFrameElement',
53
+ 'HTMLFrameSetElement',
54
+ 'HTMLHeadingElement',
55
+ 'HTMLHeadElement',
56
+ 'HTMLHRElement',
57
+ 'HTMLHtmlElement',
58
+ 'HTMLIFrameElement',
59
+ 'HTMLImageElement',
60
+ 'HTMLInputElement',
61
+ 'HTMLLabelElement',
62
+ 'HTMLLegendElement',
63
+ 'HTMLLIElement',
64
+ 'HTMLLinkElement',
65
+ 'HTMLMapElement',
66
+ 'HTMLMediaElement',
67
+ 'HTMLMenuElement',
68
+ 'HTMLMetaElement',
69
+ 'HTMLMeterElement',
70
+ 'HTMLModElement',
71
+ 'HTMLObjectElement',
72
+ 'HTMLOListElement',
73
+ 'HTMLOptGroupElement',
74
+ 'HTMLOptionElement',
75
+ 'HTMLOutputElement',
76
+ 'HTMLParagraphElement',
77
+ 'HTMLParamElement',
78
+ 'HTMLPreElement',
79
+ 'HTMLProgressElement',
80
+ 'HTMLQuoteElement',
81
+ 'HTMLScriptElement',
82
+ 'HTMLSelectElement',
83
+ 'HTMLSourceElement',
84
+ 'HTMLSpanElement',
85
+ 'HTMLStyleElement',
86
+ 'HTMLTableCaptionElement',
87
+ 'HTMLTableCellElement',
88
+ 'HTMLTableColElement',
89
+ 'HTMLTableDataCellElement',
90
+ 'HTMLTableElement',
91
+ 'HTMLTableHeaderCellElement',
92
+ 'HTMLTimeElement',
93
+ 'HTMLTitleElement',
94
+ 'HTMLTableRowElement',
95
+ 'HTMLTableSectionElement',
96
+ 'HTMLTemplateElement',
97
+ 'HTMLTextAreaElement',
98
+ 'HTMLTrackElement',
99
+ 'HTMLUListElement',
100
+ 'HTMLUnknownElement',
101
+ 'HTMLVideoElement',
102
+ 'StyleSheet',
103
+ 'MediaList',
104
+ 'CSSStyleSheet',
105
+ 'CSSRule',
106
+ 'CSSStyleRule',
107
+ 'CSSMediaRule',
108
+ 'CSSImportRule',
109
+ 'CSSStyleDeclaration',
110
+ 'StyleSheetList',
111
+ 'XPathException',
112
+ 'XPathExpression',
113
+ 'XPathResult',
114
+ 'XPathEvaluator',
115
+ 'HTMLCollection',
116
+ 'NodeFilter',
117
+ 'NodeIterator',
118
+ 'NodeList',
119
+ 'Blob',
120
+ 'File',
121
+ 'FileList',
122
+ 'FormData',
123
+ 'XMLHttpRequest',
124
+ 'XMLHttpRequestEventTarget',
125
+ 'XMLHttpRequestUpload',
126
+ 'DOMTokenList',
127
+ 'URL',
128
+ ];
129
+ const OTHER_KEYS = [
130
+ 'addEventListener',
131
+ 'alert',
132
+ 'atob',
133
+ 'blur',
134
+ 'btoa',
135
+ /* 'clearInterval', */
136
+ /* 'clearTimeout', */
137
+ 'close',
138
+ 'confirm',
139
+ /* 'console', */
140
+ 'createPopup',
141
+ 'dispatchEvent',
142
+ 'document',
143
+ 'focus',
144
+ 'frames',
145
+ 'getComputedStyle',
146
+ 'history',
147
+ 'innerHeight',
148
+ 'innerWidth',
149
+ 'length',
150
+ 'location',
151
+ 'moveBy',
152
+ 'moveTo',
153
+ 'name',
154
+ 'navigator',
155
+ 'open',
156
+ 'outerHeight',
157
+ 'outerWidth',
158
+ 'pageXOffset',
159
+ 'pageYOffset',
160
+ 'parent',
161
+ 'postMessage',
162
+ 'print',
163
+ 'prompt',
164
+ 'removeEventListener',
165
+ 'resizeBy',
166
+ 'resizeTo',
167
+ 'screen',
168
+ 'screenLeft',
169
+ 'screenTop',
170
+ 'screenX',
171
+ 'screenY',
172
+ 'scroll',
173
+ 'scrollBy',
174
+ 'scrollLeft',
175
+ 'scrollTo',
176
+ 'scrollTop',
177
+ 'scrollX',
178
+ 'scrollY',
179
+ 'self',
180
+ /* 'setInterval', */
181
+ /* 'setTimeout', */
182
+ 'stop',
183
+ /* 'toString', */
184
+ 'top',
185
+ 'window',
186
+ ];
187
+ export const KEYS = LIVING_KEYS.concat(OTHER_KEYS);
@@ -1,3 +1,5 @@
1
1
  import sinon from 'sinon';
2
2
  export { sinon };
3
3
  export const { mock, spy, stub } = sinon;
4
+ // @ts-expect-error
5
+ sinon.fn = sinon.spy;
@@ -71,8 +71,10 @@ export class DefaultReporter {
71
71
  await this.listrPromise;
72
72
  this.log();
73
73
  this.end = performance.now();
74
- const failedFiles = files.filter(i => i.error);
74
+ const suites = files.reduce((acc, file) => acc.concat(file.suites), []);
75
75
  const tasks = files.reduce((acc, file) => acc.concat(file.suites.flatMap(i => i.tasks)), []);
76
+ const failedFiles = files.filter(i => i.error);
77
+ const failedSuites = suites.filter(i => i.error);
76
78
  const runable = tasks.filter(i => i.state === 'pass' || i.state === 'fail');
77
79
  const passed = tasks.filter(i => i.state === 'pass');
78
80
  const failed = tasks.filter(i => i.state === 'fail');
@@ -87,6 +89,15 @@ export class DefaultReporter {
87
89
  this.log();
88
90
  });
89
91
  }
92
+ if (failedSuites.length) {
93
+ this.error(c.bold(`\nFailed to run ${failedSuites.length} suites:`));
94
+ failedSuites.forEach((i) => {
95
+ var _a;
96
+ this.error(`\n- ${(_a = i.file) === null || _a === void 0 ? void 0 : _a.filepath} > ${i.name}`);
97
+ console.error(i.error || 'Unknown error');
98
+ this.log();
99
+ });
100
+ }
90
101
  if (failed.length) {
91
102
  this.error(c.bold(`\nFailed Tests (${failed.length})`));
92
103
  failed.forEach((task) => {
package/dist/run.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { File, Config, Task, RunnerContext } from './types';
1
+ import { File, Config, Task, RunnerContext, Suite } from './types';
2
2
  export declare function runTask(task: Task, ctx: RunnerContext): Promise<void>;
3
3
  export declare function collectFiles(paths: string[]): Promise<File[]>;
4
+ export declare function runSite(suite: Suite, ctx: RunnerContext): Promise<void>;
4
5
  export declare function runFile(file: File, ctx: RunnerContext): Promise<void>;
5
6
  export declare function run(config: Config): Promise<void>;
package/dist/run.js CHANGED
@@ -2,26 +2,38 @@ import fg from 'fast-glob';
2
2
  import { setupChai } from './integrations/chai/setup';
3
3
  import { clearContext, defaultSuite } from './suite';
4
4
  import { context } from './context';
5
- import { afterEachHook, afterFileHook, afterAllHook, afterSuiteHook, beforeEachHook, beforeFileHook, beforeAllHook, beforeSuiteHook } from './hooks';
6
5
  import { DefaultReporter } from './reporters/default';
7
6
  import { defaultIncludes, defaultExcludes } from './constants';
7
+ import { getSnapshotManager } from './integrations/chai/snapshot';
8
+ async function callHook(suite, name, args) {
9
+ await Promise.all(suite.hooks[name].map(fn => fn(...args)));
10
+ }
8
11
  export async function runTask(task, ctx) {
9
- var _a, _b;
12
+ var _a, _b, _c;
10
13
  const { reporter } = ctx;
11
- await ((_a = reporter.onTaskBegin) === null || _a === void 0 ? void 0 : _a.call(reporter, task, ctx));
14
+ (_a = getSnapshotManager()) === null || _a === void 0 ? void 0 : _a.setTask(task);
15
+ await ((_b = reporter.onTaskBegin) === null || _b === void 0 ? void 0 : _b.call(reporter, task, ctx));
12
16
  if (task.mode === 'run') {
13
- await beforeEachHook.fire(task);
14
17
  try {
18
+ await callHook(task.suite, 'beforeEach', [task, task.suite]);
15
19
  await task.fn();
16
20
  task.state = 'pass';
17
21
  }
18
22
  catch (e) {
19
23
  task.state = 'fail';
20
24
  task.error = e;
25
+ process.exitCode = 1;
26
+ }
27
+ try {
28
+ await callHook(task.suite, 'afterEach', [task, task.suite]);
29
+ }
30
+ catch (e) {
31
+ task.state = 'fail';
32
+ task.error = e;
33
+ process.exitCode = 1;
21
34
  }
22
- await afterEachHook.fire(task);
23
35
  }
24
- await ((_b = reporter.onTaskEnd) === null || _b === void 0 ? void 0 : _b.call(reporter, task, ctx));
36
+ await ((_c = reporter.onTaskEnd) === null || _c === void 0 ? void 0 : _c.call(reporter, task, ctx));
25
37
  }
26
38
  export async function collectFiles(paths) {
27
39
  const files = [];
@@ -71,6 +83,32 @@ function interpretOnlyMode(items) {
71
83
  });
72
84
  }
73
85
  }
86
+ export async function runSite(suite, ctx) {
87
+ var _a, _b;
88
+ const { reporter } = ctx;
89
+ await ((_a = reporter.onSuiteBegin) === null || _a === void 0 ? void 0 : _a.call(reporter, suite, ctx));
90
+ if (suite.mode === 'skip') {
91
+ suite.status = 'skip';
92
+ }
93
+ else if (suite.mode === 'todo') {
94
+ suite.status = 'todo';
95
+ }
96
+ else {
97
+ try {
98
+ await callHook(suite, 'beforeAll', [suite]);
99
+ await Promise.all(suite.tasks.map(i => runTask(i, ctx)));
100
+ // for (const t of suite.tasks)
101
+ // await runTask(t, ctx)
102
+ await callHook(suite, 'afterAll', [suite]);
103
+ }
104
+ catch (e) {
105
+ suite.error = e;
106
+ suite.status = 'fail';
107
+ process.exitCode = 1;
108
+ }
109
+ }
110
+ await ((_b = reporter.onSuiteEnd) === null || _b === void 0 ? void 0 : _b.call(reporter, suite, ctx));
111
+ }
74
112
  export async function runFile(file, ctx) {
75
113
  var _a, _b;
76
114
  const { reporter } = ctx;
@@ -78,19 +116,13 @@ export async function runFile(file, ctx) {
78
116
  if (runableSuites.length === 0)
79
117
  return;
80
118
  await ((_a = reporter.onFileBegin) === null || _a === void 0 ? void 0 : _a.call(reporter, file, ctx));
81
- await beforeFileHook.fire(file);
82
- // TODO: support toggling parallel or serial
83
- await Promise.all(file.suites.map(async (suite) => {
84
- var _a, _b;
85
- await ((_a = reporter.onSuiteBegin) === null || _a === void 0 ? void 0 : _a.call(reporter, suite, ctx));
86
- await beforeSuiteHook.fire(suite);
87
- await Promise.all(suite.tasks.map(i => runTask(i, ctx)));
88
- // for (const t of suite.tasks)
89
- // await runTask(t, ctx)
90
- await afterSuiteHook.fire(suite);
91
- await ((_b = reporter.onSuiteEnd) === null || _b === void 0 ? void 0 : _b.call(reporter, suite, ctx));
92
- }));
93
- await afterFileHook.fire(file);
119
+ if (ctx.config.parallel) {
120
+ await Promise.all(file.suites.map(suite => runSite(suite, ctx)));
121
+ }
122
+ else {
123
+ for (const suite of file.suites)
124
+ await runSite(suite, ctx);
125
+ }
94
126
  await ((_b = reporter.onFileEnd) === null || _b === void 0 ? void 0 : _b.call(reporter, file, ctx));
95
127
  }
96
128
  export async function run(config) {
@@ -123,9 +155,10 @@ export async function run(config) {
123
155
  reporter,
124
156
  };
125
157
  await ((_c = reporter.onCollected) === null || _c === void 0 ? void 0 : _c.call(reporter, ctx));
126
- await beforeAllHook.fire();
127
158
  for (const file of files)
128
159
  await runFile(file, ctx);
129
- await afterAllHook.fire();
160
+ const snapshot = getSnapshotManager();
161
+ snapshot === null || snapshot === void 0 ? void 0 : snapshot.saveSnap();
162
+ snapshot === null || snapshot === void 0 ? void 0 : snapshot.report();
130
163
  await ((_d = reporter.onFinished) === null || _d === void 0 ? void 0 : _d.call(reporter, ctx));
131
164
  }
package/dist/suite.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SuiteCollector, TestFactory, TestFunction } from './types';
1
+ 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;
@@ -19,4 +19,8 @@ export declare const it: {
19
19
  only(name: string, fn: TestFunction): void;
20
20
  todo(name: string): void;
21
21
  };
22
+ export declare const beforeAll: (fn: Suite['hooks']['beforeAll'][0]) => void;
23
+ export declare const afterAll: (fn: Suite['hooks']['afterAll'][0]) => void;
24
+ export declare const beforeEach: (fn: Suite['hooks']['beforeEach'][0]) => void;
25
+ export declare const afterEach: (fn: Suite['hooks']['afterEach'][0]) => void;
22
26
  export declare function clearContext(): void;
package/dist/suite.js CHANGED
@@ -3,20 +3,30 @@ export const defaultSuite = suite('');
3
3
  function getCurrentSuite() {
4
4
  return context.currentSuite || defaultSuite;
5
5
  }
6
- export const test = (name, fn) => getCurrentSuite().test(name, fn);
7
- test.skip = (name, fn) => getCurrentSuite().test.skip(name, fn);
8
- test.only = (name, fn) => getCurrentSuite().test.only(name, fn);
9
- test.todo = (name) => getCurrentSuite().test.todo(name);
10
- function createSuiteCollector(mode, suiteName, factory) {
6
+ function createSuiteCollector(name, factory = () => { }, mode) {
11
7
  const queue = [];
12
8
  const factoryQueue = [];
9
+ const suiteBase = {
10
+ name,
11
+ mode,
12
+ hooks: {
13
+ beforeAll: [],
14
+ afterAll: [],
15
+ beforeEach: [],
16
+ afterEach: [],
17
+ },
18
+ };
13
19
  const collector = {
14
- name: suiteName,
20
+ name,
15
21
  mode,
16
22
  test,
17
23
  collect,
18
24
  clear,
25
+ on: addHook,
19
26
  };
27
+ function addHook(name, ...fn) {
28
+ suiteBase.hooks[name].push(...fn);
29
+ }
20
30
  function collectTask(name, fn, mode) {
21
31
  queue.push({
22
32
  name,
@@ -41,12 +51,8 @@ function createSuiteCollector(mode, suiteName, factory) {
41
51
  if (factory)
42
52
  await factory(test);
43
53
  const tasks = [...factoryQueue, ...queue];
44
- const suite = {
45
- name: collector.name,
46
- mode: collector.mode,
47
- tasks,
48
- file,
49
- };
54
+ const suite = Object.assign(Object.assign({}, suiteBase), { tasks,
55
+ file });
50
56
  tasks.forEach((task) => {
51
57
  task.suite = suite;
52
58
  if (file)
@@ -58,15 +64,25 @@ function createSuiteCollector(mode, suiteName, factory) {
58
64
  context.suites.push(collector);
59
65
  return collector;
60
66
  }
67
+ // 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);
61
72
  export function suite(suiteName, factory) {
62
- return createSuiteCollector('run', suiteName, factory);
73
+ return createSuiteCollector(suiteName, factory, 'run');
63
74
  }
64
- suite.skip = (suiteName, factory) => createSuiteCollector('skip', suiteName, factory);
65
- suite.only = (suiteName, factory) => createSuiteCollector('only', suiteName, factory);
66
- suite.todo = (suiteName) => createSuiteCollector('todo', suiteName);
75
+ suite.skip = (suiteName, factory) => createSuiteCollector(suiteName, factory, 'skip');
76
+ suite.only = (suiteName, factory) => createSuiteCollector(suiteName, factory, 'only');
77
+ suite.todo = (suiteName) => createSuiteCollector(suiteName, undefined, 'todo');
67
78
  // alias
68
79
  export const describe = suite;
69
80
  export const it = test;
81
+ // hooks
82
+ export const beforeAll = (fn) => getCurrentSuite().on('beforeAll', fn);
83
+ export const afterAll = (fn) => getCurrentSuite().on('afterAll', fn);
84
+ export const beforeEach = (fn) => getCurrentSuite().on('beforeEach', fn);
85
+ export const afterEach = (fn) => getCurrentSuite().on('afterEach', fn);
70
86
  // utils
71
87
  export function clearContext() {
72
88
  context.suites.length = 0;
package/dist/types.d.ts CHANGED
@@ -15,6 +15,12 @@ export interface UserOptions {
15
15
  * @default false
16
16
  */
17
17
  jsdom?: boolean;
18
+ /**
19
+ * Run tests files in parallel
20
+ *
21
+ * @default false
22
+ */
23
+ parallel?: boolean;
18
24
  }
19
25
  export interface Config extends UserOptions {
20
26
  rootDir?: string;
@@ -41,18 +47,28 @@ export interface TestCollector {
41
47
  skip: (name: string, fn: TestFunction) => void;
42
48
  todo: (name: string) => void;
43
49
  }
50
+ export declare type HookListener<T extends any[]> = (...args: T) => Awaitable<void>;
44
51
  export interface Suite {
45
52
  name: string;
46
53
  mode: RunMode;
47
54
  tasks: Task[];
48
55
  file?: File;
56
+ error?: unknown;
57
+ status?: TaskState;
58
+ hooks: {
59
+ beforeAll: HookListener<[Suite]>[];
60
+ afterAll: HookListener<[Suite]>[];
61
+ beforeEach: HookListener<[Task, Suite]>[];
62
+ afterEach: HookListener<[Task, Suite]>[];
63
+ };
49
64
  }
50
65
  export interface SuiteCollector {
51
- name: string;
52
- mode: RunMode;
66
+ readonly name: string;
67
+ readonly mode: RunMode;
53
68
  test: TestCollector;
54
69
  collect: (file?: File) => Promise<Suite>;
55
70
  clear: () => void;
71
+ on: <T extends keyof Suite['hooks']>(name: T, ...fn: Suite['hooks'][T]) => void;
56
72
  }
57
73
  export declare type TestFactory = (test: (name: string, fn: TestFunction) => void) => Awaitable<void>;
58
74
  export interface File {
package/global.d.ts CHANGED
@@ -3,19 +3,16 @@ declare global {
3
3
  const test: typeof import('vitest')['test']
4
4
  const describe: typeof import('vitest')['describe']
5
5
  const it: typeof import('vitest')['it']
6
+ const chai: typeof import('vitest')['chai']
6
7
  const expect: typeof import('vitest')['expect']
7
8
  const assert: typeof import('vitest')['assert']
9
+ const sinon: typeof import('vitest')['sinon']
8
10
  const spy: typeof import('vitest')['spy']
9
11
  const mock: typeof import('vitest')['mock']
10
12
  const stub: typeof import('vitest')['stub']
11
- const sinon: typeof import('vitest')['sinon']
12
13
  const beforeAll: typeof import('vitest')['beforeAll']
13
14
  const afterAll: typeof import('vitest')['afterAll']
14
15
  const beforeEach: typeof import('vitest')['beforeEach']
15
16
  const afterEach: typeof import('vitest')['afterEach']
16
- const beforeFile: typeof import('vitest')['beforeFile']
17
- const afterFile: typeof import('vitest')['afterFile']
18
- const beforeSuite: typeof import('vitest')['beforeSuite']
19
- const afterSuite: typeof import('vitest')['afterSuite']
20
17
  }
21
18
  export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest",
3
- "version": "0.0.16",
3
+ "version": "0.0.20",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/antfu/vitest#readme",
@@ -33,16 +33,6 @@
33
33
  "bin",
34
34
  "*.d.ts"
35
35
  ],
36
- "scripts": {
37
- "prepare": "esmo scripts/generate-types.ts",
38
- "build": "rimraf dist && tsc -p src/tsconfig.json",
39
- "lint": "eslint \"{src,test}/**/*.ts\"",
40
- "prepublishOnly": "nr build",
41
- "release": "bumpp --commit --push --tag && pnpm publish",
42
- "test": "node bin/vitest.mjs --dev",
43
- "test:update": "nr test -u",
44
- "watch": "tsc -p src/tsconfig.json --watch"
45
- },
46
36
  "dependencies": {
47
37
  "@jest/test-result": "^27.4.2",
48
38
  "@types/chai": "^4.2.22",
@@ -74,5 +64,13 @@
74
64
  "rimraf": "^3.0.2",
75
65
  "typescript": "^4.5.2",
76
66
  "vite": "^2.6.14"
67
+ },
68
+ "scripts": {
69
+ "build": "rimraf dist && tsc -p src/tsconfig.json",
70
+ "lint": "eslint \"{src,test}/**/*.ts\"",
71
+ "release": "bumpp --commit --push --tag && pnpm publish",
72
+ "test": "node bin/vitest.mjs --dev",
73
+ "test:update": "nr test -u",
74
+ "watch": "tsc -p src/tsconfig.json --watch"
77
75
  }
78
- }
76
+ }
package/dist/hooks.d.ts DELETED
@@ -1,49 +0,0 @@
1
- import { File, Suite, Task } from './types';
2
- export declare const beforeAllHook: {
3
- on(fn: (...args: any[]) => void | Promise<void>): void;
4
- fire(...args: any[]): Promise<void>;
5
- clear(): void;
6
- };
7
- export declare const afterAllHook: {
8
- on(fn: (...args: any[]) => void | Promise<void>): void;
9
- fire(...args: any[]): Promise<void>;
10
- clear(): void;
11
- };
12
- export declare const beforeEachHook: {
13
- on(fn: (args_0: Task) => void | Promise<void>): void;
14
- fire(args_0: Task): Promise<void>;
15
- clear(): void;
16
- };
17
- export declare const afterEachHook: {
18
- on(fn: (args_0: Task) => void | Promise<void>): void;
19
- fire(args_0: Task): Promise<void>;
20
- clear(): void;
21
- };
22
- export declare const beforeFileHook: {
23
- on(fn: (args_0: File) => void | Promise<void>): void;
24
- fire(args_0: File): Promise<void>;
25
- clear(): void;
26
- };
27
- export declare const afterFileHook: {
28
- on(fn: (args_0: File) => void | Promise<void>): void;
29
- fire(args_0: File): Promise<void>;
30
- clear(): void;
31
- };
32
- export declare const beforeSuiteHook: {
33
- on(fn: (args_0: Suite) => void | Promise<void>): void;
34
- fire(args_0: Suite): Promise<void>;
35
- clear(): void;
36
- };
37
- export declare const afterSuiteHook: {
38
- on(fn: (args_0: Suite) => void | Promise<void>): void;
39
- fire(args_0: Suite): Promise<void>;
40
- clear(): void;
41
- };
42
- export declare const beforeAll: (fn: (...args: any[]) => void | Promise<void>) => void;
43
- export declare const afterAll: (fn: (...args: any[]) => void | Promise<void>) => void;
44
- export declare const beforeEach: (fn: (args_0: Task) => void | Promise<void>) => void;
45
- export declare const afterEach: (fn: (args_0: Task) => void | Promise<void>) => void;
46
- export declare const beforeFile: (fn: (args_0: File) => void | Promise<void>) => void;
47
- export declare const afterFile: (fn: (args_0: File) => void | Promise<void>) => void;
48
- export declare const beforeSuite: (fn: (args_0: Suite) => void | Promise<void>) => void;
49
- export declare const afterSuite: (fn: (args_0: Suite) => void | Promise<void>) => void;
package/dist/hooks.js DELETED
@@ -1,17 +0,0 @@
1
- import { createHook } from './utils/hook';
2
- export const beforeAllHook = createHook();
3
- export const afterAllHook = createHook();
4
- export const beforeEachHook = createHook();
5
- export const afterEachHook = createHook();
6
- export const beforeFileHook = createHook();
7
- export const afterFileHook = createHook();
8
- export const beforeSuiteHook = createHook();
9
- export const afterSuiteHook = createHook();
10
- export const beforeAll = beforeAllHook.on;
11
- export const afterAll = afterAllHook.on;
12
- export const beforeEach = beforeEachHook.on;
13
- export const afterEach = afterEachHook.on;
14
- export const beforeFile = beforeFileHook.on;
15
- export const afterFile = afterFileHook.on;
16
- export const beforeSuite = beforeSuiteHook.on;
17
- export const afterSuite = afterSuiteHook.on;
package/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './dist/index'