Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/NoriSte/cypress-wait-until

Add the Cypress waiting power to virtually everything πŸŽ‰
https://github.com/NoriSte/cypress-wait-until

cypress cypress-plugin javascript wait

Last synced: about 1 month ago
JSON representation

Add the Cypress waiting power to virtually everything πŸŽ‰

Awesome Lists containing this project

README

        

# cypress-wait-until

Add the Cypress waiting power to virtually everything πŸŽ‰

[![Build Status](https://travis-ci.com/NoriSte/cypress-wait-until.svg?branch=master)](https://travis-ci.com/NoriSte/cypress-wait-until)
[![Build Cron](https://img.shields.io/badge/build%20cron-weekly-44cc11.svg)](https://travis-ci.com/NoriSte/cypress-wait-until)
[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/)
[![Cypress Dashboard](https://img.shields.io/static/v1?label=Cypress&message=Dashboard&color=00BF88)](https://dashboard.cypress.io/#/projects/g21npg/runs)
[![NPM downloads](https://img.shields.io/npm/dm/cypress-wait-until?color=CB3836)](https://www.npmjs.com/package/cypress-wait-until)


[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNoriSte%2Fcypress-wait-until.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FNoriSte%2Fcypress-wait-until?ref=badge_shield) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://badges.frapsoft.com/typescript/love/typescript.svg?v=101)](https://github.com/ellerbrock/typescript-badges/)
[![Open Source
Saturday](https://img.shields.io/badge/%E2%9D%A4%EF%B8%8F-open%20source%20saturday-F64060.svg)](https://www.meetup.com/it-IT/Open-Source-Saturday-Milano/)

Use this plugin to wait for everything not expected by [Cypress wait](https://docs.cypress.io/api/commands/wait.html#Syntax).

## Installation

```bash
npm i -D cypress-wait-until
# or
yarn add -D cypress-wait-until
```

## Usage

`cypress-wait-until` extends Cypress' `cy` command.

Add this line to your project's `cypress/support/commands.js`:

```javascript
import 'cypress-wait-until';
```

Then, in your test, you can write

```javascript
// wait until a cookie is set
cy.waitUntil(() => cy.getCookie('token').then(cookie => Boolean(cookie && cookie.value)));

// wait until a global variable has an expected value
cy.waitUntil(() => cy.window().then(win => win.foo === "bar"));

// sync function works too!
cy.waitUntil(() => true);

// with all the available options
cy.waitUntil(() => cy.window().then(win => win.foo === "bar"), {
errorMsg: 'This is a custom error message', // overrides the default error message
timeout: 2000, // waits up to 2000 ms, default to 5000
interval: 500 // performs the check every 500 ms, default to 200
});
```

If you return a truthy value, it becomes the subject for the next command. So you can assert about
it too

```javascript
// wait until the Recaptcha token will be added to the dedicated hidden input field...
cy.waitUntil(() => cy.get("input[type=hidden]#recaptchatoken").then($el => $el.val()))
// ... then, check that it's valid string asserting about it
.then(token => expect(token).to.be.a("string").to.have.length.within(1, 1000));
```

The `waitUntil` command could be chained to other commands too. As an example, the following codes are equivalent
```javascript
cy.waitUntil(() => cy.getCookie('token').then(cookie => cookie.value === ''));
// is equivalent to
cy.wrap('')
.waitUntil((subject) => cy.getCookie('token').then(cookie => cookie.value === subject));
```
**Please note**
- do not expect that the previous command is retried. Only what's inside the `checkFunction` body is retried
```javascript
cy.getCookie('token') // will not be retried
.waitUntil(cookie => cookie.value === '');
```
- you cannot put assertions inside `checkFunction`. There is no way to avoid a test failure [if an assertion throws an error](https://stackoverflow.com/questions/56743695/error-handling-using-the-catch-block-in-cypress). You must manually check what the assertions would check for you. The most common case is checking that an element exists or not, instead of using `cy.get('#id').should('exist')` you should check that `Cypress.$('#id').length` is greater than `0`. [Here](https://github.com/NoriSte/cypress-wait-until/issues/75#issuecomment-572685623) you can find a deeper explanation

- nested `cy.waitUntil` calls don't respect `timeout` options. `timeout` and `interval` are converted to a number of retries. If the parent `cy.waitUntil` retries 10 times and the nested one 15 times, then the latter will be run 150 times before giving up, resulting in an extremely long wait. See [the discussion](https://github.com/NoriSte/cypress-wait-until/issues/241) for more info

### TypeScript

If you use TypeScript you can define the `checkFunction` returning type too. Take a look at the [plugin.spec.ts](./cypress/types/plugin.spec.ts) file to read about the `cy.waitUntil` signature.

#### IMPORTANT:
1. Remember to add `cypress-wait-until` to the `cypress/tsconfig.json` file

```javascript
{
"compilerOptions": {
"types": ["cypress", "cypress-wait-until"]
}
}
```

2. If you are encountering "cy.waitUntil is not a function" or "cy.waitUntil is undefined", you might need to specify the support file in your `cypress.json` for the import to work correctly:

```javascript
{
"supportFile": "cypress/support/commands.ts"
}

```

## Arguments

- checkFunction

A function that must return a truthy value when the wait is over.

- options:Object (optional)

Pass in an options object to change the default behavior of `cy.waitUntil()`.

| Option | Type | Default | Description |
| -------------------- | ---------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `errorMsg` | `string` \| `function` | `"Timed out retrying"` | The error message to write. If it's a function, it will receive the last result and the options passed to `cy.waitUntil` |
| `timeout` | `number` | `5000` | Time to wait for the `checkFunction` to return a truthy value before throwing an error. |
| `interval` | `number` | `200` | Time to wait between the `checkFunction` invocations. |
| `description` | `string` | `"waitUntil"` | The name logged into the Cypress Test Runner. |
| `logger` | `function` | `Cypress.log` | A custom logger in place of the default [Cypress.log](https://docs.cypress.io/api/cypress-api/cypress-log.html). It's useful just for debugging purposes. |
| `log` | `boolean` | `true` | Enable/disable logging. |
| `customMessage` | `string` | `undefined` | String logged after the `options.description`. |
| `verbose` | `boolean` | `false` | If every single check result must be logged. |
| `customCheckMessage` | `string` | `undefined` | Like `customMessage`, but used for every single check. Useless if `verbose` is not set to `true`. |

Log options are a lot, take a look at the next screenshot to understand how they are printed

![Plugin log options](assets/log-explained.jpg)




## Could cy.waitUntil avoid failing the test?

No. `cy.waitUntil` waits for something that must happen, otherwise the test will fail. [Cypress enforces to avoid conditional testing](https://docs.cypress.io/guides/core-concepts/conditional-testing.html) and the plugin agrees with that.

There are cases where conditional testing makes sense but if `cy.waitUntil` would have this capability everyone will use it to create conditional tests, treating the Cypress featureβ€”because avoiding conditional testing is a featureβ€”as "a bug".

If you need conditional testing you could write your own recursive promise check function (take a look [here](https://stackoverflow.com/questions/54883861/how-can-i-wait-for-each-element-in-a-list-to-update-to-a-certain-text-using-cypr/55363629#55363629) and [here](https://stackoverflow.com/questions/54732818/how-do-i-wait-until-a-cookie-is-set/54743229#54743229) where it is explained how to do that) where you manage your case. After all, `cy.waitUntil` is just a recursive promise manager 😊

## Why did we write it?

A lot of StackOverflow users had some difficulties in implementing a recursive promise with Cypress
just to repeatedly check for something to happen (see two of the various questions about the topic: [How can i wait for each element in a list to update to a certain
text?](https://stackoverflow.com/questions/54883861/how-can-i-wait-for-each-element-in-a-list-to-update-to-a-certain-text-using-cypr/55363629#55363629)
And [How do I wait until a cookie is
set?](https://stackoverflow.com/questions/54732818/how-do-i-wait-until-a-cookie-is-set/54743229#54743229)).


This plugin is dedicated to them ❀️

## Open Source Saturday

This project has been made during one of the Open Source Saturdays, a series of Milan-based events
where everyone codes just to spread some Open Source love ❀️

## Contributing

Contributes are welcome, if you need to run the tests through `npm test`, you must update the package.json configuration setting `cypressUploadRecordings` to `false` (or set your own [Cypress recording key](https://docs.cypress.io/guides/guides/command-line.html#Options)).

## Contributors

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):



Stefano Magni
Stefano Magni

πŸ’» ⚠️ πŸ“–
Tommaso Allevi
Tommaso Allevi

πŸ’» ⚠️
brogueady
brogueady

πŸ’»
seeu1
seeu1

πŸ€”
Sarah Weir
Sarah Weir

πŸ› πŸ’»
Lee Alexis
Lee Alexis

πŸ“–
Phil Burrows
Phil Burrows

πŸ€” πŸ’» ⚠️


Leo Viezens
Leo Viezens

πŸ“–
Pier-Luc Gendreau
Pier-Luc Gendreau

πŸ“–
Liam Butler
Liam Butler

πŸ’» ⚠️
Felipe Knorr Kuhn
Felipe Knorr Kuhn

πŸ’»
Oleksii Kachan
Oleksii Kachan

πŸ›
Damien Sorel
Damien Sorel

πŸ›
piccit
piccit

πŸ›

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!