Suggested resource: https://slides.com/bahmutov/decks/cypress-introduction
source: https://star-history.t9t.io/
People testing with Selenium / WebDriver / X
Cypress users?
No E2E tests
DOM
storage
location
cookies
Cypress tests run in the same browser
DOM
storage
location
cookies
Cypress acts as a proxy for your app
if (navigator.battery) {
readBattery(navigator.battery)
} else if (navigator.getBattery) {
navigator.getBattery().then(readBattery)
} else {
document.querySelector('.not-support').removeAttribute('hidden')
}
window.onload = function () {
// show updated status when the battery changes
battery.addEventListener('chargingchange', function () {
readBattery()
})
battery.addEventListener('levelchange', function () {
readBattery()
})
}
window.navigator.battery
context('navigator.battery', () => {
it('shows battery status of 50%', function () {
cy.visit('/', {
onBeforeLoad (win) {
// mock "navigator.battery" property
// returning mock charge object
win.navigator.battery = {
level: 0.5,
charging: false,
chargingTime: Infinity,
dischargingTime: 3600, // seconds
addEventListener: () => {}
}
}
})
// now we can assert actual text - we are charged at 50%
cy.get('.battery-percentage')
.should('be.visible')
.and('have.text', '50%')
// not charging means running on battery
cy.contains('.battery-status', 'Battery').should('be.visible')
// and has enough juice for 1 hour
cy.contains('.battery-remaining', '1:00').should('be.visible')
})
})
context('navigator.battery', () => {
it('shows battery status of 50%', function () {
cy.visit('/', {
onBeforeLoad (win) {
// mock "navigator.battery" property
// returning mock charge object
win.navigator.battery = {
level: 0.5,
charging: false,
chargingTime: Infinity,
dischargingTime: 3600, // seconds
addEventListener: () => {}
}
}
})
// now we can assert actual text - we are charged at 50%
cy.get('.battery-percentage')
.should('be.visible')
.and('have.text', '50%')
// not charging means running on battery
cy.contains('.battery-status', 'Battery').should('be.visible')
// and has enough juice for 1 hour
cy.contains('.battery-remaining', '1:00').should('be.visible')
})
})
it('deletes all heroes through UI', () => {
cy.visit('/heroes')
// confirm the heroes have loaded and select "delete" buttons
cy.get('ul.heroes li button.delete')
.should('have.length.gt', 0)
// and delete all heroes
.click({ multiple: true })
})
it('deletes all heroes through UI', () => {
cy.visit('/heroes')
// confirm the heroes have loaded and select "delete" buttons
cy.get('ul.heroes li button.delete')
.should('have.length.gt', 0)
// and delete all heroes
.click({ multiple: true })
})
// App code
constructor(private heroService: HeroService) {
// @ts-ignore
if (window.Cypress) {
// @ts-ignore
window.HeroesComponent = this
}
}
const getHeroesComponent = () =>
cy.window()
.should('have.property', 'HeroesComponent')
const getHeroes = () =>
getHeroesComponent().should('have.property', 'heroes')
const clearHeroes = () =>
getHeroes()
.then(heroes => {
cy.log(`clearing ${heroes.length} heroes`)
// @ts-ignore
heroes.length = 0
})
it('deletes all heroes through app action', () => {
cy.visit('/heroes')
getHeroes().should('have.length.gt', 0)
clearHeroes()
})
Application fetches a new list of fruits every 30 seconds
How do we:
a) confirm the displayed fruits?
b) run the test quickly?
/// <reference types="Cypress" />
describe('intercept', () => {
it('returns different fruits every 30 seconds', () => {
cy.clock()
// return difference responses on each call
// notice the order of the intercepts
cy.intercept('/favorite-fruits', ['kiwi 🥝']) // 3rd, 4th, etc
cy.intercept('/favorite-fruits', { times: 1 }, ['grapes 🍇']) // 2nd
cy.intercept('/favorite-fruits', { times: 1 }, ['apples 🍎']) // 1st
cy.visit('/fruits.html')
cy.contains('apples 🍎')
cy.tick(30000)
cy.contains('grapes 🍇')
// after using the first two intercepts
// forever reply with "kiwi" stub
cy.tick(30000)
cy.contains('kiwi 🥝')
cy.tick(30000)
cy.contains('kiwi 🥝')
cy.tick(30000)
cy.contains('kiwi 🥝')
})
})
Time-traveling debugger
cypress run --record --parallel
{
"retries": {
// Configure retry attempts for `cypress run`
// Default is 0
"runMode": 2,
// Configure retry attempts for `cypress open`
// Default is 0
"openMode": 0
}
}
npm install -D @cypress/code-coverage
// cypress/support/index.js
import '@cypress/code-coverage/support'
// cypress/plugins/index.js
module.exports = (on, config) => {
require('@cypress/code-coverage/task')(on, config)
// add other tasks to be registered here
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}
$ open coverage/lcov-report/index.html
Visit perfecto.io or follow @perfectomobile