find-cypress-specs 1.15.1 → 1.18.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 +13 -1
- package/bin/find.js +23 -1
- package/package.json +7 -3
- package/src/index.js +89 -7
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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,8 @@ $ npx find-cypress-specs
|
|
|
8
8
|
cypress/e2e/spec.js,cypress/e2e/featureA/user.js
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Supports JS and TS specs
|
|
12
|
+
|
|
11
13
|
## against branch
|
|
12
14
|
|
|
13
15
|
By default, this module simply prints all spec filenames. You can add `--branch` parameter to only print the specs changed against that `origin/branch`.
|
|
@@ -45,6 +47,16 @@ $ npx find-cypress-specs --branch main --count
|
|
|
45
47
|
5
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
### filter by a tag
|
|
51
|
+
|
|
52
|
+
You can filter all changed specs and only report (and count) the specs that have changed AND include the given tag(s)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
$ npx find-cypress-specs --branch main --tagged @user,@preview
|
|
56
|
+
# prints only some specs, the ones that have changed against the "origin/main"
|
|
57
|
+
# and that have any tests or suites inside tagged "@user" or "@preview"
|
|
58
|
+
```
|
|
59
|
+
|
|
48
60
|
## Test names
|
|
49
61
|
|
|
50
62
|
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))
|
package/bin/find.js
CHANGED
|
@@ -115,7 +115,29 @@ if (args['--names'] || args['--tags']) {
|
|
|
115
115
|
debug('determining specs changed against branch %s', args['--branch'])
|
|
116
116
|
const changedFiles = findChangedFiles(args['--branch'], args['--parent'])
|
|
117
117
|
debug('changed files %o', changedFiles)
|
|
118
|
-
|
|
118
|
+
debug('comparing against the specs %o', specs)
|
|
119
|
+
let changedSpecs = specs.filter((file) => changedFiles.includes(file))
|
|
120
|
+
debug('changed specs %o', changedSpecs)
|
|
121
|
+
|
|
122
|
+
if (args['--tagged']) {
|
|
123
|
+
const splitTags = args['--tagged']
|
|
124
|
+
.split(',')
|
|
125
|
+
.map((s) => s.trim())
|
|
126
|
+
.filter(Boolean)
|
|
127
|
+
debug('filtering changed specs by tags %o', splitTags)
|
|
128
|
+
changedSpecs = changedSpecs.filter((file) => {
|
|
129
|
+
const source = fs.readFileSync(file, 'utf8')
|
|
130
|
+
const result = getTestNames(source, true)
|
|
131
|
+
const specTagCounts = countTags(result.structure)
|
|
132
|
+
const specHasTags = Object.keys(specTagCounts).some((tag) =>
|
|
133
|
+
splitTags.includes(tag),
|
|
134
|
+
)
|
|
135
|
+
debug('spec %s has tags? %o', file, specHasTags)
|
|
136
|
+
|
|
137
|
+
return specHasTags
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
119
141
|
if (args['--count']) {
|
|
120
142
|
console.log(changedSpecs.length)
|
|
121
143
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "find-cypress-specs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"description": "Find Cypress spec files using the config settings",
|
|
5
5
|
"main": "src",
|
|
6
6
|
"files": [
|
|
@@ -40,10 +40,13 @@
|
|
|
40
40
|
"homepage": "https://github.com/bahmutov/find-cypress-specs#readme",
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"ava": "^4.0.0",
|
|
43
|
-
"cypress": "
|
|
43
|
+
"cypress": "10.3.0",
|
|
44
44
|
"execa-wrap": "^1.4.0",
|
|
45
45
|
"prettier": "^2.5.1",
|
|
46
|
-
"
|
|
46
|
+
"really-need": "^1.9.2",
|
|
47
|
+
"semantic-release": "19.0.3",
|
|
48
|
+
"sinon": "^13.0.1",
|
|
49
|
+
"typescript": "^4.6.3"
|
|
47
50
|
},
|
|
48
51
|
"dependencies": {
|
|
49
52
|
"arg": "^5.0.1",
|
|
@@ -53,6 +56,7 @@
|
|
|
53
56
|
"globby": "^11.0.4",
|
|
54
57
|
"minimatch": "^3.0.4",
|
|
55
58
|
"pluralize": "^8.0.0",
|
|
59
|
+
"require-and-forget": "^1.0.0",
|
|
56
60
|
"shelljs": "^0.8.5"
|
|
57
61
|
}
|
|
58
62
|
}
|
package/src/index.js
CHANGED
|
@@ -4,13 +4,15 @@ const path = require('path')
|
|
|
4
4
|
const globby = require('globby')
|
|
5
5
|
const minimatch = require('minimatch')
|
|
6
6
|
const shell = require('shelljs')
|
|
7
|
+
const pluralize = require('pluralize')
|
|
8
|
+
const requireEveryTime = require('require-and-forget')
|
|
7
9
|
|
|
8
10
|
const MINIMATCH_OPTIONS = { dot: true, matchBase: true }
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
|
-
* Reads the
|
|
13
|
+
* Reads the Cypress config JSON file (Cypress v9) and returns the relevant properties
|
|
12
14
|
*/
|
|
13
|
-
function
|
|
15
|
+
function getConfigJson(filename = 'cypress.json') {
|
|
14
16
|
const s = fs.readFileSync(filename, 'utf8')
|
|
15
17
|
const config = JSON.parse(s)
|
|
16
18
|
const options = {
|
|
@@ -22,10 +24,24 @@ function getConfig(filename = 'cypress.json') {
|
|
|
22
24
|
return options
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
function
|
|
27
|
+
function getConfigJs(filename) {
|
|
28
|
+
const jsFile = path.join(process.cwd(), filename)
|
|
29
|
+
debug('loading Cypress config from %s', jsFile)
|
|
30
|
+
const definedConfig = requireEveryTime(jsFile)
|
|
31
|
+
return definedConfig
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getConfig(filename = './cypress.config.js') {
|
|
35
|
+
if (filename.endsWith('.json')) {
|
|
36
|
+
return getConfigJson(filename)
|
|
37
|
+
}
|
|
38
|
+
return getConfigJs(filename)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function findCypressSpecsV9(opts = {}) {
|
|
26
42
|
const defaults = {
|
|
27
43
|
integrationFolder: 'cypress/integration',
|
|
28
|
-
testFiles: '**/*.js',
|
|
44
|
+
testFiles: '**/*.{js,ts}',
|
|
29
45
|
ignoreTestFiles: [],
|
|
30
46
|
}
|
|
31
47
|
const options = {
|
|
@@ -67,9 +83,64 @@ function findCypressSpecs(opts = {}) {
|
|
|
67
83
|
return filtered.map((file) => path.join(options.integrationFolder, file))
|
|
68
84
|
}
|
|
69
85
|
|
|
86
|
+
function findCypressSpecsV10(opts = {}) {
|
|
87
|
+
if (!('e2e' in opts)) {
|
|
88
|
+
throw new Error('Missing e2e in the config object')
|
|
89
|
+
}
|
|
90
|
+
const defaults = {
|
|
91
|
+
specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
|
|
92
|
+
excludeSpecPattern: [],
|
|
93
|
+
}
|
|
94
|
+
const options = {
|
|
95
|
+
specPattern: opts.e2e.specPattern || defaults.specPattern,
|
|
96
|
+
excludeSpecPattern:
|
|
97
|
+
opts.e2e.excludeSpecPattern || defaults.excludeSpecPattern,
|
|
98
|
+
}
|
|
99
|
+
debug('options v10 %o', options)
|
|
100
|
+
|
|
101
|
+
const files = globby.sync(options.specPattern, {
|
|
102
|
+
sort: true,
|
|
103
|
+
ignore: options.excludeSpecPattern,
|
|
104
|
+
})
|
|
105
|
+
debug('found %d file(s) %o', files.length, files)
|
|
106
|
+
|
|
107
|
+
// go through the files again and eliminate files that match
|
|
108
|
+
// the ignore patterns
|
|
109
|
+
const ignorePatterns = [].concat(options.excludeSpecPattern)
|
|
110
|
+
debug('ignore patterns %o', ignorePatterns)
|
|
111
|
+
|
|
112
|
+
// a function which returns true if the file does NOT match
|
|
113
|
+
// all of our ignored patterns
|
|
114
|
+
const doesNotMatchAllIgnoredPatterns = (file) => {
|
|
115
|
+
// using {dot: true} here so that folders with a '.' in them are matched
|
|
116
|
+
// as regular characters without needing an '.' in the
|
|
117
|
+
// using {matchBase: true} here so that patterns without a globstar **
|
|
118
|
+
// match against the basename of the file
|
|
119
|
+
const MINIMATCH_OPTIONS = { dot: true, matchBase: true }
|
|
120
|
+
return ignorePatterns.every((pattern) => {
|
|
121
|
+
return !minimatch(file, pattern, MINIMATCH_OPTIONS)
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const filtered = files.filter(doesNotMatchAllIgnoredPatterns)
|
|
126
|
+
debug('filtered %d specs', filtered.length)
|
|
127
|
+
debug(filtered.join('\n'))
|
|
128
|
+
|
|
129
|
+
return filtered
|
|
130
|
+
}
|
|
131
|
+
|
|
70
132
|
function getSpecs() {
|
|
71
133
|
const options = getConfig()
|
|
72
|
-
|
|
134
|
+
return findCypressSpecs(options)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function findCypressSpecs(options) {
|
|
138
|
+
if (options.e2e) {
|
|
139
|
+
const specs = findCypressSpecsV10(options)
|
|
140
|
+
return specs
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const specs = findCypressSpecsV9(options)
|
|
73
144
|
return specs
|
|
74
145
|
}
|
|
75
146
|
|
|
@@ -139,7 +210,10 @@ function findChangedFiles(branch, useParent) {
|
|
|
139
210
|
return []
|
|
140
211
|
}
|
|
141
212
|
|
|
142
|
-
const filenames = result.stdout
|
|
213
|
+
const filenames = result.stdout
|
|
214
|
+
.split('\n')
|
|
215
|
+
.filter(Boolean)
|
|
216
|
+
.map((s) => s.trim())
|
|
143
217
|
return filenames
|
|
144
218
|
} else {
|
|
145
219
|
const command = `git diff --name-only --diff-filter=AMR origin/${branch}`
|
|
@@ -151,7 +225,15 @@ function findChangedFiles(branch, useParent) {
|
|
|
151
225
|
return []
|
|
152
226
|
}
|
|
153
227
|
|
|
154
|
-
const filenames = result.stdout
|
|
228
|
+
const filenames = result.stdout
|
|
229
|
+
.split('\n')
|
|
230
|
+
.filter(Boolean)
|
|
231
|
+
.map((s) => s.trim())
|
|
232
|
+
debug(
|
|
233
|
+
'found %d changed %s',
|
|
234
|
+
filenames.length,
|
|
235
|
+
pluralize('file', filenames.length),
|
|
236
|
+
)
|
|
155
237
|
return filenames
|
|
156
238
|
}
|
|
157
239
|
}
|