Complete E-commerce Checkout Flow Testing
This project demonstrates comprehensive end-to-end testing for an e-commerce application using Cypress. It covers the complete user journey from login to checkout, ensuring all critical paths work correctly.
E2E testing validates the entire application flow, catching integration issues that unit tests might miss. This approach simulates real user behavior and ensures the application works as expected from the user's perspective.
Below is a simplified version of the e-commerce interface being tested:
Here's an example of the Cypress test code for the complete checkout flow:
describe('E-commerce Checkout Flow', () => {
beforeEach(() => {
cy.visit('/');
});
it('completes full checkout process', () => {
// Step 1: Login
cy.get('[data-cy="email-input"]')
.type('user@example.com');
cy.get('[data-cy="password-input"]')
.type('securePassword123');
cy.get('[data-cy="login-button"]')
.click();
// Verify successful login
cy.url().should('include', '/products');
cy.get('[data-cy="user-menu"]')
.should('be.visible');
// Step 2: Search and select product
cy.get('[data-cy="search-input"]')
.type('Premium Laptop');
cy.get('[data-cy="search-button"]')
.click();
// Step 3: Add to cart
cy.get('[data-cy="product-laptop"]')
.should('be.visible');
cy.get('[data-cy="add-laptop"]')
.click();
// Verify cart updated
cy.get('[data-cy="cart-count"]')
.should('contain', '1');
cy.get('[data-cy="cart-total"]')
.should('contain', '$999.99');
// Step 4: Proceed to checkout
cy.get('[data-cy="checkout-button"]')
.click();
// Fill shipping information
cy.get('[data-cy="shipping-name"]')
.type('John Doe');
cy.get('[data-cy="shipping-address"]')
.type('123 Main St');
cy.get('[data-cy="shipping-city"]')
.type('New York');
cy.get('[data-cy="shipping-zip"]')
.type('10001');
// Select payment method
cy.get('[data-cy="payment-card"]')
.click();
cy.get('[data-cy="card-number"]')
.type('4242424242424242');
cy.get('[data-cy="card-expiry"]')
.type('12/25');
cy.get('[data-cy="card-cvc"]')
.type('123');
// Complete order
cy.get('[data-cy="place-order"]')
.click();
// Verify order confirmation
cy.get('[data-cy="order-confirmation"]')
.should('be.visible');
cy.get('[data-cy="order-number"]')
.should('exist');
cy.url().should('include', '/order-confirmation');
});
it('validates form inputs', () => {
cy.get('[data-cy="login-button"]').click();
cy.get('[data-cy="email-error"]')
.should('contain', 'Email is required');
});
it('handles cart persistence', () => {
// Add item to cart
cy.get('[data-cy="add-laptop"]').click();
// Reload page
cy.reload();
// Verify cart still has item
cy.get('[data-cy="cart-count"]')
.should('contain', '1');
});
});
Project configuration for optimal testing:
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
viewportWidth: 1280,
viewportHeight: 720,
video: true,
screenshotOnRunFailure: true,
defaultCommandTimeout: 10000,
setupNodeEvents(on, config) {
// implement node event listeners here
},
env: {
apiUrl: 'http://localhost:3001/api',
},
},
});
Reusable commands to simplify test writing:
// cypress/support/commands.js
// Login command
Cypress.Commands.add('login', (email, password) => {
cy.get('[data-cy="email-input"]').type(email);
cy.get('[data-cy="password-input"]').type(password);
cy.get('[data-cy="login-button"]').click();
cy.url().should('include', '/products');
});
// Add to cart command
Cypress.Commands.add('addToCart', (productCy) => {
cy.get(`[data-cy="${productCy}"]`).within(() => {
cy.get('[data-cy^="add-"]').click();
});
cy.get('[data-cy="cart-count"]').should('not.contain', '0');
});
// Complete checkout command
Cypress.Commands.add('completeCheckout', (shippingInfo, paymentInfo) => {
cy.get('[data-cy="checkout-button"]').click();
// Fill shipping
cy.get('[data-cy="shipping-name"]').type(shippingInfo.name);
cy.get('[data-cy="shipping-address"]').type(shippingInfo.address);
cy.get('[data-cy="shipping-city"]').type(shippingInfo.city);
cy.get('[data-cy="shipping-zip"]').type(shippingInfo.zip);
// Fill payment
cy.get('[data-cy="card-number"]').type(paymentInfo.cardNumber);
cy.get('[data-cy="card-expiry"]').type(paymentInfo.expiry);
cy.get('[data-cy="card-cvc"]').type(paymentInfo.cvc);
cy.get('[data-cy="place-order"]').click();
cy.get('[data-cy="order-confirmation"]').should('be.visible');
});
This project provided hands-on experience with modern E2E testing practices. Key takeaways include: