Bird
Raised Fist0
Cypresstesting~15 mins

Overwriting existing commands in Cypress - Deep Dive

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of overwriting existing commands in Cypress?
easy
A. To change or extend the behavior of built-in Cypress commands
B. To delete commands from Cypress
C. To create new commands unrelated to existing ones
D. To speed up test execution by skipping commands

Solution

  1. Step 1: Understand command overwriting

    Overwriting commands means changing how existing Cypress commands behave.
  2. Step 2: Identify the purpose

    This lets you add features like logging or fix issues in commands.
  3. Final Answer:

    To change or extend the behavior of built-in Cypress commands -> Option A
  4. Quick Check:

    Overwriting = Change behavior [OK]
Hint: Overwriting means changing existing command behavior [OK]
Common Mistakes:
  • Thinking overwriting deletes commands
  • Confusing overwriting with creating new commands
  • Assuming overwriting speeds up tests automatically
2. Which of the following is the correct syntax to overwrite the click command in Cypress?
easy
A. Cypress.Commands.add('click', (subject, options) => { return subject.click(options) })
B. Cypress.Commands.override('click', (originalFn, subject) => { originalFn(subject) })
C. Cypress.overwrite('click', (subject, options) => { return subject.click(options) })
D. Cypress.Commands.overwrite('click', (originalFn, subject, options) => { return originalFn(subject, options) })

Solution

  1. Step 1: Recall Cypress overwrite syntax

    Use Cypress.Commands.overwrite with the command name and a function receiving originalFn.
  2. Step 2: Check parameters and call

    The function must call originalFn(subject, options) to keep original behavior.
  3. Final Answer:

    Cypress.Commands.overwrite('click', (originalFn, subject, options) => { return originalFn(subject, options) }) -> Option D
  4. Quick Check:

    Overwrite syntax = Cypress.Commands.overwrite [OK]
Hint: Use Cypress.Commands.overwrite with originalFn first param [OK]
Common Mistakes:
  • Using Cypress.Commands.add instead of overwrite
  • Wrong method name like override
  • Missing originalFn parameter
3. Given this overwrite code:
Cypress.Commands.overwrite('type', (originalFn, subject, text, options) => {
  cy.log(`Typing: ${text}`)
  return originalFn(subject, text, options)
})

What will happen when cy.get('input').type('hello') runs?
medium
A. It types 'hello' and logs 'Typing: hello' in the test runner
B. It types 'hello' but does not log anything
C. It throws an error because of wrong parameters
D. It logs 'Typing: hello' but does not type anything

Solution

  1. Step 1: Analyze the overwrite function

    The overwrite logs the text being typed, then calls the original type command with all parameters.
  2. Step 2: Understand the effect on cy.type

    When cy.get('input').type('hello') runs, it logs the message and types 'hello' into the input.
  3. Final Answer:

    It types 'hello' and logs 'Typing: hello' in the test runner -> Option A
  4. Quick Check:

    Overwrite logs then calls original = logs and types [OK]
Hint: Overwrite calls originalFn after logging to keep behavior [OK]
Common Mistakes:
  • Assuming logging prevents typing
  • Thinking parameters are incorrect
  • Believing it throws an error
4. What is wrong with this overwrite code?
Cypress.Commands.overwrite('click', (subject, options) => {
  cy.log('Clicking element')
  return subject.click(options)
})
medium
A. It should use Cypress.Commands.add instead of overwrite
B. It misses the originalFn parameter required for overwriting
C. It uses cy.log which is not allowed inside overwrites
D. It calls subject.click instead of originalFn

Solution

  1. Step 1: Check overwrite function parameters

    Overwrites must receive originalFn as the first parameter to call the original command.
  2. Step 2: Identify missing parameter

    This code only has subject and options, missing originalFn.
  3. Final Answer:

    It misses the originalFn parameter required for overwriting -> Option B
  4. Quick Check:

    Overwrite needs originalFn first param [OK]
Hint: Overwrite must have originalFn as first parameter [OK]
Common Mistakes:
  • Omitting originalFn parameter
  • Confusing add with overwrite
  • Thinking cy.log is disallowed
5. You want to overwrite the visit command to add a console log only when the URL contains 'admin'. Which overwrite code correctly implements this?
hard
A. Cypress.Commands.overwrite('visit', (url, options) => { if (url.includes('admin')) { console.log('Admin page visited') } return cy.visit(url, options) })
B. Cypress.Commands.overwrite('visit', (originalFn, url, options) => { if (url.includes('admin')) { console.log('Admin page visited') } return originalFn(options, url) })
C. Cypress.Commands.overwrite('visit', (originalFn, url, options) => { if (url.includes('admin')) { console.log('Admin page visited') } return originalFn(url, options) })
D. Cypress.Commands.add('visit', (url, options) => { if (url.includes('admin')) { console.log('Admin page visited') } cy.visit(url, options) })

Solution

  1. Step 1: Use correct overwrite signature

    Overwrite must have originalFn as first parameter, then url and options.
  2. Step 2: Call originalFn with correct argument order

    Call originalFn(url, options) to keep original behavior.
  3. Step 3: Add conditional console log

    Check if url.includes('admin') and log message accordingly.
  4. Final Answer:

    Cypress.Commands.overwrite('visit', (originalFn, url, options) => { if (url.includes('admin')) { console.log('Admin page visited') } return originalFn(url, options) }) -> Option C
  5. Quick Check:

    Overwrite with originalFn and correct args [OK]
Hint: Always call originalFn with correct parameters in overwrite [OK]
Common Mistakes:
  • Swapping url and options in call
  • Using add instead of overwrite
  • Omitting originalFn parameter
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard