Skip to content

Cypress DOM Assertions

Most end-to-end assertions ultimately check something about the DOM: is it visible, what does it contain, what class does it have. This lesson covers the DOM-specific assertions you will use constantly.

Chai-jQuery DOM Chainers

Cypress bundles Chai-jQuery, which adds DOM-aware assertion chainers on top of standard Chai. These let you check visibility, text content, attributes, CSS classes, and element counts directly against a jQuery-wrapped subject.

Because these are implicit assertions used with .should(), they automatically retry, waiting for the DOM to settle into the expected state rather than checking only once.

cy.get('[data-cy="alert"]')
  .should('be.visible')
  .and('have.class', 'alert-success')
  .and('contain', 'Saved successfully');

This checks visibility, a CSS class, and text content on the same element, retried together until all three pass.

Common DOM Assertion Syntax

.should('exist')
.should('not.exist')
.should('be.visible')
.should('be.hidden')
.should('have.class', 'active')
.should('have.attr', 'disabled')
.should('have.length', 3)
  • exist/not.exist checks presence in the DOM, independent of visibility.
  • be.visible/be.hidden checks whether an element is rendered and visible on screen.
  • have.class and have.attr check CSS classes and HTML attributes respectively.
  • have.length checks how many elements a selector matched.

DOM Assertions Cheat Sheet

The most commonly used Chai-jQuery assertion chainers for DOM elements.

Assertion Example Checks
Existence .should('exist') Element is present in the DOM
Non-existence .should('not.exist') Element is absent from the DOM
Visibility .should('be.visible') Element is rendered and visible
Hidden .should('be.hidden') Element exists but is not visible
Text content .should('have.text', 'Done') Exact text content
Contains text .should('contain', 'Done') Substring match
CSS class .should('have.class', 'active') Has a given class
Attribute .should('have.attr', 'href', '/x') Attribute exists with value
Element count .should('have.length', 3) Number of matched elements
Enabled state .should('be.disabled') Element is disabled

exist vs. be.visible: An Important Distinction

exist only checks that an element is present somewhere in the DOM, it says nothing about whether a user could actually see it. be.visible additionally checks that the element (and its ancestors) are not hidden via CSS, have non-zero dimensions, and are not positioned off-screen.

A common bug pattern is asserting exist when the intent was really to verify something is visible to the user, this can hide real rendering bugs where an element is technically present but invisible.

// Passes even if the modal is hidden via display: none
cy.get('[data-cy="modal"]').should('exist');

// Correctly fails if the modal isn't actually visible
cy.get('[data-cy="modal"]').should('be.visible');

have.text vs. contain

have.text requires an exact match of the element's full text content, including any incidental whitespace normalization Cypress applies. contain checks for a substring match, more forgiving when surrounding text might change.

  • Use have.text when the entire expected content is known and stable.
  • Use contain when only part of the text matters, or wording around it may change.
  • Both checks normalize some whitespace but are still sensitive to exact wording differences.

Common Mistakes

  • Using should('exist') when the actual intent is to confirm the element is visible to a real user.
  • Using have.text against content that includes dynamic, frequently changing text, causing brittle failures.
  • Forgetting that be.hidden means "exists but not visible", not "does not exist."
  • Checking have.length against a selector that might legitimately match zero elements in a valid application state.

Key Takeaways

  • Chai-jQuery adds DOM-specific assertions like be.visible, have.class, and have.attr.
  • exist and be.visible check different things, presence versus actual visibility.
  • have.text requires an exact match; contain allows a substring match.
  • DOM assertions retry automatically as implicit .should() checks.

Pro Tip

When in doubt between exist and be.visible, default to be.visible, it is a strictly stronger check that also confirms presence, and it more accurately reflects what a real user actually experiences on the page.