End-to-end Testing Mobile Apps with Ionic and Cypress
Hello! 👋🏽
Cecelia Martinez
- Success Engineer @ Cypress.io 🌲
- Atlanta, GA 🍑
- Women Who Code Track Evangelist 👩🏽💻
- Out in Tech Leadership Team 🌈
- @ceceliacreates 🐦
- github.com/ceceliacreates
- github.com/CypressCecelia
About Cypress
- Free and open-source Test Runner 🌲
- Runs in a browser alongside your application code 💻
- Mocha, Chai, and jQuery selectors built in ☕️
- Built-in waits and retries ⏱
- Time Travel, Error Reporting, Screenshots, and Videos for improved debugging 🐞
- Set viewport, access application state, simulate swipe motions 📱
Mobile testing in a browser?
When mobile development happens in a browser, why not?
Benefits
- No device-specific configuration required
- Access and manipulate app state
- Develop and test in JavaScript
Limitations
- Can't directly test native device functionality
- Mimics mobile experience by setting viewport
Getting started...
Getting started...
Install Cypress in root of project directory
git clone https://github.com/ionic-team/ionic-conference-app.git
cd ionic-conference-app
npm install cypress --save-dev
Getting started...
Cypress folder structure
/cypress
/fixtures
- example.json
/integration
- tests.spec.js
/plugins
- index.js
/support
- commands.js
- index.js
Getting started
Set baseUrl in cypress.json
/// cypress.json
{
"baseUrl": "http://localhost:8100"
}
Getting started...
// launch app
ionic serve
// THEN launch Cypress (separate terminal)
npx cypress open
Running the tests
Diving in...
/// tests.spec.js
describe("critical path", () => {
beforeEach(() => {
cy.viewport('iphone-5')
})
it('visits site', () => {
cy.visit('/')
})
})
Basic test structure
Diving in...
/// tests.spec.js cont.
it("swipes through tutorial", () => {
cy.enableTutorial();
cy.swipeLeft();
cy.swipeLeft();
cy.swipeLeft();
cy.contains("Continue").click();
})
it("adds a session from list to favorites", () => {
cy.disableTutorial();
cy.contains('University of Ionic').click({force: true});
cy.get('[data-cy=favorite]').click();
cy.get('[data-cy=back').click();
cy.contains('Favorites').click();
cy.contains('University of Ionic');
})
Critical path user flow
Diving in...
/// tests.spec.js
it("enables dark mode", () => {
cy.disableTutorial();
cy.get('[data-cy=menu]').click();
cy.get('[data-cy=dark-mode]').click();
cy.contains("Dark Mode").should('have.css', 'color', 'rgb(255, 255, 255)')
})
it("searches for a session and adds to favorites", () => {
cy.disableTutorial();
cy.get('[data-cy=search]').click();
cy.get('[data-cy=searchbar]').click().type("Angular{enter}")
cy.contains("Angular Directives").click();
cy.get('[data-cy=favorite]').click();
cy.get('[data-cy=back]').click();
cy.contains("Favorites").click();
cy.contains("Angular Directives");
})
Critical path user flow
Diving in...
Setting viewport
/// cypress.json
{
"viewportHeight": 320,
"viewportWidth": 568
}
/// spec.js
cy.viewport(320, 568)
cy.viewport('iphone-5')
cy.viewport('iphone-5', 'landscape')
/// mobile-ui.spec.js
describe('mobile-tests', () => {
beforeEach(() => {
cy.viewport('iphone-5')
})
/// Tests here
})
Setting viewport
App Storage
import { Storage } from '@ionic/storage';
const storage = new Storage;
storage.set('name', 'Cecelia');
storage.get('age').then((val) => {
console.log('Your age is', val);
});
Ionic Storage is a free and open-source storage option built in to Ionic
/// cypress/support/commands.js
import { Storage } from '@ionic/storage';
const storage = new Storage;
Cypress.Commands.add('enableTutorial', () => {
cy.visit('/', {
onBeforeLoad () {
storage.set('ion_did_tutorial', false)
}
})
})
App Storage
Custom Commands in Cypress
/// tests.spec.js
it("swipes through tutorial", () => {
cy.enableTutorial();
cy.swipeLeft();
cy.swipeLeft();
cy.swipeLeft();
cy.contains("Continue").click();
})
App Storage
Custom Commands in Cypress
App Storage
Swipe like a user
Cypress Custom Command + drag-and-drop example
/// cypress/support/commands.js
Cypress.Commands.add('swipeLeft', () => {
cy.get('.swiper-slide-active')
.trigger('mousedown', {position: "right"})
.trigger('mousemove', {clientX: 100, clientY: 275})
.trigger('mouseup', {force: true})
})
Swipe like a user
Use Custom Command in our test
/// cypress/support/commands.js
it("swipes through tutorial", () => {
cy.enableTutorial()
cy.swipeLeft()
cy.swipeLeft()
cy.swipeLeft()
cy.contains("Continue").click()
})
Swipe like a user
Putting it all together...
Installing Cypress
File structure
cypress.json baseUrl
Setting viewport
Cypress Custom Commands
Accessing app storage
simulate "swipe" functionality
The critical user path
Putting it all together...
deck
By Cecelia Martinez
deck
- 1,752