Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions CYPRESS_IMPLEMENTATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Cypress Implementation for QE Showcase

## Overview
This implementation demonstrates **E2E testing** for the Sauce Demo purchase flow using Cypress. The test suite covers all required steps while implementing **Quality Engineering best practices** with a focus on maintainability, scalability, and general professional standards.

## **Architecture & Design**

### **Tiny Page Object Model (POM)**
- **`LoginPage.js`**: Authentication selectors and actions
- **`InventoryPage.js`**: Product sorting, cart operations, sorting verification
- **`CartPage.js`**: Cart verification and checkout navigation
- **`CheckoutPage.js`**: Form handling with enough error handling and validation

### **Custom Commands Layer**
- **`commands.js`**: Reusable test flows and business logic encapsulation
- **`cy.login()`**: Authentication flow
- **`cy.sortProducts()`**: Product sorting with verification
- **`cy.addToCart()`**: Cart operations
- **`cy.checkoutFlow()`**: Complete checkout process

### **Utility Layer**
- **`slugify.js`**: Dynamic selector generation for product-specific elements
- **`sortVerifier.js`**: Using sorting verification logic
- **`businessAssertions.js`**: Business-focused assertions over implementation details

### **Data Management**
- **`users.json`**: Test user credentials
- **`products.json`**: Product names, sort options, page titles, messages
- **`checkout-data.json`**: Address data for various test scenarios

## **Test Structure & Coverage**

### **Main Test Suite: `purchase-flow.cy.js`**

1. **Authentication Verification**: Login success and inventory display
2. **Product Sorting**: All 4 sorting options with data-driven approach
3. **Cart Operations**: Add/remove functionality with badge verification
4. **Checkout Validation**: Form validation for empty submissions
5. **Checkout Completion**: Successful form submission
6. **Purchase Processing**: Order completion flow
7. **Success Verification**: Order confirmation with multiple strategies
8. **Edge Case Handling**: Long names in checkout forms
9. **Cancellation Flow**: Checkout cancellation handling
10. **Cart Structure**: Enhanced cart verification

### **Edge Case Tests: `checkout-edge.cy.js`**
- **Long Names**: Extended character handling
- **Special Characters**: Non-standard input validation

## **Quality Engineering Approach**

### **Atomic Testing**
- **Single Responsibility**: Each test has one purpose only
- **Independent Execution**: Tests can run in any order
- **Clear Failure Isolation**: Failures point to specific functionality
- **Business Focus**: Tests verify user outcomes, not implementation details

### **Business-Focused Assertions**
- **Sorting Results**: Verify products are actually sorted correctly
- **Cart Updates**: Check badge counts and contents
- **Order Success**: Confirm completion with meaningful messages
- **User Experience**: Validate form behavior and navigation

### **Selector Strategy**
- **Primary**: `data-test` attributes for reliability
- **Dynamic**: `slugify` utility for product-specific selectors
- **Fallback**: Multiple verification strategies for critical flows

### **Data-Driven Testing**
```javascript
const sortTests = [
{ option: 'Price (low to high)', direction: 'ascending' },
{ option: 'Price (high to low)', direction: 'descending' },
// ... more options
];
```

### **Utility Integration**
- **`slugify`**: Converts "Sauce Labs Backpack" → "sauce-labs-backpack"
- **`SortVerifier`**: Sorting logic in dedicated utility
- **`BusinessAssertions`**: Centralized business outcome verification

### **Error Handling & Validation**
- **Input Validation**: Prevents test failures from bad data
- **Visibility Checks**: Prevents flaky tests
- **Multiple Verification Strategies**: Handles success confirmation

## 🔧 **Technical Implementation**

### **Configuration**
- **`cypress.config.js`**: Optimized settings with retries and viewport
- **`eslint.config.js`**: ESLint v9 flat config for code quality
- **`package.json`**: Linting scripts and proper dependency management

### **Code Quality**
- **ESLint Integration**: Automated code quality checks
- **Consistent Naming**: Professional method and variable naming
- **Clear Organization**: Logical grouping with section headers
- **Strategic Comments**: Minimal but impactful explanations

## **Test Coverage Analysis**

### **Required Steps (100% Covered)**
1. ✅ **Login** - Authentication with standard_user
2. ✅ **Sort Items** - All 4 sorting options tested
3. ✅ **Add to Cart** - Product addition with verification
4. ✅ **Cart Navigation** - Cart contents and checkout flow
5. ✅ **Checkout Info** - Form completion with validation
6. ✅ **Complete Purchase** - Order processing flow
7. ✅ **Success Verification** - Multiple confirmation strategies

### **Enhanced Coverage**
- **Edge Cases**: Long names, special characters, cancellation
- **Cart Operations**: Add/remove with badge updates
- **Form Validation**: Empty submission handling
- **Sorting Verification**: All options with proper assertions

## **Bugs & Oddities Found**

### **Bug 1: Dynamic Selectors**
- **Issue**: HTML uses dynamic selectors like `add-to-cart-sauce-labs-backpack`
- **Solution**: `slugify` utility for consistent selector generation

### **Bug 2: Cart Container Ambiguity**
- **Issue**: Cart container selector needs verification
- **Solution**: Multiple verification strategies

### **Bug 3: Success Message Implementation**
- **Issue**: Order completion uses `complete-header` for success
- **Solution**: Multiple verification strategies or also to Check for 'Thank you' in body + verify form disappearance

## **Design Decisions & Tradeoffs**

### **Tiny POM vs Traditional POM**
- **Choice**: Tiny POM for this scope
- **Reasoning**: Structure without over-engineering
- **Benefit**: Perfect balance for maintainability

### **Atomic Tests vs Integration Tests**
- **Choice**: Atomic tests
- **Reasoning**: Clear failure isolation and maintainability
- **Benefit**: Easy to debug and extend

### **Business Assertions vs Implementation Details**
- **Choice**: Business-focused verification
- **Reasoning**: Tests verify user value, not code structure
- **Benefit**: Resilient to UI changes

## 🏃‍♂️ **Running the Tests**

```bash
# Install dependencies
npm install

# Run tests headlessly
npm run cypress:run

# Open Cypress UI
npm run cypress:open

# Lint code
npm run lint
```
12 changes: 12 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,20 @@ const { defineConfig } = require("cypress");

module.exports = defineConfig({
e2e: {
baseUrl: 'https://www.saucedemo.com',
setupNodeEvents(on, config) {
// implement node event listeners here
},
defaultCommandTimeout: 10000,
requestTimeout: 10000,
responseTimeout: 10000,
viewportWidth: 1280,
viewportHeight: 720,
video: false,
screenshotOnRunFailure: true,
env: {
// Suppress macOS system messages and Electron logging
ELECTRON_ENABLE_LOGGING: false
},
},
});
37 changes: 37 additions & 0 deletions cypress/e2e/checkout-edge.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Checkout Edge Case Tests
* Dedicated test suite for checkout form edge cases
*
* APPROACH: Focused testing of edge cases with clean setup
* Uses fixtures to avoid hardcoded values
*/
describe('Checkout Edge Case Tests', () => {
let productsData;

beforeEach(() => {
cy.visit('/');
cy.fixture('users.json').as('users');
cy.fixture('checkout-data.json').as('checkoutData');
cy.fixture('products.json').then((data) => {
productsData = data;
});
cy.get('@users').then(({ standard_user }) => {
cy.login(standard_user.username, standard_user.password);
});
});

const edgeCases = [
{ label: 'long names', key: 'long_names' },
{ label: 'special characters', key: 'special_chars' },
];

edgeCases.forEach(({ label, key }) => {
it(`should handle ${label} in checkout form`, () => {
cy.get('@checkoutData').then((data) => {
cy.checkoutFlow(productsData.products.backpack, data[key], { finish: false });
// Use business assertion instead of hardcoded URL
cy.get('[data-test="subtotal-label"]').should('be.visible');
});
});
});
});
Loading