← Back to Blog QA Automation

Cypress Alert Handling: From Zero to Hero! Complete Guide

Nestor Alonso · March 21, 2026
Cypress Alert Handling: From Zero to Hero! Complete Guide

One of the most common mistakes in articles about Cypress is throwing any popup, modal, or dialog into the same bucket and claiming that "everything is handled the same way". It's not true. In Cypress, there is an important difference between native browser dialogs—like alert, confirm, prompt, or beforeunload—and the modals your application renders using HTML, CSS, and JavaScript. Cypress treats these cases fundamentally differently, and understanding that difference is what separates a reliable test from an improvised one.

The official documentation makes this quite clear by documenting specific events like window:alert, window:confirm, window:before:load, and window:before:unload.

The good news is that Cypress has a great story for these types of scenarios. You can listen to browser events, optionally control the behavior of a cypress confirm dialog, stub prompts before the application loads, and debug stubs and spies visually from within the Cypress App itself. If you need to locate specific elements to trigger these dialogs, XPath is an excellent tool for navigating the DOM when CSS selectors fall short.

In this guide you will see how to correctly handle alert, confirm, prompt, and beforeunload in Cypress, with clean examples, best practices, typical errors, and a structure ready for real projects. Compared to Playwright, Cypress offers a much more visual and browser-oriented execution experience. Integrating these flows within a modern QA with AI strategy allows for even broader coverage. And if you need help implementing a complete QA strategy in your company, feel free to contact me.

What types of dialogs can you encounter in Cypress

When we talk about "cypress alert handling", we are actually usually talking about four scenarios:

  • window.alert()
  • window.confirm()
  • window.prompt()
  • navigation warnings like beforeunload

Cypress explicitly documents window:alert, window:confirm, window:before:load, window:before:unload, and window:unload within its official event catalog.

How to install Cypress and prepare the project base

npm install cypress --save-dev
npx cypress open

A reasonable base configuration in TypeScript would be:

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    supportFile: 'cypress/support/e2e.ts',
  },
})

How alert works in Cypress

With window.alert(), Cypress does something very specific: it automatically accepts the alert.

Basic example with window:alert

describe('Cypress alert handling', () => {
  it('asserts alert text', () => {
    cy.on('window:alert', (text) => {
      expect(text).to.equal('User saved successfully')
    })
    cy.visit('/profile')
    cy.get('[data-cy="save-button"]').click()
  })
})

How to handle confirm in Cypress

With window.confirm(), Cypress also auto-accepts by default, but here there is a key difference: you can return false from the event to cancel the confirmation.

Case 1: accepting the confirm

describe('Confirm dialog', () => {
  it('accepts the confirm by default', () => {
    cy.on('window:confirm', (text) => {
      expect(text).to.equal('Do you want to delete this record?')
    })
    cy.visit('/records')
    cy.get('[data-cy="delete-button"]').click()
  })
})

Case 2: canceling the confirm

describe('Confirm cancellation', () => {
  it('cancels the confirm when returning false', () => {
    cy.on('window:confirm', (text) => {
      expect(text).to.equal('Do you want to delete this record?')
      return false
    })
    cy.visit('/records')
    cy.get('[data-cy="delete-button"]').click()
  })
})

How to handle prompt in Cypress

What it does officially document is the correct way to control prompt: stub window.prompt.

describe('Prompt dialog', () => {
  it('stubs window.prompt and returns a custom value', () => {
    cy.visit('/profile', {
      onBeforeLoad(win) {
        cy.stub(win, 'prompt').returns('Néstor')
      },
    })
    cy.get('[data-cy="edit-name"]').click()
    cy.window().its('prompt').should('be.called')
  })
})

How to validate navigation with beforeunload

Cypress documents the window:before:unload event and securely allows you to seamlessly inspect its properties.

describe('Before unload warning', () => {
  it('asserts unsaved changes protection', () => {
    cy.on('window:before:unload', (e) => {
      expect(e.returnValue).to.exist
    })
    cy.visit('/editor')
    cy.get('[data-cy="title"]').type('Draft article')
    cy.get('a[href="/dashboard"]').click()
  })
})

cy.on() vs Cypress.on(): an important difference

For alerts and confirms of a precise test, you should normally use this:

cy.on('window:confirm', handler)

And not this:

Cypress.on('window:confirm', handler) // Risk: Global suite contamination

Common mistakes when handling dialogs in Cypress

  1. Registering the listener too late: If you click() and then register the listener, it is too late.
  2. Trying to “click” on a native alert: Cypress natively auto-accepts it, do not search for the button in the DOM.
  3. Stubbing prompt too late: Do it safely inside onBeforeLoad.
  4. Mixing native dialogs with HTML modals: React/Vue modals are *not* window.alert().

Conclusion

The highly professional way to reliably handle alerts in Cypress does not consist of “forcing clicks” on browser popups, but understanding the correct contract natively intended for each dialog. Everything is perfectly backed by the official documentation. When you implement it effectively, your tests predictably remain highly robust, perfectly clean, and seamlessly maintainable.

FAQ

How to handle an alert in Cypress? expand_more
Cypress automatically accepts native alerts and allows listening to the window:alert event to validate the displayed text. You cannot change the auto-accept behavior.
How to cancel a confirm in Cypress? expand_more
By listening to window:confirm and returning false from the callback. Cypress strictly documents that this cancels the confirmation natively.
How to handle a prompt in Cypress? expand_more
The recommended way is to stub window.prompt, and in E2E it must be done inside onBeforeLoad of cy.visit() so it occurs before the application loads.
What is the difference between cy.on() and Cypress.on()? expand_more
cy.on() applies to the current test and is automatically removed when finished. Cypress.on() is global and persists between tests.
Are stubs automatically restored between tests? expand_more
Yes. Cypress creates stubs in a Sinon sandbox and automatically resets or restores them between tests.
How to check a beforeunload in Cypress? expand_more
You can listen to window:before:unload and validate event properties, such as returnValue, to verify that the application triggered an exit warning.