๐ฏ Overview
The Smash-QA-Framework is a comprehensive end-to-end test automation solution built with Playwright and TypeScript for testing Smashburger's online ordering platform at dev.smashburger.com. This framework validates the complete customer journey from menu browsing to order confirmation, ensuring a flawless digital ordering experience.
๐ What We Test
- Complete ordering workflow
- Custom burger creation
- Location selection (Pickup)
- Cart management
- Checkout & payment flow
- Order confirmation
๐ ๏ธ How We Test
- Page Object Model (POM)
- Data-driven scenarios
- Fixtures for reusability
- Parallel execution
- CI/CD integration
- Automated reporting
โก Key Features
- TypeScript for type safety
- Semantic locators
- Fast execution (30s/test)
- Screenshot on failure
- GitHub Pages reports
- Mock data support
๐ Tech Stack Analysis
Based on DOM and network inspection, the Smashburger website (https://dev.smashburger.com) is built with modern, scalable technologies:
โ๏ธ Core Frameworks
- Next.js (React)
- React
- Tailwind CSS
๐ Data Management
- React Query
- Via
dehydratedState
๐ Third-Party
- Google Tag Manager
- Google Maps API
- Google reCAPTCHA
- Braze (engagement)
- TrustArc (consent)
โ๏ธ Infrastructure
- Cloudflare CDN
- AWS S3 (assets)
- Google Fonts
๐ Observed APIs
Location & Menu
GET /api/location/search?query=80246
GET /api/location/menu
GET /api/location
- Search restaurants by ZIP code
- Fetch menu by location
- Retrieve location details
Basket & Ordering
POST /api/basket
GET /api/basket
POST /api/basket/products
GET /api/basket/delivery-mode
POST /api/basket/validate
GET /api/basket/freedompay-iframe?billingMethod=creditcard
- Create basket (requires
VendorId) - Add products with customization options
- Delivery/pickup mode selection
- Basket validation before checkout
- Payment iframe integration
Page Data (Next.js)
GET /_next/data/.../menu/smashburgers/create-your-own.json
GET /_next/data/.../cart.json
GET /_next/data/.../cart/checkout.json
๐ก Recommendations: Shift Left Testing Strategy
Based on the observed API dependencies, we recommend implementing a comprehensive Shift Left testing approach to catch defects earlier in the development cycle, reduce costs, and improve overall quality.
๐ The Testing Pyramid
Move from heavy reliance on E2E tests to a balanced pyramid approach:
๐งฑ Unit Tests
Coverage: 70-80%
- Fast execution (milliseconds)
- Test individual functions/components
- Low maintenance cost
- High confidence in code quality
๐ Integration Tests
Coverage: 15-20%
- Medium execution time (seconds)
- Test API endpoints & database
- Validate data flow
- Catch integration issues early
๐ Contract Tests
Coverage: 5%
- Fast execution (seconds)
- Verify API contracts
- Provider/Consumer validation
- Prevent breaking changes
๐ญ E2E Tests
Coverage: 5-10%
- Slow execution (30s per test)
- Critical user journeys only
- High maintenance cost
- Focus on business value
๐ฏ Recommended Implementation Strategy
1. Unit Tests (Backend & Frontend)
Backend API Unit Tests:
// Example: Test basket creation logic
describe('Basket Service', () => {
it('should create basket with valid VendorId', () => {
const basket = basketService.create({ vendorId: '12345' });
expect(basket.vendorId).toBe('12345');
expect(basket.items).toEqual([]);
});
it('should throw error for invalid VendorId', () => {
expect(() => basketService.create({ vendorId: null }))
.toThrow('VendorId is required');
});
});
Frontend Component Unit Tests:
// Example: Test CartItem component
describe('CartItem Component', () => {
it('should display item name and price', () => {
const item = { name: 'Classic Smash', price: 8.99 };
render(<CartItem item={item} />);
expect(screen.getByText('Classic Smash')).toBeInTheDocument();
expect(screen.getByText('$8.99')).toBeInTheDocument();
});
it('should display fallback image when image URL missing', () => {
const item = { name: 'Custom Burger', image: null };
render(<CartItem item={item} />);
const img = screen.getByRole('img');
expect(img).toHaveAttribute('src', '/fallback-burger.png');
});
});
2. Integration Tests (API Layer)
Test API endpoints with real database interactions:
// Example: Test basket API endpoints
describe('POST /api/basket', () => {
it('should create basket and return basketId', async () => {
const response = await request(app)
.post('/api/basket')
.send({ vendorId: '12345' })
.expect(201);
expect(response.body).toHaveProperty('basketId');
expect(response.body.vendorId).toBe('12345');
});
});
describe('POST /api/basket/products', () => {
it('should add product to existing basket', async () => {
const basketId = await createTestBasket();
const response = await request(app)
.post('/api/basket/products')
.send({
basketId,
productId: 'burger-001',
quantity: 1,
options: { bun: 'classic', patty: 'double' }
})
.expect(200);
expect(response.body.items).toHaveLength(1);
expect(response.body.items[0].productId).toBe('burger-001');
});
});
Key Integration Test Areas:
- โ
/api/location/*- Location search and menu retrieval - โ
/api/basket/*- Basket creation, product addition, validation - โ
/api/basket/delivery-mode- Pickup/delivery options - โ Database transactions - Ensure data consistency
- โ External API integrations - Google Maps, payment gateway
3. Contract Tests (API Contracts)
Use tools like Pact or Spring Cloud Contract to ensure API contracts are honored:
// Example: Consumer-driven contract test
describe('Basket API Contract', () => {
const provider = new Pact({
consumer: 'SmashburgerUI',
provider: 'BasketService'
});
it('should return basket with items', async () => {
await provider.addInteraction({
state: 'basket exists with items',
uponReceiving: 'a request for basket',
withRequest: {
method: 'GET',
path: '/api/basket',
query: { basketId: '12345' }
},
willRespondWith: {
status: 200,
body: {
basketId: '12345',
items: Matchers.eachLike({
productId: Matchers.string('burger-001'),
name: Matchers.string('Classic Smash'),
price: Matchers.decimal(8.99),
quantity: Matchers.integer(1)
})
}
}
});
// Consumer test validates the contract
const basket = await basketClient.getBasket('12345');
expect(basket.items).toBeDefined();
});
});
Benefits of Contract Testing:
- โ Prevent breaking changes to API contracts
- โ Enable independent deployment of services
- โ Fast feedback (runs in seconds)
- โ Clear communication between frontend and backend teams
4. E2E Tests (Critical User Journeys)
Focus only on the most important business-critical scenarios:
- โ Complete burger ordering flow (Create Your Own)
- โ Pickup order placement and confirmation
- โ Cart modifications and checkout
- โ Avoid: Testing every burger variant (covered by lower layers)
- โ Avoid: Testing API response formats (covered by contract tests)
- โ Avoid: Testing individual component rendering (covered by unit tests)
E2E Test Optimization:
- Keep tests under 30 seconds per scenario
- Use API calls for test setup (faster than UI interactions)
- Mock external dependencies when possible
- Run E2E tests only for smoke testing in CI/CD
๐ Expected Benefits
โก Faster Feedback
Catch defects in seconds (unit tests) instead of minutes (E2E tests)
๐ฐ Lower Costs
Defects found early are 10-100x cheaper to fix than in production
๐ง Easier Maintenance
Unit/integration tests are more stable and easier to debug than E2E
๐ Higher Coverage
Test more scenarios without exponentially increasing execution time
/api/basket/*, /api/location/*) before expanding E2E coverage. This will provide faster feedback, reduce flakiness, and lower maintenance costs while ensuring comprehensive quality coverage across all layers.
๐งช Testing Strategy
Core Testing Principles
- Scope: Focus on UI automation with Playwright + TypeScript, minimal framework overhead
- Primary Flow: E2E burger ordering โ pickup order via "Create Your Own Burger" page
- Data Setup: Use ZIP code
80246, select the first available restaurant - Validation Points: Ensure order details are consistent across Cart, Checkout, and Order Details pages
- Design Pattern: Page Object Model (POM), modular code, fixtures for setup, utilities for reusability
- Resilience: Prefer
data-testid/ID locators, handle dynamic elements properly with proper waits - Quality: Parallel execution (3 workers), headless runs, screenshot capture on failures
๐ Test Coverage
1. Ordering a Burger (E2E Scenario)
Test Case: Place a pickup order with "Create Your Own" burger
Implementation: tests/pickup-create-your-own-order.spec.ts
- Test URL: Create Your Own Burger Page
- Flow:
- Navigate to Create Your Own page (
product.gotoCreateYourOwn()) - Select pickup location by ZIP code 80246 (
bootstrapPickupAtZip()) - Configure burger with custom options (
create.createBurger(burger)) - Add to cart and proceed to checkout
- Verify cart displays correct burger details
- Fill customer information (name, email, phone)
- Fill payment information (credit card via iframe)
- Place order and verify confirmation page
- Navigate to Create Your Own page (
- Validations:
- โ Cart page: Verify size, bun, cheese, toppings, sauces, add-ons
- โ Checkout page: Verify order summary matches selections
- โ Confirmation page: Verify "Thank You", order number, pickup details
- โ End-to-end consistency across all pages
2. Data-Driven Testing Scenarios
Implementation: tests/pickup-orders-dataset.spec.ts
Data Source: test-data/burger-combinations.json
- Test Approach: Parameterized tests using JSON data sets
- Burger Customization Variants Covered:
- Protein options: Double Beef, Single Beef, Crispy Chicken, Double Chicken, Turkey, Black Bean
- Bun types: Classic, Spicy Chipotle
- Cheese varieties: American, Aged Swiss, Pepper Jack, Aged Cheddar
- Toppings: Lettuce, Tomatoes, Red Onion, Pickles, Jalapeรฑos, Grilled options
- Sauces: Smash Sauceยฎ, Mayo, Ranch, BBQ, Chipotle Ranch, Truffle Mayo
- Premium Add-ons: Applewood Smoked Bacon, Smashed Avocado
- Test Execution:
- 6 different burger scenarios from data file
- Each scenario tests complete E2E flow
- Parallel execution for faster feedback
- Single customer profile (default) with ZIP 80246
3. Cart Page Item's Image Validation
Implementation: tests/cart-placeholder-images.spec.ts
Objective: Validate image handling for cart items with placeholder/missing images
Test Scenario
- Setup: Add 3 items to cart from
test-data/mock-cart-items.json - Items tested:
- Double Smoked Brisket Bacon Smashยฎ (qty: 1)
- Chili Cheese Dog (qty: 2)
- Large French Fries (qty: 3)
- Action: Navigate to Cart Page
- Mock Implementation: Use Playwright route interception to replace placeholder images with actual burger image
Implementation Details
// Route interception for placeholder images
await page.route('**/placeholder.e96474ea.jpg', async (route) => {
// Fetch the actual fallback image
const response = await page.request.get(PLACEHOLDER_IMAGE_URL);
const body = await response.body();
// Fulfill request with real image
await route.fulfill({
status: 200,
contentType: 'image/png',
body
});
});
// Verify all cart images are visible
const cartImages = page.getByRole('img', { name: /cart item/i });
const count = await cartImages.count();
for (let i = 0; i < count; i++) {
await expect(cartImages.nth(i)).toBeVisible();
}
Validation Points
- โ All cart items display images after route interception
- โ
Placeholder image URL (
placeholder.e96474ea.jpg) is intercepted - โ Replacement image loaded successfully from S3
- โ
Images are visible in DOM (
toBeVisible()) - โ Cart layout remains consistent with images
๐ฏ Test Execution
โก Parallel Execution
Tests run with 3 workers for faster execution and efficient resource utilization
๐ Continuous Integration
Automated runs on push/PR to main branch via GitHub Actions
๐ Reporting
HTML reports deployed to GitHub Pages automatically with full test artifacts
๐ Quality Gates
Screenshot on failure, continue-on-error for visibility, detailed test summaries
๐ Test Data Strategy
Environment Configuration
- Base URL:
https://dev.smashburger.com - Test ZIP Code:
80246(Denver, CO area) - Restaurant Selection: First available location
- Payment Method: Test credit card data https://neapay.com/online-tools/credit-card-number-generator-validator.html
Test User Management
Guest checkout flow primarily tested to avoid account dependencies and simplify test maintenance.
๐ Success Metrics
Performance Targets
- E2E Scenario Execution Time: Under 30 seconds per test scenario
- Full Suite Execution: Complete within CI/CD pipeline timeout (60 minutes max)
- Test Reliability: 95%+ pass rate on consecutive runs
- Defect Detection: UI regressions caught before production deployment
Coverage Goals
- โ Critical user journey: Create Your Own burger order (E2E)
- โ Data-driven scenarios for typical food ordering flows
- โ Cross-browser compatibility (Chromium, Firefox, WebKit)
- โ Mobile viewport testing for responsive design