This is a step-by-step description of how I currently (2025-09-18) generate Playwright test coverage in Angular projects without Webpack instrumentation.
In the past, I implemented coverage-istanbul-loader instrumentation with Webpack for UI E2E tests. In the end, I merge the coverage from the Karma tests with the coverage from the Playwright tests (nothing changes there).
My demo project is on GitHub: https://github.com/brabenetz/angular-playwright-coverage For the Git history, I tried to represent my steps as clearly as possible:
The project starts with "ng-new" and ends with a merged test coverage report (Karma & Playwright), which is published via GitHub Actions.
For further details, you can read the sources:
- Playwright: https://playwright.dev/docs/api/class-coverage (Unfortunately very superficial and theoretical without a working example project)
- Monocart Reporter: https://www.npmjs.com/package/monocart-reporter
- Example Project: https://github.com/edumserrano/playwright-adventures/tree/main/demos/code-coverage-with-monocart-reporter
Nothing to do here! As long as the app provides a source map (e.g., with ng serve
), the Chrome browser can generate the coverage.
In my projects, I use a small test-utils.ts implementation:
- Creating a screenshot and attaching it to the test report
- Comparing the current screenshot with a reference screenshot
(i) The comparison with a reference screenshot only works locally (mainly due to different OS fonts), so it's good to only run the comparison if the ENV flag 'SCREENSHOT_VALIDATION=true' is set.
Nevertheless, the screenshot comparison is useful for every major change or simply for library updates: Generate reference results before the update, and compare the current state with the old screenshots after the update.
I always add four scripts to the package.json that I use frequently:
- playwright:test-ui: Starts the Playwright UI.
- playwright:test-ui-with-screenshots: Starts the Playwright UI with screenshot comparison. In the Playwright UI, screenshot differences are displayed particularly clearly.
- playwright:test-all: Runs the Playwright tests on the console => This is also used by the CI.
- playwright:test-update: To update the reference screenshots => Should be run before every major change.
Then I need two more libraries:
monocart-reporter
The most important one to generate the coveragecross-env
: Optional, to set the environment variable used in test-utils.ts.
Karma already supports simple configurations for coverage:
- In karma.conf.js:
- The coverage should land in the directory
coverage/karma
. - In the reporters, you need to add 'json'. ('lcovonly' is just an example).
- The coverage should land in the directory
- In package.json: When running the tests, you need to add
--code-coverage=true
.
In the Playwright config, the most important thing is to add the monocart-reporter
.
For merging the coverage data with Karma coverage, you need the 'json' reporter.
The coverage should land in the directory coverage/playwright
.
In the tests, only the import needs to be swapped.
Interesting are the files tests/_shared/app-fixtures.ts
and tests/_shared/fixtures/v8-code-coverage.ts
that are used instead.
These two files come from the Monocart Reporter example project: https://github.com/edumserrano/playwright-adventures/blob/main/demos/code-coverage-with-monocart-reporter/tests/_shared/app-fixtures.ts
After Karma coverage (with npm run test
) and Playwright coverage (with npm run playwright:test-all
) have been generated, you should see the reports in the coverage folder:
Important are the JSON files 'coverage-karma.json' & 'coverage-playwright.json': These need to be merged together in the next step.
I divide the merge into three scripts:
- coverage-collect: Copies the two JSON files to the directory 'coverage/tmp'
- coverage-merge: Generates reports from the 'coverage/tmp' directory
- coverage-all: Calls coverage-collect && coverage-merge.
Then I need two more libraries:
cpr
: Platform-independent copy command. Supports recursive creation of directories.nyc
: Standard tool for creating coverage reports.
In the end, you want to see the Playwright reports in the CI after every build. Using GitHub Actions as an example, it would look like this: