Skip to content

Commit

Permalink
add cypress-recurse (#158)
Browse files Browse the repository at this point in the history
* working on cy.recurse example

* add recipe with conditional loading that might never go away
  • Loading branch information
bahmutov committed Apr 5, 2023
1 parent 9092027 commit c4e0aea
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ chai.use(require('chai-sorted'))
// https://www.chaijs.com/plugins/chai-each/
chai.use(require('chai-each'))

// make cy.recurse command available in every spec
// https://github.com/bahmutov/cypress-recurse
require('cypress-recurse/commands')

// a little utility command for taking the screenshot of the entire runner
// to be used only in the recipes that are NOT distributed as JavaScript specs
// since this requires the support file
Expand Down
52 changes: 52 additions & 0 deletions docs/recipes/conditional-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,58 @@ cy.get('#agreed')

Read the blog post [Conditional Commands For Cypress](https://glebbahmutov.com/blog/cypress-if/).

## cypress-recurse

You can implement advanced "run Cypress commands until this condition becomes true" flows using my plugin [cypress-recurse](https://github.com/bahmutov/cypress-recurse). For example, let's test a loading element that might never change its text. We still don't want to fail the test, but we want to log a message if so.

<!-- fiddle Loading element text -->

```html hide
<div id="loader">Loading ...</div>
<script>
if (Math.random() < 0.5) {
const delay = 500 + Math.round(3000 * Math.random())
setTimeout(() => {
document.getElementById('loader').innerText =
'Matches found: ' +
String(Math.random()).slice(2, 3) +
' took ' +
delay +
'ms'
}, delay)
}
</script>
```

We do not know if the loading finishes quickly or slowly. Thus we want to keep checking, and as soon as it goes away, we want to confirm that `Matches found: <number>` is shown. But if the loading text does not go away in 5 seconds, no big deal. We will just log a message.

```js
// cy.recurse comes from cypress-recurse plugin
cy.recurse(
() => cy.get('#loader').invoke('text'),
(text) => !text.includes('Loading'),
{
timeout: 5_000,
doNotFail: true,
yield: 'value',
log: 'Loaded',
// pause between attempts
delay: 500,
},
).then((text) => {
// conditional testing depending on the text
if (text.includes('Loading')) {
cy.log('Never finished loading')
} else {
cy.contains('#loader', /Matches found: \d/)
}
})
```

<!-- fiddle-end -->

Related blog post [Cypress Needs Soft Assertions](https://glebbahmutov.com/blog/cypress-soft-assertions/).

## More examples

- [Add / delete list item recipe](./add-list-item.md)
31 changes: 31 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"cypress-book": "1.5.0",
"cypress-map": "^1.14.0",
"cypress-markdown-preprocessor": "1.8.5",
"cypress-recurse": "^1.31.2",
"dependency-version-badge": "1.2.0",
"globby": "11.0.1",
"http-server": "0.12.3",
Expand Down

0 comments on commit c4e0aea

Please sign in to comment.