E2E Test Plan
E2E Test Plan: Drop — Fintech Payment App
Project: Drop — Remittance + QR Payments Version: 1.0 Date: 2026-02-23 Author: John (AI Director) Status: Approved Reviewers: Alem Bašić (CEO)
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | 2026-02-23 | John | Initial E2E plan — 3 Playwright projects (user-flows, full-flows, input-chaos) |
1. E2E Testing Objectives
Objectives:
- Validate that the 5 most critical Drop user journeys work end-to-end on staging
- Catch integration failures between Next.js frontend, API routes, SQLite DB, and mock BaaS that unit/integration tests cannot detect
- Provide confidence before every production deployment via post-staging deploy gate
- Serve as living documentation of critical user flows for CEO UAT
What E2E tests are NOT for:
- Complete feature coverage (handled by unit/integration tests — 40+ Vitest tests)
- Testing every error state (too expensive to maintain; covered by input-chaos.spec.ts for validation)
- Performance benchmarking (handled by api-benchmarks.test.ts)
- Visual pixel-perfection (Figma source of truth: mockups/figma-make-export/)
2. Critical User Journeys
Journey 1: User Registration — 3-Step Onboarding
| Field | Value |
|---|---|
| Priority | Critical |
| Business Impact | Core user acquisition — no registration = no users |
| Frequency | Every new user (one-time) |
| Test File | src/drop-app/__tests__/e2e/user-flows.spec.ts |
Steps:
Assertions:
- 201 Created on registration (no password hash in response)
- JWT httpOnly cookie set after PIN setup
- Dashboard visible with user's name
- Audit log entry created
Journey 2: User Login + Dashboard Access
| Field | Value |
|---|---|
| Priority | Critical |
| Business Impact | Core returning user flow — no login = no revenue |
| Frequency | Every user, every session |
| Test File | src/drop-app/__tests__/e2e/user-flows.spec.ts |
Steps:
Assertions:
- 200 on login; JWT cookie set; SameSite=Strict; httpOnly
- GET /api/auth/me returns user object (no password hash)
- Balance shown is from mock BaaS (not stored in Drop DB)
Journey 3: Remittance — NOK to RSD
| Field | Value |
|---|---|
| Priority | Critical |
| Business Impact | Core revenue — 0.5% fee per transaction |
| Frequency | Multiple times per month per user |
| Test File | src/drop-app/__tests__/e2e/full-flows.spec.ts |
Steps:
- Log in as KYC-approved consumer
- Navigate to "Send penger" (Send Money)
- Select recipient; enter amount = 1,000 NOK; select currency = RSD
- Review: fee shown as 5 NOK (0.5%); exchange rate shown
- Confirm and submit
- Transaction created with status = completed
- Navigate to Transaction History — transaction visible
Assertions:
- 201 Created; transaction in DB with fee = 5 NOK
- Transaction history shows amount, fee, currency, status
- No balance change in Drop DB (pass-through — balance read from mock AISP)
Journey 4: QR Payment — Scan + Pay
| Field | Value |
|---|---|
| Priority | Critical |
| Business Impact | Core QR revenue — 1% merchant fee |
| Frequency | Multiple times per week per merchant |
| Test File | src/drop-app/__tests__/e2e/full-flows.spec.ts |
Steps:
- Log in as KYC-approved consumer
- Navigate to "Scan QR"
- Enter valid merchantId (pre-seeded merchant)
- Enter amount = 200 NOK
- Review: merchant_fee = 2 NOK (1%)
- Confirm payment
- Transaction created; visible in history
Assertions:
- 201 Created; merchant_fee = 2 NOK; amount = 200 NOK
- Transaction visible in consumer history
- Mock PISP payment recorded
Journey 5: Merchant Registration + QR Generation
| Field | Value |
|---|---|
| Priority | High |
| Business Impact | Merchant onboarding — enables QR revenue |
| Frequency | One-time per merchant |
| Test File | src/drop-app/__tests__/e2e/full-flows.spec.ts |
Steps:
- Log in as user (not yet a merchant)
- Navigate to "Bli Merchant" (Become Merchant)
- Enter business_name and bank_account
- Submit — merchant created with unique QR code value
- Navigate to merchant dashboard — QR code visible
Assertions:
- 201 Created; merchant has unique qr_code_value
- GET /api/merchants/me returns merchant details + QR code
- QR code is unique (no two merchants share a code)
All Journeys Summary
| Journey | Priority | Est. Duration | Automated | Playwright Project |
|---|---|---|---|---|
| User Registration (3-step) | Critical | ~30s | Yes | user-flows |
| User Login + Dashboard | Critical | ~15s | Yes | user-flows |
| Remittance NOK→RSD | Critical | ~30s | Yes | full-flows |
| QR Payment | Critical | ~25s | Yes | full-flows |
| Merchant Registration | High | ~20s | Yes | full-flows |
| Input Chaos (20+ edge cases) | High | ~60s | Yes | input-chaos |
3. Browser & Device Matrix
Desktop Browsers
| Browser | Version | OS | Priority | Notes |
|---|---|---|---|---|
| Chrome | Latest stable | macOS, Linux (CI) | Critical | Primary test browser in Playwright CI |
| Safari | Latest stable | macOS | High | WebKit engine — required for Norwegian users on Mac |
Mobile Browsers
| Browser | Platform | Version | Priority | Notes |
|---|---|---|---|---|
| Safari | iOS | Latest | Critical | Primary Drop platform — iPhone SE to iPhone Pro Max |
| Chrome | Android | Latest | High | Secondary mobile platform |
Screen Resolutions (configured in playwright.config.ts)
| Category | Resolution | Test Priority | Notes |
|---|---|---|---|
| Mobile S (iPhone SE) | 375×667 | Critical | Drop primary target device |
| Mobile L (iPhone 14 Pro) | 428×926 | Critical | Drop primary target device |
| Tablet | 768×1024 | Medium | Secondary |
| Desktop | 1280×800 | Medium | Fallback / admin use |
Matrix in CI: Chromium + WebKit (mobile viewports 375px and 428px) on every deployment.
4. Test Data Setup & Teardown
Setup Strategy
| Data Type | Method | Scope |
|---|---|---|
| Consumer account (KYC approved) | Pre-seeded in beforeAll via API |
Test suite |
| Merchant account | Pre-seeded in beforeAll via API |
Test suite |
| Test recipients (for remittance) | Pre-seeded in beforeAll |
Test suite |
| Isolated fresh user (for registration tests) | Created via API in beforeEach with unique email |
Individual test |
Seed command: npm run db:seed (populates staging SQLite with synthetic test data)
Teardown Strategy
| Cleanup Item | Method | Trigger |
|---|---|---|
| Fresh users created per test | DELETE via API | afterEach |
| Test session data | Clear browser storage | afterEach |
| Transactions created during test | Archive (not delete — audit trail) | Test suite end |
Rule: Tests must not leave state that affects other tests. Each test creates its own isolated data.
Test Accounts
| Account | Role | Purpose | |
|---|---|---|---|
| Consumer (Amir) | [email protected] |
Consumer, KYC approved | Standard journeys: login, remittance, QR |
| Merchant (Ahmet) | [email protected] |
Merchant | Merchant dashboard, QR generation |
| Fresh user | e2e-fresh-{timestamp}@test.alai.no |
None | Registration flow tests |
Credentials stored in: Vaultwarden (vault.basicconsulting.no) → "Drop E2E Test Accounts"
5. Authentication Handling in Tests
Strategy: API-based auth — authenticate via POST /api/auth/login in beforeAll, save storage state, reuse for all tests in the suite. Only use UI login when testing the login flow itself.
// playwright.config.ts approach:
// 1. beforeAll: POST /api/auth/login → save JWT cookie to storage state
// 2. Each test that needs auth: restore storage state (< 1ms overhead)
// 3. Tests for login UI: always fresh (no saved state)
Session reuse:
- Session state saved per role (consumer, merchant) after first auth
- Reused for all tests requiring that role
- JWT expires in 7 days — within test run duration
6. Test Environment Requirements
| Requirement | Specification |
|---|---|
| Environment | Staging (https://drop-staging.fly.dev/) |
| Database | Staging SQLite with synthetic seed data only |
| External services | Mock BaaS (NEXT_PUBLIC_SERVICE_MODE=mock); mock Sumsub |
| Stability | No active deployments during E2E run (Fly.io deployment check) |
| Data persistence | Isolated from manual testing during E2E run |
| Response times | < 5,000ms for all endpoints (Playwright default timeout) |
Critical: E2E tests must NOT run against a production environment. Drop handles financial data — all E2E tests use mock BaaS exclusively.
7. Flaky Test Management Strategy
Definition: A test that fails inconsistently for the same code.
Prevention:
- Use explicit waits:
waitForResponse('/api/...')notpage.waitForTimeout(1000) - Isolate test data — unique emails per test run (
e2e-fresh-{Date.now()}@test.alai.no) - Use
data-testidselectors — not CSS classes or text (can change with Norwegian/English toggle) - Disable animations in test env via
prefers-reduced-motion
Detection:
- Any test failing > 5% of runs without code changes = flaky
- Playwright HTML report shows flaky tests in CI artifacts
Response:
- Tag flaky test with
test.fixme()annotation in Playwright - Create Mission Control task with P2 priority
- Fix within 3 days or remove the test
- Monthly flaky test review during sprint retrospective
8. Visual Regression Testing
Approach: Playwright screenshot comparisons on critical screens.
Baseline: Stored in src/drop-app/__tests__/e2e/snapshots/ (committed to repo)
Source of Truth: Figma Make export: mockups/figma-make-export/src/components/
| Check | Scope | Trigger |
|---|---|---|
| Dashboard screenshot | Dashboard screen | Post-staging deploy |
| Send Money form | Remittance form | On UI changes |
| QR Scan screen | QR payment screen | On UI changes |
| Mobile 375px layout | All critical screens | On responsive changes |
Review process: Screenshot diffs require Builder + Validator sign-off before merge. Figma is the source of truth — any diff vs Figma is a regression.
9. Performance Assertions Within E2E
| Assertion | Metric | Threshold | Journey |
|---|---|---|---|
| Page load | Time to Interactive | < 3,000ms | Dashboard, Send Money |
| Core Web Vitals — LCP | Largest Contentful Paint | < 2,500ms | Homepage, Dashboard |
| API response | Remittance endpoint | < 1,000ms | Journey 3 |
| API response | Login endpoint | < 1,000ms | Journey 2 |
| API response | Exchange rates | < 200ms | Journey 3 (rates call) |
10. CI Integration
Trigger: Post-staging deployment (GitHub Actions workflow: .github/workflows/e2e.yml)
Parallelization:
- 3 Playwright projects run in parallel: user-flows, full-flows, input-chaos
- 2 workers per project on CI (total: 6 parallel Playwright workers)
- Estimated total time: < 10 minutes
CI configuration:
# .github/workflows/e2e.yml
# Key settings:
# - Projects: user-flows, full-flows, input-chaos
# - Retries: 1 (flaky detection; not masking failures)
# - Timeout per test: 30,000ms
# - Timeout total: 600,000ms (10 min)
# - Base URL: https://drop-staging.fly.dev/
On failure:
- Collect screenshots, videos, Playwright traces as CI artifacts
- Retain artifacts for 7 days
- Alert Slack #drop-e2e-failures on alai-talk.slack.com
- Block production deployment until fixed
11. Test Report Format & Artifacts
Report format: Playwright HTML report + JUnit XML for CI Report location: GitHub Actions CI artifacts (7-day retention)
Artifacts collected on failure:
| Artifact | Format | When Collected |
|---|---|---|
| Screenshot | PNG | On step failure |
| Screen recording | WebM video | On test failure |
| Network trace | HAR file | On test failure |
| Browser console log | JSON | On test failure |
| Playwright trace | .zip (Playwright trace viewer) |
On test failure |
12. Maintenance Strategy
Page Object Pattern:
- All page interactions wrapped in lightweight Page Object classes
- Selectors centralized in
tests/e2e/pages/ - Location:
src/drop-app/__tests__/e2e/pages/
Selector strategy (Drop-specific):
data-testidattributes — preferred (e.g.,data-testid="remittance-amount")- ARIA roles + accessible name (e.g.,
getByRole('button', { name: 'Send penger' })) - Text content — acceptable for stable Norwegian/English text
- CSS class names — avoid (Tailwind classes can change)
- XPath — never
Review cadence:
- E2E tests updated in same PR as feature changes (tests are part of the PR)
- Monthly review: remove tests for deprecated features
- Figma-make-export checked after every UI change
Related Documents
Approval
| Role | Name | Date | Signature |
|---|---|---|---|
| Author | John (AI Director) | 2026-02-23 | Approved (AI) |
| QA Lead | Validator Agent | 2026-02-23 | Approved (AI) |
| AI Director (John) | John | 2026-02-23 | Approved |
| CEO (Alem) | Alem Bašić | TBD |