https://cypress.io logo
Cypress Component test coverage not working
# i-need-help
a
Hi, I'm working on a project based on: React (react-create-app) and Typescript, recently I've tried to introduce test coverage for component tests, it is worth mentioning that the same config works just fine for E2E tests and results correct coverage. I've tried using multiple approaches including: NYC (directly), the exact steps from the https://docs.cypress.io/guides/tooling/code-coverage and just default cypress config. I've also tried instrumenting the code in different ways before running the tests: for example ``npx nyc instrument --compact=false --all src --in-place`` and cra instrumentation I've introduced additional nyc config and fiddled with that but no luck. My cypress config and nyc config can be found within the attached screenshots Once component tests run the coverage looks as follows (command that I use to run the test: ``nyc cypress run --headless --component --browser chrome --config-file ./cypress.config.ts``
h
I don't have a perfect answer for you but I do have some thoughts - I have coverage for component tests working, but with Vite, so the webpack parts I'm not going to be much help with. My gut says that your main issue is probably that the application code isn't being instrumented properly. For code coverage to work, there are two sides: instrumentation of the application code, and collection of that instrumentation data by the Cypress plugin. Cypress is going to launch a dev server internally to serve the components for testing, so you whatever configuration that dev server needs to serve your application code with instrumentation needs to be specified in your cypress.config.js file. A quick way to test whether the instrumentation is working is: - Open Cypress component testing in Chrome with the code coverage plugin enabled (which you already seem to be doing) - Run one of your component spec files - Open the Chrome dev tools, go to the "Console" tab, and select "Your project ..." from the dropdown just below that (there are multiple different frames on the page, so need to be very sure you have the right one) - In the console, evaluate
window.__coverage__
. If instrumentation is being applied to your application code, this should evaluate to an object where the keys are absolute paths to files within application code, and the values are the coverage data about the individual files. If instrumentation is not being applied, this would evaluate to
undefined
Can you give that a check and let me know what you see?
The reason why the steps in the doc you linked from the Cypress docs aren't really working for you is that Cypress's relationship to the application server is totally different for e2e tests and component tests. That doc is written from the perspective of e2e tests. In e2e tests, you are responsible for launching the application server outside of Cypress, so basically anything goes and you can forget that Cypress exists while setting up instrumentation. For component tests though, you need to get the instructions on how to start the server with instrumentation defined such that instrumentation is applied when Cypress starts the dev server internally. That difference between you starting the dev server vs. Cypress starting the dev server on its own is crucial here.
a
@high-holiday-75305 Hi, thanks for responding. Yes it seems like the instrumentation might be the problem here. The ``window.__coverage__`` is indeed undefined when I run it in the open mode. I was trying to find anything in these articles to see how to properly instrument the build (which I suspect is the ``devServer`` object is responsible), but I seem to have the correct but the most basic setup as described here https://docs.cypress.io/guides/references/configuration#devServer I really appreciate the effort and time you put into this. Cheers. Let me know if you have any steps or articles that could help
I did try using ``"instrument:code": "npx nyc instrument --compact=false --all src --in-place"`` to instrument code manually and then serve it to the component test but it didn't seem to work
h
Yeah that wouldn't work. Cypress aside, you need to find a way to launch your dev server such that it serves instrumented code. In our project that uses CRA and Cypress for e2e tests, we use CRACO to inject babel-plugin-istanbul dependent on an environment variable. It's not pretty, but CRA doesn't really leave you with many options. Snippet from craco.config.js:
Copy code
const { when } = require('@craco/craco');

module.exports = () => ({
  babel: when(process.env.COVERAGE, () => ({
    plugins: ['istanbul'],
  })),
});
This makes it so that when you run, say,
COVERAGE=true craco start
babel will instrument the build.
Even if you don't plan on using craco long-term, it wouldn't be a bad idea to just do a quick and dirty check to see if that kind of thing would work for you
Would at least set you on the right track
You can check it outside of Cypress by just running
COVERAGE=true craco start
then loading your app in a regular web browser. You should be able to get at the
window.__coverage__
object that way. Then you can take the next step of seeing how you would set the Cypress
devServer
settings to make that happen in component tests.
iirc I got that solution from a combination of the Cypress code coverage docs recommending
babel-plugin-istanbul
(https://github.com/cypress-io/code-coverage#instrument-your-application) and CRACO's docs on configuring babel (https://craco.js.org/docs/configuration/babel/)
29 Views