Skip to main content

E2E Test Plan

E2E Test PlanPlan: Drop — Fintech Payment App

Project: {{PROJECT_NAME}}Drop — Remittance + QR Payments Version: {{VERSION}}1.0 Date: {{DATE}}2026-02-23 Author: {{AUTHOR}}John (AI Director) Status: Draft | In Review | Approved Reviewers: {{REVIEWERS}}Alem Bašić (CEO)

Document History

Version Date Author Changes
0.1 {{DATE}}2026-02-23 {{AUTHOR}}John Initial draftE2E plan — 3 Playwright projects (user-flows, full-flows, input-chaos)

1. E2E Testing Objectives

Objectives:

  1. Validate that the {{COUNT}}5 most critical Drop user journeys work end-to-end inon a production-like environmentstaging
  2. Catch integration failures between Next.js frontend, backend,API routes, SQLite DB, and third-partymock servicesBaaS that unit/integration tests cannot detect
  3. Provide confidence before every production deployment via post-staging deploy gate
  4. Serve as living documentation of critical user flows for CEO UAT

What E2E tests are NOT for:

  • Complete feature coverage (that'shandled forby unit/integration tests — 40+ Vitest tests)
  • Testing every error state (too expensive to maintain)maintain; covered by input-chaos.spec.ts for validation)
  • Performance benchmarking (usehandled performanceby tests)api-benchmarks.test.ts)
  • Visual pixel-perfection (useFigma visualsource regressionof teststruth: separately)mockups/figma-make-export/)

2. Critical User Journeys

Journey 1: {{JOURNEY_1_NAME}}User Registration — 3-Step Onboarding

Field Value
Priority Critical
Business Impact {{IMPACT}}Core user acquisition — no registration = no users
Frequency {{FREQUENCY}}Every new user (one-time)
Test File {{TEST_PATH}}src/drop-app/__tests__/e2e/user-flows.spec.ts

Steps:

  1. {{STEP_1}}Navigate to https://drop-staging.fly.dev/
  2. {{STEP_2}}Click "Registrer deg" — registration form opens
  3. {{STEP_3}}Enter valid data: name (with Unicode: Amir Hasić), email, password ≥ 8 chars, Norwegian phone (+47), DOB ≥ 18 years
  4. {{STEP_4}}Submit form — OTP sent to phone, OTP input shown
  5. {{STEP_5}}Enter correct 6-digit OTP
  6. {{STEP_6}}Enter and confirm 4-digit PIN
  7. Redirect to dashboard — account activated

Assertions:

  • {{ASSERTION_1}}201 Created on registration (no password hash in response)
  • {{ASSERTION_2}}JWT httpOnly cookie set after PIN setup
  • {{ASSERTION_3}}Dashboard visible with user's name
  • Audit log entry created

Journey 2: {{JOURNEY_2_NAME}}User Login + Dashboard Access

Field Value
Priority Critical
Business Impact {{IMPACT}}Core returning user flow — no login = no revenue
Frequency {{FREQUENCY}}Every user, every session
Test File {{TEST_PATH}}src/drop-app/__tests__/e2e/user-flows.spec.ts

Steps:

  1. {{STEP_1}}Navigate to /login
  2. {{STEP_2}}Enter valid email and password
  3. {{STEP_3}}Submit
  4. Redirected to dashboard
  5. Bank balance shown (from mock AISP)
  6. Recent transactions visible

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

FieldValue
PriorityCritical
Business ImpactCore revenue — 0.5% fee per transaction
FrequencyMultiple times per month per user
Test Filesrc/drop-app/__tests__/e2e/full-flows.spec.ts

Steps:

  1. Log in as KYC-approved consumer
  2. Navigate to "Send penger" (Send Money)
  3. Select recipient; enter amount = 1,000 NOK; select currency = RSD
  4. Review: fee shown as 5 NOK (0.5%); exchange rate shown
  5. Confirm and submit
  6. Transaction created with status = completed
  7. 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

FieldValue
PriorityCritical
Business ImpactCore QR revenue — 1% merchant fee
FrequencyMultiple times per week per merchant
Test Filesrc/drop-app/__tests__/e2e/full-flows.spec.ts

Steps:

  1. Log in as KYC-approved consumer
  2. Navigate to "Scan QR"
  3. Enter valid merchantId (pre-seeded merchant)
  4. Enter amount = 200 NOK
  5. Review: merchant_fee = 2 NOK (1%)
  6. Confirm payment
  7. 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

FieldValue
PriorityHigh
Business ImpactMerchant onboarding — enables QR revenue
FrequencyOne-time per merchant
Test Filesrc/drop-app/__tests__/e2e/full-flows.spec.ts

Steps:

  1. Log in as user (not yet a merchant)
  2. Navigate to "Bli Merchant" (Become Merchant)
  3. Enter business_name and bank_account
  4. Submit — merchant created with unique QR code value
  5. 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 LastPlaywright PassProject
{{JOURNEY_1_NAME}}User Registration (3-step) Critical {{DURATION}}s~30s Yes {{DATE}}
{{JOURNEY_2_NAME}}Critical{{DURATION}}sYes{{DATE}}user-flows
User registrationLogin + email verificationDashboard Critical ~15sYesuser-flows
Remittance NOK→RSDCritical~30sYesfull-flows
QR PaymentCritical~25sYesfull-flows
Merchant RegistrationHigh~20sYesfull-flows
Input Chaos (20+ edge cases)High~60s Yes
Password reset flowHigh45sYes
Account settings updateMedium30sYesinput-chaos

3. Browser & Device Matrix

Desktop Browsers

browserinPlaywright requiredforuserson
Browser Version OS Priority Notes
Chrome Latest stable Windows,macOS, macOSLinux (CI) Critical HighestPrimary markettest share
FirefoxLatest stableWindows, macOSHighCI
Safari Latest stable macOS High WebKit engine
Edge LatestNorwegian stable Windows MediumChromium-basedMac

Mobile Browsers

Browser Platform Version Priority Notes
Safari iOS Latest Critical HighestPrimary mobileDrop shareplatform — iPhone SE to iPhone Pro Max
Chrome Android Latest CriticalHigh Secondary mobile platform

Screen Resolutions (configured in playwright.config.ts)

/
Category Resolution Test Priority Notes
DesktopMobile HDS (iPhone SE) 1920×1080375×667 CriticalDrop primary target device
Mobile L (iPhone 14 Pro)428×926CriticalDrop primary target device
Tablet768×1024MediumSecondary
Desktop 1366×768High
Laptop1280×800 Medium
Fallback
Tabletadmin (landscape)1024×768High
Mobile L428×926Critical
Mobile M375×667Criticaluse

Matrix in CI: RunChromium Critical+ priorityWebKit browser/resolution(mobile combinationsviewports 375px and 428px) on every deployment. Full matrix on nightly schedule.


4. Test Data Setup & Teardown

Setup Strategy

Data Type Method Scope
TestConsumer useraccount accounts(KYC approved) Pre-seeded beforein testbeforeAll runvia API Test suite
{{DATA_TYPE}}Merchant account CreatedPre-seeded in beforeAll via APITest suite
Test recipients (for remittance)Pre-seeded in beforeAll Test suite
Isolated testfresh datauser (for registration tests) Created via API in beforeEach with unique email Individual test

Seed command: bashnpm scripts/e2e-seed.shrun {{ENVIRONMENT}}db:seed Seed(populates verification:staging bashSQLite scripts/verify-seed.shwith {{ENVIRONMENT}}synthetic test data)

Teardown Strategy

Testsuite
Cleanup Item Method Trigger
Test-specificFresh recordsusers created per test DELETE via API afterEach
Test session data Clear browser storage afterEach
EmailsTransactions increated during test inbox APIArchive clear(not delete — audit trail) afterAll
Payment test dataStripe test mode auto-cleanupDaily jobend

Rule: Tests must not leave state that affects other tests. TestsEach musttest becreates executableits inown anyisolated order.data.

Test Accounts

flow
Account Email Role Purpose
Consumer (Amir)[email protected]Consumer, KYC approvedStandard journeys: login, remittance, QR
Merchant (Ahmet)[email protected]MerchantMerchant dashboard, QR generation
Fresh user e2e-user@test.fresh-{{DOMAIN}}timestamp}@test.alai.no UserNone StandardRegistration journeys
Admin usere2e-admin@test.{{DOMAIN}}AdminAdmin panel journeys
{{ROLE}} usere2e-{{ROLE}}@test.{{DOMAIN}}{{ROLE}}{{PURPOSE}}tests

Credentials stored in: {{CREDENTIAL_STORE}}Vaultwarden (nevervault.basicconsulting.no) hardcoded in"Drop tests)E2E Test Accounts"


5. Authentication Handling in Tests

Strategy: {{AUTH_STRATEGY}}API-based

auth
// tests/fixtures/auth.ts
// Authenticateauthenticate via API,POST /api/auth/login in beforeAll, save storage statestate, //reuse Reusefor state acrossall tests in the same suite
//suite. Only use UI login when testing the login flow itselfitself.

// 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
  • InvalidatedJWT andexpires refreshedin if7 expireddays — within test run duration

6. Test Environment Requirements

Requirement Specification
Environment Staging (https://drop-staging.{{DOMAIN}}fly.dev/)
Database DedicatedStaging E2ESQLite database,with seededsynthetic beforeseed rundata only
External services SandboxMock / test modeBaaS (StripeNEXT_PUBLIC_SERVICE_MODE=mock); test,mock email sandbox)Sumsub
Stability No active deployments during E2E run (Fly.io deployment check)
Data persistence Isolated — not shared withfrom manual testing during E2E run
Response times < {{TIMEOUT}}s5,000ms for all endpoints (E2EPlaywright assertionsdefault time out at 2× this)timeout)

Environment locking:Critical: CIE2E acquirestests must NOT run against a lockproduction beforeenvironment. Drop handles financial data — all E2E runtests touse preventmock concurrentBaaS deployments Lock mechanism: {{LOCK_MECHANISM}}exclusively.


7. Flaky Test Management Strategy

Definition: A test that fails inconsistently for the same codecode.

Prevention:

  • Use explicit waitswaits: (waitForResponse('/api/...') not sleeppage.waitForTimeout(1000)) — wait for elements/network, not time
  • Isolate test data — unique emails per test run (e2e-fresh-{Date.now()}@test.alai.no shared state between tests))
  • Use retry-on-assertion,data-testid selectors — not retry-on-runCSS classes or text (can change with Norwegian/English toggle)
  • AvoidDisable animationanimations timingin issuestest withenv via prefers-reduced-motion in test env

Detection:

  • Track flakiness rate per test in CI
  • Any test failing > {{FLAKY_THRESHOLD}}%5% of runs without code changes = flaky
  • Playwright HTML report shows flaky tests in CI artifacts

Response:

  • Immediately tagTag flaky test with @flakytest.fixme() annotation in Playwright
  • Create bugMission ticketControl task with P2 priority based on journey criticality
  • Quarantine (run separately, don't block CI) while fixing
  • Fix within {{FLAKY_FIX_SLA}}3 days or remove the test
  • Monthly flaky test review during sprint retrospective

8. Visual Regression Testing

Tool:Approach: {{VIS_TOOL}}Playwright screenshot comparisons on critical screens. Baseline: Stored in {{BASELINE_STORAGE}}src/drop-app/__tests__/e2e/snapshots/ Threshold: Allow up(committed to {{VIS_THRESHOLD}}%repo) pixelSource differenceof forTruth: fontFigma renderingMake export: mockups/figma-make-export/src/components/

Check Scope Trigger
FullDashboard page screenshotsscreenshot CriticalDashboard pagesscreen UI-touchingPost-staging PRsdeploy
ComponentSend snapshotsMoney form UIRemittance componentsform ComponentOn UI changes
ResponsiveQR Scan screenQR payment screenOn UI changes
Mobile 375px layout MobileAll +critical desktopscreens LayoutOn responsive changes

Review process: VisualScreenshot diffs inrequire PRBuilder requiring+ explicitValidator approvalsign-off before mergemerge. 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 < {{TTI}}ms3,000ms AllDashboard, criticalSend pagesMoney
Core Web Vitals — LCP Largest Contentful Paint < {{LCP}}ms2,500ms Homepage, landing pages
Core Web Vitals — CLSCumulative Layout Shift< {{CLS}}All pagesDashboard
API response TimeRemittance in test assertionsendpoint < {{API_TIMEOUT}}ms1,000ms AllJourney 3
API callsresponseLogin endpoint< 1,000msJourney 2
API responseExchange rates< 200msJourney 3 (rates call)

10. CI Integration

Trigger: Post-staging deployment (GitHub Actions workflow: .github/workflows/e2e.yml)

Parallelization:

  • Test3 sharding:Playwright {{SHARD_COUNT}}projects shardsrun in parallel: user-flows, full-flows, input-chaos
  • Browser parallelism: {{BROWSER_WORKERS}}2 workers per shardproject on CI (total: 6 parallel Playwright workers)
  • Estimated total time: {{E2E_TOTAL_TIME}}< 10 minutes

CI configuration:

# Reference: {{CI_CONFIG_PATH}}.github/workflows/e2e.yml
# Key settings:
# - Shards:Projects: {{SHARD_COUNT}}user-flows, full-flows, input-chaos
# - Retries: {{RETRY_COUNT}}1 (for non-flaky testsdetection; only)not masking failures)
# - Timeout per test: {{TEST_TIMEOUT}}ms30,000ms
# - Timeout total: {{SUITE_TIMEOUT}}min600,000ms (10 min)
# - Base URL: https://drop-staging.fly.dev/

On failure:

  • Collect screenshots, videos, Playwright traces as CI artifacts
  • Retain artifacts for {{ARTIFACT_RETENTION}}7 days
  • Alert Slack channel#drop-e2e-failures #e2e-failureson alai-talk.slack.com
  • Block production deployment until fixed

11. Test Report Format & Artifacts

Report format: {{REPORT_FORMAT}}Playwright HTML report + JUnit XML for CI Report location: {{REPORT_URL}}GitHub orActions 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 — change in one placetests/e2e/pages/
  • Location: tests/src/drop-app/__tests__/e2e/pages/

Selector strategy:strategy (Drop-specific):

  1. data-testid attributes (preferred (e.g., stable, intent-clear)data-testid="remittance-amount")
  2. ARIA roles + accessible name (goode.g., forgetByRole('button', accessibility{ alignment)name: 'Send penger' }))
  3. Text content (acceptable for staticstable text)Norwegian/English text
  4. CSS class names (avoid (Tailwind coupledclasses tocan styling)change)
  5. XPath (never fragile)never

Review cadence:

  • Test suite reviewed monthly for relevance
  • RemoveE2E tests forupdated deprecatedin featuressame immediately
  • PR
  • Update tests before mergingas feature changes (tests are part of the PR)
  • Monthly review: remove tests for deprecated features
  • Figma-make-export checked after every UI change


Approval

Role Name Date Signature
Author John (AI Director) 2026-02-23 Approved (AI)
ReviewerQA Lead Validator Agent 2026-02-23 Approved (AI)
ApproverAI Director (John) John 2026-02-23Approved
CEO (Alem)Alem BašićTBD