Core Technical Topics to Master in Cypress for Effective E2E Testing
End-to-end (E2E) testing is a crucial part of modern web development, ensuring that applications work as expected from the user’s…
Core Technical Topics to Master in Cypress for Effective E2E Testing
End-to-end (E2E) testing is a crucial part of modern web development, ensuring that applications work as expected from the user’s perspective. Cypress has emerged as a leading tool for E2E testing due to its speed, reliability, and developer-friendly features.
In this guide, we’ll explore the core technical topics you need to master in Cypress, including writing tests, best practices, and integrating Cypress into CI/CD pipelines.
1. Writing Cypress Tests (Selectors, Commands, Assertions)
Selectors
Cypress provides multiple ways to select DOM elements:
-
cy.get()
– Uses CSS selectors (e.g.,cy.get('.btn')
). -
cy.contains()
– Finds elements by text content (e.g.,cy.contains('Submit')
). -
data-*
attributes – Best practice for stable selectors (e.g.,cy.get('[data-test="login-button"]')
).
Commands & Assertions
Cypress chains commands for readability:
cy.visit('/login')
.get('\[data-test="username"\]').type('testuser')
.get('\[data-test="password"\]').type('password123')
.get('\[data-test="submit"\]').click()
.url().should('include', '/dashboard')
Common assertions:
-
.should('be.visible')
– Checks element visibility. -
.should('have.text', 'Success')
– Verifies text content.
Core Technical Topics to Master in Cypress for Effective E2E Testing
2. Page Object Model (POM) in Cypress
The Page Object Model (POM) improves test maintainability by encapsulating page logic:
// pages/LoginPage.js
class LoginPage {
visit() {
cy.visit('/login');
}
fillUsername(username) {
cy.get('\[data-test="username"\]').type(username);
}
submit() {
cy.get('\[data-test="submit"\]').click();
}
}
export default new LoginPage();
Usage in Tests:
import LoginPage from '../pages/LoginPage';
describe('Login Test', () => {
it('logs in successfully', () => {
LoginPage.visit();
LoginPage.fillUsername('testuser');
LoginPage.submit();
cy.url().should('include', '/dashboard');
});
});
Benefits:
✔ Reduces code duplication
✔ Easier maintenance
✔ Clear separation of concerns
3. Handling API Requests & Network Interception
cy.request()
for API Testing
Cypress can directly call APIs:
cy.request('POST', '/api/login', {
username: 'testuser',
password: 'password123'
}).then((response) => {
expect(response.status).to.eq(200);
});
cy.intercept()
for Mocking & Stubbing
Intercept and mock API calls:
cy.intercept('GET', '/api/users', {
fixture: 'users.json'
}).as('getUsers');
cy.visit('/dashboard');
cy.wait('@getUsers').then((interception) => {
expect(interception.response.body).to.have.length(3);
});
4. Running Tests on Different Viewports/Devices
Cypress supports responsive testing with cy.viewport()
:
describe('Responsive Test', () => {
it('displays correctly on mobile', () => {
cy.viewport('iphone-6');
cy.visit('/');
cy.get('.navbar-toggle').should('be.visible');
});
});
Common Viewports:
-
cy.viewport(1920, 1080)
(Desktop) -
cy.viewport('ipad-2')
(Tablet) -
cy.viewport('samsung-s10')
(Mobile)
5. Handling Test Flakiness & Retries
Causes of Flakiness:
- Dynamic content loading
- Unstable network requests
- Race conditions
Solutions:
✔ Use cy.wait()
with aliased requests.
✔ Implement retries in cypress.json
:
{
"retries": {
"runMode": 2,
"openMode": 0
}
}
✔ Avoid cy.wait(5000)
(prefer cy.get().should()
).
6. Using Cypress with GitHub/GitLab CI
GitHub Actions Example:
name: Cypress Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npx cypress run --headless
### GitLab CI Example:
stages:
- test
e2e:
stage: test
image: cypress/base:14
script:
- npm install
- npx cypress run --headless
Key CI Optimizations:
- Parallelization (
--parallel
) - Caching dependencies for faster runs
- Artifact storage for test videos/screenshots
Example Question: Structuring Cypress Tests for a Large React App
Best Practices:
✅ Modularize tests (e.g., auth
, dashboard
, settings
).
✅ Use POM for reusable page interactions.
✅ Mock APIs to avoid backend dependencies.
✅ Separate specs
by feature (e.g., login.spec.js
, checkout.spec.js
).
✅ Leverage custom commands for repetitive actions.
Example Structure:
/cypress
/fixtures
- users.json
/integration
/auth
- login.spec.js
- signup.spec.js
/dashboard
- overview.spec.js
/pages
- LoginPage.js
- DashboardPage.js
/support
- commands.js
Conclusion
Mastering Cypress involves understanding:
✔ Writing efficient tests (selectors, assertions).
✔ Using POM for scalability.
✔ Handling APIs & network calls.
✔ Responsive testing across devices.
✔ Reducing flakiness with retries.
✔ CI/CD integration for automated testing.
By applying these techniques, you can build reliable, maintainable, and fast E2E test suites for any web application.
🚀 Ready to supercharge your testing workflow? Start implementing these Cypress best practices today!
Further Reading:
Cypress #Testing #QA #Automation #WebDevelopment #JavaScript #ContinuousIntegration
Would you like a deeper dive into any of these topics? Let me know in the comments! 👇
By Mohamed Said Ibrahim on May 30, 2025.
Exported from Medium on October 2, 2025.
Top comments (0)