Use explicit TDD assertions with assert
assert to make TDD-style assertions about a specific subject.const person = {
name: 'Joe',
age: 20,
}
assert.isObject(person, 'value is object')website·Indexed 43 days ago
https://example.cypress.ioA collection of practical examples demonstrating Cypress commands and API usage, including querying with cy.get(), network requests via cy.request() and cy.intercept(), assertions using .should(), and managing storage, cookies, and viewports.
assert to make TDD-style assertions about a specific subject.const person = {
name: 'Joe',
age: 20,
}
assert.isObject(person, 'value is object')expect to make BDD-style assertions about a specific subject. Unlike .should(), expect is an explicit assertion and does not automatically retry.expect(true).to.be.true
const o = { foo: 'bar' }
expect(o).to.equal(o)
expect(o).to.deep.equal({ foo: 'bar' })
// Match text using regular expression
expect('FooBar').to.match(/bar$/i).should() command to make assertions about the current subject in a Cypress chain. This command is used to verify the state or behavior of an element, such as its class, text content, HTML, or visibility.cy.get('.assertion-table')
.find('tbody tr:last').should('have.class', 'success')
.find('td')
.first()
// Check text content
.should('have.text', 'Column content')
.should('contain', 'Column content')
.should('have.html', 'Column content')
// Check if element matches a selector
.should('match', 'td')
// Match text content against a regular expression
.invoke('text')
.should('match', /column content/i)
// Alternative: use cy.contains for regex text matching
cy.get('.assertion-table')
.find('tbody tr:last')
.contains('td', /column content/i)
.should('be.visible')data-cy or data-test) over CSS classes, IDs, or text content. Avoid generic selectors (like button) or those coupled to styling (like .btn-large).// ❌ Worst: Too generic
cy.get('button').click()
// ❌ Bad: Coupled to styling
cy.get('.btn.btn-large').click()
// ⚠️ Average: Coupled to HTML semantics
cy.get('[name=submission]').click()
// ⚠️ Better: Coupled to ID/Styling
cy.get('#main').click()
// ⚠️ Much better: Coupled to text (may change)
cy.contains('Submit').click()
// ✅ Best: Insulated from changes
cy.get('[data-cy=submit]').click()cy.spy() to wrap an existing method to track its calls without changing its behavior. cy.spy() retries until the assertions that follow it pass, making it useful for asynchronous operations.const obj = {
foo () {},
}
// Wrap method and create an alias
const spy = cy.spy(obj, 'foo').as('foo')
setTimeout(() => {
obj.foo()
}, 500)
// Assertion will retry until the spy has been called twice
cy.get('@foo').should('have.been.calledTwice')Use the .then() command to invoke a callback function with the current subject.
Behavioral rules for yielding values:
undefined, the original subject passed into .then() is yielded to the next command.// Example 1: Basic usage and returning a value
cy.wrap(1)
.then((num) => {
expect(num).to.equal(1)
return 2
})
.then((num) => {
expect(num).to.equal(2)
})
// Example 2: Returning undefined yields the original value
cy.wrap(1)
.then((num) => {
expect(num).to.equal(1)
// nothing returned
})
.then((num) => {
expect(num).to.equal(1)
})
// Example 3: Last Cypress command in block determines the yielded value
cy.wrap(1)
.then((num) => {
expect(num).to.equal(1)
cy.wrap(2) // This value is yielded
})
.then((num) => {
expect(num).to.equal(2)
})cy.clock() to freeze the browser's clock at a specific time (recommended to use UTC to ensure consistency across timezones). Use cy.tick() to move the clock forward by a specified number of milliseconds.// Set clock to a specific UTC date
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
cy.clock(now)
cy.visit('/your-page')
cy.get('#clock-div').click()
cy.get('#clock-div').should('have.text', '1489449600')
// Move time forward by 10 seconds
cy.tick(10000)
cy.get('#clock-div').click()
cy.get('#clock-div').should('have.text', '1489449610')When built-in assertions are insufficient, pass a callback function to .should(). Cypress will retry the entire callback function until all explicit assertions inside it pass or the command times out. This is particularly useful for:
// Example 1: Complex checks on multiple elements
cy.get('.assertions-p').find('p')
.should(($p) => {
let texts = $p.map((i, el) => Cypress.$(el).text()).get()
expect(texts).to.have.length(3)
expect(texts, 'has expected text in each paragraph').to.deep.eq([
'Some text from first p',
'More text from second p',
'And even more text from third p',
])
})
// Example 2: Retrying until a value is parsed correctly
cy.get('#random-number')
.should(($div) => {
const n = parseFloat($div.text())
expect(n).to.be.gte(1).and.be.lte(10)
})
// Example 3: Comparing two elements
let text
cy.get('.two-elements').find('.first').then(($first) => {
text = $first.text().toLowerCase().replace(/\s/g, '')
})
cy.get('.two-elements').find('.second').should(($div) => {
const secondText = $div.text().toLowerCase().replace(/\s/g, '')
expect(secondText, 'second text').to.equal(text)
})
cy.fixture() command (which can be aliased to the test context this) or synchronously using the JavaScript require() function via the built-in bundler.// Synchronous load using require
const requiredExample = require('../../fixtures/example')
beforeEach(() => {
// Asynchronous load and alias to test context
cy.fixture('example.json').as('example')
})
it('compare fixture and require', function () {
// Access aliased fixture via 'this'
expect(this.example).to.deep.equal(requiredExample)
// Or use cy.wrap
cy.wrap(this.example).should('deep.equal', requiredExample)
})
cy.stub() to replace a function with a stub. This allows you to control the return value, throw errors, or track calls. You can use .callThrough() to allow non-matched calls to execute the original method.const greeter = {
greet (name) {
return `Hello, ${name}!`
},
}
cy.stub(greeter, 'greet')
.callThrough() // Original method is called if no matchers apply
.withArgs(Cypress.sinon.match.string).returns('Hi')
.withArgs(Cypress.sinon.match.number).throws(new Error('Invalid name'))
expect(greeter.greet('World')).to.equal('Hi')
expect(() => greeter.greet(42)).to.throw('Invalid name')You can pass response data to subsequent requests using .then() or save data to the shared test context using .as().
Important: When using .as() to save an alias, you must use the function () { ... } callback syntax instead of arrow functions to access the shared context via this.
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
.its('body.0')
.as('user') // saves the object in the test context
.then(function () {
// Use function() syntax to access 'this.user'
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
userId: this.user.id,
title: 'Cypress Test Runner',
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
})
.its('body').as('post')
})
.then(function () {
expect(this.post).property('userId').to.equal(this.user.id)
}).as() command to assign a name (alias) to a DOM element or a network intercept. This avoids repeating long selector chains and allows you to reference the element or request later in the test by prefixing the alias name with @.// 1. Aliasing a DOM element to avoid repeating a complex selector
cy.get('.as-table')
.find('tbody>tr').first()
.find('td').first()
.find('button').as('firstBtn')
// Reference the alias using '@'
cy.get('@firstBtn').click()
cy.get('@firstBtn').should('have.class', 'btn-success')
// 2. Aliasing a network route to wait for a response
cy.intercept('GET', '**/comments/*').as('getComment')
// Trigger the action that causes the network request
cy.get('.network-btn').click()
// Wait for the aliased route and assert on the response
cy.wait('@getComment').its('response.statusCode').should('eq', 200)