find-cypress-specs 1.20.2 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # find-cypress-specs [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-12.0.1-brightgreen) [![ci](https://github.com/bahmutov/find-cypress-specs/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/bahmutov/find-cypress-specs/actions/workflows/ci.yml)
1
+ # find-cypress-specs [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-12.2.0-brightgreen) [![ci](https://github.com/bahmutov/find-cypress-specs/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/bahmutov/find-cypress-specs/actions/workflows/ci.yml)
2
2
 
3
3
  > Find Cypress spec files using the config settings
4
4
 
@@ -19,6 +19,20 @@ $ npx find-cypress-specs --branch main
19
19
  # prints only some specs, the ones that have changed against the "origin/main"
20
20
  ```
21
21
 
22
+ ## set GitHub Actions outputs
23
+
24
+ If you add `--set-gh-outputs` command line switch, then the number of changed specs and the comma-separated file list will be set as GH Actions outputs `changedSpecsN` and `changedSpecs`. See [pr.yml](./.github/workflows/pr.yml) for example
25
+
26
+ ```yml
27
+ - name: Print specs changed against the parent of this branch 🌳
28
+ # and set GitHub Actions output
29
+ id: step1
30
+ run: node ./bin/find --branch main --parent --set-gha-outputs
31
+
32
+ - name: Print set outputs
33
+ run: echo ${{ steps.step1.outputs.changedSpecsN }} ${{ steps.step1.outputs.changedSpecs }}
34
+ ```
35
+
22
36
  ## against the parent commit
23
37
 
24
38
  When dealing with a long-term branch, you do not want to see the changed files in the main branch. Instead, you want to only consider the specs changed in the _current_ branch all the way to its parent commit. You can pass the flag `--parent` to only pick the modified and added specs.
@@ -37,6 +51,16 @@ $ git fetch
37
51
  $ npx find-cypress-specs --branch main --parent
38
52
  ```
39
53
 
54
+ ## with traced import and require statements
55
+
56
+ Imagine you open a pull request and only change something in an `utils.js` file used by other specs. Which specs should you run? By default `--branch main --parent` would not find any changed specs, so no specs would execute, and you will have to run _all_ specs just to be safe. This program has a mode `--trace-imports <subfolder>` which uses [spec-change](https://github.com/bahmutov/spec-change) to inspect JS/TS files and find dependencies between them. Thus it can discover that when `utils.js` changes, the specs that `import './utils'` or `require('./utils')` should also be considered modified.
57
+
58
+ ```
59
+ $ npx find-cypress-specs --branch main --parent --trace-imports cypress
60
+ ```
61
+
62
+ **Note:** the argument is the subfolder name to limit the number of files to inspect when tracing the imports.
63
+
40
64
  ### number of changed files
41
65
 
42
66
  You can print just the number of changed specs
package/bin/find.js CHANGED
@@ -7,9 +7,12 @@ const { addCounts } = require('../src/count')
7
7
  const { stringAllInfo } = require('../src/print')
8
8
 
9
9
  const fs = require('fs')
10
+ const path = require('path')
10
11
  const { getTestNames, countTags } = require('find-test-names')
11
12
  const consoleTable = require('console.table')
12
13
  const debug = require('debug')('find-cypress-specs')
14
+ const { getDependsInFolder } = require('spec-change')
15
+ const core = require('@actions/core')
13
16
 
14
17
  const args = arg({
15
18
  '--names': Boolean,
@@ -25,7 +28,15 @@ const args = arg({
25
28
  '--tagged': String,
26
29
  // print only the "it.only" tests
27
30
  '--skipped': Boolean,
28
-
31
+ // when finding specs changed against a given parent of the branch
32
+ // also look at the import and require statements to trace dependencies
33
+ // and consider specs that import a changes source file changed to
34
+ // The value of this argument is the subfolder with Cypress tests, like "cypress"
35
+ '--trace-imports': String,
36
+ // when enabled, this code uses GitHub Actions Core package
37
+ // to set two named outputs, one for number of changed specs
38
+ // another for actual list of files
39
+ '--set-gha-outputs': Boolean,
29
40
  // aliases
30
41
  '-n': '--names',
31
42
  '--name': '--names',
@@ -33,6 +44,7 @@ const args = arg({
33
44
  '--tag': '--tags',
34
45
  '-j': '--json',
35
46
  '-b': '--branch',
47
+ '--deps': '--trace-imports',
36
48
  // Cypress test status (just like Mocha)
37
49
  // calls "it.skip" pending tests
38
50
  // https://glebbahmutov.com/blog/cypress-test-statuses/
@@ -124,11 +136,39 @@ if (args['--names'] || args['--tags']) {
124
136
  }
125
137
  } else if (args['--branch']) {
126
138
  debug('determining specs changed against branch %s', args['--branch'])
127
- const changedFiles = findChangedFiles(args['--branch'], args['--parent'])
139
+ let changedFiles = findChangedFiles(args['--branch'], args['--parent'])
128
140
  debug('changed files %o', changedFiles)
129
141
  debug('comparing against the specs %o', specs)
142
+ if (args['--trace-imports']) {
143
+ debug('tracing dependent changes in folder %s', args['--trace-imports'])
144
+ const absoluteFolder = path.join(process.cwd(), args['--trace-imports'])
145
+ const deps = getDependsInFolder(absoluteFolder)
146
+ debug('traced dependencies via imports and require')
147
+ debug(deps)
148
+ Object.entries(deps).forEach(([filename, fileDependents]) => {
149
+ const f = path.join(args['--trace-imports'], filename)
150
+ if (changedFiles.includes(f)) {
151
+ debug(
152
+ 'the source file %s has changed, including its dependents %o in the list of changed files',
153
+ f,
154
+ fileDependents,
155
+ )
156
+ fileDependents.forEach((name) => {
157
+ const nameInCypressFolder = path.join(args['--trace-imports'], name)
158
+ if (!changedFiles.includes(nameInCypressFolder)) {
159
+ changedFiles.push(nameInCypressFolder)
160
+ }
161
+ })
162
+ }
163
+ })
164
+ }
130
165
  let changedSpecs = specs.filter((file) => changedFiles.includes(file))
131
- debug('changed specs %o', changedSpecs)
166
+ debug('changed %d specs %o', changedSpecs.length, changedSpecs)
167
+ if (args['--set-gha-outputs']) {
168
+ debug('setting GitHub Actions outputs changedSpecsN and changedSpecs')
169
+ core.setOutput('changedSpecsN', changedSpecs.length)
170
+ core.setOutput('changedSpecs', changedSpecs.join(','))
171
+ }
132
172
 
133
173
  if (args['--tagged']) {
134
174
  const splitTags = args['--tagged']
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "find-cypress-specs",
3
- "version": "1.20.2",
3
+ "version": "1.22.0",
4
4
  "description": "Find Cypress spec files using the config settings",
5
5
  "main": "src",
6
6
  "files": [
@@ -24,7 +24,9 @@
24
24
  "demo-names-tagged": "node ./bin/find --names --tagged @user",
25
25
  "print-changed-specs": "node ./bin/find --branch main",
26
26
  "count-changed-specs": "node ./bin/find --branch main --count",
27
- "semantic-release": "semantic-release"
27
+ "semantic-release": "semantic-release",
28
+ "deps": "spec-change --folder . --mask 'cypress/**/*.{js,ts}'",
29
+ "deps-changed": "DEBUG=find-cypress-specs node ./bin/find --branch main --parent --trace-imports cypress"
28
30
  },
29
31
  "repository": {
30
32
  "type": "git",
@@ -41,7 +43,7 @@
41
43
  "homepage": "https://github.com/bahmutov/find-cypress-specs#readme",
42
44
  "devDependencies": {
43
45
  "ava": "^4.0.0",
44
- "cypress": "12.0.1",
46
+ "cypress": "12.2.0",
45
47
  "execa-wrap": "^1.4.0",
46
48
  "prettier": "^2.5.1",
47
49
  "really-need": "^1.9.2",
@@ -50,6 +52,7 @@
50
52
  "typescript": "^4.6.3"
51
53
  },
52
54
  "dependencies": {
55
+ "@actions/core": "^1.10.0",
53
56
  "arg": "^5.0.1",
54
57
  "console.table": "^0.10.0",
55
58
  "debug": "^4.3.3",
@@ -59,6 +62,7 @@
59
62
  "pluralize": "^8.0.0",
60
63
  "require-and-forget": "^1.0.0",
61
64
  "shelljs": "^0.8.5",
65
+ "spec-change": "^1.4.0",
62
66
  "ts-node": "^10.9.1"
63
67
  }
64
68
  }
package/src/index.js CHANGED
@@ -240,8 +240,8 @@ function findChangedFiles(branch, useParent) {
240
240
 
241
241
  const filenames = result.stdout
242
242
  .split('\n')
243
- .filter(Boolean)
244
243
  .map((s) => s.trim())
244
+ .filter(Boolean)
245
245
  return filenames
246
246
  } else {
247
247
  const command = `git diff --name-only --diff-filter=AMR origin/${branch}`
@@ -255,8 +255,8 @@ function findChangedFiles(branch, useParent) {
255
255
 
256
256
  const filenames = result.stdout
257
257
  .split('\n')
258
- .filter(Boolean)
259
258
  .map((s) => s.trim())
259
+ .filter(Boolean)
260
260
  debug(
261
261
  'found %d changed %s',
262
262
  filenames.length,