Test Inventory
Drop Test Inventory
Last updated: 2026-02-13
Source: src/drop-app/tests/
Total test files: 14 (7 unit, 1 integration, 1 performance, 1 regression, 3 E2E, 1 setup)
Directory Structure
tests/
setup.ts # Global setup (sets NODE_ENV=test)
unit/
auth.test.ts # Password hashing + JWT tokens
db.test.ts # Database schema validation
feature-flags.test.ts # Feature flag system
middleware.test.ts # Rate limiting + error responses
utils.test.ts # Utility functions (randomId, maskBankAccount)
validation.test.ts # Input validation functions
api-routes.test.ts # API routes with DB integration
integration/
api-endpoints.test.ts # Full API endpoint integration tests
performance/
api-benchmarks.test.ts # Performance benchmarks
regression/
known-bugs.test.ts # Regression tests for fixed bugs
e2e/
user-flows.spec.ts # Basic user journey E2E
full-flows.spec.ts # Complete feature journey E2E
input-chaos.spec.ts # Malicious/edge-case input E2E
Unit Tests (Vitest)
tests/unit/auth.test.ts -- 7 tests
Password Hashing (4 tests):
hashPasswordproduces bcrypt hash (starts with$2)verifyPasswordvalidates correct bcrypt passwordverifyPasswordrejects wrong passwordverifyPassworddoes NOT accept SHA-256 hashes (security fix C4)
JWT Token Management (3 tests):
signTokenandverifyTokenround-trip worksverifyTokenrejects invalid tokensverifyTokenrejects tampered tokens
tests/unit/db.test.ts -- 5 tests
- Creates all 11 expected tables (users, transactions, recipients, merchants, cards, bank_accounts, sessions, notifications, settings, exchange_rates, spending_limits)
- Users table does NOT have
balancecolumn (pass-through model verification) - Cards table does NOT have
card_numberorcvvcolumns (PCI-DSS fix verification). Haslast_fourandtoken_refinstead. - Transaction type constraint only allows
remittanceandqr_payment - Foreign key constraints are enforced
tests/unit/feature-flags.test.ts -- 6 tests
isEnabledreturns default when no env var is setisEnabledreadsNEXT_PUBLIC_FF_*env varsfeatureGatereturns 404-like response when disabledfeatureGatereturns null when enabledgetAllFlagsreturns complete flag set (8 flags)topUpViaCardflag does NOT exist (removed feature)
tests/unit/middleware.test.ts -- 7 tests
Rate Limiting (3 tests):
- Allows requests within limit
- Blocks after limit exceeded
- Resets after window expires
jsonError (2 tests):
- Returns correct JSON format (
{error, message, details}) - Includes details array when provided
getClientIp (2 tests):
- Extracts from
X-Forwarded-Forheader (first IP) - Returns
127.0.0.1when no header present
tests/unit/utils.test.ts -- 5 tests
randomId (3 tests):
- Generates prefixed IDs with correct format (
prefix_<hex16>) - Generates unique IDs on each call
- Uses the provided prefix
maskBankAccount (2 tests):
- Masks correctly, showing only last 4 characters
- Returns short accounts unchanged
tests/unit/validation.test.ts -- 10 tests
Email Validation (2 tests):
- Accepts valid emails (standard, tag, domain variants)
- Rejects invalid emails (empty, no @, space, null)
Phone Validation (2 tests):
- Accepts international format (+47, +381)
- Rejects invalid numbers (no +, too short, letters, null)
Amount Validation (2 tests):
- Accepts valid positive amounts (including 0.01)
- Rejects negative, zero, NaN, and >2 decimal places
IBAN Validation (2 tests):
- Validates correct IBANs (Norwegian, German)
- Rejects invalid IBANs (empty, too short, bad checksum, null)
Name Validation (6 tests, grouped):
- Accepts valid names (Latin, Bosnian chars, apostrophes, hyphens, umlauts)
- Rejects numbers-only input
- Accepts names with numbers mixed in (has letters)
- Rejects empty and null
- Rejects XSS payloads (
<script>,onclick=) - Rejects special-chars-only input
PIN Validation (2 tests):
- Validates 4-digit PINs
- Rejects invalid PINs (too short, too long, letters, null)
tests/unit/api-routes.test.ts -- 8 test groups
- DB + Auth Integration -- User creation with bcrypt, password verification, hash uniqueness
- Exchange Rates Seeded -- 6 NOK rates, queryable for API response
- Rate Limiting -- Allows within limit, blocks after exceeded, resets after window, cleans expired entries
- User Registration Flow -- Insert, unique constraint, default values, KYC/role constraints
- Session Tracking -- Create, retrieve, revocation, expiry, index verification
- End-to-End User Flow -- Register -> login -> session -> revoke
- Foreign Key Constraints -- Cannot create orphan sessions, cannot delete user with sessions
- Utility Functions -- randomId format and uniqueness
Integration Tests (Vitest)
tests/integration/api-endpoints.test.ts -- 20+ tests
Tests actual API route handlers with mocked database and auth.
POST /api/auth/register (5 tests):
- Successfully registers with valid input (201, checks DB)
- Returns 422 for missing email
- Returns 422 for short password
- Returns 422 for missing first name
- Returns 409 for duplicate email
- Returns 400 for invalid JSON body
POST /api/auth/login (5 tests):
- Successfully logs in with valid credentials (200)
- Returns 401 for wrong password
- Returns 401 for non-existent user
- Returns 400 for missing email or password
- Returns 400 for invalid JSON body
GET /api/rates (2 tests):
- Returns all exchange rates (6 currencies)
- Returns empty rates when none seeded
GET /api/rates/[currency] (3 tests):
- Returns rate for valid currency
- Returns 404 for unsupported currency
- Handles case-insensitive codes
POST /api/transactions/remittance (7 tests):
- Successfully creates remittance (201, verifies balance deduction)
- Returns 401 when not authenticated
- Returns 403 when KYC not approved
- Returns 404 when recipient not found
- Returns 402 when insufficient balance
- Returns 400 for amount below/above limits
- Returns 400 for invalid amount (NaN)
POST /api/transactions/qr-payment (8 tests):
- Successfully creates QR payment (201, verifies balance, fee calc)
- Returns 401 when not authenticated
- Returns 404 when merchant not found
- Returns 402 when insufficient balance
- Returns 400 for amount below/above limits
- Returns 400 for missing merchantId
- Returns 400 for invalid JSON body
Performance Tests (Vitest)
tests/performance/api-benchmarks.test.ts -- 8 tests
| Test | Threshold |
|---|---|
hashPassword (bcrypt rounds=12) |
< 1000ms |
verifyPassword (bcrypt compare) |
< 1000ms |
rateLimit single check |
< 50ms |
| DB SELECT query | < 10ms |
| DB INSERT query | < 20ms |
| Exchange rate lookup | < 10ms |
| 50 concurrent rateLimit calls | < 2000ms total |
| Transaction INSERT | < 50ms |
Regression Tests (Vitest)
tests/regression/known-bugs.test.ts -- 4 bug groups
BUG-001: rateLimit() missing await (3 tests):
- Rate limit actually blocks after exceeded
- Count increments correctly in database
- Resets after window expires
BUG-002: Validation errors generic message (3 tests):
- Register returns details array for validation errors
- Details contain specific field errors
- Multiple validation errors all included
BUG-003: Email without @ passed client-side (3 tests):
- API rejects email without @ symbol
- API rejects empty string as email
- API accepts valid email with @
BUG-004: Missing getDb import in auth.ts (5 tests):
- All auth module exports are functional (signToken, verifyToken, setAuthCookie, clearAuthCookie, getCurrentUser)
- getCurrentUser returns null when no token
- All exports are functions
E2E Tests (Playwright)
tests/e2e/user-flows.spec.ts -- 5 test groups
Landing Page (3 tests):
- Loads homepage with Drop branding
- Has navigation to login and onboarding
- Navigates to login page
Login Flow (4 tests):
- Shows login form with correct fields
- Shows error with empty credentials (client-side)
- Shows error with wrong credentials
- Logs in with demo credentials, redirects to dashboard
Registration Flow (4 tests):
- Shows form with required fields, disabled button
- Validates email format client-side
- Validates password length client-side
- Full flow: form -> OTP -> PIN -> success
Dashboard (2 tests):
- Login redirects to dashboard with action buttons
- Authenticated pages load after login
API Health (4 tests):
- GET /api/rates returns exchange rates
- GET /api/rates/RSD returns specific rate
- GET /api/rates/XXX returns 404
- POST /api/auth/register validates input
All Pages Load (10 tests):
- Each page (
/,/login,/onboarding,/dashboard,/send,/scan,/history,/accounts,/profile,/cards) returns no server error
tests/e2e/full-flows.spec.ts -- 8 journeys
- New User Registration -- form -> OTP -> PIN -> success -> dashboard (skipped)
- Send Money -- login -> recipient -> amount -> confirm -> verify in history
- QR Payment -- login -> scan -> amount -> pay -> verify in history
- Virtual Card -- login -> cards -> order -> verify card appears
- Bank Accounts -- login -> accounts -> verify Open Banking info, DNB account
- Profile and Logout -- login -> profile -> verify info -> logout -> redirect
- Full Navigation -- login -> navigate all 7 pages via direct links
- Error Handling -- wrong credentials -> error -> correct -> success (skipped)
tests/e2e/input-chaos.spec.ts -- 7 test groups, 40+ tests
Login Chaos (8 tests):
- Empty fields, spaces-only email, XSS in email, SQL injection in email, 10K char email, unicode password, special characters, Norwegian characters
Registration Chaos (20+ tests):
- All fields empty, XSS in firstName, email without @, email with only @, email with spaces, password 7 chars (boundary), password all-numbers, SQL injection in lastName, HTML injection, 10K char name, numbers-only names, special-chars-only, Bosnian chars, emoji, spaces-only, password complexity, underage DOB, duplicate email, far-future DOB, OTP with letters/5 digits/7+ digits, phone with letters
Send Money Chaos (6 tests):
- Amount 0, negative, extremely large, text in number field, XSS in search, special chars in search
QR Payment Chaos (4 tests):
- Amount 0, negative, very large, many decimals
API Impossible Inputs (14 tests):
- Empty JSON, number as email, null values, array/object as email, wrong Content-Type, path traversal, XSS in name, 1MB password, unicode email, numbers-only name, underage DOB, duplicate email, password no letters
Page Resilience (5 tests):
- Dashboard without auth, send without auth, rapid navigation, double-click submit, browser back from OTP