Cypress Custom Command Not Working Fix
In this tutorial, you'll learn about Cypress Custom Command Not Working Fix. We cover key concepts, practical examples, and best practices.
Your custom Cypress command is undefined — calling cy.login() throws "cy.login is not a function" even though you defined it.
The Problem
// WRONG — command defined in test file
it('logs in', () => {
Cypress.Commands.add('login', () => {
cy.get('#email').type('user@example.com');
cy.get('#password').type('secret123');
cy.get('button').click();
});
cy.login(); // Error — command definition is queued, not executed yet
});
<a href="/testing-qa/cypress/">Cypress</a>.Commands.add() must be called before the test runs, not during it. It's a synchronous registration, not a queued command.
Step-by-Step Fix
1. Define commands in support file
// RIGHT — cypress/support/commands.js
Cypress.Commands.add('login', (email = 'user@example.com', password = 'secret123') => {
cy.get('#email').type(email);
cy.get('#password').type(password);
cy.get('button[type="submit"]').click();
cy.url().should('include', '/dashboard');
});
2. Import the support file
// RIGHT — cypress/support/e2e.js
import './commands';
// Now available in all test files:
it('logs in', () => {
cy.login();
cy.get('.dashboard').should('be.visible');
});
3. Create commands with options
// RIGHT — command with options object
Cypress.Commands.add('login', { prevSubject: false }, (email, password, options = {}) => {
cy.get('#email').type(email);
cy.get('#password').type(password);
cy.get('button[type="submit"]').click();
});
4. Create child commands (chained)
// RIGHT — child command
Cypress.Commands.add('shouldHaveText', { prevSubject: true }, (subject, text) => {
cy.wrap(subject).should('have.text', text);
return subject;
});
cy.get('.message').shouldHaveText('Success').and('be.visible');
Expected output:
✓ logs in successfully
✓ uses custom assertion command
Prevention Tips
- Define custom commands in
<a href="/testing-qa/cypress/">cypress</a>/support/commands.js - Use
{ prevSubject }option for child commands - Add TypeScript declarations for custom commands
- Keep commands focused on single responsibilities
- Import commands in
<a href="/testing-qa/cypress/">cypress</a>/support/e2e.js
Common Mistakes with custom command
- Using
headandtailinstead of pattern matching, causing runtime errors on empty lists - Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
- Using
returnto exit a function early instead of wrapping a pure value in the monad
These mistakes appear frequently in real-world CYPRESS code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro