@bahmutov/cy-grep 1.9.17 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +28 -1
- package/package.json +8 -6
- package/src/file-utils.js +35 -0
- package/src/plugin.js +18 -0
- package/src/support.js +24 -0
package/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# @bahmutov/cy-grep ![cypress version](https://img.shields.io/badge/cypress-
|
1
|
+
# @bahmutov/cy-grep ![cypress version](https://img.shields.io/badge/cypress-13.11.0-brightgreen)
|
2
2
|
|
3
3
|
> Filter tests using substring or tag
|
4
4
|
|
@@ -55,10 +55,12 @@ Watch the video [intro to cypress-grep plugin](https://www.youtube.com/watch?v=H
|
|
55
55
|
- [NOT tags](#not-tags)
|
56
56
|
- [Tags in test suites](#tags-in-test-suites)
|
57
57
|
- [Grep untagged tests](#grep-untagged-tests)
|
58
|
+
- [Access the tags in the test](#access-the-tags-in-the-test)
|
58
59
|
- [Pre-filter specs (grepFilterSpecs)](#pre-filter-specs-grepfilterspecs)
|
59
60
|
- [Omit filtered tests (grepOmitFiltered)](#omit-filtered-tests-grepomitfiltered)
|
60
61
|
- [Disable grep](#disable-grep)
|
61
62
|
- [Burn (repeat) tests](#burn-repeat-tests)
|
63
|
+
- [grepExtraSpecs](#grepextraspecs)
|
62
64
|
- [Required tags](#required-tags)
|
63
65
|
- [Negative grep](#negative-grep)
|
64
66
|
- [TypeScript support](#typescript-support)
|
@@ -407,6 +409,22 @@ Sometimes you want to run only the tests without any tags, and these tests are i
|
|
407
409
|
$ npx cypress run --env grepUntagged=true
|
408
410
|
```
|
409
411
|
|
412
|
+
### Access the tags in the test
|
413
|
+
|
414
|
+
You can check the current test's tags (including its parent suites) by checking the `Cypress.env('testTags')` list
|
415
|
+
|
416
|
+
```js
|
417
|
+
describe('parent', { tags: ['@p1', '@p2'] }, () => {
|
418
|
+
describe('child', { tags: '@c1' }, () => {
|
419
|
+
it('has all effective test tags', { tags: '@t1' }, () => {
|
420
|
+
const tags = Cypress.env('testTags')
|
421
|
+
// includes tags from the parent suites and the test itself
|
422
|
+
expect(tags, 'tags').to.deep.equal(['@p1', '@p2', '@c1', '@t1'])
|
423
|
+
})
|
424
|
+
})
|
425
|
+
})
|
426
|
+
```
|
427
|
+
|
410
428
|
## Pre-filter specs (grepFilterSpecs)
|
411
429
|
|
412
430
|
By default, when using `grep` and `grepTags` all specs are executed, and inside each the filters are applied. This can be very wasteful, if only a few specs contain the `grep` in the test titles. Thus when doing the positive `grep`, you can pre-filter specs using the `grepFilterSpecs=true` parameter.
|
@@ -488,6 +506,14 @@ You can pass the number of times to run the tests via environment name `burn` or
|
|
488
506
|
|
489
507
|
If you do not specify the "grep" or "grep tags" option, the "burn" will repeat _every_ test.
|
490
508
|
|
509
|
+
## grepExtraSpecs
|
510
|
+
|
511
|
+
Sometimes you want to pre-filter specs using tags AND then run extra specs without any filtering. You can set the list of specs / patterns using the `grepExtraSpecs` env string. For example, to filter specs using tag `@a` plus run the spec "b.cy.js":
|
512
|
+
|
513
|
+
```
|
514
|
+
npx cypress run --env grepTags=@a,grepExtraSpecs=cypress/e2e/b.cy.js
|
515
|
+
```
|
516
|
+
|
491
517
|
## Required tags
|
492
518
|
|
493
519
|
Sometimes you might want to run a test or a suite of tests _only_ if a specific tag or tags are present. For example, you might have a test that cleans the data. This test is meant to run nightly, not on every test run. Thus you can set a `required` tag:
|
@@ -708,6 +734,7 @@ To see how to debug this plugin, watch the video [Debug cypress-grep Plugin](htt
|
|
708
734
|
- [cypress-select-tests](https://github.com/bahmutov/cypress-select-tests)
|
709
735
|
- [cypress-skip-test](https://github.com/cypress-io/cypress-skip-test)
|
710
736
|
- 📝 Read the blog post [Cypress GitHub Actions Slash Command](https://glebbahmutov.com/blog/cypress-slash-command/)
|
737
|
+
- plugin [dennisbergevin/cypress-plugin-last-failed](https://github.com/dennisbergevin/cypress-plugin-last-failed)
|
711
738
|
|
712
739
|
## cy-grep vs cypress-grep vs @cypress/grep
|
713
740
|
|
package/package.json
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@bahmutov/cy-grep",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.11.0",
|
4
4
|
"description": "Filter Cypress tests using title or tags",
|
5
5
|
"main": "src/support.js",
|
6
6
|
"scripts": {
|
7
7
|
"cy:run": "cypress run --config specPattern='**/unit.js'",
|
8
8
|
"cy:open": "cypress open --e2e -b electron --config specPattern='**/unit.js'",
|
9
|
+
"cy:open:tags": "cypress open --e2e -b electron --config specPattern='cypress/e2e/test-tags/*.cy.js'",
|
9
10
|
"badges": "npx -p dependency-version-badge update-badge cypress",
|
10
11
|
"semantic-release": "semantic-release",
|
11
12
|
"deps": "npm audit --report --omit dev",
|
@@ -15,16 +16,17 @@
|
|
15
16
|
"cypress-plugin-config": "^1.2.0",
|
16
17
|
"debug": "^4.3.2",
|
17
18
|
"find-cypress-specs": "^1.35.1",
|
18
|
-
"find-test-names": "1.28.
|
19
|
+
"find-test-names": "1.28.21",
|
20
|
+
"globby": "^11.1.0"
|
19
21
|
},
|
20
22
|
"devDependencies": {
|
21
|
-
"cypress": "13.
|
23
|
+
"cypress": "13.11.0",
|
22
24
|
"cypress-each": "^1.11.0",
|
23
25
|
"cypress-expect": "^3.1.0",
|
24
|
-
"prettier": "^
|
25
|
-
"semantic-release": "^
|
26
|
+
"prettier": "^3.0.0",
|
27
|
+
"semantic-release": "^24.0.0",
|
26
28
|
"stop-only": "^3.3.1",
|
27
|
-
"typescript": "^
|
29
|
+
"typescript": "^5.0.0"
|
28
30
|
},
|
29
31
|
"peerDependencies": {
|
30
32
|
"cypress": ">=8"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
// @ts-check
|
2
|
+
|
3
|
+
const globby = require('globby')
|
4
|
+
const debug = require('debug')('cy-grep')
|
5
|
+
|
6
|
+
function resolveFilePattern(pattern) {
|
7
|
+
if (pattern.includes('*')) {
|
8
|
+
const globbyOptions = {
|
9
|
+
sort: true,
|
10
|
+
objectMode: false,
|
11
|
+
}
|
12
|
+
debug('globby options "%s" %o', pattern, globbyOptions)
|
13
|
+
|
14
|
+
const files = globby.sync(pattern, globbyOptions)
|
15
|
+
debug('found %d file(s) %o', files.length, files)
|
16
|
+
return files
|
17
|
+
} else {
|
18
|
+
return pattern
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
function resolveFilePatterns(patterns) {
|
23
|
+
const extraSpecsList = patterns
|
24
|
+
.split(',')
|
25
|
+
.map((s) => s.trim())
|
26
|
+
.filter(Boolean)
|
27
|
+
debug('extra specs list %o', extraSpecsList)
|
28
|
+
|
29
|
+
return extraSpecsList.flatMap(resolveFilePattern)
|
30
|
+
}
|
31
|
+
|
32
|
+
module.exports = {
|
33
|
+
resolveFilePattern,
|
34
|
+
resolveFilePatterns,
|
35
|
+
}
|
package/src/plugin.js
CHANGED
@@ -7,6 +7,7 @@ const fs = require('fs')
|
|
7
7
|
const path = require('path')
|
8
8
|
const { version } = require('../package.json')
|
9
9
|
const { parseGrep, shouldTestRun, getMentionedTags } = require('./utils')
|
10
|
+
const { resolveFilePatterns } = require('./file-utils')
|
10
11
|
const minimatch = require('minimatch')
|
11
12
|
|
12
13
|
const MINIMATCH_OPTIONS = { dot: true, matchBase: true }
|
@@ -224,6 +225,23 @@ function cypressGrepPlugin(config) {
|
|
224
225
|
})
|
225
226
|
}
|
226
227
|
|
228
|
+
const extraSpecsPattern = config.env.grepExtraSpecs
|
229
|
+
if (extraSpecsPattern) {
|
230
|
+
debug('processing the extra specs pattern "%s"', extraSpecsPattern)
|
231
|
+
const extraSpecs = resolveFilePatterns(extraSpecsPattern)
|
232
|
+
// update the config env object with resolved extra specs
|
233
|
+
const resolvedExtraSpecs = []
|
234
|
+
extraSpecs.forEach((specFilename) => {
|
235
|
+
if (!greppedSpecs.includes(specFilename)) {
|
236
|
+
greppedSpecs.push(specFilename)
|
237
|
+
resolvedExtraSpecs.push(specFilename)
|
238
|
+
debug('added extra spec %s', specFilename)
|
239
|
+
}
|
240
|
+
})
|
241
|
+
|
242
|
+
config.env.grepExtraSpecs = resolvedExtraSpecs
|
243
|
+
}
|
244
|
+
|
227
245
|
if (greppedSpecs.length) {
|
228
246
|
if (isCypressV9(config)) {
|
229
247
|
debug('setting selected %d specs (< v10)', greppedSpecs.length)
|
package/src/support.js
CHANGED
@@ -16,6 +16,22 @@ debug.log = console.info.bind(console)
|
|
16
16
|
// preserve the real "it" function
|
17
17
|
const _it = it
|
18
18
|
const _describe = describe
|
19
|
+
// keeps all collected test tags by the full test title
|
20
|
+
// includes both the test tags and the suite tags
|
21
|
+
// and the required test tags
|
22
|
+
const testTree = {}
|
23
|
+
|
24
|
+
beforeEach(() => {
|
25
|
+
// set the test tags for the current test
|
26
|
+
const testTitle = Cypress.currentTest.titlePath.join(' ')
|
27
|
+
const info = testTree[testTitle]
|
28
|
+
if (info) {
|
29
|
+
const allTags = info.effectiveTestTags.concat(info.requiredTestTags)
|
30
|
+
Cypress.env('testTags', allTags)
|
31
|
+
} else {
|
32
|
+
Cypress.env('testTags', null)
|
33
|
+
}
|
34
|
+
})
|
19
35
|
|
20
36
|
/**
|
21
37
|
* Wraps the "it" and "describe" functions that support tags.
|
@@ -42,6 +58,8 @@ function registerCyGrep() {
|
|
42
58
|
getPluginConfigValue('grepUntagged') ||
|
43
59
|
getPluginConfigValue('grep-untagged')
|
44
60
|
|
61
|
+
const extraSpecs = getPluginConfigValue('grepExtraSpecs')
|
62
|
+
|
45
63
|
// if (!grep && !grepTags && !burnSpecified && !grepUntagged) {
|
46
64
|
// nothing to do, the user has no specified the "grep" string
|
47
65
|
// debug('Nothing to grep, version %s', version)
|
@@ -109,6 +127,11 @@ function registerCyGrep() {
|
|
109
127
|
configRequiredTags = [configRequiredTags]
|
110
128
|
}
|
111
129
|
|
130
|
+
if (extraSpecs?.length && extraSpecs.includes(Cypress.spec.relative)) {
|
131
|
+
// the user wants to run all tests in this extra spec file
|
132
|
+
return _it(name, options, callback)
|
133
|
+
}
|
134
|
+
|
112
135
|
const nameToGrep = suiteStack
|
113
136
|
.map((item) => item.name)
|
114
137
|
.concat(name)
|
@@ -122,6 +145,7 @@ function registerCyGrep() {
|
|
122
145
|
.concat(configRequiredTags)
|
123
146
|
.filter(Boolean)
|
124
147
|
debug({ nameToGrep, effectiveTestTags, requiredTestTags })
|
148
|
+
testTree[nameToGrep] = { effectiveTestTags, requiredTestTags }
|
125
149
|
|
126
150
|
const shouldRun = shouldTestRun(
|
127
151
|
parsedGrep,
|