Skip to content

Commit a77f9b0

Browse files
authoredApr 29, 2023
feat: added Vitest support (#203)
1 parent b3e0d36 commit a77f9b0

File tree

6 files changed

+130
-10
lines changed

6 files changed

+130
-10
lines changed
 

‎README.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,21 @@ See the _Documentation_ link for each supported framework for how to set up cons
153153
</a>
154154
</td>
155155
</tr>
156+
<tr>
157+
<td>Vitest</td>
158+
<td>
159+
✅️
160+
161+
</td>
162+
<td>
163+
<code>"vitest"</code>
164+
</td>
165+
<td>
166+
<a href="./docs/Vitest.md">
167+
<code>Vitest.md</code>
168+
</a>
169+
</td>
170+
</tr>
156171
<tr>
157172
<td>Cypress</td>
158173
<td>⚙️</td>
@@ -203,16 +218,6 @@ See the _Documentation_ link for each supported framework for how to set up cons
203218
</a>
204219
</td>
205220
</tr>
206-
<tr>
207-
<td>Vitest</td>
208-
<td>⚙️</td>
209-
<td></td>
210-
<td>
211-
<a href="https://github.com/JoshuaKGoldberg/console-fail-test/issues/197">
212-
<code>/issues/197</code>
213-
</a>
214-
</td>
215-
</tr>
216221
</tbody>
217222
</table>
218223

‎docs/Vitest.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Vitest
2+
3+
Vitest is supported both as a testing framework and a spy library.
4+
It will be auto-detected if available.
5+
6+
## Setup
7+
8+
In your `vitest.config.ts`, include `console-fail-test/vitest` in your [`setupFiles`](https://vitest.dev/config/#setupfiles):
9+
10+
```js
11+
// vitest.config.ts
12+
import { defineConfig } from "vitest/config";
13+
14+
export default defineConfig({
15+
setupFiles: ["console-fail-test/setup"],
16+
});
17+
```
18+
19+
Alternately, if you have a setup file already being run first, or you'd like to manually enable this in individual files, you can use the Node API:
20+
21+
```js
22+
// some.test.js
23+
import * as vitest from "vitest";
24+
25+
require("console-fail-test").cft();
26+
```

‎src/environments/selectTestFramework.ts

+4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import { selectLabEnvironment } from "./lab";
77
import { selectMochaEnvironment } from "./mocha";
88
import { selectNodeTapEnvironment } from "./nodeTap";
99
import { TestFrameworkSelector } from "./testEnvironmentTypes";
10+
import { selectVitestEnvironment } from "./vitest";
1011

1112
const testEnvironmentsByName = new Map<SupportedTestFramework, TestFrameworkSelector>([
1213
["jasmine", selectJasmineEnvironment],
1314
["jest", selectJestEnvironment],
1415
["mocha", selectMochaEnvironment],
16+
["vitest", selectVitestEnvironment],
1517
]);
1618

1719
const detectableTestEnvironmentSelectors: TestFrameworkSelector[] = [
@@ -20,6 +22,8 @@ const detectableTestEnvironmentSelectors: TestFrameworkSelector[] = [
2022
selectLabEnvironment,
2123
selectNodeTapEnvironment,
2224

25+
selectVitestEnvironment,
26+
2327
// Jest should come before Jasmine because Jest includes a monkey-patched Jasmine
2428
selectJestEnvironment,
2529
selectJasmineEnvironment,

‎src/environments/vitest.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { TestFrameworkSelector } from "./testEnvironmentTypes";
2+
3+
declare interface VitestModule {
4+
afterEach: (callback: () => void) => void;
5+
beforeEach: (callback: () => void) => void;
6+
}
7+
8+
declare const __vitest_index__: VitestModule | undefined;
9+
10+
export const selectVitestEnvironment: TestFrameworkSelector = () => {
11+
if (typeof __vitest_index__ === "undefined") {
12+
return undefined;
13+
}
14+
15+
const vitest = __vitest_index__;
16+
17+
let afterEachCallback: (() => void) | undefined;
18+
let beforeEachCallback: (() => void) | undefined;
19+
20+
vitest.afterEach(() => {
21+
afterEachCallback?.();
22+
});
23+
24+
vitest.beforeEach(() => {
25+
beforeEachCallback?.();
26+
});
27+
28+
return {
29+
afterEach: (callback) => {
30+
afterEachCallback = callback;
31+
},
32+
beforeEach: (callback) => {
33+
beforeEachCallback = callback;
34+
},
35+
};
36+
};

‎src/spies/selectSpyFactory.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@ import { selectJasmineSpyFactory } from "./jasmine";
55
import { selectJestSpyFactory } from "./jest";
66
import { selectSinonSpyFactory } from "./sinon";
77
import { SpyFactoryGetter as SpyFactorySelector } from "./spyTypes";
8+
import { selectVitestSpyFactory } from "./vitest";
89

910
const spyFactoriesByName = new Map<SupportedSpyLibrary, SpyFactorySelector>([
1011
["fallback", selectFallbackSpyFactory],
1112
["jest", selectJestSpyFactory],
1213
["jasmine", selectJasmineSpyFactory],
1314
["sinon", selectSinonSpyFactory],
15+
["vitest", selectVitestSpyFactory],
1416
]);
1517

1618
const detectableSpyFactorySelectors: SpyFactorySelector[] = [
19+
selectVitestSpyFactory,
20+
1721
// Jest should come before Jasmine because Jest includes a monkey-patched Jasmine
1822
selectJestSpyFactory,
1923
selectJasmineSpyFactory,

‎src/spies/vitest.ts

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { SpyCallArgs, SpyFactory, SpyFactoryGetter } from "./spyTypes";
2+
3+
declare interface Vitest {
4+
vi: {
5+
spyOn(container: unknown, methodName: string): ViSpy;
6+
};
7+
}
8+
9+
declare interface ViSpy {
10+
calls: SpyCallArgs[];
11+
restore(): void;
12+
}
13+
14+
declare const __vitest_index__: Vitest | undefined;
15+
16+
const isVitestModule = (spyLibrary: unknown): spyLibrary is Vitest => {
17+
return (
18+
typeof spyLibrary === "object" &&
19+
!!(spyLibrary as Partial<Vitest>).vi &&
20+
typeof (spyLibrary as Vitest).vi.spyOn === "function"
21+
);
22+
};
23+
24+
const createVitestSpyFactory = (spyLibrary: Vitest): SpyFactory => {
25+
return (container: any, methodName: string) => {
26+
const spy = spyLibrary.vi.spyOn(container, methodName);
27+
28+
return {
29+
getCalls: () => spy.calls,
30+
restore: spy.restore,
31+
};
32+
};
33+
};
34+
35+
export const selectVitestSpyFactory: SpyFactoryGetter = ({ spyLibrary }) => {
36+
if (isVitestModule(spyLibrary)) {
37+
return createVitestSpyFactory(spyLibrary);
38+
}
39+
40+
if (typeof __vitest_index__ !== "undefined" && isVitestModule(__vitest_index__)) {
41+
return createVitestSpyFactory(__vitest_index__);
42+
}
43+
44+
return undefined;
45+
};

0 commit comments

Comments
 (0)
Please sign in to comment.