Skip to content

Commit 461417a

Browse files
authored
feat: use nyc NPM dependency directly without bin executable (cypress-io#162)
BREAKING CHANGE: `nyc` is no longer a peer dependency, instead this module calls its API directly. * use nyc as direct dependency * feat: use nyc directly as a module * skip binary install, close cypress-io#163 * hide CircleCI PR env variables * add typescript example * run ts-example server * update README file * use command * feat: move istanbul-lib-coverage from peer to prod dependencies * describe how to generate other reports * add link to Docker example, close cypress-io#164
1 parent f376548 commit 461417a

File tree

15 files changed

+684
-354
lines changed

15 files changed

+684
-354
lines changed

.circleci/config.yml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,29 @@ jobs:
1010
executor:
1111
name: node/default
1212
tag: '12'
13+
environment:
14+
# we don't need Cypress to check code style
15+
CYPRESS_INSTALL_BINARY: '0'
1316
steps:
1417
- checkout
1518
- node/with-cache:
1619
steps:
17-
- run: npm ci
20+
- run: CYPRESS_INSTALL_BINARY=0 npm ci
1821
- run: npm run format:check
1922

2023
publish:
2124
description: Publishes the new version of the plugin to NPM
2225
executor:
2326
name: node/default
2427
tag: '12'
28+
environment:
29+
# we don't need Cypress to do the release
30+
CYPRESS_INSTALL_BINARY: '0'
31+
# trick semantic-release into thinking this is NOT a pull request
32+
# (under the hood the module env-ci is used to check if this is a PR)
33+
CIRCLE_PR_NUMBER: ''
34+
CIRCLE_PULL_REQUEST: ''
35+
CI_PULL_REQUEST: ''
2536
steps:
2637
- checkout
2738
- node/with-cache:
@@ -135,14 +146,38 @@ workflows:
135146
command: npx nyc report --check-coverage true --lines 100
136147
working_directory: examples/before-all-visit
137148

149+
- cypress/run:
150+
attach-workspace: true
151+
name: example-ts-example
152+
requires:
153+
- cypress/install
154+
# there are no jobs to follow this one
155+
# so no need to save the workspace files (saves time)
156+
no-workspace: true
157+
working_directory: examples/ts-example
158+
start: npm start
159+
wait-on: 'http://localhost:1234'
160+
command: '../../node_modules/.bin/cypress run'
161+
post-steps:
162+
# store the created coverage report folder
163+
# you can click on it in the CircleCI UI
164+
# to see live static HTML site
165+
- store_artifacts:
166+
path: examples/ts-example/coverage
167+
- run:
168+
command: npm run coverage:check
169+
working_directory: examples/ts-example
170+
138171
- publish:
139172
filters:
140173
branches:
141174
only:
142175
- master
176+
- beta
143177
requires:
144178
- unit
145179
- frontend coverage
146180
- backend coverage
147181
- example-before-each-visit
148182
- example-before-all-visit
183+
- example-ts-example

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ dist/
99
cypress-coverage/
1010
examples/*/cypress/videos
1111
examples/*/cypress/screenshots
12+
yarn.lock

README.md

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ This plugin will slow down your tests. There will be more web application JavaSc
1111
npm install -D @cypress/code-coverage
1212
```
1313

14-
and its peer dependencies
15-
16-
```shell
17-
npm install -D nyc istanbul-lib-coverage cypress
18-
```
14+
Note: this plugin assumes `cypress` is a peer dependency already installed in your project.
1915

2016
Add to your `cypress/support/index.js` file
2117

@@ -57,6 +53,40 @@ If you have instrumented your application's code and see the `window.__coverage_
5753

5854
That should be it!
5955

56+
## Reports
57+
58+
The `coverage` folder has results in several formats, and the coverage raw data is stored in `.nyc_output` folder. You can see the coverage numbers yourself. This plugin has `nyc` as a dependency, so it should be available right away. Here are common examples:
59+
60+
```shell
61+
# see just the coverage summary
62+
$ npx nyc report --reporter=text-summary
63+
# see just the coverage file by file
64+
$ npx nyc report --reporter=text
65+
# save the HTML report again
66+
$ npx nyc report --reporter=lcov
67+
```
68+
69+
It is useful to enforce [minimum coverage](https://github.com/istanbuljs/nyc#common-configuration-options) numbers. For example:
70+
71+
```shell
72+
$ npx nyc report --check-coverage --lines 80
73+
----------|---------|----------|---------|---------|-------------------
74+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
75+
----------|---------|----------|---------|---------|-------------------
76+
All files | 100 | 100 | 100 | 100 |
77+
main.js | 100 | 100 | 100 | 100 |
78+
----------|---------|----------|---------|---------|-------------------
79+
80+
$ npx nyc report --check-coverage --lines 101
81+
----------|---------|----------|---------|---------|-------------------
82+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
83+
----------|---------|----------|---------|---------|-------------------
84+
All files | 100 | 100 | 100 | 100 |
85+
main.js | 100 | 100 | 100 | 100 |
86+
----------|---------|----------|---------|---------|-------------------
87+
ERROR: Coverage for lines (100%) does not meet global threshold (101%)
88+
```
89+
6090
## Instrument unit tests
6191

6292
If you test your application code directly from `specs` you might want to instrument them and combine unit test code coverage with any end-to-end code coverage (from iframe). You can easily instrument spec files using [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul) for example.
@@ -181,17 +211,6 @@ You can specify custom coverage reporter(s) to use. For example to output text s
181211

182212
**Tip:** find list of reporters [here](https://istanbul.js.org/docs/advanced/alternative-reporters/)
183213

184-
## NYC
185-
186-
This module tries to find the `nyc` tool using [bin-up][bin-up], so it would be found in the current `node_modules/.bin` or folders up the parent chain
187-
188-
```text
189-
node_modules/.bin/
190-
../node_modules/.bin/
191-
../../node_modules/.bin/
192-
etc
193-
```
194-
195214
## Custom NYC command
196215

197216
Sometimes NYC tool might be installed in a different folder not in the current or parent folder, or you might want to customize the report command. In that case, put the custom command into `package.json` in the current folder and this plugin will automatically use it.
@@ -204,42 +223,14 @@ Sometimes NYC tool might be installed in a different folder not in the current o
204223
}
205224
```
206225

207-
See examples below.
208-
209-
### Install NYC on the fly
210-
211-
The simplest solution: let `npx` install `nyc` on the fly
212-
213-
```json
214-
{
215-
"scripts": {
216-
"coverage:report": "npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --reporter=clover --reporter=json"
217-
}
218-
}
219-
```
220-
221-
### Find NYC in a parent folder
222-
223-
If you have [bin-up][bin-up] installed globally, you can use it to find `nyc` installed somewhere in the higher folder.
224-
225-
```json
226-
{
227-
"scripts": {
228-
"coverage:report": "bin-up nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --reporter=clover --reporter=json"
229-
}
230-
}
231-
```
232-
233-
**Tip:** finding and running pre-installed tool is always faster than installing it again and again.
234-
235226
## TypeScript users
236227

237228
TypeScript source files are NOT included in the code coverage report by default, even if they are properly instrumented. In order to tell `nyc` to include TS files in the report, you need to:
238229

239230
1. Add these dev dependencies that let Istanbul work with TypeScript
240231

241232
```shell
242-
npm i -D @istanbuljs/nyc-config-typescript source-map-support ts-node
233+
npm i -D @istanbuljs/nyc-config-typescript source-map-support
243234
```
244235

245236
2. In `package.json` use the following `nyc` configuration object
@@ -253,6 +244,8 @@ npm i -D @istanbuljs/nyc-config-typescript source-map-support ts-node
253244
}
254245
```
255246

247+
See [examples/ts-example](examples/ts-example)
248+
256249
## Exclude code
257250

258251
You can exclude parts of the code or entire files from the code coverage report. See [Istanbul guide](https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md). Common cases:
@@ -337,6 +330,7 @@ npm run dev:no:coverage
337330

338331
- [examples/before-each-visit](examples/before-each-visit) checks if code coverage correctly keeps track of code when doing `cy.visit` before each test
339332
- [examples/before-all-visit](examples/before-all-visit) checks if code coverage works when `cy.visit` is made once in the `before` hook
333+
- [examples/ts-example](examples/ts-example) uses Babel + Parcel to instrument and serve TypeScript file
340334

341335
### External examples
342336

@@ -353,6 +347,7 @@ npm run dev:no:coverage
353347
- [bahmutov/next-and-cypress-example](https://github.com/bahmutov/next-and-cypress-example) shows how to get backend and frontend coverage for a [Next.js](https://nextjs.org) project. Uses [middleware/nextjs.js](middleware/nextjs.js).
354348
- [akoidan/vue-webpack-typescript](https://github.com/akoidan/vue-webpack-typescript) Pure webpack config with vue + typescript with codecov reports. This setup uses babel-loader with TS checker as a separate thread.
355349
- [bahmutov/code-coverage-subfolder-example](https://github.com/bahmutov/code-coverage-subfolder-example) shows how to instrument `app` folder using `nyc instrument` as a separate step before running E2E tests
350+
- [bahmutov/docker-with-cypress-included-code-coverage-example](https://github.com/bahmutov/docker-with-cypress-included-code-coverage-example) runs tests inside pre-installed Cypress using [cypress/included:x.y.z](https://github.com/cypress-io/cypress-docker-images/tree/master/included) Docker image and reports code coverage.
356351

357352
## Debugging
358353

@@ -392,4 +387,3 @@ This project is licensed under the terms of the [MIT license](LICENSE.md).
392387

393388
[renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg
394389
[renovate-app]: https://renovateapp.com/
395-
[bin-up]: https://github.com/bahmutov/bin-up

examples/ts-example/.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"plugins": ["istanbul"]
3+
}

examples/ts-example/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# example: ts-example
2+
3+
Code coverage for TypeScript code. See [nyc TS support](https://github.com/istanbuljs/nyc#typescript-projects) docs too.
4+
5+
Code is instrumented on the fly using [.babelrc](.babelrc) and Parcel to run it.
6+
7+
## Use
8+
9+
- start the server and Cypress with `npm run dev`
10+
- run the Cypress tests
11+
- look at the generated reports in folder `coverage`

examples/ts-example/cypress.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"baseUrl": "http://localhost:1234",
3+
"fixturesFolder": false
4+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference types="cypress" />
2+
describe('ts-example', () => {
3+
beforeEach(() => {
4+
cy.visit('/')
5+
})
6+
7+
it('calls add', () => {
8+
cy.window()
9+
.invoke('add', 2, 3)
10+
.should('equal', 5)
11+
})
12+
13+
it('calls sub', () => {
14+
cy.window()
15+
.invoke('sub', 2, 3)
16+
.should('equal', -1)
17+
})
18+
19+
it('calls abs twice', () => {
20+
cy.window()
21+
.invoke('abs', 2)
22+
.should('equal', 2)
23+
24+
cy.window()
25+
.invoke('abs', -5)
26+
.should('equal', 5)
27+
})
28+
})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = (on, config) => {
2+
on('task', require('../../../../task'))
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import '../../../../support'

examples/ts-example/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<body>
2+
Page body
3+
<script src="main.ts"></script>
4+
</body>

examples/ts-example/main.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const add = (a: number, b: number) => {
2+
return a + b
3+
}
4+
5+
const sub = (a: number, b: number) => {
6+
return a - b
7+
}
8+
9+
function abs(x: number) {
10+
if (x >= 0) {
11+
return x
12+
} else {
13+
return -x
14+
}
15+
}
16+
17+
// @ts-ignore
18+
window.add = add
19+
// @ts-ignore
20+
window.sub = sub
21+
// @ts-ignore
22+
window.abs = abs

examples/ts-example/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "example-before-each-visit",
3+
"description": "Getting code coverage when cy.visit is used in beforeEach hook",
4+
"devDependencies": {
5+
"@babel/core": "7.9.0"
6+
},
7+
"nyc": {
8+
"extends": "@istanbuljs/nyc-config-typescript",
9+
"all": true
10+
},
11+
"scripts": {
12+
"start": "../../node_modules/.bin/parcel serve index.html",
13+
"build": "../../node_modules/.bin/parcel build index.html",
14+
"serve": "../../node_modules/.bin/serve dist",
15+
"cy:open": "../../node_modules/.bin/cypress open",
16+
"coverage": "../../node_modules/.bin/nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov",
17+
"coverage:check": "../../node_modules/.bin/nyc report --check-coverage true --lines 100",
18+
"dev": "../../node_modules/.bin/start-test 1234 cy:open",
19+
"dev:dist": "CYPRESS_baseUrl=http://localhost:5000 ../../node_modules/.bin/start-test serve 5000 cy:open"
20+
}
21+
}

0 commit comments

Comments
 (0)