@bahmutov/cy-grep 1.5.2 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -70,6 +70,7 @@ Watch the video [intro to cypress-grep plugin](https://www.youtube.com/watch?v=H
70
70
  - [Debugging in the browser](#debugging-in-the-browser)
71
71
  - [Examples](#examples)
72
72
  - [See also](#see-also)
73
+ - [cy-grep vs cypress-grep vs @cypress/grep](#cy-grep-vs-cypress-grep-vs-cypressgrep)
73
74
  - [Small Print](#small-print)
74
75
 
75
76
  <!-- /MarkdownTOC -->
@@ -288,6 +289,13 @@ If you can pass commas in the environment variable `grepTags`, you can use `,` t
288
289
  CYPRESS_grepTags=one,two npx cypress run
289
290
  ```
290
291
 
292
+ If a specific tag is not found in the specs, you will get a warning in the terminal:
293
+
294
+ ```
295
+ $ npx cypress run --env grepTags=@wrong-tag
296
+ cy-grep: could not find the tag "@wrong-tag" in any of the specs
297
+ ```
298
+
291
299
  ### Tags in the test config object
292
300
 
293
301
  Cypress tests can have their own [test config object](https://on.cypress.io/configuration#Test-Configuration), and when using this plugin you can put the test tags there, either as a single tag string or as an array of tags.
@@ -643,8 +651,25 @@ To see how to debug this plugin, watch the video [Debug cypress-grep Plugin](htt
643
651
  - [cypress-select-tests](https://github.com/bahmutov/cypress-select-tests)
644
652
  - [cypress-skip-test](https://github.com/cypress-io/cypress-skip-test)
645
653
 
654
+ ## cy-grep vs cypress-grep vs @cypress/grep
655
+
656
+ Many years ago I wrote a plugin `cypress-grep`. When I left the company Cypress, I transferred that MIT-licensed plugin to the Cypress GitHub organization. They moved it to the Cypress monorepo and renamed the NPM module `@cypress/grep`. I still use this grep plugin in some projects. When Cypress v10 was released, it broke some of the things in the plugin. Since I needed to fix it quickly and the monorepo setup is suboptimal, I forked the plugin back to my own repo `bahmutov/cy-grep` (this repo) and released under NPM name `@bahmutov/cy-grep`.
657
+
658
+ I plan to maintain the plugin `@bahmutov/cy-grep` in the future, since I rely on it myself **a lot**.
659
+
646
660
  ## Small Print
647
661
 
662
+ Author: Gleb Bahmutov &lt;gleb.bahmutov@gmail.com&gt; &copy; 2022
663
+
664
+ - [@bahmutov](https://twitter.com/bahmutov)
665
+ - [glebbahmutov.com](https://glebbahmutov.com)
666
+ - [blog](https://glebbahmutov.com/blog)
667
+ - [videos](https://www.youtube.com/glebbahmutov)
668
+ - [presentations](https://slides.com/bahmutov)
669
+ - [cypress.tips](https://cypress.tips)
670
+ - [Cypress Tips & Tricks Newsletter](https://cypresstips.substack.com/)
671
+ - [my Cypress courses](https://cypress.tips/courses)
672
+
648
673
  License: MIT - do anything with the code, but don't blame me if it does not work.
649
674
 
650
675
  Support: if you find any problems with this module, email / tweet /
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bahmutov/cy-grep",
3
- "version": "1.5.2",
3
+ "version": "1.7.0",
4
4
  "description": "Filter Cypress tests using title or tags",
5
5
  "main": "src/support.js",
6
6
  "scripts": {
package/src/plugin.js CHANGED
@@ -1,13 +1,12 @@
1
1
  // @ts-check
2
2
  const debug = require('debug')('cy-grep')
3
- const globby = require('globby')
4
3
 
5
4
  const { getSpecs } = require('find-cypress-specs')
6
5
  const { getTestNames, findEffectiveTestTags } = require('find-test-names')
7
6
  const fs = require('fs')
8
7
  const path = require('path')
9
8
  const { version } = require('../package.json')
10
- const { parseGrep, shouldTestRun } = require('./utils')
9
+ const { parseGrep, shouldTestRun, getMentionedTags } = require('./utils')
11
10
 
12
11
  const isCypressV9 = (config) => !('specPattern' in config)
13
12
 
@@ -107,8 +106,12 @@ function cypressGrepPlugin(config) {
107
106
  debug('%o', greppedSpecs)
108
107
  } else if (grepTags) {
109
108
  const parsedGrep = parseGrep(null, grepTags)
110
-
111
109
  debug('parsed grep tags %o', parsedGrep)
110
+ const mentionedTags = getMentionedTags(grepTags)
111
+ debug('user mentioned tags %o', mentionedTags)
112
+ // unique tags found across all specs we search
113
+ const foundTags = new Set()
114
+
112
115
  greppedSpecs = specFiles.filter((specFile) => {
113
116
  const text = fs.readFileSync(specFile, { encoding: 'utf8' })
114
117
 
@@ -121,6 +124,15 @@ function cypressGrepPlugin(config) {
121
124
  return Object.keys(testTags).some((testTitle) => {
122
125
  const effectiveTags = testTags[testTitle].effectiveTags
123
126
  const requiredTags = testTags[testTitle].requiredTags
127
+
128
+ // remember all found tags
129
+ effectiveTags.forEach((tag) => {
130
+ foundTags.add(tag)
131
+ })
132
+ requiredTags.forEach((tag) => {
133
+ foundTags.add(tag)
134
+ })
135
+
124
136
  return shouldTestRun(
125
137
  parsedGrep,
126
138
  undefined,
@@ -139,6 +151,17 @@ function cypressGrepPlugin(config) {
139
151
 
140
152
  debug('found grep tags "%s" in %d specs', grepTags, greppedSpecs.length)
141
153
  debug('%o', greppedSpecs)
154
+
155
+ debug('all found tags across the specs %o', ...foundTags)
156
+ debug('user mentioned tags %o', mentionedTags)
157
+ mentionedTags.forEach((tag) => {
158
+ if (!foundTags.has(tag)) {
159
+ console.warn(
160
+ 'cy-grep: could not find the tag "%s" in any of the specs',
161
+ tag,
162
+ )
163
+ }
164
+ })
142
165
  } else {
143
166
  // we have no tags to grep
144
167
  debug('will try eliminating specs with required tags')
@@ -191,10 +214,10 @@ function cypressGrepPlugin(config) {
191
214
  }
192
215
  } else {
193
216
  // hmm, we filtered out all specs, probably something is wrong
194
- console.warn('grep and/or grepTags has eliminated all specs')
195
- grep ? console.warn('grep: %s', grep) : null
196
- grepTags ? console.warn('grepTags: %s', grepTags) : null
197
- console.warn('Will leave all specs to run to filter at run-time')
217
+ console.warn('cy-grep: grep and/or grepTags has eliminated all specs')
218
+ grep ? console.warn('cy-grep: title: %s', grep) : null
219
+ grepTags ? console.warn('cy-grep: tags: %s', grepTags) : null
220
+ console.warn('cy-grep: Will leave all specs to run to filter at run-time')
198
221
  }
199
222
  }
200
223
 
package/src/utils.js CHANGED
@@ -37,13 +37,20 @@ function parseFullTitleGrep(s) {
37
37
 
38
38
  /**
39
39
  * Parses tags to grep for.
40
- * @param {string} s Tags string like "@tag1+@tag2"
40
+ * @param {string|string[]} s Tags string like "@tag1+@tag2", or array of tags
41
+ * @example
42
+ * parseTagsGrep('@tag1+@tag2')
43
+ * @example
44
+ * parseTagsGrep(['@tag1', '@tag2'])
41
45
  */
42
46
  function parseTagsGrep(s) {
43
47
  if (!s) {
44
48
  return []
45
49
  }
46
50
 
51
+ if (Array.isArray(s)) {
52
+ s = s.join(',')
53
+ }
47
54
  const explicitNotTags = []
48
55
 
49
56
  // top level split - using space or comma, each part is OR
@@ -95,6 +102,28 @@ function parseTagsGrep(s) {
95
102
  return ORS_filtered
96
103
  }
97
104
 
105
+ /**
106
+ * Given a user string of tags to find, with various connectors,
107
+ * returns the list of just the tags themselves. Could be used to
108
+ * quickly filter test specs or find misspelled tags.
109
+ * @returns {string[]} list of unique tags
110
+ */
111
+ function getMentionedTags(s) {
112
+ if (!s) {
113
+ return []
114
+ }
115
+ const spaced = s.replaceAll(/[+,]/g, ' ')
116
+ const tags = spaced
117
+ .split(' ')
118
+ .map((s) => s.trim())
119
+ .filter(Boolean)
120
+ // remove any "-" at the start of the tag
121
+ // because these are to signal inverted tags
122
+ .map((s) => (s.startsWith('-') ? s.slice(1) : s))
123
+ const uniqueTags = [...new Set(tags)]
124
+ return uniqueTags.sort()
125
+ }
126
+
98
127
  function shouldTestRunRequiredTags(parsedGrepTags, requiredTags = []) {
99
128
  if (!requiredTags.length) {
100
129
  // there are no tags to check
@@ -216,4 +245,5 @@ module.exports = {
216
245
  shouldTestRunTags,
217
246
  shouldTestRunRequiredTags,
218
247
  shouldTestRunTitle,
248
+ getMentionedTags,
219
249
  }