cypress-wait-until

repository·master·Indexed 20 days ago

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

A Cypress plugin that provides the `cy.waitUntil()` command, allowing developers to wait for arbitrary conditions—such as cookies, window variables, or DOM states—by repeatedly executing a check function until it returns a truthy value. It supports synchronous and asynchronous check functions with configurable options for interval, timeout, and logging.

Tokens
2.8K
Snippets
8
Records
8
Agent score
22%

What's inside cypress-wait-until

  1. Setup cypress-wait-until with TypeScript

    master

    To use cypress-wait-until with TypeScript, follow these steps:

    1. Update tsconfig.json: Add cypress-wait-until to the types array in your cypress/tsconfig.json.

    2. Verify Support File: If you encounter errors like cy.waitUntil is not a function, ensure your cypress.json (or cypress.config.ts) correctly specifies the supportFile where the plugin is imported.

    3. Type the checkFunction: You can define the return type of the checkFunction to improve type safety.

    {
      "compilerOptions": {
        "types": ["cypress", "cypress-wait-until"]
      }
    }
  2. Use cy.waitUntil() to wait for conditions

    master

    The cy.waitUntil() command extends the Cypress cy object. It accepts a checkFunction that must return a truthy value when the condition is met.

    Key Behaviors

    • Subject Passing: If the checkFunction returns a truthy value, that value becomes the subject for the next command in the chain.
    • Chaining: You can chain cy.waitUntil() to other commands. For example, cy.wrap(subject).waitUntil(...) is equivalent to cy.waitUntil(...) where the function uses the subject.
    • Retries: Only the code inside the checkFunction body is retried. The command preceding waitUntil is not retried.

    Important Constraints

    • No Assertions in checkFunction: Do not use assertions (like .should()) inside the checkFunction. If an assertion throws an error, the test will fail immediately instead of retrying. Instead, use manual checks (e.g., checking Cypress.$('#id').length > 0 instead of cy.get('#id').should('exist')).
    • Nested Calls: Avoid nesting cy.waitUntil() calls, as timeout and interval are converted to retry counts, which can lead to extremely long wait times (multiplicative effect).
    // 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"));
    
    // Using the returned value as a subject for assertions
    cy.waitUntil(() => cy.get("input[type=hidden]#recaptchatoken").then($el => $el.val()))
      .then(token => expect(token).to.be.a("string").to.have.length.within(1, 1000));
  3. Configure cy.waitUntil() options

    master

    You can pass an optional options object to cy.waitUntil() to customize the behavior of the wait loop.

    cy.waitUntil(() => cy.window().then(win => win.foo === "bar"), {
      errorMsg: 'This is a custom error message',
      timeout: 2000,
      interval: 500
    });
  4. Reference: cy.waitUntil() options

    master

    The following options are available for the cy.waitUntil() command:

    | 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` |
  5. Use cy.waitUntil() to wait for a condition

    master

    The cy.waitUntil() command allows you to wait for a specific condition to be met by repeatedly executing a checkFunction. It will retry the function at a specified interval until it returns a truthy value or the timeout is reached.

    It supports both synchronous and asynchronous (Promise-based) check functions. If the check function returns a Promise, cy.waitUntil() will wait for that Promise to resolve before checking the result.

    Arguments

    • subject (optional): The subject to pass to the checkFunction. If using as a command chain, this is the subject from the previous command.
    • checkFunction: A function that receives the subject and returns a truthy value (to stop waiting) or a falsy value (to continue waiting).
    • options (optional): An object to configure the behavior:
      • interval: Time in milliseconds between retries (default: 200).
      • timeout: Total time in milliseconds to wait before failing (default: 5000).
      • errorMsg: The error message thrown on timeout. Can be a string or a function that returns a string (default: 'Timed out retrying').
      • description: The name used in Cypress logs (default: 'waitUntil').
      • log: Whether to log the command to the Cypress command log (default: true).
      • logger: The logger function to use (default: Cypress.log).
      • verbose: If true, logs the result of every check to the console (default: false).
      • customMessage: A message to display in the Cypress log (default: undefined).
      • customCheckMessage: A message to display in the console when using verbose: true (default: undefined).
    // Example: Waiting for an element to have specific text
    cy.get('.status-label').waitUntil(() => {
      return cy.get('.status-label').then($el => $el.text() === 'Completed');
    }, {
      timeout: 10000,
      interval: 500,
      errorMsg: 'The status never became Completed'
    });
    
    // Example: Using with a subject (chaining)
    cy.get('.container').waitUntil(($el) => {
      return $el.find('.child').length > 0;
    });
  6. Configure cy.waitUntil() options

    master

    You can pass an options object as the third argument to cy.waitUntil() to control timing, logging, and error handling.

    OptionTypeDefaultDescription
    intervalnumber200Milliseconds between retries.
    timeoutnumber5000Total time to wait before throwing an error.
    errorMsgstring or Function'Timed out retrying'Message or function returning a message when timeout occurs.
    descriptionstring'waitUntil'Name displayed in the Cypress command log.
    logbooleantrueEnables/disables command logging.
    loggerFunctionCypress.logThe logging utility used.
    verbosebooleanfalseIf true, logs every check result to the console.
    customMessagestringundefinedCustom message for the command log.
    customCheckMessagestringundefinedCustom message for verbose console logs.
    // Configuration reference
    {
      interval: 200,
      timeout: 5000,
      errorMsg: 'Timed out retrying',
      description: 'waitUntil',
      log: true,
      customMessage: undefined,
      logger: Cypress.log,
      verbose: false,
      customCheckMessage: undefined
    }