Skip to main content

Test Inventory

DropBilko — Test Inventory

Status: Active — Tests Implemented Version: 2.0 Last updated:Updated: 2026-02-1303-02 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
















































PackageTest FilesTest CasesStatus
apps/api/tests/ (mock suite)11 test files~130Implemented
apps/api/tests/unit/ (unit suite)4 test files~60Implemented
apps/api/tests/e2e/ (E2E suite)2 test files~30Implemented
apps/api/tests/integration/ (real DB)5 test files~50Implemented
packages/core/tests/ (unit)5 test files121Implemented
Total27~390Active

Test Category Breakdown

# 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-benchmarks.test.tsbenchmarksregression/known-bugs.test.ts
CategoryDescriptionRequires DB
Mock suite (tests/ setup.ts # Global setup (sets NODE_ENV=test) unit/ auth.*.test.ts) API endpoint integrationtests with mocked Prisma — fast, no DBNo
Unit suite (tests/unit/)Service-layer tests, financial logic, SEF clientNo
E2E suite (tests/e2e/)End-to-end billing flows with mocked servicesNo
Integration suite (tests/integration/)Real DB tests performance/(docker-compose.test.yml) Yes # PerformancePostgreSQL
Core #unit Regression(packages/core/)Pure business logic — no HTTP, no DBNo

packages/core/tests/ — Unit Tests

Pure unit 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/ — Mock API routeTests

handlers

Integration withtests 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

chatbot.test.ts — Chatbot API Tests

Test NameRouteStatus
returns 200 with assistant responsePOST /chatbot/messageImplemented
returns 400 when message is emptyPOST /chatbot/messageImplemented
returns 429 when rate limit exceededPOST /chatbot/messageImplemented
returns 401 without authPOST /chatbot/messageImplemented
returns 200 with conversation historyGET /chatbot/historyImplemented
returns empty array when no history existsGET /chatbot/historyImplemented
returns 401 without auth on historyGET /chatbot/historyImplemented
returns 204 when history clearedDELETE /chatbot/historyImplemented
returns 401 without auth on clear historyDELETE /chatbot/historyImplemented

invoice-gl-reversal.test.ts — Invoice GL Reversal Tests

Tests InvoiceService.cancelInvoice() — when a SENT invoice is cancelled, reversing double-entry GL entries are created to undo the original booking.

Test AreaStatus
Cancels draft invoice (sets status to cancelled, no GL reversal)Implemented
Cancels sent invoice (creates reversing GL transactions)Implemented
Reversal debits = original credits (GL stays balanced)Implemented
Throws 404 when invoice not foundImplemented
Throws 400 when invoice is already cancelledImplemented
Throws 400 when invoice is paid (cannot cancel paid invoices)Implemented

new-endpoints.test.ts — Additional Endpoint Tests

Tests for supplemental endpoints not covered in the main mock suite.

Test AreaRouteStatus
Receipt not attached (404)GET /expenses/:id/receiptImplemented
Receipt auth required (401)GET /expenses/:id/receiptImplemented
VAT export PDF (200 / 404)GET /reports/vat/export/pdfImplemented
VAT export XML (200 / 404)GET /reports/vat/export/xmlImplemented
Dashboard metrics (200)GET /reports/dashboardImplemented
Dashboard auth required (401)GET /reports/dashboardImplemented
Audit log (200 + owner/admin only)GET /security/audit-logImplemented
Audit log role check (403 for viewer)GET /security/audit-logImplemented
Data export (200 + owner only)POST /security/data-exportImplemented
Data export role check (403 for admin)POST /security/data-exportImplemented

e2e/api.test.ts — Full E2E (no mocks, live server)

End-to-end API integration test. Exercises the full Express application stack with a live server.

Status
Implemented

e2e/billing-flow.e2e.test.ts — Billing Workflow E2E

Tests the full billing flow through HTTP endpoints with mocked services (no real DB required):

  1. Create contact
  2. Create invoice
  3. Send invoice (draft → sent)
  4. Mark invoice paid (sent → paid)
  5. Check P&L shows revenue
  6. Verify trial balance returns isBalanced=true
  7. Multi-currency invoice in EUR with country VAT rates
  8. Credit note creation
Status
Implemented

Regressionapps/api/tests/unit/ — Unit Tests (Vitest)service layer)

Service-level unit tests with mocked Prisma. No HTTP layer. Tests business logic in individual service classes.

tests/regression/known-bugs.invoice-service-calculations.test.ts -- 4Invoice bug groupsArithmetic

BUG-001:Tests rateLimit(InvoiceService.createInvoice() missingarithmetic awaitat (3the tests):service layer. Verifies:

  • RatelineTotal limit= actuallyquantity blocks× after exceededunitPrice
  • CountlineTax increments= correctlylineTotal in× databasetaxRate / 100
  • Resetssubtotal after= windowsum(lineTotals)
  • expires
  • taxAmount = sum(lineTaxes)
  • total = subtotal + taxAmount
  • baseAmount = total × exchangeRate
Test AreaStatus
Single-line invoice arithmeticImplemented
Multi-line invoice with mixed tax ratesImplemented
Multi-currency exchange rate applicationImplemented
Zero-quantity line items rejectedImplemented
NUMERIC(19,4) precision maintainedImplemented

two-factor.test.ts — Two-Factor Authentication Service

Tests TwoFactorService at the service level. Mocks: bcryptjs, speakeasy, qrcode, Prisma.

Test NameStatus
enable - wrong password → throws unauthorizedImplemented
enable - correct password → returns secret + QR data URL + 10 codesImplemented
enable - backup codes are hashed before storingImplemented
enable - plaintext backup codes returned once onlyImplemented
verify - valid TOTP + window=1 → activates 2FAImplemented
verify - invalid TOTP → throws badRequestImplemented
disable - correct password → clears secret + backup codesImplemented
disable - wrong password → throws unauthorizedImplemented

sef-submission.test.ts — SEF (Serbia E-Invoicing) Client

Tests SefClient class and InvoiceService.submitToSef() fire-and-forget behavior. HTTP calls are mocked via vi.spyOn(global, 'fetch').

Test AreaStatus
SefClient submits UBL XML to SEF sandbox URLImplemented
SefClient uses production URL in production envImplemented
SefClient retries on network failureImplemented
createSefClientFromEnv() reads credentials from env varsImplemented
generateSEFInvoiceXML() produces valid UBL 2.1 XMLImplemented
InvoiceService.submitToSef() never re-throws errorsImplemented

vat-calculation.test.ts — VAT Calculation Tests (Country Packages)

Tests pure calculation functions from @bilko/country-rs, @bilko/country-ba, and @bilko/country-hr. No Prisma, no HTTP — stateless math functions.

CountryFunctions TestedStatus
SerbiacalculateSerbianPDV, calculateNetFromGrossPDV, qualifiesForPausalRegime, requiresVATRegistration, calculateSerbianCITImplemented
BosniacalculateBosnianPDV, calculateNetFromGrossPDV, requiresVATRegistrationImplemented
CroatiacalculateCroatianPDV, calculateNetFromGrossPDV, requiresVATRegistrationImplemented
All ratesStandard, reduced, zero, super-reduced rates per countryImplemented

apps/api/tests/integration/ — Real Database Tests

Integration tests that run against a real PostgreSQL database via docker-compose.test.yml. Requires Docker.

BUG-002:Run Validationwith:

errors
cd genericapps/api
messagedocker-compose -f ../../docker-compose.test.yml up -d
npm run test:integration

auth.integration.test.ts — Auth Integration

Full registration + login + refresh flow against real DB.

Test AreaStatus
Register new organization + owner userImplemented
Login with correct credentialsImplemented
Refresh access token via cookieImplemented
Reject duplicate email registrationImplemented

invoice.integration.test.ts — Invoice CRUD Integration

Invoice lifecycle against real DB: create → read → update → status change.

Test AreaStatus
Create invoice with line itemsImplemented
Read invoice by IDImplemented
Update draft invoiceImplemented
Send invoice (3draft tests):→ sent)Implemented
Mark paid (sent → paid)Implemented

credit-note-gl.integration.test.ts — Credit Note GL Integration

Tests credit note creation against real DB — verifies reversing GL entries balance.

Test AreaStatus
Credit note creates reversing journal entriesImplemented
Reversing entries balance (debits = credits)Implemented
Original invoice marked as creditedImplemented

report.integration.test.ts — Reports Integration

Report generation against real DB with seeded transactions.

Test AreaStatus
P&L report returns revenue/expense dataImplemented
VAT report returns correct tax amountsImplemented
Trial balance returns isBalanced=trueImplemented

tenant-isolation.integration.test.ts — Multi-Tenant Security

Verifies multi-tenant isolation: Organization A cannot read or modify Organization B's data.

Test AreaStatus
Org A cannot list Org B's invoicesImplemented
Org A cannot read Org B's invoice by IDImplemented
Org A cannot update Org B's invoiceImplemented
Org A cannot delete Org B's contactImplemented
Cross-tenant requests return 404 (not 403 — no data leakage)Implemented

Coverage Tracking

ModuleCurrent StatusTarget
@bilko/core accounting engineTests implemented (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%
Chatbot APITests implemented (9 cases)>80%
Security/Audit APITests implemented (via new-endpoints)>80%
Invoice GL Reversal (service layer)Tests implemented>90%
Two-Factor Auth (service layer)Tests implemented (8 cases)>90%
SEF Client + SubmissionTests implemented>85%
VAT Calculations (country packages)Tests implemented>95%
Multi-tenant isolation (real DB)Tests implemented (5 scenarios)100%
Invoice CRUD (real DB)Tests implemented>80%
Credit note GL (real DB)Tests implemented>90%

Test Execution Commands

# All tests (from project root — mock + unit + E2E suites)
npm run test

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

# API mock suite only (no DB required)
cd apps/api-express && npx vitest run

# API unit suite only
cd apps/api-express && npx vitest run tests/unit/

# API E2E suite only (mocked services, no DB)
cd apps/api-express && npx vitest run tests/e2e/

# Real DB integration tests (requires docker-compose.test.yml)
docker-compose -f docker-compose.test.yml up -d
cd apps/api-express && npm run test:integration

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

# Specific file
cd apps/api-express && npx vitest run tests/auth.test.ts
cd apps/api-express && npx vitest run tests/unit/two-factor.test.ts

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

# Verbose output
npx vitest run --reporter=verbose

  • RegisterTesting returnsGuide: details array for validation errorsTESTING-GUIDE.md
  • DetailsBackend containArchitecture: 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-03-02

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

Landing Pagefiles (3mock tests):+ unit + E2E + integration)

  • 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