---
id: app/references/assertions
title: 'Assertions in Cypress: A Guide'
description: >-
  Assertions available in Cypress with Chai, Chai-jQuery, and Sinon-Chai
  assertions
section: app
source_path: docs/app/references/assertions.mdx
version: ce02913654e2655ee63448bdc92bb92c7b46a619
updated_at: '2026-04-22T19:37:51.587Z'
---
# Assertions

##### &#x20;What you'll learn

- Assertions available in Cypress with Chai, Chai-jQuery, and Sinon-Chai assertions
- How to write assertions for common use cases
- How to chain assertions together

Cypress bundles the popular [Chai](/llm/markdown/app/references/assertions.md#Chai) assertion
library, as well as helpful extensions for
[Sinon](/llm/markdown/app/references/assertions.md#Sinon-Chai) and
[jQuery](/llm/markdown/app/references/assertions.md#Chai-jQuery), bringing you dozens of
powerful assertions for free.

If you're looking to understand **how** to use these assertions please read
about assertions in our
[Introduction to Cypress](/llm/markdown/app/core-concepts/introduction-to-cypress.md#Assertions)
guide.

## Chai

Icon

These chainers are available for BDD assertions (`expect`/`should`). Aliases
listed can be used interchangeably with their original chainer. You can see the
entire list of available BDD Chai assertions [here](http://chaijs.com/api/bdd/).

| Chainer                                                          | Example                                                                                                                                                                                              |
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| not                                                              | `.should('not.equal', 'Jane')``expect(name).to.not.equal('Jane')`                                                                                                                                    |
| deep                                                             | `.should('deep.equal', { name: 'Jane' })``expect(obj).to.deep.equal({ name: 'Jane' })`                                                                                                               |
| nested                                                           | `.should('have.nested.property', 'a.b[1]')``.should('nested.include', {'a.b[1]': 'y'})``expect({a: {b: 'x'}}).to.have.nested.property('a.b')``expect({a: {b: 'x'}}).to.nested.include({'a.b': 'x'})` |
| ordered                                                          | `.should('have.ordered.members', [1, 2])``expect([1, 2]).to.have.ordered.members([1, 2])``expect([1, 2]).not.to.have.ordered.members([2, 1])`                                                        |
| any                                                              | `.should('have.any.keys', 'age')``expect(arr).to.have.any.keys('age')`                                                                                                                               |
| all                                                              | `.should('have.all.keys', 'name', 'age')``expect(arr).to.have.all.keys('name', 'age')`                                                                                                               |
| a(*type*) Aliases: an                                            | `.should('be.a', 'string')``expect('test').to.be.a('string')`                                                                                                                                        |
| include(*value*) Aliases: contain, includes, contains            | `.should('include', 2)``expect([1,2,3]).to.include(2)`                                                                                                                                               |
| ok                                                               | `.should('not.be.ok')``expect(undefined).to.not.be.ok`                                                                                                                                               |
| true                                                             | `.should('be.true')``expect(true).to.be.true`                                                                                                                                                        |
| false                                                            | `.should('be.false')``expect(false).to.be.false`                                                                                                                                                     |
| null                                                             | `.should('be.null')``expect(null).to.be.null`                                                                                                                                                        |
| undefined                                                        | `.should('be.undefined')``expect(undefined).to.be.undefined`                                                                                                                                         |
| exist                                                            | `.should('exist')``expect(myVar).to.exist`                                                                                                                                                           |
| empty                                                            | `.should('be.empty')``expect([]).to.be.empty`                                                                                                                                                        |
| arguments Aliases: Arguments                                     | `.should('be.arguments')``expect(arguments).to.be.arguments`                                                                                                                                         |
| equal(*value*) Aliases: equals, eq                               | `.should('equal', 42)``expect(42).to.equal(42)`                                                                                                                                                      |
| deep.equal(*value*)                                              | `.should('deep.equal', { name: 'Jane' })``expect({ name: 'Jane' }).to.deep.equal({ name: 'Jane' })`                                                                                                  |
| eql(*value*) Aliases: eqls                                       | `.should('eql', { name: 'Jane' })``expect({ name: 'Jane' }).to.eql({ name: 'Jane' })`                                                                                                                |
| greaterThan(*value*) Aliases: gt, above                          | `.should('be.greaterThan', 5)``expect(10).to.be.greaterThan(5)`                                                                                                                                      |
| least(*value*)Aliases: gte                                       | `.should('be.at.least', 10)``expect(10).to.be.at.least(10)`                                                                                                                                          |
| lessThan(*value*) Aliases: lt, below                             | `.should('be.lessThan', 10)``expect(5).to.be.lessThan(10)`                                                                                                                                           |
| most(*value*) Aliases: lte                                       | `.should('have.length.of.at.most', 4)``expect('test').to.have.length.of.at.most(4)`                                                                                                                  |
| within(*start*, *finish*)                                        | `.should('be.within', 5, 10)``expect(7).to.be.within(5, 10)`                                                                                                                                         |
| instanceOf(*constructor*) Aliases: instanceof                    | `.should('be.instanceOf', Array)``expect([1, 2, 3]).to.be.instanceOf(Array)`                                                                                                                         |
| property(*name*, *\[value]*)                                     | `.should('have.property', 'name')``expect(obj).to.have.property('name')`                                                                                                                             |
| deep.property(*name*, *\[value]*)                                | `.should('have.deep.property', 'tests[1]', 'e2e')``expect(deepObj).to.have.deep.property('tests[1]', 'e2e')`                                                                                         |
| ownProperty(*name*) Aliases: haveOwnProperty, own.property       | `.should('have.ownProperty', 'length')``expect('test').to.have.ownProperty('length')`                                                                                                                |
| ownPropertyDescriptor(*name*) Aliases: haveOwnPropertyDescriptor | `.should('have.ownPropertyDescriptor', 'a')``expect({a: 1}).to.have.ownPropertyDescriptor('a')`                                                                                                      |
| lengthOf(*value*)                                                | `.should('have.lengthOf', 4)``expect('test').to.have.lengthOf(4)`                                                                                                                                    |
| match(*RegExp*) Aliases: matches                                 | `.should('to.match', /^test/)``expect('testing').to.match(/^test/)`                                                                                                                                  |
| string(*string*)                                                 | `.should('have.string', 'test')``expect('testing').to.have.string('test')`                                                                                                                           |
| keys(*key1*, *\[key2]*, *\[...]*) Aliases: key                   | `.should('have.keys', 'pass', 'fail')``expect({ pass: 1, fail: 2 }).to.have.keys('pass', 'fail')`                                                                                                    |
| throw(*constructor*) Aliases: throws, Throw                      | `.should('throw', Error)``expect(fn).to.throw(Error)`                                                                                                                                                |
| respondTo(*method*) Aliases: respondsTo                          | `.should('respondTo', 'getName')``expect(obj).to.respondTo('getName')`                                                                                                                               |
| itself                                                           | `.should('itself.respondTo', 'getName')``expect(Foo).itself.to.respondTo('bar')`                                                                                                                     |
| satisfy(*method*) Aliases: satisfies                             | `.should('satisfy', (num) => num > 0)``expect(1).to.satisfy((num) => num > 0)`                                                                                                                       |
| closeTo(*expected*, *delta*) Aliases: approximately              | `.should('be.closeTo', 1, 0.5)``expect(1.5).to.be.closeTo(1, 0.5)`                                                                                                                                   |
| members(*set*)                                                   | `.should('include.members', [3, 2])``expect([1, 2, 3]).to.include.members([3, 2])`                                                                                                                   |
| oneOf(*values*)                                                  | `.should('be.oneOf', [1, 2, 3])``expect(2).to.be.oneOf([1,2,3])`                                                                                                                                     |
| change(*function*) Aliases: changes                              | `.should('change', obj, 'val')``expect(fn).to.change(obj, 'val')`                                                                                                                                    |
| increase(*function*) Aliases: increases                          | `.should('increase', obj, 'val')``expect(fn).to.increase(obj, 'val')`                                                                                                                                |
| decrease(*function*) Aliases: decreases                          | `.should('decrease', obj, 'val')``expect(fn).to.decrease(obj, 'val')`                                                                                                                                |

These getters are also available for BDD assertions. They don't actually do
anything, but they enable you to write clear, English sentences.

| Chainable getters                                                                           |
| ------------------------------------------------------------------------------------------- |
| `to`, `be`, `been`, `is`, `that`, `which`, `and`, `has`, `have`, `with`, `at`, `of`, `same` |

## Chai-jQuery

Icon

These chainers are available when asserting about a DOM object.

You will commonly use these chainers after using DOM commands like:
[`cy.get()`](/llm/markdown/api/commands/get.md), [`cy.contains()`](/llm/markdown/api/commands/contains.md), etc.

/\* textlint-disable \*/

| Chainers                 | Assertion                                                                                                              |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| attr(*name*, *\[value]*) | `.should('have.attr', 'bar')``expect($el).to.have.attr('foo', 'bar')`                                                  |
| prop(*name*, *\[value]*) | `.should('have.prop', 'disabled', false)``expect($el).to.have.prop('disabled', false)`                                 |
| css(*name*, *\[value]*)  | `.should('have.css', 'background-color', 'rgb(0, 0, 0)')``expect($el).to.have.css('background-color', 'rgb(0, 0, 0)')` |
| data(*name*, *\[value]*) | `.should('have.data', 'foo', 'bar')``expect($el).to.have.data('foo', 'bar')`                                           |
| class(*className*)       | `.should('have.class', 'foo')``expect($el).to.have.class('foo')`                                                       |
| id(*id*)                 | `.should('have.id', 'foo')``expect($el).to.have.id('foo')`                                                             |
| html(*html*)             | `.should('have.html', 'I love testing')``expect($el).to.have.html('with Cypress')`                                     |
| text(*text*)             | `.should('have.text', 'I love testing')``expect($el).to.have.text('with Cypress')`                                     |
| value(*value*)           | `.should('have.value', 'test@dev.com')``expect($el).to.have.value('test@dev.com')`                                     |
| visible                  | `.should('be.visible')``expect($el).to.be.visible`                                                                     |
| hidden                   | `.should('be.hidden')``expect($el).to.be.hidden`                                                                       |
| selected                 | `.should('be.selected')``expect($option).not.to.be.selected`                                                           |
| checked                  | `.should('be.checked')``expect($input).not.to.be.checked`                                                              |
| focus\[ed]               | `.should('have.focus')``expect($input).not.to.be.focused``expect($input).to.have.focus`                                |
| enabled                  | `.should('be.enabled')``expect($input).to.be.enabled`                                                                  |
| disabled                 | `.should('be.disabled')``expect($input).to.be.disabled`                                                                |
| empty                    | `.should('be.empty')``expect($el).not.to.be.empty`                                                                     |
| exist                    | `.should('exist')``expect($nonexistent).not.to.exist`                                                                  |
| match(*selector*)        | `.should('match', ':empty')``expect($emptyEl).to.match(':empty')`                                                      |
| contain(*text*)          | `.should('contain', 'text')``expect($el).to.contain('text')`                                                           |
| descendants(*selector*)  | `.should('have.descendants', 'div')``expect($el).to.have.descendants('div')`                                           |

/\* textlint-enable \*/

## Sinon-Chai

Icon

These chainers are used on assertions with [`cy.stub()`](/llm/markdown/api/commands/stub.md) and
[`cy.spy()`](/llm/markdown/api/commands/spy.md).

| Sinon.JS property/method | Assertion                                                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| called                   | `.should('have.been.called')``expect(spy).to.be.called`                                                             |
| callCount                | `.should('have.callCount', 3)``expect(spy).to.have.callCount(n)`                                                    |
| calledOnce               | `.should('have.been.calledOnce')``expect(spy).to.be.calledOnce`                                                     |
| calledTwice              | `.should('have.been.calledTwice')``expect(spy).to.be.calledTwice`                                                   |
| calledThrice             | `.should('have.been.calledThrice')``expect(spy).to.be.calledThrice`                                                 |
| calledBefore             | `.should('have.been.calledBefore', spy2)``expect(spy1).to.be.calledBefore(spy2)`                                    |
| calledAfter              | `.should('have.been.calledAfter', spy2)``expect(spy1).to.be.calledAfter(spy2)`                                      |
| calledWithNew            | `.should('have.been.calledWithNew')``expect(spy).to.be.calledWithNew`                                               |
| alwaysCalledWithNew      | `.should('have.always.been.calledWithNew')``expect(spy).to.always.be.calledWithNew`                                 |
| calledOn                 | `.should('have.been.calledOn', context)``expect(spy).to.be.calledOn(context)`                                       |
| alwaysCalledOn           | `.should('have.always.been.calledOn', context)``expect(spy).to.always.be.calledOn(context)`                         |
| calledWith               | `.should('have.been.calledWith', ...args)``expect(spy).to.be.calledWith(...args)`                                   |
| alwaysCalledWith         | `.should('have.always.been.calledWith', ...args)``expect(spy).to.always.be.calledWith(...args)`                     |
| calledOnceWith           | `.should('have.been.calledOnceWith', ...args)``expect(spy).to.be.calledOnceWith(...args)`                           |
| calledWithExactly        | `.should('have.been.calledWithExactly', ...args)``expect(spy).to.be.calledWithExactly(...args)`                     |
| alwaysCalledWithExactly  | `.should('have.always.been.calledWithExactly', ...args)``expect(spy).to.always.be.calledWithExactly(...args)`       |
| calledOnceWithExactly    | `.should('have.been.calledOnceWithExactly', ...args)``expect(spy).to.be.calledOnceWithExactly(...args)`             |
| calledWithMatch          | `.should('have.been.calledWithMatch',...args)``expect(spy).to.be.calledWithMatch(...args)`                          |
| alwaysCalledWithMatch    | `.should('have.always.been.calledWithMatch',...args)``expect(spy).to.always.be.calledWithMatch(...args)`            |
| returned                 | `.should('have.returned', 'foo')``expect(spy).to.have.returned(returnVal)`                                          |
| alwaysReturned           | `.should('have.always.returned', 'foo')``expect(spy).to.have.always.returned(returnVal)`                            |
| threw                    | `.should('have.thrown', TypeError)``expect(spy).to.have.thrown(errorObjOrErrorTypeStringOrNothing)`                 |
| alwaysThrew              | `.should('have.always.thrown', 'TypeError')``expect(spy).to.have.always.thrown(errorObjOrErrorTypeStringOrNothing)` |

## Adding New Assertions

Because we are using `chai`, that means you can extend it however you'd like.
Cypress will "just work" with new assertions added to `chai`. You can:

- Write your own `chai` assertions as
  [documented here](https://chaijs.com/guide/helpers/).
- npm install any existing `chai` library and import into your test file or
  [support file](/llm/markdown/app/core-concepts/writing-and-organizing-tests.md#Support-file).

[Check out our example recipe extending chai with new assertions.](/llm/markdown/app/references/recipes.md#Fundamentals)

## Common Assertions

Here is a list of common element assertions. Notice how we use these assertions
(listed above) with [`.should()`](/llm/markdown/api/commands/should.md). You may also want to
read about how Cypress [retries](/llm/markdown/app/core-concepts/retry-ability.md)
assertions.

### Length

```javascript
// retry until we find 3 matching <li.selected>
cy.get('li.selected').should('have.length', 3)
```

### Class

```javascript
// retry until this input does not have class disabled
cy.get('form').find('input').should('not.have.class', 'disabled')
```

### Value

```javascript
// retry until this textarea has the correct value
cy.get('textarea').should('have.value', 'foo bar baz')
```

### Text Content

```javascript
// assert the element's text content is exactly the given text
cy.get('[data-testid="user-name"]').should('have.text', 'Joe Smith')
// assert the element's text includes the given substring
cy.get('[data-testid="address"]').should('include.text', 'Atlanta')
// retry until this span does not contain 'click me'
cy.get('a').parent('span.help').should('not.contain', 'click me')
// the element's text should start with "Hello"
cy.get('[data-testid="greeting"]')
  .invoke('text')
  .should('match', /^Hello/)
// use cy.contains to find an element with its text
// matching the given regular expression
cy.contains('[data-testid="greeting"]', /^Hello/)
```

**Tip:** read about assertions against text with non-breaking space entities in
[How do I get an element's text contents?](/llm/markdown/app/faq.md#How-do-I-get-an-elements-text-contents)

### Visibility

```javascript
// retry until the element with
// data-testid "form-submit" is visible
cy.get('[data-testid="form-submit"]').should('be.visible')
// retry until the list item with
// text "write tests" is visible
cy.contains('[data-testid="todo"] li', 'write tests').should('be.visible')
```

**Note:** if there are multiple elements, the assertions `be.visible` and
`not.be.visible` act differently:

```javascript
// retry until SOME elements are visible
cy.get('li').should('be.visible')
// retry until EVERY element is invisible
cy.get('li.hidden').should('not.be.visible')
```

Watch the short video
["Multiple elements and should('be.visible') assertion"](https://www.youtube.com/watch?v=LxkrhUEE2Qk)
that shows how to correctly check the visibility of elements.

**Visibility Semantics**

For detailed information about how Cypress determines element visibility, including the default behavior and the experimental fast visibility algorithm, see [Visibility](/llm/markdown/app/core-concepts/interacting-with-elements.md#Visibility).

### Existence

```javascript
// retry until loading spinner no longer exists
cy.get('[data-testid="loading"]').should('not.exist')
```

### State

```javascript
// retry until our radio is checked
cy.get(':radio').should('be.checked')
```

### CSS

```javascript
// retry until element has matching css
cy.get('[data-testid="completed"]').should(
  'have.css',
  'text-decoration',
  'line-through'
)
```

```javascript
// retry while accordion css has the
// "display: none" property
cy.get('[data-testid="accordion"]').should('not.have.css', 'display', 'none')
```

### Disabled property

```html
<input type="text" data-testid="example-input" disabled />
```

```javascript
cy.get('[data-testid="example-input"]')
  .should('be.disabled')
  // let's enable this element from the test
  .invoke('prop', 'disabled', false)

cy.get('[data-testid="example-input"]')
  // we can use "enabled" assertion
  .should('be.enabled')
  // or negate the "disabled" assertion
  .and('not.be.disabled')
```

## Negative assertions

There are positive and negative assertions. Examples of positive assertions are:

```javascript
cy.get('[data-testid="todo-item"]')
  .should('have.length', 2)
  .and('have.class', 'completed')
```

The negative assertions have the "not" chainer prefixed to the assertion.
Examples of negative assertions are:

```javascript
cy.contains('first todo').should('not.have.class', 'completed')
cy.get('[data-testid="loading"]').should('not.be.visible')
```

### &#x20;False passing tests

Negative assertions may pass for reasons you weren't expecting. Let's say we
want to test that a Todo list app adds a new Todo item after typing the Todo and
pressing enter.

**Positive assertions**

When adding an element to the list and using a **positive assertion**, the test
asserts a specific number of Todo items in our application.

The test below may still falsely pass if the application behaves unexpectedly,
like adding a blank Todo, instead of adding the new Todo with the text "Write
tests".

```javascript
cy.get('[data-testid="todos"]').should('have.length', 2)
cy.get('[data-testid="new-todo"]').type('Write tests{enter}')

// using a positive assertion to check the
// exact number of items
cy.get('[data-testid="todos"]').should('have.length', 3)
```

**Negative assertions**

But when using a **negative assertion** in the test below, the test can falsely
pass when the application behaves in multiple unexpected ways:

- The app deletes the entire list of Todo items instead of inserting the 3rd
  Todo
- The app deletes a Todo instead of adding a new Todo
- The app adds a blank Todo

```javascript
cy.get('[data-testid="todos"]').should('have.length', 2)
cy.get('[data-testid="new-todo"]').type('Write tests{enter}')

// using negative assertion to check it's
// not a number of items
cy.get('[data-testid="todos"]').should('not.have.length', 2)
```

## Should callback

If built-in assertions are not enough, you can write your own assertion function
and pass it as a callback to the `.should()` command. Cypress will automatically
[retry](/llm/markdown/app/core-concepts/retry-ability.md) the callback function until it
passes or the command times out. See the
[`.should()`](/llm/markdown/api/commands/should.md#Function) documentation.

```html
<div class="main-abc123 heading-xyz987">Introduction</div>
```

```javascript
cy.get('div').should(($div) => {
  expect($div).to.have.length(1)

  const className = $div[0].className

  // className will be a string like "main-abc123 heading-xyz987"
  expect(className).to.match(/heading-/)
})
```

## Multiple assertions

You can attach multiple assertions to the same command.

```html
<a
  data-testid="assertions-link"
  class="active"
  href="https://on.cypress.io"
  target="_blank"
>
  Cypress Docs
</a>
```

```js
cy.get('[data-testid="assertions-link"]')
  .should('have.class', 'active')
  .and('have.attr', 'href')
  .and('include', 'cypress.io')
```

Note that all chained assertions will use the same reference to the original
subject. For example, if you wanted to test a loading element that first appears
and then disappears, the following WILL NOT WORK because the same element cannot
be visible and invisible at the same time:

```js
// ⛔️ DOES NOT WORK
cy.get('[data-testid="loading"]').should('be.visible').and('not.be.visible')
```

Instead you should split the assertions and re-query the element:

```js
// ✅ THE CORRECT WAY
cy.get('[data-testid="loading"]').should('be.visible')
cy.get('[data-testid="loading"]').should('not.be.visible')
```

## See also

- [Guide: Introduction to Cypress](/llm/markdown/app/core-concepts/introduction-to-cypress.md#Assertions)
- [cypress-example-kitchensink Assertions](https://example.cypress.io/commands/assertions)
