find-cypress-specs 1.7.0 → 1.11.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 ![cypress version](https://img.shields.io/badge/cypress-9.2.0-brightgreen)
1
+ # find-cypress-specs [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-9.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
 
@@ -8,6 +8,15 @@ $ npx find-cypress-specs
8
8
  cypress/e2e/spec.js,cypress/e2e/featureA/user.js
9
9
  ```
10
10
 
11
+ ## against branch
12
+
13
+ By default, this module simply prints all spec filenames. You can add `--branch` parameter to only print the specs changed against that `origin/branch`.
14
+
15
+ ```bash
16
+ $ npx find-cypress-specs --branch main
17
+ # prints only some specs, the ones that have changed against the "origin/main"
18
+ ```
19
+
11
20
  ## Test names
12
21
 
13
22
  You can print each spec file with the suite and test names inside of it (found using [find-test-names](https://github.com/bahmutov/find-test-names))
@@ -31,6 +40,8 @@ found 2 specs (4 tests, 1 pending)
31
40
 
32
41
  Where the tags are listed inside `[ ... ]` (see [cypress-grep](https://github.com/cypress-io/cypress-grep)) and the [pending tests](https://glebbahmutov.com/blog/cypress-test-statuses/) are marked with `⊙` character.
33
42
 
43
+ You can print the results in JSON format using `--json` or `-j` option.
44
+
34
45
  ## Test tags
35
46
 
36
47
  You can count tags attached to the individual tests using `--tags` arguments
@@ -47,6 +58,8 @@ Tag Tests
47
58
 
48
59
  Each tag count includes the tests that use the tag directly, and the _effective_ tags applied from the parent suites.
49
60
 
61
+ You can print the results in JSON format using `--json` or `-j` option.
62
+
50
63
  ## Details
51
64
 
52
65
  Cypress uses the resolved [configuration values](https://on.cypress.io/configuration) to find the spec files to run. It searches the `integrationFolder` for all patterns listed in `testFiles` and removes any files matching the `ignoreTestFiles` patterns.
@@ -57,6 +70,10 @@ You can see how Cypress finds the specs using `DEBUG=cypress:cli,cypress:server:
57
70
 
58
71
  Run the utility with environment variable `DEBUG=find-cypress-specs` to see the verbose logs
59
72
 
73
+ ## Videos
74
+
75
+ - [Use Ava Snapshots And Execa-wrap To Write End-to-End Tests For CLI Utilities](https://youtu.be/rsw17RqP0G0)
76
+
60
77
  ## Small print
61
78
 
62
79
  Author: Gleb Bahmutov <gleb.bahmutov@gmail.com> © 2022
@@ -97,3 +114,6 @@ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
97
114
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
98
115
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
99
116
  OTHER DEALINGS IN THE SOFTWARE.
117
+
118
+ [renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg
119
+ [renovate-app]: https://renovateapp.com/
package/bin/find.js CHANGED
@@ -1,23 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const arg = require('arg')
4
- const { getSpecs } = require('../src')
4
+ const { getSpecs, collectResults, findChangedFiles } = require('../src')
5
5
  const fs = require('fs')
6
6
  const pluralize = require('pluralize')
7
7
  const { getTestNames, formatTestList, countTags } = require('find-test-names')
8
8
  const consoleTable = require('console.table')
9
+ const debug = require('debug')('find-cypress-specs')
9
10
 
10
11
  const args = arg({
11
12
  '--names': Boolean,
12
13
  '--tags': Boolean,
14
+ // output in JSON format
15
+ '--json': Boolean,
16
+ // find the specs that have changed against this Git branch
17
+ '--branch': String,
13
18
 
14
19
  // aliases
15
20
  '-n': '--names',
16
21
  '--name': '--names',
17
22
  '-t': '--tags',
18
23
  '--tag': '--tags',
24
+ '-j': '--json',
25
+ '-b': '--branch',
19
26
  })
20
27
 
28
+ debug('arguments %o', args)
29
+
21
30
  const specs = getSpecs()
22
31
  if (args['--names'] || args['--tags']) {
23
32
  if (!specs.length) {
@@ -30,7 +39,10 @@ if (args['--names'] || args['--tags']) {
30
39
  // counts the number of tests for each tag across all specs
31
40
  const tagTestCounts = {}
32
41
 
42
+ const jsonResults = {}
43
+
33
44
  specs.forEach((filename) => {
45
+ jsonResults[filename] = []
34
46
  const source = fs.readFileSync(filename, 'utf8')
35
47
  const result = getTestNames(source, true)
36
48
  // enable if need to debug the parsed test
@@ -41,18 +53,22 @@ if (args['--names'] || args['--tags']) {
41
53
  pendingTestsN += result.pendingTestCount
42
54
 
43
55
  if (args['--names']) {
44
- if (result.pendingTestCount) {
45
- console.log(
46
- '%s (%s, %d pending)',
47
- filename,
48
- testCount,
49
- result.pendingTestCount,
50
- )
56
+ if (args['--json']) {
57
+ collectResults(result.structure, jsonResults[filename])
51
58
  } else {
52
- console.log('%s (%s)', filename, testCount)
59
+ if (result.pendingTestCount) {
60
+ console.log(
61
+ '%s (%s, %d pending)',
62
+ filename,
63
+ testCount,
64
+ result.pendingTestCount,
65
+ )
66
+ } else {
67
+ console.log('%s (%s)', filename, testCount)
68
+ }
69
+ console.log(formatTestList(result.structure))
70
+ console.log('')
53
71
  }
54
- console.log(formatTestList(result.structure))
55
- console.log('')
56
72
  }
57
73
 
58
74
  if (args['--tags']) {
@@ -68,19 +84,23 @@ if (args['--names'] || args['--tags']) {
68
84
  })
69
85
 
70
86
  if (args['--names']) {
71
- if (pendingTestsN) {
72
- console.log(
73
- 'found %s (%s, %d pending)',
74
- pluralize('spec', specs.length, true),
75
- pluralize('test', testsN, true),
76
- pendingTestsN,
77
- )
87
+ if (args['--json']) {
88
+ console.log(JSON.stringify(jsonResults, null, 2))
78
89
  } else {
79
- console.log(
80
- 'found %s (%s)',
81
- pluralize('spec', specs.length, true),
82
- pluralize('test', testsN, true),
83
- )
90
+ if (pendingTestsN) {
91
+ console.log(
92
+ 'found %s (%s, %d pending)',
93
+ pluralize('spec', specs.length, true),
94
+ pluralize('test', testsN, true),
95
+ pendingTestsN,
96
+ )
97
+ } else {
98
+ console.log(
99
+ 'found %s (%s)',
100
+ pluralize('spec', specs.length, true),
101
+ pluralize('test', testsN, true),
102
+ )
103
+ }
84
104
  }
85
105
  console.log('')
86
106
  }
@@ -91,10 +111,22 @@ if (args['--names'] || args['--tags']) {
91
111
  // every entry is [tag, count], so compare the tags
92
112
  return a[0].localeCompare(b[0])
93
113
  })
94
- const table = consoleTable.getTable(['Tag', 'Tests'], sortedTagEntries)
95
- console.log(table)
114
+ if (args['--json']) {
115
+ // assemble a json object with the tag counts
116
+ const tagResults = Object.fromEntries(sortedTagEntries)
117
+ console.log(JSON.stringify(tagResults, null, 2))
118
+ } else {
119
+ const table = consoleTable.getTable(['Tag', 'Tests'], sortedTagEntries)
120
+ console.log(table)
121
+ }
96
122
  }
97
123
  }
124
+ } else if (args['--branch']) {
125
+ debug('determining specs changed against branch %s', args['--branch'])
126
+ const changedFiles = findChangedFiles(args['--branch'])
127
+ debug('changed files %o', changedFiles)
128
+ const changedSpecs = specs.filter((file) => changedFiles.includes(file))
129
+ console.log(changedSpecs.join(','))
98
130
  } else {
99
131
  console.log(specs.join(','))
100
132
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "find-cypress-specs",
3
- "version": "1.7.0",
3
+ "version": "1.11.0",
4
4
  "description": "Find Cypress spec files using the config settings",
5
5
  "main": "src",
6
6
  "files": [
@@ -16,7 +16,11 @@
16
16
  "demo": "DEBUG=find-cypress-specs node ./bin/find",
17
17
  "demo-names": "node ./bin/find --names",
18
18
  "demo-tags": "node ./bin/find --tags",
19
+ "demo-tags-json": "node ./bin/find --tags --json",
19
20
  "demo-names-and-tags": "node ./bin/find --names --tags",
21
+ "demo-names-and-tags-json": "node ./bin/find --names --tags --json",
22
+ "demo-names-json": "node ./bin/find --names --json",
23
+ "print-changed-specs": "node ./bin/find --branch main",
20
24
  "semantic-release": "semantic-release"
21
25
  },
22
26
  "repository": {
@@ -35,6 +39,7 @@
35
39
  "devDependencies": {
36
40
  "ava": "^4.0.0",
37
41
  "cypress": "^9.2.0",
42
+ "execa-wrap": "^1.4.0",
38
43
  "prettier": "^2.5.1",
39
44
  "semantic-release": "^18.0.1"
40
45
  },
@@ -45,6 +50,7 @@
45
50
  "find-test-names": "^1.14.1",
46
51
  "globby": "^11.0.4",
47
52
  "minimatch": "^3.0.4",
48
- "pluralize": "^8.0.0"
53
+ "pluralize": "^8.0.0",
54
+ "shelljs": "^0.8.5"
49
55
  }
50
56
  }
package/src/index.js CHANGED
@@ -3,6 +3,7 @@ const fs = require('fs')
3
3
  const path = require('path')
4
4
  const globby = require('globby')
5
5
  const minimatch = require('minimatch')
6
+ const shell = require('shelljs')
6
7
 
7
8
  const MINIMATCH_OPTIONS = { dot: true, matchBase: true }
8
9
 
@@ -72,9 +73,66 @@ function getSpecs() {
72
73
  return specs
73
74
  }
74
75
 
76
+ function collectResults(structure, results) {
77
+ structure.forEach((t) => {
78
+ const info = {
79
+ name: t.name,
80
+ type: t.type,
81
+ tags: t.tags,
82
+ }
83
+ if (t.pending) {
84
+ info.pending = t.pending
85
+ }
86
+ results.push(info)
87
+ if (t.type === 'suite') {
88
+ if (t.suites && t.suites.length) {
89
+ // skip empty nested suites
90
+ info.suites = []
91
+ collectResults(t.suites, info.suites)
92
+ }
93
+
94
+ if (t.tests && t.tests.length) {
95
+ // skip empty nested tests
96
+ info.tests = []
97
+ collectResults(t.tests, info.tests)
98
+ }
99
+ }
100
+ })
101
+ }
102
+
103
+ /**
104
+ * Finds files changed or added in the current branch when compared to the "origin/branch".
105
+ * Returns a list of filenames. If there are no files, returns an empty list.
106
+ * @param {string} branch The branch to compare against.
107
+ */
108
+ function findChangedFiles(branch) {
109
+ if (!branch) {
110
+ throw new Error('branch is required')
111
+ }
112
+
113
+ if (!shell.which('git')) {
114
+ shell.echo('Sorry, this script requires git')
115
+ return []
116
+ }
117
+
118
+ const result = shell.exec(
119
+ `git diff --name-only --diff-filter=AMR origin/${branch}`,
120
+ { silent: true },
121
+ )
122
+ if (result.code !== 0) {
123
+ debug('git diff failed with code %d', result.code)
124
+ return []
125
+ }
126
+
127
+ const filenames = result.stdout.split('\n').filter(Boolean)
128
+ return filenames
129
+ }
130
+
75
131
  module.exports = {
76
132
  getSpecs,
77
133
  // individual utilities
78
134
  getConfig,
79
135
  findCypressSpecs,
136
+ collectResults,
137
+ findChangedFiles,
80
138
  }