0
0
Cypresstesting~15 mins

TypeScript support for custom commands in Cypress - Build an Automation Script

Choose your learning style9 modes available
Add and use a custom Cypress command with TypeScript support
Preconditions (3)
Step 1: Create a custom command named 'login' that accepts username and password
Step 2: Implement the 'login' command to fill username and password fields and click the login button
Step 3: Add TypeScript declaration to extend Cypress namespace with the 'login' command
Step 4: Use the 'login' command in a test to log in with valid credentials
Step 5: Verify that after login, the URL contains '/dashboard'
✅ Expected Result: The test runs successfully using the custom 'login' command with TypeScript support, and the assertion confirms the URL contains '/dashboard'
Automation Requirements - Cypress with TypeScript
Assertions Needed:
Verify URL contains '/dashboard' after login
Best Practices:
Use Cypress.Commands.add to define custom commands
Extend Cypress namespace in a .d.ts file for TypeScript support
Use explicit selectors with data-cy attributes
Use async/await or Cypress chaining properly
Keep test code clean and readable
Automated Solution
Cypress
/// <reference types="cypress" />

// cypress/support/commands.ts
Cypress.Commands.add('login', (username: string, password: string) => {
  cy.get('[data-cy=username]').clear().type(username);
  cy.get('[data-cy=password]').clear().type(password);
  cy.get('[data-cy=login-button]').click();
});

// cypress/support/index.d.ts
// This file adds TypeScript support for the custom command

/// <reference types="cypress" />

declare namespace Cypress {
  interface Chainable {
    /**
     * Custom command to login
     * @example cy.login('user1', 'pass123')
     */
    login(username: string, password: string): Chainable<void>;
  }
}

// cypress/e2e/login.cy.ts

describe('Login Test with Custom Command', () => {
  beforeEach(() => {
    cy.visit('/login');
  });

  it('logs in using custom command and verifies dashboard URL', () => {
    cy.login('testuser', 'TestPass123!');
    cy.url().should('include', '/dashboard');
  });
});

The code defines a custom Cypress command named login in commands.ts. It uses cy.get with data-cy attributes to find username, password fields, and the login button, then performs typing and clicking.

In index.d.ts, the Cypress namespace is extended to add TypeScript support for the login command. This allows TypeScript to recognize cy.login() with proper parameter types.

The test file login.cy.ts visits the login page, uses the custom login command with sample credentials, and asserts that the URL contains /dashboard after login.

This setup ensures type safety, code reuse, and clear test steps.

Common Mistakes - 5 Pitfalls
{'mistake': 'Not extending Cypress namespace in a .d.ts file', 'why_bad': "TypeScript will show errors when using the custom command because it doesn't know about it.", 'correct_approach': 'Create or update a declaration file to extend Cypress.Chainable interface with the custom command signature.'}
{'mistake': "Using generic selectors like '.input' or '#username' instead of data-cy attributes", 'why_bad': 'Selectors can break easily if UI changes, making tests flaky.', 'correct_approach': 'Use stable selectors like data-cy attributes dedicated for testing.'}
{'mistake': 'Defining the custom command inside the test file instead of support/commands.ts', 'why_bad': "Commands won't be globally available and code reuse is limited.", 'correct_approach': 'Define custom commands in support/commands.ts so they load automatically.'}
Not clearing input fields before typing in the login command
Using incorrect Cypress command chaining or mixing async/await incorrectly
Bonus Challenge

Now add data-driven testing to run the login test with 3 different username and password combinations

Show Hint