0
0
Cypresstesting~15 mins

Retry-ability of commands in Cypress - Deep Dive

Choose your learning style9 modes available
Overview - Retry-ability of commands
What is it?
Retry-ability of commands in Cypress means that when you ask Cypress to do something, like find a button or check text, it will keep trying for a short time until it succeeds or times out. This helps tests be more reliable because web pages can be slow or change dynamically. Instead of failing immediately, Cypress waits and retries automatically.
Why it matters
Without retry-ability, tests would often fail just because the page was a little slow or elements took time to appear. This would make tests flaky and unreliable, wasting time and causing frustration. Retry-ability makes tests more stable and trustworthy, so developers can focus on real problems, not random failures.
Where it fits
Before learning retry-ability, you should understand basic Cypress commands and how to write simple tests. After this, you can learn about custom commands, assertions, and advanced synchronization techniques to write even more robust tests.
Mental Model
Core Idea
Cypress automatically repeats commands and assertions until they pass or a timeout happens, making tests wait for the right moment without extra code.
Think of it like...
It's like knocking on a door repeatedly until someone answers, instead of knocking once and giving up immediately.
┌─────────────────────────────┐
│ Start command execution      │
├─────────────────────────────┤
│ Is element found or assert   │
│ condition true?              │
├───────────────┬─────────────┤
│ Yes           │ No          │
│               │             │
│ Proceed       │ Wait a short│
│               │ time, retry │
│               │ command     │
└───────────────┴─────────────┘
Build-Up - 7 Steps
1
FoundationWhat is retry-ability in Cypress
🤔
Concept: Introduce the basic idea that Cypress commands automatically retry until success or timeout.
When you write a command like cy.get('button'), Cypress does not just check once. It keeps trying to find the button for up to the default timeout (usually 4 seconds). If the button appears within that time, the command passes. If not, it fails.
Result
Tests become more stable because they wait for elements to appear instead of failing immediately.
Understanding automatic retries explains why Cypress tests often pass even if the page is slow or dynamic.
2
FoundationHow assertions use retry-ability
🤔
Concept: Assertions in Cypress also retry until they pass or timeout, not just commands.
If you write cy.get('h1').should('contain', 'Welcome'), Cypress will keep checking the h1 text until it contains 'Welcome' or the timeout expires. This means assertions wait for the page to update.
Result
Assertions become more reliable and reduce flaky test failures caused by timing issues.
Knowing that assertions retry helps you write simpler tests without manual waits.
3
IntermediateTimeouts control retry duration
🤔Before reading on: do you think you can change how long Cypress retries commands? Commit to yes or no.
Concept: You can customize how long Cypress retries commands and assertions by setting timeouts.
By default, Cypress retries for 4 seconds. You can change this globally in configuration or per command using options like { timeout: 10000 } to wait up to 10 seconds. This helps when some elements take longer to appear.
Result
Tests can be tuned to wait longer or shorter depending on application speed, improving reliability and speed.
Understanding timeout customization lets you balance test speed and stability.
4
IntermediateRetry-ability with chained commands
🤔Before reading on: do you think Cypress retries each command in a chain separately or the whole chain together? Commit to your answer.
Concept: Cypress retries each command and assertion in a chain individually until success or timeout.
For example, cy.get('form').find('input').should('be.visible') retries the get, then the find, then the assertion separately. If any step fails, Cypress retries that step until it passes or times out.
Result
This fine-grained retry makes tests more robust and easier to write without manual waits.
Knowing retry works per command in chains helps you understand test flow and debug failures better.
5
IntermediateCommands that do NOT retry automatically
🤔Before reading on: do you think all Cypress commands retry automatically? Commit to yes or no.
Concept: Some Cypress commands, like cy.click() or cy.type(), do not retry automatically because they perform actions, not queries.
Commands that cause side effects or interact with the page usually run once. If the element is not ready, these commands fail immediately. You must ensure the element is ready before these commands.
Result
Understanding which commands retry helps avoid flaky tests and write proper waits.
Knowing retry limits prevents confusion and helps write correct test sequences.
6
AdvancedCustom commands and retry-ability
🤔Before reading on: do you think custom Cypress commands inherit retry behavior automatically? Commit to yes or no.
Concept: Custom commands can be written to support retry-ability by returning Cypress commands properly.
If a custom command returns a Cypress chainable, it inherits retry behavior. If it returns a raw value or promise, it loses retry. Writing custom commands correctly ensures they benefit from automatic retries.
Result
Custom commands become reliable and integrate smoothly with Cypress's retry system.
Understanding how to write retry-friendly custom commands unlocks powerful reusable test code.
7
ExpertHow retry-ability affects test performance
🤔Before reading on: do you think retry-ability always makes tests slower? Commit to yes or no.
Concept: Retry-ability can both improve reliability and impact test speed depending on usage and timeouts.
While retries prevent failures, excessive or long timeouts can slow tests. Experts balance retry timeouts and use commands like cy.wait() sparingly. They also use conditional testing and smart selectors to minimize retries.
Result
Tests become both stable and fast by tuning retry behavior thoughtfully.
Knowing retry's performance impact helps optimize tests for real-world CI environments.
Under the Hood
Cypress commands are queued and executed asynchronously. When a command queries the DOM, Cypress repeatedly checks the page state every few milliseconds until the element or condition is met or the timeout expires. This retry loop is built into the command execution engine and applies to queries and assertions. Commands that cause actions run once after the queries succeed.
Why designed this way?
Cypress was designed to solve flaky tests caused by asynchronous web pages. Traditional tests fail if elements are not immediately present. Automatic retry removes the need for manual waits and complex synchronization code, making tests simpler and more reliable. Alternatives like manual waits were error-prone and slow.
┌───────────────┐
│ Test command  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Query DOM     │
│ (e.g. get())  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Condition met?│
├──────┬────────┤
│ Yes  │ No     │
│      │        │
│      ▼        │
│  Proceed      │
│               │
│  Wait & retry │
│  until timeout│
└──────┴────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does Cypress retry commands forever until success? Commit to yes or no.
Common Belief:Cypress retries commands endlessly until they pass.
Tap to reveal reality
Reality:Cypress retries commands only up to a configurable timeout (default 4 seconds), then fails if the condition is not met.
Why it matters:Believing retries are endless can cause confusion when tests fail after timeout, leading to wasted debugging time.
Quick: Do all Cypress commands retry automatically? Commit to yes or no.
Common Belief:Every Cypress command retries automatically until success.
Tap to reveal reality
Reality:Only query and assertion commands retry automatically. Action commands like cy.click() do not retry and fail immediately if the element is not ready.
Why it matters:Misunderstanding this causes flaky tests when actions are attempted on elements not yet ready.
Quick: Does increasing timeout always make tests better? Commit to yes or no.
Common Belief:Setting very long timeouts always improves test reliability.
Tap to reveal reality
Reality:Excessive timeouts can slow tests and mask real problems like slow page loads or broken UI.
Why it matters:Overusing long timeouts leads to slow test suites and delayed feedback in development.
Quick: Do custom commands automatically retry if they contain Cypress commands? Commit to yes or no.
Common Belief:All custom commands inherit retry behavior automatically.
Tap to reveal reality
Reality:Custom commands only retry if they return Cypress chainables properly. Returning raw values or promises disables retry.
Why it matters:Incorrect custom commands cause unexpected test failures and harder debugging.
Expert Zone
1
Retry-ability applies per command, not per test, so understanding command chains is key to debugging retries.
2
Assertions retry until they pass, but side-effect commands do not, so test order and command placement affect reliability.
3
Custom commands must return Cypress chainables to participate in retry, otherwise retry is lost silently.
When NOT to use
Retry-ability is not suitable for commands that cause irreversible side effects or external state changes, like API calls or database writes. In those cases, explicit waits or retries at the application level are better. Also, for very fast UI elements, disabling retry can speed up tests.
Production Patterns
In real projects, retry-ability is combined with smart selectors (data attributes), custom commands that wrap retries, and timeout tuning per test type. Teams often set global timeouts but override them for slow pages. Retry-ability is also used with Cypress's network stubbing to wait for API responses before UI actions.
Connections
Event Loop in JavaScript
Retry-ability relies on asynchronous command execution and event loop cycles to check conditions repeatedly.
Understanding the event loop helps grasp how Cypress schedules retries without blocking the browser or test runner.
Circuit Breaker Pattern in Software Engineering
Both retry-ability and circuit breakers manage repeated attempts with limits to avoid endless failures.
Knowing circuit breakers clarifies why Cypress limits retries with timeouts to prevent infinite waiting.
Human Patience in Waiting for Responses
Retry-ability mimics how humans wait and check repeatedly for something to happen before giving up.
Recognizing this natural pattern helps appreciate why automatic retries improve test reliability.
Common Pitfalls
#1Assuming all commands retry and writing flaky tests with immediate actions.
Wrong approach:cy.click(); // clicks immediately without waiting for element readiness
Correct approach:cy.get('button').click(); // waits for button to appear before clicking
Root cause:Misunderstanding that action commands do not retry and require prior queries.
#2Setting very long global timeouts to fix flaky tests without root cause analysis.
Wrong approach:Cypress.config('defaultCommandTimeout', 30000); // 30 seconds timeout globally
Correct approach:Use targeted timeout only where needed, e.g., cy.get('slow-element', { timeout: 10000 });
Root cause:Belief that longer waits always fix flakiness, ignoring underlying performance or selector issues.
#3Writing custom commands that return raw values, losing retry behavior.
Wrong approach:Cypress.Commands.add('getText', (selector) => { return cy.get(selector).then($el => $el.text()); });
Correct approach:Cypress.Commands.add('getText', (selector) => { return cy.get(selector).invoke('text'); });
Root cause:Not returning Cypress chainables causes retry to be disabled silently.
Key Takeaways
Cypress automatically retries query and assertion commands until they pass or timeout, making tests more stable.
Action commands like clicks do not retry and require elements to be ready beforehand.
Timeouts control how long Cypress retries; tuning them balances test speed and reliability.
Custom commands must return Cypress chainables to inherit retry behavior.
Understanding retry-ability helps write simpler, more reliable tests and avoid common flakiness.