Skip to content

Commit b0ea528

Browse files
cafesanurluvaton
andauthored
Support extension settings ('pretest', 'packageManager', 'testCommand', 'extraArguments', and 'executableOptions') (#11)
* Support extension settings ('pretest', 'packageManager', 'testCommand', 'extraArguments', and 'executableOptions') Co-authored-by: Raz Luvaton <16746759+rluvaton@users.noreply.github.com>
1 parent 728655c commit b0ea528

7 files changed

Lines changed: 147 additions & 38 deletions

File tree

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.3.0",
2+
"version": "0.4.0",
33
"configurations": [
44
{
55
"name": "Launch Extension",

README.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,32 @@
22

33
Vitest runner for vscode that actually works
44

5-
Supports:
6-
-
7-
![preview](https://github.com/rluvaton/vitest-vs-code-plugin/blob/main/docs/preview.png?raw=true)
5+
### Run/Watch/debug any test (`it`, `test`, or `describe`) in `.js`, `.ts`, `.jsx`, or `.tsx` files:
6+
7+
![preview](screenshot.png)
8+
9+
10+
## Extension Settings
11+
12+
| Command | Description | Examples | Default |
13+
| --------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------| --------------------------------------------- |
14+
| `vscode-vitest.preTest` | Any command(s) to run before test starts | `["npm run script1", "npm run script2"` (will run in the given order. If command(s) fail, tests will not run) | [] |
15+
| `vscode-vitest.postTest` | Any command(s) to run after test finishes | `["npm run clean1", "npm run clean2"` (will run in the given order) | [] |
16+
| `vscode-vitest.packageManager` | Desired package manager | `npm`, `yarn`, `pnpm`, `pnpn dlx`, etc | `npx` |
17+
| `vscode-vitest.testCommand` | Define an alternative vitest command | `test` (e.g. for CRA, package.json `test` script, or similar abstractions) | `vitest` |
18+
| `vscode-vitest.extraArguments` | Any additional vitest arguments | `--silent=true --maxWorkers=2` | `""` |
19+
| `vscode-vitest.executableOptions` | Executable option to show | `{"debug": false, "run": false}` (will only display `watch`) | `{"debug": true,"run": true, "run": true}` |
20+
21+
22+
### Example Settings:
23+
```
24+
"vscode-vitest.preTest": ["npm run script1"],
25+
"vscode-vitest.postTest": ["npm run cleanAfterTest"],
26+
"vscode-vitest.packageManager": "pnpm",
27+
"vscode-vitest.testCommand": "test",
28+
"vscode-vitest.extraArguments": "--silent --maxWorkers=2",
29+
"vscode-vitest.executableOptions": {
30+
"debug": false,
31+
"watch": false
32+
},
33+
```

package.json

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vscode-vitest",
33
"displayName": "Vitest Runner for VSCode that actually work",
4-
"version": "0.3.0",
4+
"version": "0.4.0",
55
"main": "dist/index.js",
66
"icon": "logo.png",
77
"license": "MIT",
@@ -44,5 +44,69 @@
4444
},
4545
"dependencies": {
4646
"find-up": "^5.0.0"
47+
},
48+
"contributes": {
49+
"configuration": {
50+
"title": "Vitest Runner Configuration",
51+
"properties": {
52+
"vscode-vitest.preTest": {
53+
"type": ["array"],
54+
"items": {
55+
"type": "string"
56+
},
57+
"default": [],
58+
"description": "Command to run before tests run. e.g npm run preTest"
59+
},
60+
"vscode-vitest.postTest": {
61+
"type": ["array"],
62+
"items": {
63+
"type": "string"
64+
},
65+
"default": [],
66+
"description": "Command to run after tests run. e.g npm run cleanAfterTest"
67+
},
68+
"vscode-vitest.packageManager": {
69+
"type": "string",
70+
"default": "npx",
71+
"description": "Command to run tests. e.g npm, pnpm, npx, yarn"
72+
},
73+
"vscode-vitest.testCommand": {
74+
"type": "string",
75+
"default": "vitest",
76+
"description": "Command to run tests. e.g test, vitest"
77+
},
78+
"vscode-vitest.extraArguments": {
79+
"type": "string",
80+
"default": "",
81+
"description": "Extra arguments to run the test. e.g --maxWorkers --silent"
82+
},
83+
"vscode-vitest.executableOptions": {
84+
"type": "object",
85+
"default": {
86+
"run": true,
87+
"watch": true,
88+
"debug": true
89+
},
90+
"properties": {
91+
"run": {
92+
"type": "boolean",
93+
"default": true,
94+
"description": "Enable or disable Run(Vitest)"
95+
},
96+
"watch": {
97+
"type": "boolean",
98+
"default": true,
99+
"description": "Enable or disable Watch(Vitest)"
100+
},
101+
"debug": {
102+
"type": "boolean",
103+
"default": true,
104+
"description": "Enable or disable Debug(Vitest)."
105+
}
106+
},
107+
"description": "Choose which executable options to enable"
108+
}
109+
}
110+
}
47111
}
48112
}

screenshot.png

25.9 KB
Loading

src/codelens.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ import {DebugVitestCommand, RunVitestCommand, WatchVitestCommand} from './vscode
55
import {TestTreeBuilder} from "./test-tree/build";
66
import {TestTreeNode} from './test-tree/types';
77

8+
interface ExecutableOptions {
9+
run: boolean;
10+
watch: boolean;
11+
debug: boolean;
12+
}
13+
14+
const config = vscode.workspace.getConfiguration('vscode-vitest');
15+
816
export class CodeLensProvider implements vscode.CodeLensProvider {
917
constructor(private typescript: typeof ts) {
1018
}
@@ -24,19 +32,37 @@ export class CodeLensProvider implements vscode.CodeLensProvider {
2432
const start = document.positionAt(testNode.position.start);
2533
const end = document.positionAt(testNode.position.end);
2634

27-
return [
35+
const executableOptions: ExecutableOptions = config.get("executableOptions") ?? {
36+
run: true,
37+
watch: true,
38+
debug: true,
39+
}
40+
41+
const runCommand = executableOptions.run ? [
2842
new vscode.CodeLens(
2943
new vscode.Range(start, end),
3044
new RunVitestCommand(testNode.name, document.fileName)
31-
),
45+
)
46+
] : []
47+
48+
const debugCommand = executableOptions.debug ? [
3249
new vscode.CodeLens(
3350
new vscode.Range(start, end),
3451
new DebugVitestCommand(testNode.name, document.fileName)
35-
),
52+
)
53+
] : []
54+
55+
const watchCommand = executableOptions.watch ? [
3656
new vscode.CodeLens(
3757
new vscode.Range(start, end),
3858
new WatchVitestCommand(testNode.name, document.fileName)
3959
)
60+
] : []
61+
62+
return [
63+
...runCommand,
64+
...debugCommand,
65+
...watchCommand,
4066
];
4167
});
4268
}

src/run.ts

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as path from 'path';
33
import * as findUp from 'find-up';
44
import { configFiles } from './vitest-config-files';
55

6+
const config = vscode.workspace.getConfiguration('vscode-vitest');
7+
68
function getCwd(testFile: string) {
79
const configFilePath = findUp.sync(configFiles, { cwd: testFile });
810

@@ -12,14 +14,16 @@ function getCwd(testFile: string) {
1214
return path.dirname(configFilePath);
1315
}
1416

15-
function buildVitestArgs({ caseName, casePath, sanitize = true, command = 'run' }: { caseName: string, casePath: string, sanitize?: boolean, command?: 'run' | 'watch' }) {
17+
function buildVitestArgs({ caseName, casePath, sanitize = true, testMode = 'run' }: { caseName: string, casePath: string, sanitize?: boolean, testMode?: 'run' | 'watch' }) {
1618
let sanitizedCasePath = casePath;
1719
if (sanitize) {
1820
sanitizedCasePath = JSON.stringify(casePath);
1921
caseName = JSON.stringify(caseName);
2022
}
2123

22-
const args = ['vitest', command, '--testNamePattern', caseName, sanitizedCasePath];
24+
const testCommand = config.get("testCommand")
25+
26+
const args = [testCommand, testMode, '--testNamePattern', caseName, sanitizedCasePath];
2327

2428
const rootDir = getCwd(casePath);
2529
if (rootDir) {
@@ -35,38 +39,25 @@ async function saveFile(filePath: string) {
3539
await vscode.workspace.textDocuments.find((doc) => doc.fileName === filePath)?.save();
3640
}
3741

38-
export async function runInTerminal(text: string, filename: string) {
42+
export async function executeInTerminal(text: string, filename: string, testMode: "run" | "watch" = "run") {
3943
let terminalAlreadyExists = true;
4044
if (!terminal || terminal.exitStatus) {
4145
terminalAlreadyExists = false;
4246
terminal?.dispose();
4347
terminal = vscode.window.createTerminal(`vscode-vitest-runner`);
4448
}
4549

46-
const vitestArgs = buildVitestArgs({ caseName: text, casePath: filename });
47-
const npxArgs = ['npx', ...vitestArgs];
48-
49-
if (terminalAlreadyExists) {
50-
// CTRL-C to stop the previous run
51-
terminal.sendText('\x03');
52-
}
50+
const preTest = (config.get("preTest") as string[]);
51+
const finalPreTest = preTest.length > 0 ? [`${preTest.join(" && ")} && `] : []
5352

54-
await saveFile(filename);
53+
const postTest = (config.get("postTest") as string[]);
54+
const finalPostTest = postTest.length > 0 ? [` && ${postTest.join(" && ")}`] : []
55+
56+
const packageManager = config.get("packageManager")
57+
const extraArguments = config.get("extraArguments")
5558

56-
terminal.sendText(npxArgs.join(' '), true);
57-
terminal.show();
58-
}
59-
60-
export async function watchInTerminal(text: string, filename: string) {
61-
let terminalAlreadyExists = true;
62-
if (!terminal || terminal.exitStatus) {
63-
terminalAlreadyExists = false;
64-
terminal?.dispose();
65-
terminal = vscode.window.createTerminal(`vscode-vitest-runner`);
66-
}
67-
68-
const vitestArgs = buildVitestArgs({ command: 'watch', caseName: text, casePath: filename });
69-
const npxArgs = ['npx', ...vitestArgs];
59+
const vitestArgs = buildVitestArgs({ caseName: text, casePath: filename, testMode });
60+
const commandToRun = [...finalPreTest, packageManager, ...vitestArgs, extraArguments, ...finalPostTest];
7061

7162
if (terminalAlreadyExists) {
7263
// CTRL-C to stop the previous run
@@ -75,20 +66,22 @@ export async function watchInTerminal(text: string, filename: string) {
7566

7667
await saveFile(filename);
7768

78-
terminal.sendText(npxArgs.join(' '), true);
69+
terminal.sendText(commandToRun.join(' '), true);
7970
terminal.show();
8071
}
8172

8273
function buildDebugConfig(
8374
casePath: string,
8475
text: string
8576
): vscode.DebugConfiguration {
77+
const packageManager = config.get("packageManager")
78+
8679
return {
8780
name: 'Debug vitest case',
8881
request: 'launch',
8982
runtimeArgs: buildVitestArgs({ caseName: text, casePath: casePath, sanitize: false }),
9083
cwd: getCwd(casePath) || path.dirname(casePath),
91-
runtimeExecutable: 'npx',
84+
runtimeExecutable: packageManager,
9285
skipFiles: ['<node_internals>/**'],
9386
type: 'pwa-node',
9487
console: 'integratedTerminal',

src/vscode.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as vscode from 'vscode';
2-
import { debugInTerminal, runInTerminal, watchInTerminal } from './run';
2+
import { debugInTerminal, executeInTerminal } from './run';
33

44
export class RunVitestCommand implements vscode.Command {
55
static ID = 'vitest.runTest';
@@ -37,14 +37,14 @@ export class DebugVitestCommand implements vscode.Command {
3737
vscode.commands.registerCommand(
3838
RunVitestCommand.ID,
3939
(text: string, filename: string) => {
40-
runInTerminal(text, filename)
40+
executeInTerminal(text, filename, "run")
4141
}
4242
);
4343

4444
vscode.commands.registerCommand(
4545
WatchVitestCommand.ID,
4646
(text: string, filename: string) => {
47-
watchInTerminal(text, filename);
47+
executeInTerminal(text, filename, "watch");
4848
}
4949
);
5050

0 commit comments

Comments
 (0)