Skip to content

Commit

Permalink
add element is stable recipe
Browse files Browse the repository at this point in the history
  • Loading branch information
bahmutov committed Jan 18, 2024
1 parent c0b96c8 commit a1fc5b6
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ The Cypress API enables you to configure the behavior of how Cypress works inter
- [Conditional accept](./recipes/conditional-accept.md)
- Avoid "Mixing async and sync code" by controlling the [value the code yields](./recipes/yield-value.md)
- [use sanity assertions](./recipes/use-sanity-assertions.md)
- wait for the element [to be stable](./recipes/element-is-stable.md)

### Working with network

Expand Down
82 changes: 82 additions & 0 deletions docs/recipes/element-is-stable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Element Is Stable

Sometimes the element changes and we want to continue testing it once it stabilizes. Let's see how we can write such tests.

## The text does not change for N milliseconds

<!-- fiddle Element text does not change -->

In this example, I want to wait for the given element to stop changing its text N milliseconds.

```html
<div id="message">--</div>
<script>
setTimeout(() => {
document.getElementById('message').innerText = 'loading...'
}, 1000)
setTimeout(() => {
document.getElementById('message').innerText = 'Hello'
}, 2000)
</script>
```

```js hide
Cypress.Commands.addQuery('stableText', (ms = 1000) => {
const log = Cypress.log({
name: 'stableText',
message: `stable for ${ms}ms`,
})
console.log(log)
let started = null
let initialText = null
let initialAt = null
return ($el) => {
if (initialText === null) {
started = +new Date()
initialText = $el.text()
initialAt = started
console.log('started with text "%s"', initialText)
throw new Error('start')
}
if ($el.text() === initialText) {
const now = +new Date()
if (now - started > ms) {
console.log(
'after %dms stable text "%s"',
now - started,
initialText,
)
log.set('consoleProps', () => {
return {
time: now - started,
totalTime: now - initialAt,
result: initialText,
}
})
// yield the original element
// so we can chain more commands and assertions
return $el
} else {
throw new Error('waiting')
}
} else {
started = +new Date()
initialText = $el.text()
console.log('text changed to "%s"', initialText)
throw new Error('reset')
}
}
})
```

Get the element, wait for the text to be stable, and confirm the text is "Hello".

```js
cy.get('#message').stableText().should('have.text', 'Hello')
```

If we click on the command, we see the details in the DevTools console

![stableText command](./pics/stable-command.png)

<!-- fiddle-end -->
Binary file added docs/recipes/pics/stable-command.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a1fc5b6

Please sign in to comment.