0
0
Cypresstesting~15 mins

Overwriting existing commands in Cypress - Deep Dive

Choose your learning style9 modes available
Overview - Overwriting existing commands
What is it?
Overwriting existing commands in Cypress means changing how built-in commands work by replacing them with your own versions. This lets you customize or extend the behavior of commands like clicking or typing. Instead of writing new commands, you modify existing ones to fit your test needs better. This helps tests become simpler and more expressive.
Why it matters
Without the ability to overwrite commands, you would have to repeat the same setup or checks every time you use a command. This leads to longer, harder-to-maintain tests. Overwriting commands saves time and reduces mistakes by centralizing changes. It makes tests more reliable and easier to read, which is important when testing complex apps.
Where it fits
Before learning this, you should know how to write basic Cypress tests and use custom commands. After mastering overwriting commands, you can explore advanced test design patterns and plugins that improve test reuse and maintainability.
Mental Model
Core Idea
Overwriting commands lets you replace Cypress’s built-in actions with your own code to customize test behavior everywhere that command is used.
Think of it like...
It's like changing the recipe for a common dish in your family cookbook so every time someone cooks it, they use your improved version without rewriting the whole recipe each time.
┌───────────────────────────────┐
│ Cypress built-in command (e.g., click) │
└───────────────┬───────────────┘
                │
                ▼
┌───────────────────────────────┐
│ Overwritten command with extra checks │
└───────────────────────────────┘
                │
                ▼
┌───────────────────────────────┐
│ Test uses 'click' command, runs overwritten version │
└───────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Cypress commands
🤔
Concept: Learn what Cypress commands are and how they work in tests.
Cypress commands are functions like cy.click() or cy.type() that perform actions or assertions on your web page. They are chainable and asynchronous, meaning they wait for actions to complete before moving on. Commands help you simulate user behavior in tests.
Result
You know how to use basic Cypress commands to interact with web elements.
Understanding commands is essential because overwriting changes how these core actions behave everywhere in your tests.
2
FoundationCreating custom commands
🤔
Concept: Learn how to add new commands to Cypress without changing existing ones.
You can add custom commands using Cypress.Commands.add('name', () => {...}). These commands let you reuse complex actions by giving them a simple name. For example, a login command that types username and password.
Result
You can write new commands to simplify repetitive test steps.
Knowing how to add commands prepares you to understand how overwriting modifies existing commands instead of adding new ones.
3
IntermediateBasics of overwriting commands
🤔Before reading on: do you think overwriting a command replaces it completely or extends it? Commit to your answer.
Concept: Overwriting replaces an existing command’s behavior but can also call the original command inside the new one.
Use Cypress.Commands.overwrite('commandName', (originalFn, ...args) => {...}) to overwrite. The first argument is the original command function, which you can call inside your new code to keep original behavior and add extra steps.
Result
You can change how commands like cy.click() behave, adding extra checks or logging.
Knowing you can call the original command inside your overwrite prevents losing important default behavior.
4
IntermediatePractical example: overwriting click
🤔Before reading on: do you think adding a console log before clicking will affect test speed or reliability? Commit to your answer.
Concept: Overwriting cy.click() to add a console log before performing the click.
Cypress.Commands.overwrite('click', (originalFn, subject, options) => { console.log('Clicking element:', subject); return originalFn(subject, options); }); This logs the element before clicking it in every test.
Result
Every cy.click() logs the element, helping debug tests without changing click behavior.
Adding simple code before or after original commands helps debug or add checks without rewriting tests.
5
IntermediateOverwriting commands with arguments
🤔Before reading on: do you think overwritten commands must accept the same arguments as original? Commit to your answer.
Concept: Overwritten commands receive the original function and all arguments, so you must handle them correctly.
When overwriting, the first argument is always the original command function. The rest are the arguments the command expects. For example, cy.type() expects a string and options. Your overwrite must accept and pass these correctly to avoid breaking tests.
Result
You can safely overwrite commands with arguments without breaking their usage.
Handling arguments properly in overwrites prevents subtle bugs and test failures.
6
AdvancedChaining and asynchronous behavior
🤔Before reading on: do you think overwriting commands affects Cypress’s command queue and timing? Commit to your answer.
Concept: Overwritten commands must return the original command’s result to keep Cypress’s chaining and timing intact.
Cypress commands run asynchronously and chain together. Your overwrite must return the call to originalFn to keep this chain working. Forgetting to return breaks chaining and causes tests to fail or hang.
Result
Tests continue to run smoothly with overwritten commands maintaining Cypress’s async flow.
Returning the original command’s result is critical to preserve Cypress’s internal command queue and timing.
7
ExpertAvoiding pitfalls with multiple overwrites
🤔Before reading on: do you think overwriting the same command multiple times stacks or replaces previous overwrites? Commit to your answer.
Concept: Multiple overwrites replace previous ones; they do not stack automatically, so you must manage chaining manually.
If you overwrite cy.click() in two different files, the last overwrite wins. To combine behaviors, you must call the previous overwrite inside the new one manually. This requires careful design to avoid losing functionality.
Result
You understand how to manage multiple overwrites safely in large projects.
Knowing overwrites replace rather than stack prevents accidental loss of important behavior in complex test suites.
Under the Hood
Cypress commands are queued and executed asynchronously. When you overwrite a command, Cypress replaces the original function in its internal command registry with your new function. The original function is passed as an argument so you can call it inside your overwrite. This preserves Cypress’s command queue and chaining behavior. The overwrite runs whenever the command is called in tests, allowing centralized control.
Why designed this way?
Cypress was designed to be flexible and extensible. Overwriting commands allows users to customize behavior without modifying Cypress core code. Passing the original function as an argument lets users extend rather than completely replace commands, reducing errors. This design balances power and safety, enabling maintainable test customization.
┌───────────────────────────────┐
│ Cypress command registry       │
│ ┌───────────────────────────┐ │
│ │ Original command function  │ │
│ └─────────────┬─────────────┘ │
│               │               │
│  Overwrite replaces function  │
│               ▼               │
│ ┌───────────────────────────┐ │
│ │ Overwritten command function│ │
│ │ (calls originalFn inside)  │ │
│ └───────────────────────────┘ │
└───────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does overwriting a command automatically keep the original behavior? Commit yes or no.
Common Belief:Overwriting a command replaces it completely, so the original behavior is lost unless you rewrite it all.
Tap to reveal reality
Reality:You can call the original command inside your overwrite to keep its behavior and add extra steps.
Why it matters:Not calling the original function causes tests to break or behave unexpectedly, wasting debugging time.
Quick: Can you overwrite a command multiple times and have all overwrites run automatically? Commit yes or no.
Common Belief:Multiple overwrites stack automatically, so all custom behaviors run in order.
Tap to reveal reality
Reality:Only the last overwrite is active; previous ones are replaced unless you manually chain them.
Why it matters:Assuming stacking leads to lost functionality and confusing test failures in large projects.
Quick: Does forgetting to return the original command in an overwrite cause problems? Commit yes or no.
Common Belief:Returning the original command’s result is optional and does not affect test flow.
Tap to reveal reality
Reality:Not returning breaks Cypress’s command chaining and asynchronous execution, causing tests to fail or hang.
Why it matters:Understanding this prevents subtle bugs that are hard to diagnose.
Quick: Is overwriting commands only useful for adding new commands? Commit yes or no.
Common Belief:Overwriting is just another way to add commands, not to change existing ones.
Tap to reveal reality
Reality:Overwriting specifically changes existing commands’ behavior, which is different from adding new commands.
Why it matters:Confusing these leads to misuse and missed opportunities to simplify tests.
Expert Zone
1
Overwrites can affect test performance if they add heavy operations; use them judiciously.
2
Careful argument handling in overwrites is crucial to avoid breaking commands with optional or variable parameters.
3
Overwrites can be scoped to specific test files or globally, affecting test isolation and maintainability.
When NOT to use
Avoid overwriting commands when you only need to add new behavior without changing existing commands; use custom commands instead. Also, avoid overwrites for very complex logic better handled by helper functions or plugins to keep tests clear.
Production Patterns
In real projects, overwriting commands is used to add logging, error handling, or automatic retries globally. Teams often overwrite commands like click or type to add accessibility checks or wait for animations, improving test reliability and debugging.
Connections
Aspect-Oriented Programming (AOP)
Overwriting commands is similar to AOP’s method interception where behavior is added before or after existing methods.
Understanding AOP helps grasp how Cypress overwrites inject extra behavior without changing original code, improving modularity.
Decorator Pattern (Software Design)
Overwriting commands acts like decorators that wrap existing functions to extend behavior dynamically.
Knowing the decorator pattern clarifies how overwrites can add features while preserving original command functionality.
Quality Control in Manufacturing
Overwriting commands is like adding quality checks at specific steps in a production line to catch defects early.
This cross-domain link shows how adding checks in Cypress commands improves test quality just like inspections improve product quality.
Common Pitfalls
#1Overwriting a command but forgetting to call the original function inside.
Wrong approach:Cypress.Commands.overwrite('click', (originalFn, subject, options) => { console.log('Clicked element'); // Missing call to originalFn });
Correct approach:Cypress.Commands.overwrite('click', (originalFn, subject, options) => { console.log('Clicked element'); return originalFn(subject, options); });
Root cause:Misunderstanding that the original command must be called to preserve its behavior and chaining.
#2Overwriting a command but not returning the result, breaking chaining.
Wrong approach:Cypress.Commands.overwrite('type', (originalFn, subject, text, options) => { originalFn(subject, text, options); // No return statement });
Correct approach:Cypress.Commands.overwrite('type', (originalFn, subject, text, options) => { return originalFn(subject, text, options); });
Root cause:Not returning the original command’s result breaks Cypress’s async command queue.
#3Overwriting the same command multiple times without chaining previous overwrites.
Wrong approach:// First overwrite Cypress.Commands.overwrite('click', (originalFn, subject, options) => { console.log('First overwrite'); return originalFn(subject, options); }); // Second overwrite replaces first Cypress.Commands.overwrite('click', (originalFn, subject, options) => { console.log('Second overwrite'); return originalFn(subject, options); });
Correct approach:// Save first overwrite const firstClick = Cypress.Commands._commands.click; // Second overwrite calls first Cypress.Commands.overwrite('click', (originalFn, subject, options) => { console.log('Second overwrite'); return firstClick(subject, options); });
Root cause:Assuming overwrites stack automatically instead of replacing previous ones.
Key Takeaways
Overwriting commands in Cypress lets you customize built-in actions globally to simplify and improve tests.
Always call and return the original command inside your overwrite to preserve behavior and chaining.
Multiple overwrites replace previous ones unless you manually chain them, so manage carefully in large projects.
Overwrites are powerful but should be used thoughtfully to avoid adding complexity or performance issues.
Understanding overwriting commands connects to broader software design patterns like decorators and method interception.