domain project / e-commerce
E-Commerce
Test strategies for shopping carts, checkout flows, product search, payments, and order management in retail platforms.
demo: SauceDemo
Product search & filteringShopping cart & checkoutPayment processingOrder managementInventory & stockUser accounts & wishlists
Domain Overview
E-commerce is the highest-stakes domain for automated testing — a checkout bug directly costs revenue. Testing covers the full purchase funnel: product discovery → cart → checkout → payment → confirmation → order tracking.
Typical stack: Next.js / Nuxt storefront, Stripe / Braintree payments, microservices (cart, inventory, orders, notifications), CDN-delivered product images.
Key Test Areas
| Area | What to test | Risk |
|---|---|---|
| Product search | Filters, pagination, sorting, empty results | Discovery failure → lost sale |
| Product detail | Images, variants (size/colour), stock status, add-to-cart | Wrong variant ordered |
| Cart | Add, remove, quantity update, price calculation, persistence | Price error, lost cart |
| Checkout | Address form, shipping selection, discount codes | Drop-off, wrong address |
| Payment | Card validation, 3DS redirect, failure handling | Revenue loss, double charge |
| Order confirmation | Email trigger, inventory decrement, order record | Fulfilment failure |
| Account | Registration, login, order history, saved addresses | Data exposure |
Test Pyramid for E-Commerce
Unit (60%): Price calculation, discount logic, tax rules, validation
Integration (30%): Cart API, payment gateway integration, inventory service
E2E (10%): Critical path: login → search → add to cart → checkout → confirm
Critical E2E tests (must pass before every deploy):
- Guest checkout with credit card
- Registered user checkout with saved address
- Apply discount code, verify price
- Out-of-stock product blocks checkout
- Payment failure shows error, no order created
Common Failure Scenarios
1. Race condition: two users buy last item simultaneously → oversell
Test: concurrent checkout API calls, assert only one succeeds
2. Cart total doesn't update after discount → user sees wrong price
Test: apply coupon, verify cart total, verify order total match
3. 3DS redirect returns to wrong URL → order stuck in pending
Test: mock 3DS with Stripe test card 4000002500003155
4. Address autocomplete submits before user finishes → wrong delivery
Test: partial address entry, intercept autocomplete, verify confirmation
5. Inventory not decremented after payment → stock integrity broken
Test: verify inventory API after successful order
Playwright Patterns for E-Commerce
// Payment with Stripe test cards via page.route()
test('checkout completes with test card', async ({ page }) => {
await page.goto('/checkout');
// Fill Stripe Elements iframe
const stripeFrame = page.frameLocator('iframe[name*="stripe"]').first();
await stripeFrame.getByPlaceholder('Card number').fill('4242424242424242');
await stripeFrame.getByPlaceholder('MM / YY').fill('12/28');
await stripeFrame.getByPlaceholder('CVC').fill('123');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByText('Order confirmed')).toBeVisible();
});
// Cart persistence across sessions
test('cart persists after logout and login', async ({ page, context }) => {
await page.goto('/products');
await page.locator('.product-card').first().getByRole('button', { name: 'Add to cart' }).click();
// Save cookies, new page (simulates new session)
const cookies = await context.cookies();
await context.clearCookies();
await context.addCookies(cookies);
await page.reload();
await expect(page.locator('.cart-count')).toHaveText('1');
});