Skip to content

Testing Guide

This guide covers testing strategies, IDE setup, and debugging for the Freeze Design webshop.

Test Pyramid

        ┌───────────┐
        │   E2E     │  ← Few, slow, high confidence
        ├───────────┤
        │Integration│  ← Medium number
        ├───────────┤
        │   Unit    │  ← Many, fast, focused
        └───────────┘

Backend Testing (Django)

Run Tests

cd backend
python manage.py test

# Run specific app tests
python manage.py test apps.payments
python manage.py test apps.invoices
python manage.py test apps.orders

# Run specific test modules
python manage.py test apps.payments.tests.test_webhook
python manage.py test apps.payments.tests.test_refund_service
python manage.py test apps.invoices.tests.test_invoice_service

# Run with verbosity
python manage.py test --verbosity=2

With Coverage

coverage run manage.py test
coverage report
coverage html  # Open htmlcov/index.html

Test Structure

# tests/test_products.py
from django.test import TestCase
from rest_framework.test import APITestCase

class ProductAPITests(APITestCase):
    def setUp(self):
        self.product = Product.objects.create(
            name='Test Product',
            base_price=29.95
        )

    def test_list_products(self):
        response = self.client.get('/api/products/')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.data['results']), 1)

    def test_product_detail(self):
        response = self.client.get(f'/api/products/{self.product.slug}/')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['name'], 'Test Product')

Frontend Testing

Unit Tests (Jest)

cd frontend
npm run test
npm run test:coverage
npm run test:watch          # Watch mode (auto-rerun)
npm test TeamOrderContext   # Specific test file

Test Structure

// Component.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { QuantitySelector } from './QuantitySelector';

describe('QuantitySelector', () => {
  it('increments quantity when plus clicked', () => {
    const onChange = jest.fn();
    render(<QuantitySelector quantity={1} onQuantityChange={onChange} />);

    fireEvent.click(screen.getByLabelText('Verhoog aantal'));

    expect(onChange).toHaveBeenCalledWith(2);
  });

  it('disables decrement at minimum', () => {
    render(<QuantitySelector quantity={1} onQuantityChange={() => {}} min={1} />);

    expect(screen.getByLabelText('Verlaag aantal')).toBeDisabled();
  });
});

Running Specific Tests

# Single test file
npm test TeamOrderContext.test.tsx

# Single test case
npm test -- -t "should save team order to context"

# All tests matching pattern
npm test -- --testPathPattern=contexts

E2E Testing (Playwright)

Run Tests

cd frontend
npm run test:e2e            # All E2E tests (headless)
npm run test:e2e:headed     # See browser while testing
npm run test:e2e:ui         # Interactive Playwright UI

Running Specific E2E Tests

# Single test file
npx playwright test team-order-designer-flow.spec.ts

# Single test case
npx playwright test -g "should preserve team order"

# By tag
npx playwright test --grep="@smoke"
npx playwright test --grep="@regression"

# Specific browser
npx playwright test --project=chromium
npx playwright test --project=firefox
npx playwright test --project=webkit

Test Structure

// e2e/checkout.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Checkout Flow', () => {
  test('complete order', async ({ page }) => {
    await page.goto('/products/classic-t-shirt');
    await page.click('[data-testid="color-swatch-1"]');
    await page.click('[data-testid="size-option-3"]');
    await page.click('[data-testid="add-to-cart"]');
    await page.click('[data-testid="checkout-button"]');
    await page.fill('[name="email"]', 'test@example.com');
    await page.click('[data-testid="submit-order"]');
    await expect(page.locator('.order-confirmation')).toBeVisible();
  });
});

Viewing E2E Results

  • HTML Report: Auto-opens after test run, or manually: npx playwright show-report
  • Trace Viewer: For failed tests: npx playwright show-trace trace.zip

VS Code Setup

Extension ID Purpose
Jest Orta.vscode-jest Inline test results, coverage, run/debug tests
Playwright Test ms-playwright.playwright Run/debug E2E tests, record tests, trace viewer

Install via terminal:

code --install-extension Orta.vscode-jest
code --install-extension ms-playwright.playwright

Configure Jest Extension

Add to .vscode/settings.json:

{
  "jest.autoRun": "off",
  "jest.showCoverageOnLoad": false,
  "jest.rootPath": "frontend"
}

VS Code Shortcuts

Unit Tests (Jest):

  • Hover over test and click play button to run
  • Right-click test for "Debug Test"
  • Cmd+Shift+P then "Jest: Toggle Coverage"

E2E Tests (Playwright):

  • Click play button in gutter next to test
  • Right-click for "Debug Test"
  • Cmd+Shift+P then "Test: Record New"

Debugging Tests

Debug Unit Tests (Jest)

  1. Set breakpoint (click left of line number)
  2. Right-click test and select "Debug Test"
  3. Use debug toolbar to step through

node --inspect-brk node_modules/.bin/jest --runInBand TeamOrderContext
Then open chrome://inspect in Chrome.

Debug E2E Tests (Playwright)

npx playwright test --debug
  1. Set breakpoint in test file
  2. Right-click test and select "Debug Test"
  3. Playwright Inspector opens automatically

npm run test:e2e:headed
See browser actions in real-time.

CI/CD Integration

Tests run automatically on every push via GitHub Actions. See .github/workflows/ci.yml.

Required Checks

  • Backend tests pass
  • Frontend tests pass
  • E2E tests pass
  • Linting passes
  • Type checking passes
  • Seed data export/import round-trip

E2E Strategy in CI

Trigger Tests Run Browsers
Pull requests Smoke tests (@smoke tag only) Chromium
Push to main Full E2E suite All scenarios

Pre-push Hook

A pre-push git hook runs backend and frontend tests before pushing. If tests fail, the push is blocked.

Test File Locations

backend/
├── apps/
│   ├── payments/tests/              # Payment tests
│   │   ├── test_models.py           # Payment, Refund, AuditLog model tests
│   │   ├── test_services.py         # PaymentService unit tests
│   │   ├── test_views.py            # API endpoint tests
│   │   ├── test_webhook.py          # Mollie webhook handler tests
│   │   ├── test_refund_service.py   # Refund creation/validation
│   │   ├── test_refund_webhook.py   # Refund webhook processing
│   │   ├── test_retry.py            # Payment retry tests
│   │   └── test_audit.py            # Audit logging tests
│   ├── invoices/tests/              # Invoice tests
│   │   ├── test_invoice_service.py  # Generation, numbering, idempotency
│   │   └── test_invoice_views.py    # Download authorization tests
│   └── orders/tests/
│       └── test_refund_admin.py     # Admin refund action tests

frontend/
├── __tests__/                    # Unit tests
│   ├── contexts/
│   │   └── TeamOrderContext.test.tsx
│   └── README.md
├── e2e/                          # E2E tests
│   ├── flows/
│   │   └── customer-journey.spec.ts  # Full payment journey
│   ├── team-order-designer-flow.spec.ts
│   ├── anonymous-team-order.spec.ts
│   └── ...
├── coverage/                     # Coverage reports (generated)
├── playwright-report/            # E2E reports (generated)
└── test-results/                # E2E artifacts (generated)

Troubleshooting

"Cannot find module '@testing-library/react'"

cd frontend && npm install

"Playwright browsers not installed"

cd frontend && npx playwright install --with-deps

Tests timing out

Increase timeout in test file:

test.setTimeout(60000); // 60 seconds

Port 3000 already in use (E2E tests)

lsof -ti:3000 | xargs kill -9

Coverage not showing

npm test -- --clearCache
npm run test:coverage

Quick Reference

Task Command
Backend
All backend tests cd backend && python manage.py test
Payment tests python manage.py test apps.payments
Invoice tests python manage.py test apps.invoices
Webhook tests python manage.py test apps.payments.tests.test_webhook
Frontend (Jest)
All unit tests npm test
Watch mode npm run test:watch
With coverage npm run test:coverage
Frontend (Playwright)
All E2E tests npm run test:e2e
Headed mode npm run test:e2e:headed
Interactive UI npm run test:e2e:ui
Debug E2E npx playwright test --debug
Smoke tests only npx playwright test --grep="@smoke"
View report npx playwright show-report