vscode-jest
vscode-jest copied to clipboard
Using with Yarn workspaces
It's great that vscode-jest
now supports VS Code's Workspaces.
The problem is, the way VS Code Workspaces currently works is, one has to define each of the services in one's monorepo as a VS Code workspace.
It's a pretty tedious process for a project with 15+ services, and counting...
It's obviously not vscode-jest
's fault, but I think there might be a rather simple way to support running jest in the right monorepo service without having to configure VS Code for Workspaces.
There are two key aspects to vscode-jest
:
- Running all tests (+watch mode)
- Debugging a single test
1. Running all tests
For running all tests, I was able to run all my services tests, each with each own jest configuration, without having to add define each as workspace.
If you're using Yarn Workspaces (or Lerna), all I had to do is change the run configuration like so:
"jest.pathToJest": "yarn workspaces run test"
That's it!
Running this will make Yarn run yarn test
in each of its workspaces, running jest
all tests for services.
So I think that part just works out of the box.
Here's what needs tweaking to work -
2. Debugging a single test
OK so the idea here is similar, run the right Yarn workspace for the file we're trying to debug:
// launch.json
"configurations": [
{
"type": "node",
"name": "vscode-jest-tests",
"request": "launch",
"runtimeArgs": ["workspace","${command:extension.yarnWorkspaceName}", "run", "test"], // ${yarnWorkspaceName} is what we're missing
"args": [
"--runInBand"
],
"runtimeExecutable": "yarn" // ...along with this one,
// will run each Yarn workspace test script
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
}
]
My initial I thought was, maybe we can have vscode-jest
resolve that variable workspace via a command that would be added?
Would love your ideas here @connectdotz , wether that's an approach that's seems valid to you, or possibly help me think of alternatives? If you think this might be a good way to go I can have a look at implementing it in a PR.
@roni-frantchi I think this is pretty cool!
Are you able to get yarn workspaces run test
working with vscode-jest? I wasn't sure how yarn would handle these multiple test outputs... did you see the test status/errors properly reflected in the test files and problem view?
Regarding debug, I assume you are thinking to integrate with the debug codeLens, right? Adding a command variable is not a problem, but it requires to examine the invoking document, if the command can't take a dynamic argument, it might not work... you can look at how we inject debug arguments at runtime to see if it's useful for you.
If this worked, it would be pretty cool and can save a lot of manual config upfront...
Thanks @connectdotz !
Are you able to get yarn workspaces run test working with vscode-jest? I wasn't sure how yarn would handle these multiple test outputs... did you see the test status/errors properly reflected in the test files and problem view?
Yes I am:
However, I have noticed the tests won't rerun when I make changes. I wonder why is that 🤔
It does let me know it's done running all tests and is entering watch mode, but nothing happens when I make a change in say, the failing spec
:
Finished running all tests. Starting watch mode.
yarn run v1.19.0
$ jest --passWithNoTests --testLocationInResults --json --useStderr --outputFile /var/folders/7k/srsxvglx3hbgnvz4qvz1n1640000gn/T/jest_runner_env0.json --watch --no-color
`
No tests found related to files changed since last commit.
Regarding debug, I assume you are thinking to integrate with the debug codeLens, right?
Right. I am.
but it requires to examine the invoking document
Doesn't it anyway?. I mean, you have to send the in the filename you're trying to run to pass to jest
.
I'm assuming I should be able to get its path instead somehow and make my way upwards till I get to a package.json
, that's where I'll find my workspace name!
However, I have noticed the tests won't rerun when I make changes. I wonder why is that 🤔
The reason is that when triggered with --watch
, the child process blocks as yarn
won't run those in parallel.
I was able to make it work by using lerna
, like so -
lerna exec 'yarn test --passWithNoTests --watch' --parallel --no-bail
Thing is, running --parallel
works well in --watch
mode as it only triggers few tests at a time, but it makes vs code hang when in the initial run all tests phase, because there are two many processes happening at once.
Ideally, I wish I could customize the jest
command for the first command...
Still, that's great progress. I can disable the run all tests initial run and use lerna
as I have described here, and I get watch mode an Problems reported back to VS Code!
Next priority is to sort out the debug problem really.
I mean, you have to send the in the filename you're trying to run to pass to jest
precisely, it is done in resolveDebugConfiguration, i.e. you might need to change this method to append workspace info.
I was able to make it work by using lerna
hmmm... not sure this method would work with vscode-jest
, which appends --json --outputFile
to jest.pathToJest
at runtime so it can parse the test results and display accordingly.
precisely, it is done in resolveDebugConfiguration, i.e. you might need to change this method to append workspace info.
I'll check it out and update here as soon as I can. Thanks!
hmmm... not sure this method would work with vscode-jest, which appends --json --outputFile to jest.pathToJest at runtime so it can parse the test results and display accordingly.
🤔 it does seem to work... I was seeing the errors back on VSCode
I've managed to run debug with some help when running the process...
The issue I see here is that the runner will run the tests from the workspace root dir thus skipping any existing configuration specific for the project the file in context belongs to.
So, instead of running jest, I run a script and I send the ${fileDirname} to it so I can locate the proper configuration file and point to it and then I pass it on to jest...
{
"type": "node",
"name": "vscode-jest-tests",
"request": "launch",
"args": [
"--runInBand",
"--fileDirname", // ADDING THE CURRENT FILENAME DIR FOR THE SCRIPT
"${fileDirname}"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"program": "${workspaceFolder}/tools/vscode-jest-tests/index.js" // THE SCRIPT
}
tools/vscode-jest-tests/index.js (the script):
const Path = require('path');
const findUp = require('find-up'); // yarn add -D -W find-up
if (process.env.CI === 'vscode-jest-tests') {
const index = process.argv.indexOf('--fileDirname');
if (index > 0) {
const [command, fileDirname] = process.argv.splice(index, 2);
const match = findUp.sync(['jest.config.js', 'jest.config.json'], { cwd: fileDirname, type: 'file' });
// if match and it's not outside the workspace:
if (match && Path.dirname(match) >= process.cwd()) {
process.argv.push('--config', match)
}
}
}
require('jest-cli/bin/jest');
This is simple, find the nearest jest configuration and make jest use it...
Works perfectly for me (monorepo, learn, yarn workspaces (1.2x))
@roni-frantchi When I use lerna exec 'yarn test --passWithNoTests --watch' --parallel --no-bail
I get:
lerna Unknown arguments: testLocationInResults, json, useStderr, outputFile, watch, coverage, color, reporters
@tettoffensive here's what works for us:
yarn lerna -- run test --parallel --no-bail -- --passWithNoTests --runInBand
Where
# package.json
"scripts": {
"lerna": "lerna"
}
Quick workaround for anybody how just needs a quick fix:
Create a new launch.json config in each of your workspaces. ...Assuming your workspace is called my_workspace you need this launch.json config:
// launch.json
"configurations": [
{
"type": "node",
"name": "vscode-jest-tests",
"request": "launch",
"runtimeArgs": ["workspace","my_workspace", "run", "test"],
"args": [
"--runInBand"
],
"runtimeExecutable": "yarn",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
}
]
(based on comments above of course)
Is there any way to make vscode-jest codeLens work with in a yarn PnP workspaces monorepo?
I am using yarn berry workspaces and do not intend to use VS Code workspaces. How can I get this to work, or is it still not possible?
With lint-staged I have a config file in each workspace that sets up the command to use:
{
"*.{js,jsx,ts,tsx}": "yarn workspace some-workspace g:eslint --fix"
}
Maybe vscode-jest could look for a config file relative to where a single test is run that lets it know the jestCommandLine to use there?
Maybe vscode-jest could look for a config file relative to where a single test is run that lets it know the jestCommandLine to use there?
that is precisely what we use the vscode multiroot workspaces for. It really just requires a single . code-workspace
file listing the workspace name and location... I think I am open to auto-generate this file based on the workspaces definition in the package.json
. There might already be some extensions that exist to do just that, otherwise a good simple PR candidate... interested?
close as this can be done via monorepo setup tool