@bahmutov/cy-grep 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -19,13 +19,13 @@ All other tests will be marked pending, see why in the [Cypress test statuses](h
19
19
 
20
20
  If you have multiple spec files, all specs will be loaded, and every test will be filtered the same way, since the grep is run-time operation and cannot eliminate the spec files without loading them. If you want to run only specific tests, use the built-in [--spec](https://on.cypress.io/command-line#cypress-run-spec-lt-spec-gt) CLI argument.
21
21
 
22
- Watch the video [intro to cypress-grep plugin](https://www.youtube.com/watch?v=HS-Px-Sghd8)
22
+ Watch the video [intro to cypress-grep plugin](https://www.youtube.com/watch?v=HS-Px-Sghd8) and study my 🎓 Cypress course [Cypress Plugins](https://cypress.tips/courses/cypress-plugins).
23
23
 
24
24
  Table of Contents
25
25
 
26
26
  <!-- MarkdownTOC autolink="true" -->
27
27
 
28
- - [@bahmutov/cy-grep](#bahmutovcy-grep)
28
+ - [@bahmutov/cy-grep ](#bahmutovcy-grep-)
29
29
  - [Install](#install)
30
30
  - [Support file](#support-file)
31
31
  - [Config file](#config-file)
@@ -49,6 +49,7 @@ Table of Contents
49
49
  - [TypeScript support](#typescript-support)
50
50
  - [General advice](#general-advice)
51
51
  - [DevTools console](#devtools-console)
52
+ - [grepFailed](#grepfailed)
52
53
  - [Debugging](#debugging)
53
54
  - [Log messages](#log-messages)
54
55
  - [Debugging in the plugin](#debugging-in-the-plugin)
@@ -80,7 +81,8 @@ yarn add -D @bahmutov/cy-grep
80
81
  **required:** load this module from the [support file](https://on.cypress.io/writing-and-organizing-tests#Support-file) or at the top of the spec file if not using the support file. You import the registration function and then call it:
81
82
 
82
83
  ```js
83
- // cypress/support/index.js
84
+ // cypress/support/e2e.js
85
+
84
86
  // load and register the grep feature using "require" function
85
87
  // https://github.com/bahmutov/cy-grep
86
88
  const registerCypressGrep = require('@bahmutov/cy-grep')
@@ -89,7 +91,7 @@ registerCypressGrep()
89
91
  // if you want to use the "import" keyword
90
92
  // note: `./index.d.ts` currently extends the global Cypress types and
91
93
  // does not define `registerCypressGrep` so the import path is directly
92
- // pointed to the `support.js` file
94
+ // pointed to the support file
93
95
  import registerCypressGrep from '@bahmutov/cy-grep/src/support'
94
96
  registerCypressGrep()
95
97
 
@@ -110,13 +112,14 @@ registerCypressGrep()
110
112
  e2e: {
111
113
  setupNodeEvents(on, config) {
112
114
  require('@bahmutov/cy-grep/src/plugin')(config);
115
+ // IMPORTANT: return the config object
113
116
  return config;
114
- },
117
+ },
115
118
  }
116
119
  }
117
120
  ```
118
121
 
119
- Installing the plugin via `setupNodeEvents()` is required to enable the [grepFilterSpecs](#grepfilterspecs) feature.
122
+ Installing the plugin via `setupNodeEvents()` is required to enable the [grepFilterSpecs](#pre-filter-specs-grepfilterspecs) feature.
120
123
 
121
124
  ## Usage Overview
122
125
 
@@ -352,9 +355,12 @@ $ npx cypress run --env grepTags=@smoke,grepFilterSpecs=true
352
355
  **Tip:** you can set this environment variable in the [config file](https://docs.cypress.io/guides/references/configuration) file to enable it by default and skip using the environment variable:
353
356
 
354
357
  ```js
358
+ // config file
355
359
  {
356
- "env": {
357
- "grepFilterSpecs": true
360
+ "e2e": {
361
+ "env": {
362
+ "grepFilterSpecs": true
363
+ }
358
364
  }
359
365
  }
360
366
  ```
@@ -494,20 +500,33 @@ Cypress.grep('hello', '@smoke', 10)
494
500
 
495
501
  - to remove the grep strings enter `Cypress.grep()`
496
502
 
503
+ ### grepFailed
504
+
505
+ Once the tests finish, you can run just the failed tests from DevTools console
506
+
507
+ ```text
508
+ > Cypress.grepFailed()
509
+ ```
510
+
511
+ **Tip:** use `Cypress.grep()` to reset and run all the tests
512
+
513
+ 📝 Read the blog post [Run Just The Failed Tests In Cypress](https://glebbahmutov.com/blog/run-failed-tests/).
514
+
497
515
  ## Debugging
498
516
 
499
- When debugging a problem, first make sure you are using the expected version of this plugin, as some features might be only available in the [later releases](https://github.com/cypress-io/cypress-grep/releases).
517
+ When debugging a problem, first make sure you are using the expected version of this plugin, as some features might be only available in the [later releases](https://github.com/bahmutov/cy-grep/releases).
500
518
 
501
519
  ```
502
- # get the cypress-grep version using NPM
503
- $ npm ls cypress-grep
520
+ # get the plugin's version using NPM
521
+ $ npm ls @bahmutov/cy-grep
504
522
  ...
505
- └── cypress-grep@2.10.1
506
- # get the cypress-grep version using Yarn
507
- $ yarn why cypress-grep
523
+ └── @bahmutov/cy-grep@1.1.0
524
+
525
+ # get the plugin's version using Yarn
526
+ $ yarn why @bahmutov/cy-grep
508
527
  ...
509
- => Found "cypress-grep@2.10.1"
510
- info Has been hoisted to "cypress-grep"
528
+ => Found "@bahmutov/cy-grep@1.1.0"
529
+ info Has been hoisted to "@bahmutov/cy-grep"
511
530
  info This module exists because it's specified in "devDependencies".
512
531
  ...
513
532
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bahmutov/cy-grep",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Filter Cypress tests using title or tags",
5
5
  "main": "src/support.js",
6
6
  "scripts": {
package/src/index.d.ts CHANGED
@@ -26,6 +26,20 @@ declare namespace Cypress {
26
26
  }
27
27
 
28
28
  interface Cypress {
29
+ /**
30
+ * Runs only the tests that contain the given "grep" string
31
+ * in the title, or have specific tags.
32
+ * @param grep Part of the test title
33
+ * @param tags Tags to filter tests by
34
+ * @param burn Number of times to repeat each test
35
+ */
29
36
  grep?: (grep?: string, tags?: string, burn?: string) => void
37
+ /**
38
+ * Take the current test statuses and run only the failed tests.
39
+ * Run this static method from the DevTools console.
40
+ * Tip: use Cypress.grep() to reset and run all tests.
41
+ * @example Cypress.grepFailed()
42
+ */
43
+ grepFailed?: () => void
30
44
  }
31
45
  }
package/src/plugin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const debug = require('debug')('cypress-grep')
2
2
  const globby = require('globby')
3
- const { getTestNames } = require('find-test-names')
3
+ const { getTestNames, findEffectiveTestTags } = require('find-test-names')
4
4
  const fs = require('fs')
5
5
  const { version } = require('../package.json')
6
6
  const { parseGrep, shouldTestRun } = require('./utils')
@@ -9,7 +9,7 @@ const { parseGrep, shouldTestRun } = require('./utils')
9
9
  * Prints the cypress-grep environment values if any.
10
10
  * @param {Cypress.ConfigOptions} config
11
11
  */
12
- function cypressGrepPlugin (config) {
12
+ function cypressGrepPlugin(config) {
13
13
  if (!config || !config.env) {
14
14
  return config
15
15
  }
@@ -117,15 +117,14 @@ function cypressGrepPlugin (config) {
117
117
  const text = fs.readFileSync(specFile, { encoding: 'utf8' })
118
118
 
119
119
  try {
120
- const testInfo = getTestNames(text)
121
-
120
+ const testTags = findEffectiveTestTags(text)
121
+ // we get back a single object with keys being full test titles
122
+ // and the values being arrays of effective test tags
122
123
  debug('spec file %s', specFile)
123
- debug('test info: %o', testInfo.tests)
124
-
125
- return testInfo.tests.some((info) => {
126
- const shouldRun = shouldTestRun(parsedGrep, null, info.tags)
127
-
128
- return shouldRun
124
+ debug('effective test tags %o', testTags)
125
+ return Object.keys(testTags).some((testTitle) => {
126
+ const effectiveTags = testTags[testTitle]
127
+ return shouldTestRun(parsedGrep, null, effectiveTags)
129
128
  })
130
129
  } catch (err) {
131
130
  console.error('Could not determine test names in file: %s', specFile)
package/src/support.js CHANGED
@@ -253,4 +253,38 @@ if (!Cypress.grep) {
253
253
  }
254
254
  }
255
255
 
256
+ if (!Cypress.grepFailed) {
257
+ Cypress.grepFailed = function () {
258
+ // @ts-ignore
259
+ let root = Cypress.state('runnable')
260
+ while (root.parent) {
261
+ root = root.parent
262
+ }
263
+ const failedTestTitles = []
264
+
265
+ function findFailedTests(suite) {
266
+ suite.tests.forEach((test) => {
267
+ if (test.state === 'failed') {
268
+ // TODO use the full test title
269
+ failedTestTitles.push(test.title)
270
+ }
271
+ })
272
+ suite.suites.forEach((suite) => {
273
+ findFailedTests(suite)
274
+ })
275
+ }
276
+ findFailedTests(root)
277
+
278
+ if (!failedTestTitles.length) {
279
+ console.log('No failed tests found')
280
+ } else {
281
+ console.log('running only the failed tests')
282
+ console.log(failedTestTitles)
283
+ const grepTitles = failedTestTitles.join(';')
284
+ // @ts-ignore
285
+ Cypress.grep(grepTitles)
286
+ }
287
+ }
288
+ }
289
+
256
290
  module.exports = cypressGrep