Files
cypress/docs/source/api/commands/and.md
T
2017-05-24 13:08:27 -04:00

6.4 KiB

title, comments, description
title comments description
and true

.and is an alias of .should and is used in making assertions.

You'd typically use cy.and when you are making multiple assertions about the same subject.

{% note info New to Cypress? %} Read about Making Assertions first. {% endnote %}

Syntax

.and(chainers)
.and(chainers, value)
.and(chainers, method, value)
.and(function() {})

Usage

.and() requires being chained off another cy command.

{% fa fa-check-circle green %} Valid Usage

cy.get('.error').should('be.empty').and('be.hidden') // Yields '.error' el
cy.contains('Login').and('be.visible')               // Yields el containing Login

{% fa fa-exclamation-triangle red %} Invalid Usage

cy.and('eq', '42')   // Errors, cannot be chained off 'cy'

Arguments

{% fa fa-angle-right %} chainers (String)

Chainers that come from Chai or Chai-jQuery

{% fa fa-angle-right %} value (String)

Value to assert against chainer.

{% fa fa-angle-right %} method (String)

A method to be called on the chainer.

{% fa fa-angle-right %} function (Function)

Pass a function that can have any number of explicit assertions within it. Whatever was passed to the function is what is yielded.

Yields

In most cases, .and() yields the previous cy command's yield.

cy
  .get('nav')                       // yields <nav>
  .should('be.visible')             // yields <nav>
  .and('have.class', 'open')        // yields <nav>

Although some chainers change what is yielded. In the example below, .and() yields the String 'sans-serif' because the chainer have.css, 'font-family' yields a string.

cy
  .get('nav')                       // yields <nav>
  .should('be.visible')             // yields <nav>
  .and('have.css', 'font-family')   // yields 'sans-serif'

Timeout

.and will continue to retry the assertion to the duration of the previous cy commands timeout or the defaultCommandTimeout](https://on.cypress.io/guides/configuration#timeouts)

cy.get('input', {timeout: 10000}).should('have.value', '10').and('have.class', 'error')
                         
      // timeout here will be passed down to the '.and()'
      // and it will retry for up to 10 secs

Examples

Chainers

Chain assertions on the same subject

cy.get('button').should('have.class', 'active').and('not.be.disabled')

Chainers with Value

Chain assertions when yield changes

<!-- App Code -->
<ul>
  <li>
    <a href="users/123/edit">Edit User</a>
  </li>
</ul>
cy
  .get('a')
  .should('contain', 'Edit User') // yields <a>
  .and('have.attr', 'href')       // yields string value of href
  .and('match', /users/)          // yields string value of href
  .and('not.include', '#')        // yields string value of href

Chainers with Method and Value

Assert the href is equal to '/users'

cy
  .get('#header a')
  .should('have.class', 'active')
  .and('have.attr', 'href', '/users')

Function

Verify length, content, and classes from multiple <p>

Passing a function to cy.and enables you to assert on arbitrary subjects. This gives you the opportunity to massage what you'd like to assert.

Just be sure not to include any code that has side effects in your callback function.

The callback function will be retried over and over again until no assertions within it throw.

<div>
  <p class="text-primary">Hello World</p>
  <p class="text-danger">You have an error</p>
  <p class="text-default">Try again later</p>
</div>
cy
  .get('p')
  .should('not.be.empty')
  .and(function($p){
    expect($p).to.have.length(3)
    expect($p.first()).to.contain('Hello World')

    // use jquery's map to grab all of their classes
    // jquery's map returns a new jquery object
    var classes = $p.map(function(i, el){
      return cy.$(el).attr('class')
    })

    // call classes.get() to make this a plain array
    expect(classes.get()).to.deep.eq([
      'text-primary',
      'text-danger',
      'text-default'
    ])
  })

Using a callback function will not change what is yielded

Whatever is returned in the function is ignored. Cypress always forces the command to yield the value from the previous cy command's yield (which in the example below is <button>)

cy
  .get('button')
  .should('be.active')
  .and(function($button){
    expect({foo: 'bar'}).to.deep.eq({foo: 'bar'})
    return {foo: 'bar'} // return is ignored, .and() yields <button>
  })
  .then(function($button){
    // do anything we want with <button>
  })

Notes

Similarities to Chai

If you've worked in Chai before, you will recognize that .and() matches the same fluent assertion syntax.

Take this explicit assertion for example:

expect({foo: 'bar'}).to.have.property('foo').and.eq('bar')

cy.and reproduces this same assertion behavior.

How do I know which assertions change the subject and which keep it the same?

The chainers that come from Chai or Chai-jQuery will always document what they return.

Alternatively, it is very easy to use Cypress itself to figure this out.

You can read more about debugging assertions here.

Command Log

Chain assertions on the same subject

cy
  .get('.list')
  .find('input[type="checkbox"]')
    .should('be.checked')
    .and('not.be.disabled')

The commands above will display in the command log as:

screen shot 2015-11-29 at 12 16 46 pm

When clicking on assert within the command log, the console outputs the following:

screen shot 2015-11-29 at 12 17 03 pm

See also