Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
cypress-wait-until
Advanced tools
The cypress-wait-until package is a Cypress plugin that allows you to wait for arbitrary conditions to be met before proceeding with the next steps in your test. This is particularly useful for waiting for asynchronous operations or specific states in your application that are not directly tied to DOM elements.
Wait for a condition to be true
This feature allows you to wait until a specific condition is true. In this example, the test waits until an input element becomes visible before proceeding.
cy.waitUntil(() => cy.get('input').then($input => $input.is(':visible')));
Wait for a promise to resolve
This feature allows you to wait until a promise resolves. In this example, the test waits for a promise that resolves after 1 second before proceeding.
cy.waitUntil(() => new Cypress.Promise((resolve) => setTimeout(resolve, 1000)));
Wait for a custom command
This feature allows you to wait until a custom Cypress command returns a specific value. In this example, the test waits until the custom command returns 'expectedValue' before proceeding.
cy.waitUntil(() => cy.customCommand().then(result => result === 'expectedValue'));
The cypress-waitfor package provides similar functionality by allowing you to wait for specific conditions or elements. It offers a more declarative syntax compared to cypress-wait-until.
The cypress-wait-until package is another alternative that provides similar functionality. It allows you to wait for arbitrary conditions to be met before proceeding with the next steps in your test.
Add the Cypress waiting power to virtually everything 🎉
Use this plugin to wait for everything not expected by Cypress wait.
npm i -D cypress-wait-until
# or
yarn add -D cypress-wait-until
cypress-wait-until
extends Cypress' cy
command.
Add this line to your project's cypress/support/commands.js
:
import 'cypress-wait-until';
Then, in your test, you can write
// 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
// 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
cy.waitUntil(() => cy.getCookie('token').then(cookie => cookie.value === '<EXPECTED_VALUE>'));
// is equivalent to
cy.wrap('<EXPECTED_VALUE>')
.waitUntil((subject) => cy.getCookie('token').then(cookie => cookie.value === subject));
Please note
checkFunction
body is retriedcy.getCookie('token') // will not be retried
.waitUntil(cookie => cookie.value === '<EXPECTED_VALUE>');
you cannot put assertions inside checkFunction
. There is no way to avoid a test failure if an assertion throws an error. 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 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 for more info
If you use TypeScript you can define the checkFunction
returning type too. Take a look at the plugin.spec.ts file to read about the cy.waitUntil
signature.
cypress-wait-until
to the cypress/tsconfig.json
file{
"compilerOptions": {
"types": ["cypress", "cypress-wait-until"]
}
}
cypress.json
for the import to work correctly:{
"supportFile": "cypress/support/commands.ts"
}
A function that must return a truthy value when the wait is over.
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. 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
No. cy.waitUntil
waits for something that must happen, otherwise the test will fail. Cypress enforces to avoid conditional testing 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 and here where it is explained how to do that) where you manage your case. After all, cy.waitUntil
is just a recursive promise manager 😊
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?
And How do I wait until a cookie is
set?).
This plugin is dedicated to them ❤️
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 ❤️
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).
Thanks goes to these wonderful people (emoji key):
Stefano Magni 💻 ⚠️ 📖 | Tommaso Allevi 💻 ⚠️ | brogueady 💻 | seeu1 🤔 | Sarah Weir 🐛 💻 | Lee Alexis 📖 | Phil Burrows 🤔 💻 ⚠️ |
Leo Viezens 📖 | Pier-Luc Gendreau 📖 | Liam Butler 💻 ⚠️ | Felipe Knorr Kuhn 💻 | Oleksii Kachan 🐛 | Damien Sorel 🐛 | piccit 🐛 |
This project follows the all-contributors specification. Contributions of any kind welcome!
FAQs
A waiting plugin for Cypress
We found that cypress-wait-until demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.