Comprehensive Cypress Troubleshooting Guide

A detailed guide to understanding and resolving common Cypress testing issues

Understanding Cypress Behavior

Before diving into specific issues, it's crucial to understand how Cypress works. Think of Cypress as a meticulous inspector examining your application. Just like a real inspector doesn't immediately fail an inspection when they spot an issue, Cypress has built-in retry and waiting mechanisms. It will automatically wait and retry operations before determining that something has truly failed.

Element Not Found Issues

One of the most common issues in Cypress is the "Element not found" error. This is similar to trying to find a book in a library before it's been placed on the shelf.

Common Scenario


// This might fail
cy.get('.dynamic-element').click()

// Better approach
cy.get('.dynamic-element', { timeout: 10000 }).should('be.visible').click()
                

The second approach gives the element time to appear, just like waiting for a librarian to put the book on the shelf.

Handling Dynamic Content

Modern web applications often load content dynamically, like a theater where the stage setup changes during the performance. Here's how to handle such scenarios:


// Waiting for API response
cy.intercept('GET', '/api/data').as('getData')
cy.visit('/dashboard')
cy.wait('@getData')
cy.get('.data-container').should('be.visible')

// Alternative approach using assertions
cy.get('.data-container').should(($element) => {
    // Custom assertion to verify content
    expect($element.text()).to.include('Expected Content')
})
                

Network Request Issues

Network requests in Cypress are like sending and receiving mail. Sometimes the mail might get lost, delayed, or arrive in an unexpected format.


// Proper way to handle and stub network requests
cy.intercept('GET', '/api/users', (req) => {
    // Simulate network delay
    req.reply((res) => {
        res.delay = 1000
        res.body = { users: [] }
    })
}).as('getUsers')

// Wait for the request and verify response
cy.wait('@getUsers').then((interception) => {
    expect(interception.response.body).to.have.property('users')
})
                

Cross-Origin Issues

Cross-origin issues in Cypress are like trying to enter a building with a security checkpoint. You need the proper credentials and permissions.

Add to your cypress.config.js:


module.exports = {
    chromeWebSecurity: false,
    modifyObstructiveCode: false,
    experimentalCspAllowList: ['script-src', 'style-src'],
}
                

Dealing with Iframes

Working with iframes in Cypress is like trying to interact with a room within a room. You need to enter the outer room before you can access the inner one.


// Correct way to handle iframes
cy.get('iframe').then($iframe => {
    const body = $iframe.contents().find('body')
    cy.wrap(body)
        .find('.iframe-element')
        .should('be.visible')
        .click()
})
                

Performance Optimization

Slow tests can be like a traffic jam - they slow down your entire development process. Here are some optimization techniques:

Best Practices for Speed


// Instead of repeating login for each test
beforeEach(() => {
    // Use cy.session to cache login state
    cy.session('user-session', () => {
        cy.login() // Custom command
    })
})

// Group related tests
describe('User Dashboard', () => {
    beforeEach(() => {
        cy.visit('/dashboard')
    })

    // Your tests here
})
                

Effective Debugging Techniques

Debugging Cypress tests is like being a detective - you need the right tools and methods to find clues about what's going wrong.


// Using debug() to pause execution
cy.get('.troublesome-element')
    .debug()
    .should('be.visible')

// Taking screenshots on failure
Cypress.on('test:after:run', (test, runnable) => {
    if (test.state === 'failed') {
        const screenshotFileName = `${runnable.parent.title} -- ${test.title} (failed).png`
        cy.screenshot(screenshotFileName)
    }
})
                

Testing Best Practices

Writing reliable tests is like building a sturdy house - you need a solid foundation and good practices throughout.


// Use data-* attributes for testing
cy.get('[data-testid="submit-button"]')

// Custom commands for common operations
Cypress.Commands.add('loginByApi', (email, password) => {
    cy.request({
        method: 'POST',
        url: '/api/login',
        body: { email, password }
    }).then((response) => {
        window.localStorage.setItem('token', response.body.token)
    })
})

// Proper error handling
cy.get('.element').then($el => {
    if ($el.length) {
        // Element exists
        cy.wrap($el).click()
    } else {
        // Handle missing element
        cy.log('Element not found, taking alternative action')
    }
})
                

Quick Solutions for Common Issues

Issue Solution
Test times out Increase defaultCommandTimeout in cypress.config.js
Element not visible Add .should('be.visible') assertion before interaction
Flaky tests Use more specific selectors and proper waiting strategies