Debugging¶
Debugging never runs a command of its own: Jest Runner assembles a launch configuration and hands it to
vscode.debug.startDebugging. VS Code's JavaScript debugger (or the Bun extension) does the rest, including
source maps, breakpoints and the call stack. The code is src/debug/DebugConfigurationProvider.ts, called
through TestRunnerConfig.getDebugConfiguration(file, testName) from both the terminal path (TestRunner)
and the Test Explorer (DebugHandler).
The common base¶
createDebugConfigBase gives every framework:
{
"name": "Debug <Framework> Tests",
"type": "node", // "bun" for Bun
"request": "launch",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"cwd": "<getTestRunCwd(file)>" // only with changeDirectoryToWorkspaceRoot
}
followed by the user's jestrunner.*DebugOptions, which may override any key. The cwd is the same
directory a Test Explorer run would use, so Playwright and Deno find their config when debugging too.
Per framework¶
| Framework | program / runtimeExecutable |
args / runtimeArgs |
|---|---|---|
| Jest | program: the jest.js resolved from the working directory; else runtimeExecutable: npx with --no-install jest |
--runInBand + the adapter's args (<file regex> [-c] [-t]), unquoted |
| Vitest | program: vitest.mjs; else npx |
the adapter's args (run <file> [--config] [-t]) |
| Rstest | program: the rstest bin of @rstest/core; else npx |
the adapter's args |
| Playwright | program: the playwright bin of @playwright/test; else npx |
the adapter's args + --workers=1 |
| Node.js | program: the test file, runtimeExecutable from nodeTestCommand when set |
runtimeArgs: --test [--test-name-pattern <name>] + nodeTestRunOptions |
| Bun | type: bun, program: the test file |
runtimeArgs: test --inspect-wait [-t <name>] + bunRunOptions |
| Deno | runtimeExecutable: deno, port: 9229, attachSimplePort: 9229 |
runtimeArgs: test --inspect-brk --allow-all [--filter <name>] + denoRunOptions <file> |
The test name is passed raw (placeholders already replaced by (.*?)), never shell-quoted: the debugger
passes arguments as an array.
Custom commands¶
A jestrunner.*Command setting also shapes the debug session (getProgramCommandState /
resolveCommandExecution):
FOO=bar <cmd>โ the variables go intoenv.node [--options] <script> [args]โ<script>is theprogram, the options areruntimeArgs, the args stayargs; anodegiven with a path becomesruntimeExecutable. This makesnode --experimental-vm-modules ./node_modules/jest/bin/jest.jsdebuggable as written.- any other executable (
npx jest,yarn vitest,pnpm exec rstest) โruntimeExecutablewith the rest asruntimeArgs; the generated test arguments are appended.
For Jest only, a runtimeExecutable inside jestrunner.debugOptions takes over: program is dropped, the
user's runtimeArgs are kept and only the generated file and name arguments are appended (the Create React
App recipe relies on this).
Environment¶
mergeEnv layers, later wins: the ESM env (NODE_OPTIONS=--experimental-vm-modules for Jest with
enableESM), the env parsed from the command, the env of the *DebugOptions. An empty env is left out
so VS Code's defaults apply.
What is not done¶
- No reporter is injected and no result is read back: the Test Explorer shows the debugged test as finished without a state, the terminal shows the output.
- Only one test (or file) is debugged per request.
- Coverage is not collected in debug sessions.