Skip to main content

Customer Portal — Testing Strategy

Status: populated Owner: Product Engineering (Frontend) Last updated: 2026-04-18

1. Test Pyramid

┌─────────────┐
│ E2E (10%) │ Playwright — critical flows
├─────────────┤
│ Integration │ Next.js route handler tests
│ (20%) │ MSW-backed server component tests
├─────────────┤
│ Unit (70%) │ Vitest — components, hooks, utils
└─────────────┘

Target coverage: 80% on unit + integration combined.

2. Unit Tests (Vitest + React Testing Library)

Component Tests

  • Test rendered output for each major UI state (loading, empty, populated, error).
  • Test user interactions: clicks, form submissions, keyboard navigation.
  • Mock API calls with MSW — no real network in unit tests.

Key components to test:

ComponentTest focus
ApiKeyCreateModalCreate flow, raw key display, copy button, close clears state
MessageLogTableRenders all status badges, pagination, filter change emits correct URL
WebhookCreateModalCreate flow, signing secret displayed once, close clears
TestSmsFormValidation errors, character counter, submit flow
BillingUsageCardRenders all fields; handles missing data gracefully

Utility / Hook Tests

UnitTest focus
validateE164(number)Valid numbers, invalid numbers, edge cases
useMessageFilters()URL sync, filter state updates
formatCurrency(amount, currency)Formatting, zero values, large amounts
formatDeliveryRate(rate)0%, 100%, decimal rounding

3. Integration Tests (Next.js Route Handlers)

Using @testing-library/react + MSW for route handler tests.

Route HandlerTest cases
POST /api/api-keysSuccess → returns ApiKeyCreated; upstream 422 → propagates errors; missing auth → 401
DELETE /api/api-keys/[keyId]Success → 204; not found → 404
POST /api/send-testSuccess → messageId returned; validation error → 422
POST /api/auth/refreshValid refresh token → new cookie set; invalid token → 401

4. E2E Tests (Playwright)

Critical user journeys:

JourneyStepsAssertion
Login → DashboardNavigate to /, sign in with test credentialsDashboard summary cards visible
Create API KeyNavigate to /api-keys, click create, fill form, submitRaw key displayed in modal
Send Test SMSNavigate to /send-test, fill form, submitSuccess message with messageId shown
View Message LogNavigate to /messages, apply status filterFiltered results shown; URL updated
Configure WebhookNavigate to /webhooks, create webhookSigning secret shown once in modal
Billing overviewNavigate to /billingInvoice table and usage card render

Playwright config:

  • Browser matrix: Chromium, Firefox, WebKit
  • Breakpoints tested: 375px (mobile), 1440px (desktop)
  • Test account: seeded via API in globalSetup

5. Accessibility Testing

  • axe-core via @axe-core/playwright runs on each Playwright test.
  • Zero violations required for WCAG 2.1 AA before merge.

6. Visual Regression (Optional / Post-MVP)

Playwright screenshots of key pages at 375px and 1440px. Compared with Argos CI or Chromatic.

7. CI Pipeline

pnpm test:unit # Vitest unit
pnpm test:coverage # Coverage check (fail if < 80%)
pnpm test:e2e # Playwright (against mock backend)
pnpm lint
pnpm typecheck