The Problem

Having implemented Cypress recently for end to end testing I quickly realized the framework itself although pretty robust, was seriously lacking in the ajax support department. In other words, if an element wasn’t present within 5 seconds, the framework would throw and error and the test would fail.

This quickly becomes an issue for API calls that may require more time. There were quickly many scenarios where I needed the framework to wait for an element to be present and there was no native support for it that I could find.

The Solution

A quick web search showed a few threads on various websites where others discussed how to implement a simple version, but I wanted something a bit more robust, configurable and complete. Specifically, it needed to support custom timeouts as well as the default chaining behavior of all other Cypress queries. Here is the version I came up with.

Add the following to your /project/cypress/support/commands.js file:

Cypress.Commands.add("waitForElement", (selector, options) => {
  const defaults = {
    timeout: 30000,
    log: false,
    time: Date.now(),
    defaultCommandTimeout: Cypress.config("defaultCommandTimeout"),
  };

  options = { ...defaults, ...options };
  const doc = cy.get("body", { log: options.log }).specWindow.parent[0]
    .document;

  if (Date.now() - options.time >= options.timeout) {
    throw new Error(`Timed out waiting for element ${selector}`);
  }

  if (!doc.querySelector(selector)) {
    cy.wait(options.defaultCommandTimeout, { log: options.log });
    return cy.waitForElement(selector, options);
  }
  return cy.get(selector);
});

Example Usage

Once implemented, the waitForElement command can be used in the following way:

cy.waitForElement(".my-element-to-be-rendered").click();

The command can be used in the standard chainable way as any other Cypress command, complete with a option blocks for customization. The option block supports a custom timeout parameter which allows for customization of the timeout.

Hopefully, this helps anyone out there currently fighting with timing issues where elements aren’t immediately present or require a longer wait time. I’m always open to suggestions or ways to make code better, so if you have any feedback, I’d love to hear it. Thanks for stopping by.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *