Test Inventory
DropBilko — Test Inventory
Status: Active — Tests Implemented
Version: 1.0
Last updated:Updated: 2026-02-1325
Source:Author: ALAI src/drop-app/tests/TotalDocumentation testTeam
This 14inventory (7catalogs unit,all 1implemented integration,tests 1in performance,Bilko, 1organized regression,by 3package E2E,and 1 setup)file.
Directory StructureSummary
| Package | Test Files | Test Cases | Status |
|---|---|---|---|
apps/api/tests/ |
9 |
~99 | Implemented |
packages/core/tests/ |
5 |
121 | Implemented |
| Total | 15 | ~220 | Active |
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):
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 havebalancecolumn (pass-through model verification)Cards table does NOT havecard_numberorcvvcolumns (PCI-DSS fix verification). Haslast_fourandtoken_refinstead.Transaction type constraint only allowsremittanceandqr_paymentForeign 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 limitBlocks after limit exceededResets after window expires
jsonError (2 tests):
Returns correct JSON format ({error, message, details})Includes details array when provided
getClientIp (2 tests):
Extracts fromX-Forwarded-Forheader (first IP)Returns127.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 callUses the provided prefix
maskBankAccount (2 tests):
Masks correctly, showing only last 4 charactersReturns 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 inputAccepts names with numbers mixed in (has letters)Rejects empty and nullRejects XSS payloads (<script>,onclick=)Rejects special-chars-only input
PIN Validation (2 tests):
Validates 4-digit PINsRejects 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 uniquenessExchange Rates Seeded-- 6 NOK rates, queryable for API responseRate Limiting-- Allows within limit, blocks after exceeded, resets after window, cleans expired entriesUser Registration Flow-- Insert, unique constraint, default values, KYC/role constraintsSession Tracking-- Create, retrieve, revocation, expiry, index verificationEnd-to-End User Flow-- Register -> login -> session -> revokeForeign Key Constraints-- Cannot create orphan sessions, cannot delete user with sessionsUtility 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 Name | What It Tests | Status |
|---|---|---|
validateDoubleEntry - returns true for balanced entry |
Debit total equals credit total | Implemented |
validateDoubleEntry - returns false for unbalanced entry |
Debit ≠ credit | Implemented |
validateDoubleEntry - returns false for fewer than 2 lines |
Minimum 2 lines required | Implemented |
validateDoubleEntry - returns false for empty lines |
Empty array → false | Implemented |
validateDoubleEntry - returns false for negative amounts |
Negative amounts invalid | Implemented |
validateDoubleEntry - returns false for zero amounts |
Zero amounts invalid | Implemented |
validateDoubleEntry - handles multiple lines that sum to balanced |
Multi-line balanced entry | Implemented |
validateDoubleEntry - handles decimal amounts with precision |
NUMERIC(19,4) precision | Implemented |
createJournalEntry - returns entry when valid and balanced |
Happy path | Implemented |
createJournalEntry - throws for fewer than 2 lines |
Error: "at least 2 lines" | Implemented |
createJournalEntry - throws for empty lines array |
Error: "at least 2 lines" | Implemented |
createJournalEntry - throws for missing description |
Error: "must have a description" | Implemented |
createJournalEntry - throws for whitespace-only description |
Whitespace = missing | Implemented |
createJournalEntry - throws for missing date |
Error: "must have a date" | Implemented |
createJournalEntry - throws for unbalanced entry |
Error shows debit vs credit amounts | Implemented |
createJournalEntry - throws for negative amount lines |
Negative amounts rejected | Implemented |
calculateTrialBalance - returns balanced from balanced entries |
isBalanced=true, totals correct | Implemented |
calculateTrialBalance - groups by account number |
Rows aggregated per account | Implemented |
calculateTrialBalance - returns empty rows for no transactions |
Empty array → zero totals | Implemented |
calculateTrialBalance - sorts rows by account number |
Rows sorted ascending | Implemented |
chart-of-accounts.test.ts — 32 tests
Tests chart of accounts operations: account creation, parent-child hierarchy, account type validation.
| Test Area | Test Count | Status |
|---|---|---|
| Account creation (valid + invalid inputs) | ~10 | Implemented |
| Account hierarchy (parent-child relationships) | ~8 | Implemented |
| Account type validation (Asset/Liability/Equity/Revenue/Expense) | ~7 | Implemented |
| Account code format validation (1xxx-5xxx range) | ~7 | Implemented |
invoicing.test.ts — 22 tests
Tests invoice number generation, total calculations, and line item validation.
| Test Name | What It Tests | Status |
|---|---|---|
generateInvoiceNumber - generates INV-YYYY-NNN format |
Standard format | Implemented |
generateInvoiceNumber - increments from last number |
Sequential numbering | Implemented |
generateInvoiceNumber - pads number to 3 digits |
Zero-padding | Implemented |
generateInvoiceNumber - handles numbers beyond 999 |
No truncation for 1000+ | Implemented |
generateInvoiceNumber - throws for empty prefix |
Error: "prefix is required" | Implemented |
generateInvoiceNumber - throws for whitespace-only prefix |
Whitespace = invalid | Implemented |
generateInvoiceNumber - throws for negative lastNumber |
Error: "non-negative integer" | Implemented |
generateInvoiceNumber - throws for non-integer lastNumber |
Float rejected | Implemented |
calculateInvoiceTotals - calculates line item total |
quantity × unitPrice | Implemented |
calculateInvoiceTotals - calculates subtotal as sum of lines |
Sum of all line totals | Implemented |
calculateInvoiceTotals - calculates tax per line item |
lineTotal × taxRate / 100 | Implemented |
calculateInvoiceTotals - calculates total = subtotal + tax |
Final total | Implemented |
calculateInvoiceTotals - handles items without taxRate |
Missing tax = 0 | Implemented |
calculateInvoiceTotals - returns zeros for empty items |
Empty array → all zeros | Implemented |
calculateInvoiceTotals - handles multiple items with different rates |
Mixed 20%/10% tax | Implemented |
calculateInvoiceTotals - maintains decimal precision |
3 × 33.33 = 99.99 | Implemented |
validateLineItem - returns true for valid item |
Happy path | Implemented |
validateLineItem - returns false for zero quantity |
qty=0 invalid | Implemented |
validateLineItem - returns false for negative quantity |
qty<0 invalid | Implemented |
validateLineItem - returns false for negative unitPrice |
price<0 invalid | Implemented |
validateLineItem - returns false for empty description |
Description required | Implemented |
validateLineItem - returns false for whitespace-only description |
Whitespace = empty | Implemented |
multi-currency.test.ts — 24 tests
Tests currency conversion, exchange rate locking, and NUMERIC precision handling.
| Test Area | Test Count | Status |
|---|---|---|
| Currency conversion (EUR/RSD/BAM) | ~8 | Implemented |
| Exchange rate locking at transaction date | ~6 | Implemented |
| NUMERIC(19,4) precision (no float drift) | ~5 | Implemented |
| Edge cases (zero rate, missing rate, same currency) | ~5 | Implemented |
tax.test.ts — 23 tests
Tests VAT calculations for all supported countries and edge cases.
| Test Area | Test Count | Status |
|---|---|---|
| Serbia PDV (20% standard, 10% reduced, 0% exempt) | ~6 | Implemented |
| BiH PDV (17% standard) | ~4 | Implemented |
| Croatia PDV (25% standard, 13% reduced, 5% super-reduced) | ~5 | Implemented |
| Mixed tax rates on single invoice | ~3 | Implemented |
| Zero-rate exports | ~2 | Implemented |
| Reverse VAT / gross-to-net | ~3 | Implemented |
apps/api/tests/ — API routeIntegration handlersTests
Integration tests for Express API endpoints. Tests use mocked Prisma client — no real database andrequired. auth.Setup in tests/setup.ts.
POST
a test file)
setup.ts /api/auth/register— Test Infrastructure (5not tests):
Provides:
SuccessfullyPrismaregistersclientwithmock viavi.mock('../src/lib/prisma')- Environment variable setup (JWT secrets, rate limits)
createTestUser()— factory for test user objectsgenerateTestAccessToken()— validinputJWT(201,forchecksauthenticatedDB)requestsReturnsgenerateTestRefreshToken()422—forvalidmissingrefreshemailtokenReturnsConstants:422TEST_ORG_ID,forTEST_USER_ID,short passwordReturns 422 for missing first nameReturns 409 for duplicate emailReturns 400 for invalid JSON body
POST /api/auth/login (5 tests):
Successfully logs in with valid credentials (200)Returns 401 for wrong passwordReturns 401 for non-existent userReturns 400 for missing email or passwordReturns 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 currencyReturns 404 for unsupported currencyHandles case-insensitive codes
POST /api/transactions/remittance (7 tests):
Successfully creates remittance (201, verifies balance deduction)Returns 401 when not authenticatedReturns 403 when KYC not approvedReturns 404 when recipient not foundReturns 402 when insufficient balanceReturns 400 for amount below/above limitsReturns 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 authenticatedReturns 404 when merchant not foundReturns 402 when insufficient balanceReturns 400 for amount below/above limitsReturns 400 for missing merchantIdReturns 400 for invalid JSON bodyTEST_USER_EMAIL
Performance Tests (Vitest)
tests/performance/api-benchmarks.auth.test.ts --— 811 tests
| Test Name | Status | |
|---|---|---|
|
Implemented | |
|
Implemented | |
|
Implemented | |
returns |
Implemented | |
returns |
Implemented | |
returns |
Implemented | |
returns |
Implemented | |
returns |
Implemented | |
returns 200 with current user when authenticated |
GET /auth/me | Implemented |
returns 401 when no token provided |
GET /auth/me | Implemented |
returns 401 for invalid token |
GET /auth/me | Implemented |
invoices.test.ts — 11 tests
| Test Name | Route | Status |
|---|---|---|
returns 200 with paginated list |
GET /invoices | Implemented |
returns 401 without auth |
GET /invoices | Implemented |
returns 201 with created invoice |
POST /invoices | Implemented |
returns 200 with full invoice |
GET /invoices/:id | Implemented |
returns 404 when invoice not found |
GET /invoices/:id | Implemented |
returns 200 when updating draft invoice |
PUT /invoices/:id | Implemented |
returns 400 when updating sent invoice |
PUT /invoices/:id | Implemented |
returns 200 when sending invoice (draft -> sent) |
PATCH /invoices/:id/status | Implemented |
returns 200 when marking invoice as paid (sent -> paid) |
PATCH /invoices/:id/status | Implemented |
returns 204 when deleting draft invoice |
DELETE /invoices/:id | Implemented |
returns 400 when deleting sent invoice |
DELETE /invoices/:id | Implemented |
expenses.test.ts — 9 tests
| Test Area | Route | Status |
|---|---|---|
| List expenses (200 + auth) | GET /expenses | Implemented |
| Create expense (201) | POST /expenses | Implemented |
| Get expense by ID (200 + 404) | GET /expenses/:id | Implemented |
| Update expense (200 + 400 for non-pending) | PUT /expenses/:id | Implemented |
| Approve expense (200 + role check) | PATCH /expenses/:id/approve | Implemented |
| Delete expense (204 + 400 for approved) | DELETE /expenses/:id | Implemented |
contacts.test.ts — 9 tests
| Test Area | Route | Status |
|---|---|---|
| List contacts (200 + auth) | GET /contacts | Implemented |
| Create contact (201 + validation) | POST /contacts | Implemented |
| Get contact (200 + 404) | GET /contacts/:id | Implemented |
| Update contact (200) | PUT /contacts/:id | Implemented |
| Delete contact (204) | DELETE /contacts/:id | Implemented |
accounts.test.ts — 4 tests
| Test Area | Route | Status |
|---|---|---|
| List chart of accounts (200) | GET /accounts | Implemented |
| Get account by ID (200 + 404) | GET /accounts/:id | Implemented |
| Create account (201) | POST /accounts | Implemented |
| Delete account (204) | DELETE /accounts/:id | Implemented |
banking.test.ts — 10 tests
| Test Area | Route | Status |
|---|---|---|
| List bank accounts (200) | GET /banking/accounts | Implemented |
| Create bank account (201) | POST /banking/accounts | Implemented |
| Import bank statement (200 + validation) | POST /banking/accounts/:id/import | Implemented |
| List bank transactions (200) | GET /banking/accounts/:id/transactions | Implemented |
| Reconcile transaction (200 + 400 for mismatch) | POST /banking/accounts/:id/reconcile | Implemented |
reports.test.ts — 9 tests
| Test Area | Route | Status |
|---|---|---|
| Profit & Loss report (200 + date range) | GET /reports/profit-loss | Implemented |
| Balance sheet (200) | GET /reports/balance-sheet | Implemented |
| VAT report for RS (200 + correct rates) | GET /reports/vat | Implemented |
| Trial balance (200) | GET /reports/trial-balance | Implemented |
| Auth required on all report endpoints | All report routes | Implemented |
transactions.test.ts — 9 tests
| Test Area | Route | Status |
|---|---|---|
| List transactions (200 + pagination) | GET /transactions | Implemented |
| Filter by account (200) | GET /transactions?accountId= | Implemented |
| Get transaction by ID (200 + 404) | GET /transactions/:id | Implemented |
| Auth required | All transaction routes | Implemented |
country.test.ts — 27 tests
Tests the country plugin integration — routes that return country-specific tax configuration.
| Test Area | Route | Status |
|---|---|---|
| Serbian PDV rates (20/10/0) for RS org | GET /country/tax-rates | Implemented |
| Bosnian PDV rate (17) for BA org | GET /country/tax-rates | Implemented |
| Croatian PDV rates (25/13/5/0) for HR org | GET /country/tax-rates | Implemented |
| Invoice number format per country | GET /country/invoice-format | Implemented |
| Auth required | All country routes | Implemented |
| Unknown country code (400) | GET /country/tax-rates | Implemented |
e2e/api.test.ts — Full E2E
End-to-end API integration test (no mocks). Exercises the full Express application stack.
| Status |
|---|
| Implemented |
RegressionCoverage Tracking
| Module | Current Status | Target |
|---|---|---|
@bilko/core accounting engine |
Tests implemented ( |
>95% |
@bilko/core invoicing |
Tests implemented (22 cases) | >95% |
@bilko/core tax/VAT |
Tests implemented (23 cases) | >95% |
@bilko/core multi-currency |
Tests implemented (24 cases) | >90% |
@bilko/core chart of accounts |
Tests implemented (32 cases) | >90% |
| Auth API | Tests implemented (11 cases) | >85% |
| Invoices API | Tests implemented (11 cases) | >80% |
| Expenses API | Tests implemented (9 cases) | >80% |
| Banking API | Tests implemented (10 cases) | >75% |
| Reports API | Tests implemented (9 cases) | >75% |
| Country/Tax-Rates API | Tests 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
# 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
BUG-001:npx rateLimit()vitest missingrun await--reporter=verbose
(3
tests):
Related Documents
RateTestinglimitGuide:actually blocks after exceededTESTING-GUIDE.mdCountBackendincrementsArchitecture:correctly in databaseResets after window expires
BUG-002: Validation errors generic message (3 tests):
Register returns details array for validation errorsDetails contain specific field errorsMultiple validation errors all included
BUG-003: Email without @ passed client-side (3 tests):
API rejects email without @ symbolAPI rejects empty string as emailAPI 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 tokenAll 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 brandingHas navigation to login and onboardingNavigates to login page
Login Flow (4 tests):
Shows login form with correct fieldsShows error with empty credentials (client-side)Shows error with wrong credentialsLogs in with demo credentials, redirects to dashboard
Registration Flow (4 tests):
Shows form with required fields, disabled buttonValidates email format client-sideValidates password length client-sideFull flow: form -> OTP -> PIN -> success
Dashboard (2 tests):
Login redirects to dashboard with action buttonsAuthenticated pages load after login
API Health (4 tests):
GET /api/rates returns exchange ratesGET /api/rates/RSD returns specific rateGET /api/rates/XXX returns 404POST /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 historyQR Payment-- login -> scan -> amount -> pay -> verify in historyVirtual Card-- login -> cards -> order -> verify card appearsBank Accounts-- login -> accounts -> verify Open Banking info, DNB accountProfile and Logout-- login -> profile -> verify info -> logout -> redirectFull Navigation-- login -> navigate all 7 pages via direct linksError 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