Enhancing Cypress Tests with Dynamic Waiting: A Deep Dive into Timeout Options

Niluka Sripali Monnankulama
Many Minds
Published in
6 min readMar 30, 2024

--

Cypress is a powerful testing framework known for its ability to provide fast, reliable, and efficient end-to-end testing for web applications.

However, one common challenge faced by testers is handling dynamic elements or conditions that may take varying amounts of time to appear during test execution.

In this blog post, I’ll explore the importance of dynamic waiting in Cypress and how leveraging timeout options can significantly improve the reliability and effectiveness of your tests.

Understanding Dynamic Waiting in Cypress

  • Introduction to Dynamic Waiting: Dynamic waiting refers to the practice of waiting for elements or conditions to appear or change during test execution. ( Refer More in My Previous Blog: How to Handle Dynamic Waits in Cypress.)
  • Challenges with Static Waits: Static waits, such as cy.wait(), introduce unnecessary delays and can lead to brittle tests that are prone to failure.

🎯 The Role of Timeout Options

  • Introduction to Timeout Options: Cypress provides the timeout option with the cy.get() command, allowing testers to specify the maximum time Cypress should wait for an element to appear.
  • Dynamic Waiting Behavior: Cypress dynamically adjusts the wait time based on when the element appears, rather than waiting for a fixed duration.

Technical Insights into Timeout Options

  • Syntax and Usage: The timeout option is passed as a parameter to the cy.get() command, along with the selector of the element to wait for.

The first code snippet provided does not work as intended. Because it tries to use the should method with a timeout parameter to check if the element with the class 'selector' is visible. However, the correct syntax for setting a timeout in Cypress is to include it as an option when selecting the element, not when using the should method.

The correct way to achieve the same functionality is shown in the second code snippet you provided. Here’s a clear explanation of the corrected code:

cy.get('.selector', { timeout: 1000 }): This line of code selects the element with the class 'selector' and sets a timeout of 1000 milliseconds for the selection. This means that Cypress will wait for up to 1000 milliseconds for the element to become available before throwing an error.

.should('be.visible'): After selecting the element, the should method is used to assert that the element is visible. This ensures that the test passes only if the element is visible on the page.

  • Incremental Waiting: Cypress waits incrementally, checking for the element at intervals until the timeout is reached or the element is found.
  • Handling Failures: If the element is not found within the specified timeout, Cypress raises a failure, providing immediate feedback to the tester.

🚴‍♂️ Practical Examples of Dynamic Waiting

Scenario 1: Waiting for a Login Button to Appear

  • Problem: The login button may take varying amounts of time to appear after the page loads.
  • Solution: Use cy.get() with a timeout option to wait dynamically for the login button to appear.
cy.get('.login-button', { timeout: 10000 }).click(); // Wait for up to 10 seconds for the login button to appear

Scenario 2: Waiting for a Confirmation Message

  • Problem: The confirmation message may not appear immediately after submitting a form.
  • Solution: Use cy.get() with a timeout option to wait dynamically for the confirmation message to appear.
cy.get('.confirmation-message', { timeout: 5000 }).should('be.visible'); // Wait for up to 5 seconds for the confirmation message to appear

A Few More Examples:

Using Timeout with cy.contains() for Dynamic Text:

  • When waiting for dynamic text to appear on the page, we can use cy.contains() with a timeout option.
// Wait for the text 'Welcome' to appear within 5 seconds 
cy.contains('Welcome', { timeout: 5000 }).should('be.visible');

Custom Commands with Timeout Options:

  • Custom commands can encapsulate common dynamic wait scenarios, allowing for reusable and more readable code.
// Custom command to wait for an element with a specific selector 
Cypress.Commands.add('waitForElement', { prevSubject: 'optional' }, (subject, selector, options = {}) => {
cy.get(selector, options);
});
// Usage of custom command with timeout option cy.waitForElement('.dynamic-element', { timeout: 10000 }).click();

Using Timeout with cy.intercept() for Network Requests:

  • We can also use timeout options with cy.intercept() to wait for network requests to complete.
// Intercept a network request and wait for it to complete within 10 seconds 
cy.intercept('GET', '/api/data').as('dataRequest');
cy.visit('/dashboard');
cy.wait('@dataRequest', { timeout: 10000 });

Conditional Timeout Handling:

  • Cypress allows for conditional handling of timeouts using .then() and .should() chains.
// Conditional handling of timeout: wait for element with class 'dynamic-element' to appear within 10 seconds 
cy.get('.dynamic-element').should('be.visible').then(() => {
// Perform actions after element appears
cy.get('.dynamic-element').click(); }).timeout(10000);
// Timeout after 10 seconds

By utilizing timeout options in these different ways, we can effectively handle dynamic waits in Cypress tests, ensuring reliability and efficiency in our test automation process.

💓 The most important part…

If the element loads before the specified timeout time in Cypress, the test execution will proceed normally.

Cypress will not wait for the entire timeout duration if the element appears earlier. Instead, it dynamically checks for the presence of the element at regular intervals within the specified timeout period.

Here’s what happens when the element loads before the timeout time:

  1. Element Appears Early:
  • If the element appears on the page before the specified timeout duration elapses, Cypress recognizes it immediately.
  • Cypress proceeds with the test execution, moving on to the next command in the test script without waiting for the full timeout duration to complete.

2. No Unnecessary Waiting:

  • Cypress does not wait for the entire timeout duration if the element is found earlier. It avoids unnecessary waiting and optimizes the test execution process.

3. Dynamic Waiting:

  • Cypress employs dynamic waiting behavior, continuously checking for the presence of the element at regular intervals within the specified timeout period.
  • As soon as the element is detected, Cypress proceeds with the test execution without waiting for the entire timeout duration.

In summary, if the element loads before the specified timeout time in Cypress, the test execution will not wait for the full timeout duration. Instead, Cypress dynamically checks for the element’s presence and proceeds with the test execution as soon as the element is found. This dynamic waiting behavior ensures efficient and responsive test execution.

Let’s see, the main difference between “timeout” and “wait” in Cypress is in how they manage time during test execution.

In Cypress, both timeout and wait are used to manage the timing of commands during test execution, but they serve different purposes:

  1. Timeout:
  • The timeout option is used to specify the maximum amount of time Cypress should wait for a specific command to complete before considering it a failure.
  • It is typically used with commands like cy.get(), cy.contains(), cy.intercept(), etc., to set the maximum time Cypress should wait for an element to appear, a network request to complete, or a condition to be met.
  • If the command does not complete within the specified timeout, Cypress will fail the test and provide an error message indicating a timeout.

2. Wait:

  • The wait command, on the other hand, is used to introduce a fixed delay in test execution.
  • It pauses the test execution for a specified amount of time, regardless of the completion status of other commands.
  • While wait can be useful for scenarios where you expect a delay or need to synchronize with external events, it is generally considered a bad practice in Cypress because it introduces unnecessary delays and makes tests brittle.
  • It is recommended to avoid using wait and instead leverage Cypress's built-in features like timeout options and conditional commands for dynamic waiting.

In summary, timeout is used to set the maximum waiting time for specific commands to complete, while wait introduces a fixed delay in test execution, which is generally discouraged in Cypress testing.

Conclusion:

Dynamic waiting is a crucial aspect of Cypress testing, especially when dealing with elements or conditions that may take varying amounts of time to appear.

By understanding and leveraging timeout options effectively, testers can write more reliable tests that adapt to the dynamic nature of web applications, leading to faster feedback and improved test efficiency.

Thanks…

--

--

Niluka Sripali Monnankulama
Many Minds

An IT professional with over 7+ years of experience. Member of the WSO2 Identity & Access Management Team.