title |
---|
and |
Create an assertion. Assertions are automatically retried until they pass or time out.
{% note info %}
An alias of {% url .should()
should %}
{% endnote %}
{% note info %}
Note: .and()
assumes you are already familiar with core concepts such as {% url 'assertions' introduction-to-cypress#Assertions %}
{% endnote %}
.and(chainers)
.and(chainers, value)
.and(chainers, method, value)
.and(callbackFn)
{% fa fa-check-circle green %} Correct Usage
cy.get('.err').should('be.empty').and('be.hidden') // Assert '.err' is empty & hidden
cy.contains('Login').and('be.visible') // Assert el is visible
cy.wrap({ foo: 'bar' })
.should('have.property', 'foo') // Assert 'foo' property exists
.and('eq', 'bar') // Assert 'foo' property is 'bar'
{% fa fa-exclamation-triangle red %} Incorrect Usage
cy.and('eq', '42') // Errors, cannot be chained off 'cy'
{% fa fa-angle-right %} chainers (String)
Any valid chainer that comes from {% url 'Chai' assertions#Chai %} or {% url 'Chai-jQuery' assertions#Chai-jQuery %} or {% url 'Sinon-Chai' assertions#Sinon-Chai %}.
{% 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 %} callbackFn (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 assertion_indeterminate .and %}
cy
.get('nav') // yields <nav>
.should('be.visible') // yields <nav>
.and('have.class', 'open') // yields <nav>
However, some chainers change the subject. In the example below, .and()
yields the string sans-serif
because the chainer have.css, 'font-family'
changes the subject.
cy
.get('nav') // yields <nav>
.should('be.visible') // yields <nav>
.and('have.css', 'font-family') // yields 'sans-serif'
.and('match', /serif/) // yields 'sans-serif'
cy.get('button').should('have.class', 'active').and('not.be.disabled')
<!-- 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
cy
.get('#header a')
.should('have.class', 'active')
.and('have.attr', 'href', '/users')
Passing a function to .and()
enables you to assert on the yielded subject. 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(($p) => {
// should have found 3 elements
expect($p).to.have.length(3)
// make sure the first contains some text content
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
const classes = $p.map((i, el) => {
return Cypress.$(el).attr('class')
})
// call classes.get() to make this a plain array
expect(classes.get()).to.deep.eq([
'text-primary',
'text-danger',
'text-default'
])
})
{% note info %} Using a callback function {% urlHash 'will not change the subject' Subjects %} {% endnote %}
If you've worked in {% url "Chai" http://chaijs.com/ %} 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')
.and()
reproduces this same assertion behavior.
The chainers that come from {% url 'Chai' bundled-tools#Chai %} or {% url 'Chai-jQuery' bundled-tools#Chai-jQuery %} will always document what they return.
Whenever you use a callback function, its return value is always 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(($button) => {
expect({ foo: 'bar' }).to.deep.eq({ foo: 'bar' })
return { foo: 'bar' } // return is ignored, .and() yields <button>
})
.then(($button) => {
// do anything we want with <button>
})
{% partial then_should_difference %}
{% requirements child .and %}
{% timeouts timeouts .and %}
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
cy.get('input', {timeout: 10000}).should('have.value', 'US').and(($input) => {
↲
// timeout here will be passed down to the '.and()'
// unless an assertion throws earlier,
// ALL of the assertions will retry for up to 10 secs
expect($input).to.not.be('disabled')
expect($input).to.not.have.class('error')
})
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:
{% imgTag /img/api/and/cypress-and-command-log.png "Command log for assertions" %}
When clicking on assert
within the command log, the console outputs the following:
{% imgTag /img/api/and/cypress-assertions-console-log.png "console.log for assertions" %}
- {% url
.should()
should %} - {% url 'Guide: Introduction to Cypress' introduction-to-cypress#Assertions %}
- {% url 'Reference: List of Assertions' assertions %}