Clone my repo https://github.com/tbossi/jest-bug-coverage-per-project
The repo contains two folders coverage-global and coverage-per-project. They are the same codebase with the exact same code but different Jest configuration.
In each of those folders run npm install then npm run test:coverage.
You can see the files included in coverage report are different depending on which of the two main folder you look at.
Additionally, enter in any of the packages (for example pack1) again in both folders coverage-global and coverage-per-project. Then run npm run test:coverage for that single package.
You can see the files included in these coverage report are different.
Expected behavior
The files without tests (pack1/file-without-test-1.js and pack2/file-without-test-2.js) should always be present in the coverage report if collectCoverageFrom is set on each package (both when running jest from root and from each individual package).
Actual behavior
The files without tests (pack1/file-without-test-1.js and pack2/file-without-test-2.js) are present in the coverage report only if:
coverage is configured globally (folder coverage-global) and jest --coverage is run from the root package.json
coverage is configured per project (folder coverage-per-project) and jest --coverage is run from each individual package of the workspace
Additional context
The project shown in the repo is organized using npm workspaces. There is a global jest configuration file (jest.config.js) that maps workspaces to jest's projects setting.
Individual packages each have their own configuration file, and share a common preset (jest.preset.js).
In this context, I want jest --coverage to also show me files without tests in each package. For this reason I used the collectCoverageFrom setting. However, this setting combined with the projects one seems to have unexpected results.
When setting collectCoverageFrom in the root jest.config.js (as it is in folder coverage-global) the files without tests are visible only when jest is run from the root, and not for a single package. That is kind of expected, since the jest.config.js of a single package has no setting collectCoverageFrom even in the preset.
What is not expected, is the other case (in folder coverage-per-project), where collectCoverageFrom is set in the preset and therefore shared by the jest.config.js of each single package. In this situation, which by the way is my go to configuration when dealing with jest combined with workspaces, if you run jest for a single package then the coverage of that package is correct. But if you run jest from the root then the files without coverage are missing.
Also note that having collectCoverageFrom in a preset is just to simplify the problem, but each individual package could also have its own collectCoverageFrom with different values.
I also did a bit of research on my own to find the root cause, and it seems to boil down to the method _addUntestedFiles of CoverageReporter. In the for loop there is a call to context.hasteFS.matchFilesWithGlob passing the global config, but there is no call to the same function passing the config of the current context under iteration.
Adding that missing piece seems to solve the issue, but I'm not sure if it's the right way to fix it.
Version
29.7.0
Steps to reproduce
coverage-global
andcoverage-per-project
. They are the same codebase with the exact same code but different Jest configuration.npm install
thennpm run test:coverage
.pack1
) again in both folderscoverage-global
andcoverage-per-project
. Then runnpm run test:coverage
for that single package.Expected behavior
The files without tests (
pack1/file-without-test-1.js
andpack2/file-without-test-2.js
) should always be present in the coverage report ifcollectCoverageFrom
is set on each package (both when running jest from root and from each individual package).Actual behavior
The files without tests (
pack1/file-without-test-1.js
andpack2/file-without-test-2.js
) are present in the coverage report only if:coverage-global
) andjest --coverage
is run from the rootpackage.json
coverage-per-project
) andjest --coverage
is run from each individual package of the workspaceAdditional context
The project shown in the repo is organized using npm workspaces. There is a global jest configuration file (
jest.config.js
) that maps workspaces to jest'sprojects
setting. Individual packages each have their own configuration file, and share a common preset (jest.preset.js
).In this context, I want
jest --coverage
to also show me files without tests in each package. For this reason I used thecollectCoverageFrom
setting. However, this setting combined with theprojects
one seems to have unexpected results.When setting
collectCoverageFrom
in the rootjest.config.js
(as it is in foldercoverage-global
) the files without tests are visible only when jest is run from the root, and not for a single package. That is kind of expected, since thejest.config.js
of a single package has no settingcollectCoverageFrom
even in the preset.What is not expected, is the other case (in folder
coverage-per-project
), wherecollectCoverageFrom
is set in the preset and therefore shared by thejest.config.js
of each single package. In this situation, which by the way is my go to configuration when dealing with jest combined with workspaces, if you run jest for a single package then the coverage of that package is correct. But if you run jest from the root then the files without coverage are missing. Also note that havingcollectCoverageFrom
in a preset is just to simplify the problem, but each individual package could also have its owncollectCoverageFrom
with different values.I also did a bit of research on my own to find the root cause, and it seems to boil down to the method
_addUntestedFiles
ofCoverageReporter
. In the for loop there is a call tocontext.hasteFS.matchFilesWithGlob
passing the global config, but there is no call to the same function passing the config of the current context under iteration. Adding that missing piece seems to solve the issue, but I'm not sure if it's the right way to fix it.Environment