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 +21 -1
- package/bin/find.js +57 -25
- package/package.json +8 -2
- package/src/index.js +58 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# find-cypress-specs 
|
|
1
|
+
# find-cypress-specs [![renovate-app badge][renovate-badge]][renovate-app]  [](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 (
|
|
45
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
95
|
-
|
|
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.
|
|
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
|
}
|