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 CHANGED
@@ -1,4 +1,4 @@
1
- # find-cypress-specs [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-9.5.3-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-10.3.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,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
- const changedSpecs = specs.filter((file) => changedFiles.includes(file))
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.15.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": "9.5.3",
43
+ "cypress": "10.3.0",
44
44
  "execa-wrap": "^1.4.0",
45
45
  "prettier": "^2.5.1",
46
- "semantic-release": "19.0.2"
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 cypress config file and returns the relevant properties
13
+ * Reads the Cypress config JSON file (Cypress v9) and returns the relevant properties
12
14
  */
13
- function getConfig(filename = 'cypress.json') {
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 findCypressSpecs(opts = {}) {
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
- const specs = findCypressSpecs(options)
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.split('\n').filter(Boolean)
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.split('\n').filter(Boolean)
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
  }