Skip to main content

Test Inventory

DropBilko — Test Inventory

Status: Active — Tests Implemented Version: 1.0 Last updated:Updated: 2026-02-1325 Source:Author: src/drop-app/tests/ALAI TotalDocumentation testTeam

files:

This 14inventory (7catalogs unit,all 1implemented integration,tests 1in performance,Bilko, 1organized regression,by 3package E2E,and 1 setup)file.


Directory StructureSummary












setup.tsdb.test.ts#Databaseschemavalidationfeature-flags.test.tsflagsystemmiddleware.test.ts#Ratelimiting+errorresponsesutils.test.ts#
PackageTest FilesTest CasesStatus
apps/api/tests/ 9 #test Global setup (sets NODE_ENV=test) unit/ auth.test.ts # Password hashingfiles + JWT1 tokense2e ~99 Implemented
packages/core/tests/ 5 #test Featurefiles 121 Implemented
Total 15 ~220 Active
Utility
functions

packages/core/tests/ (randomId, maskBankAccount)Unit validation.test.tsTests

#

Pure 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 # Regressionunit tests for fixedthe bugs@bilko/core e2e/financial user-flows.spec.tsengine. #No Basicdatabase, userno journeyHTTP. E2EUses full-flows.spec.tsglobals: # Complete feature journey E2E input-chaos.spec.ts # Malicious/edge-case input E2E true


Unit Tests (Vitest)

no explicit imports of describe/it/expect).

tests/unit/auth.accounting.test.ts -- 7 tests

Password Hashing (4 tests):

  • hashPassword produces bcrypt hash (starts with $2)
  • verifyPassword validates correct bcrypt password
  • verifyPassword rejects wrong password
  • verifyPassword does NOT accept SHA-256 hashes (security fix C4)

JWT Token Management (3 tests):

  • signToken and verifyToken round-trip works
  • verifyToken rejects invalid tokens
  • verifyToken rejects 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 balance column (pass-through model verification)
  • Cards table does NOT have card_number or cvv columns (PCI-DSS fix verification). Has last_four and token_ref instead.
  • Transaction type constraint only allows remittance and qr_payment
  • Foreign key constraints are enforced

tests/unit/feature-flags.test.ts -- 6 tests

  • isEnabled returns default when no env var is set
  • isEnabled reads NEXT_PUBLIC_FF_* env vars
  • featureGate returns 404-like response when disabled
  • featureGate returns null when enabled
  • getAllFlags returns complete flag set (8 flags)
  • topUpViaCard flag 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-For header (first IP)
  • Returns 127.0.0.1 when 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

  1. DB + Auth Integration -- User creation with bcrypt, password verification, hash uniqueness
  2. Exchange Rates Seeded -- 6 NOK rates, queryable for API response
  3. Rate Limiting -- Allows within limit, blocks after exceeded, resets after window, cleans expired entries
  4. User Registration Flow -- Insert, unique constraint, default values, KYC/role constraints
  5. Session Tracking -- Create, retrieve, revocation, expiry, index verification
  6. End-to-End User Flow -- Register -> login -> session -> revoke
  7. Foreign Key Constraints -- Cannot create orphan sessions, cannot delete user with sessions
  8. Utility Functions -- randomId format and uniqueness

Integration Tests (Vitest)

tests/integration/api-endpoints.test.ts -- 20+20 tests

Tests actualdouble-entry bookkeeping engine: validateDoubleEntry, createJournalEntry, calculateTrialBalance.

Test NameWhat It TestsStatus
validateDoubleEntry - returns true for balanced entryDebit total equals credit totalImplemented
validateDoubleEntry - returns false for unbalanced entryDebit ≠ creditImplemented
validateDoubleEntry - returns false for fewer than 2 linesMinimum 2 lines requiredImplemented
validateDoubleEntry - returns false for empty linesEmpty array → falseImplemented
validateDoubleEntry - returns false for negative amountsNegative amounts invalidImplemented
validateDoubleEntry - returns false for zero amountsZero amounts invalidImplemented
validateDoubleEntry - handles multiple lines that sum to balancedMulti-line balanced entryImplemented
validateDoubleEntry - handles decimal amounts with precisionNUMERIC(19,4) precisionImplemented
createJournalEntry - returns entry when valid and balancedHappy pathImplemented
createJournalEntry - throws for fewer than 2 linesError: "at least 2 lines"Implemented
createJournalEntry - throws for empty lines arrayError: "at least 2 lines"Implemented
createJournalEntry - throws for missing descriptionError: "must have a description"Implemented
createJournalEntry - throws for whitespace-only descriptionWhitespace = missingImplemented
createJournalEntry - throws for missing dateError: "must have a date"Implemented
createJournalEntry - throws for unbalanced entryError shows debit vs credit amountsImplemented
createJournalEntry - throws for negative amount linesNegative amounts rejectedImplemented
calculateTrialBalance - returns balanced from balanced entriesisBalanced=true, totals correctImplemented
calculateTrialBalance - groups by account numberRows aggregated per accountImplemented
calculateTrialBalance - returns empty rows for no transactionsEmpty array → zero totalsImplemented
calculateTrialBalance - sorts rows by account numberRows sorted ascendingImplemented

chart-of-accounts.test.ts — 32 tests

Tests chart of accounts operations: account creation, parent-child hierarchy, account type validation.

Test AreaTest CountStatus
Account creation (valid + invalid inputs)~10Implemented
Account hierarchy (parent-child relationships)~8Implemented
Account type validation (Asset/Liability/Equity/Revenue/Expense)~7Implemented
Account code format validation (1xxx-5xxx range)~7Implemented

invoicing.test.ts — 22 tests

Tests invoice number generation, total calculations, and line item validation.

Test NameWhat It TestsStatus
generateInvoiceNumber - generates INV-YYYY-NNN formatStandard formatImplemented
generateInvoiceNumber - increments from last numberSequential numberingImplemented
generateInvoiceNumber - pads number to 3 digitsZero-paddingImplemented
generateInvoiceNumber - handles numbers beyond 999No truncation for 1000+Implemented
generateInvoiceNumber - throws for empty prefixError: "prefix is required"Implemented
generateInvoiceNumber - throws for whitespace-only prefixWhitespace = invalidImplemented
generateInvoiceNumber - throws for negative lastNumberError: "non-negative integer"Implemented
generateInvoiceNumber - throws for non-integer lastNumberFloat rejectedImplemented
calculateInvoiceTotals - calculates line item totalquantity × unitPriceImplemented
calculateInvoiceTotals - calculates subtotal as sum of linesSum of all line totalsImplemented
calculateInvoiceTotals - calculates tax per line itemlineTotal × taxRate / 100Implemented
calculateInvoiceTotals - calculates total = subtotal + taxFinal totalImplemented
calculateInvoiceTotals - handles items without taxRateMissing tax = 0Implemented
calculateInvoiceTotals - returns zeros for empty itemsEmpty array → all zerosImplemented
calculateInvoiceTotals - handles multiple items with different ratesMixed 20%/10% taxImplemented
calculateInvoiceTotals - maintains decimal precision3 × 33.33 = 99.99Implemented
validateLineItem - returns true for valid itemHappy pathImplemented
validateLineItem - returns false for zero quantityqty=0 invalidImplemented
validateLineItem - returns false for negative quantityqty<0 invalidImplemented
validateLineItem - returns false for negative unitPriceprice<0 invalidImplemented
validateLineItem - returns false for empty descriptionDescription requiredImplemented
validateLineItem - returns false for whitespace-only descriptionWhitespace = emptyImplemented

multi-currency.test.ts — 24 tests

Tests currency conversion, exchange rate locking, and NUMERIC precision handling.

Test AreaTest CountStatus
Currency conversion (EUR/RSD/BAM)~8Implemented
Exchange rate locking at transaction date~6Implemented
NUMERIC(19,4) precision (no float drift)~5Implemented
Edge cases (zero rate, missing rate, same currency)~5Implemented

tax.test.ts — 23 tests

Tests VAT calculations for all supported countries and edge cases.

Test AreaTest CountStatus
Serbia PDV (20% standard, 10% reduced, 0% exempt)~6Implemented
BiH PDV (17% standard)~4Implemented
Croatia PDV (25% standard, 13% reduced, 5% super-reduced)~5Implemented
Mixed tax rates on single invoice~3Implemented
Zero-rate exports~2Implemented
Reverse VAT / gross-to-net~3Implemented

apps/api/tests/ — API routeIntegration handlersTests

with

Integration tests for Express API endpoints. Tests use mocked Prisma client — no real database andrequired. auth.Setup in tests/setup.ts.

POST

setup.ts /api/auth/register— Test Infrastructure (5not tests):a test file)

Provides:

  • SuccessfullyPrisma registersclient withmock via vi.mock('../src/lib/prisma')
  • Environment variable setup (JWT secrets, rate limits)
  • createTestUser() — factory for test user objects
  • generateTestAccessToken() — valid inputJWT (201,for checksauthenticated DB)requests
  • ReturnsgenerateTestRefreshToken() 422 forvalid missingrefresh emailtoken
  • ReturnsConstants: 422TEST_ORG_ID, forTEST_USER_ID, 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 bodyTEST_USER_EMAIL

Performance Tests (Vitest)

tests/performance/api-benchmarks.auth.test.ts -- 811 tests

total
Test Name ThresholdRouteStatus
hashPasswordreturns 201 with user, organization, and tokens (bcrypt rounds=12) <POST 1000ms/auth/registerImplemented
verifyPasswordreturns 400 for duplicate email (bcrypt compare) <POST 1000ms/auth/registerImplemented
rateLimitreturns 200 with tokens for valid credentials single check <POST 50ms/auth/loginImplemented
DBreturns SELECT401 queryfor invalid password <POST 10ms/auth/loginImplemented
DBreturns INSERT401 queryfor non-existent email <POST 20ms/auth/loginImplemented
Exchangereturns rate200 lookupwith new access token for valid refresh token <POST 10ms/auth/refreshImplemented
50returns concurrent401 rateLimitwhen callsno refresh token cookie is present <POST 2000ms/auth/refresh Implemented
Transactionreturns INSERT204 and clears cookie <POST 50ms/auth/logoutImplemented
returns 200 with current user when authenticatedGET /auth/meImplemented
returns 401 when no token providedGET /auth/meImplemented
returns 401 for invalid tokenGET /auth/meImplemented

invoices.test.ts — 11 tests

Test NameRouteStatus
returns 200 with paginated listGET /invoicesImplemented
returns 401 without authGET /invoicesImplemented
returns 201 with created invoicePOST /invoicesImplemented
returns 200 with full invoiceGET /invoices/:idImplemented
returns 404 when invoice not foundGET /invoices/:idImplemented
returns 200 when updating draft invoicePUT /invoices/:idImplemented
returns 400 when updating sent invoicePUT /invoices/:idImplemented
returns 200 when sending invoice (draft -> sent)PATCH /invoices/:id/statusImplemented
returns 200 when marking invoice as paid (sent -> paid)PATCH /invoices/:id/statusImplemented
returns 204 when deleting draft invoiceDELETE /invoices/:idImplemented
returns 400 when deleting sent invoiceDELETE /invoices/:idImplemented

expenses.test.ts — 9 tests

Test AreaRouteStatus
List expenses (200 + auth)GET /expensesImplemented
Create expense (201)POST /expensesImplemented
Get expense by ID (200 + 404)GET /expenses/:idImplemented
Update expense (200 + 400 for non-pending)PUT /expenses/:idImplemented
Approve expense (200 + role check)PATCH /expenses/:id/approveImplemented
Delete expense (204 + 400 for approved)DELETE /expenses/:idImplemented

contacts.test.ts — 9 tests

Test AreaRouteStatus
List contacts (200 + auth)GET /contactsImplemented
Create contact (201 + validation)POST /contactsImplemented
Get contact (200 + 404)GET /contacts/:idImplemented
Update contact (200)PUT /contacts/:idImplemented
Delete contact (204)DELETE /contacts/:idImplemented

accounts.test.ts — 4 tests

Test AreaRouteStatus
List chart of accounts (200)GET /accountsImplemented
Get account by ID (200 + 404)GET /accounts/:idImplemented
Create account (201)POST /accountsImplemented
Delete account (204)DELETE /accounts/:idImplemented

banking.test.ts — 10 tests

Test AreaRouteStatus
List bank accounts (200)GET /banking/accountsImplemented
Create bank account (201)POST /banking/accountsImplemented
Import bank statement (200 + validation)POST /banking/accounts/:id/importImplemented
List bank transactions (200)GET /banking/accounts/:id/transactionsImplemented
Reconcile transaction (200 + 400 for mismatch)POST /banking/accounts/:id/reconcileImplemented

reports.test.ts — 9 tests

Test AreaRouteStatus
Profit & Loss report (200 + date range)GET /reports/profit-lossImplemented
Balance sheet (200)GET /reports/balance-sheetImplemented
VAT report for RS (200 + correct rates)GET /reports/vatImplemented
Trial balance (200)GET /reports/trial-balanceImplemented
Auth required on all report endpointsAll report routesImplemented

transactions.test.ts — 9 tests

Test AreaRouteStatus
List transactions (200 + pagination)GET /transactionsImplemented
Filter by account (200)GET /transactions?accountId=Implemented
Get transaction by ID (200 + 404)GET /transactions/:idImplemented
Auth requiredAll transaction routesImplemented

country.test.ts — 27 tests

Tests the country plugin integration — routes that return country-specific tax configuration.

Test AreaRouteStatus
Serbian PDV rates (20/10/0) for RS orgGET /country/tax-ratesImplemented
Bosnian PDV rate (17) for BA orgGET /country/tax-ratesImplemented
Croatian PDV rates (25/13/5/0) for HR orgGET /country/tax-ratesImplemented
Invoice number format per countryGET /country/invoice-formatImplemented
Auth requiredAll country routesImplemented
Unknown country code (400)GET /country/tax-ratesImplemented

e2e/api.test.ts — Full E2E

End-to-end API integration test (no mocks). Exercises the full Express application stack.

Status
Implemented

RegressionCoverage Tracking

ModuleCurrent StatusTarget
@bilko/core accounting engineTests implemented (Vitest)20 cases)>95%
@bilko/core invoicingTests implemented (22 cases)>95%
@bilko/core tax/VATTests implemented (23 cases)>95%
@bilko/core multi-currencyTests implemented (24 cases)>90%
@bilko/core chart of accountsTests implemented (32 cases)>90%
Auth APITests implemented (11 cases)>85%
Invoices APITests implemented (11 cases)>80%
Expenses APITests implemented (9 cases)>80%
Banking APITests implemented (10 cases)>75%
Reports APITests implemented (9 cases)>75%
Country/Tax-Rates APITests implemented (27 cases)>80%

Test Execution Commands

# All tests (from project root)
npm run test

# Core unit tests only
cd packages/core && npx vitest run

# API integration tests only
cd apps/api && npx vitest run

# Watch mode (re-run on change)
cd packages/core && npx vitest

# Specific file
cd apps/api && npx vitest run tests/regression/known-bugs.auth.test.ts

# With coverage
cd packages/core && npx vitest run --coverage

4# bugVerbose groups

output

BUG-001:npx rateLimit()vitest missingrun await--reporter=verbose (3 tests):


  • RateTesting limitGuide: actually blocks after exceededTESTING-GUIDE.md
  • CountBackend incrementsArchitecture: 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../backend/BACKEND-ARCHITECTURE.md

E2E

Last TestsUpdated: (Playwright)

2026-02-25

tests/e2e/user-flows.spec.tsStatus: --Active 5Total Tests: ~220 across 14 test groups

Landing Page (3 tests):files

  • 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

  1. New User Registration -- form -> OTP -> PIN -> success -> dashboard (skipped)
  2. Send Money -- login -> recipient -> amount -> confirm -> verify in history
  3. QR Payment -- login -> scan -> amount -> pay -> verify in history
  4. Virtual Card -- login -> cards -> order -> verify card appears
  5. Bank Accounts -- login -> accounts -> verify Open Banking info, DNB account
  6. Profile and Logout -- login -> profile -> verify info -> logout -> redirect
  7. Full Navigation -- login -> navigate all 7 pages via direct links
  8. 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