Test Inventory
DropBilko — Test Inventory
Status: Active — Tests Implemented
Version: 2.0
Last updated:Updated: 2026-02-1303-02
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/ (mock suite) |
11 test files | ~130 | Implemented |
apps/api/tests/unit/ (unit suite) |
4 test files | ~60 | Implemented |
apps/api/tests/e2e/ (E2E suite) |
2 test files | ~30 | Implemented |
apps/api/tests/integration/ (real DB) |
5 test files | ~50 | Implemented |
packages/core/tests/ (unit) |
5 test files | 121 | Implemented |
| Total | 27 | ~390 | Active |
Test Category Breakdown
| Category | Description | Requires DB |
|---|---|---|
Mock suite (tests/) |
API endpoint |
No |
Unit suite (tests/unit/) |
Service-layer tests, financial logic, SEF client | No |
E2E suite (tests/e2e/) |
End-to-end billing flows with mocked services | No |
Integration suite (tests/integration/) |
Real DB tests |
Yes |
Core packages/core/) |
Pure business logic — no HTTP, no DB | No |
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):
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/ — Mock API routeTests
Integration withtests 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 |
chatbot.test.ts — Chatbot API Tests
| Test Name | Route | Status |
|---|---|---|
returns 200 with assistant response |
POST /chatbot/message | Implemented |
returns 400 when message is empty |
POST /chatbot/message | Implemented |
returns 429 when rate limit exceeded |
POST /chatbot/message | Implemented |
returns 401 without auth |
POST /chatbot/message | Implemented |
returns 200 with conversation history |
GET /chatbot/history | Implemented |
returns empty array when no history exists |
GET /chatbot/history | Implemented |
returns 401 without auth on history |
GET /chatbot/history | Implemented |
returns 204 when history cleared |
DELETE /chatbot/history | Implemented |
returns 401 without auth on clear history |
DELETE /chatbot/history | Implemented |
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 Area | Status |
|---|---|
| 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 found | Implemented |
| Throws 400 when invoice is already cancelled | Implemented |
| 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 Area | Route | Status |
|---|---|---|
| Receipt not attached (404) | GET /expenses/:id/receipt | Implemented |
| Receipt auth required (401) | GET /expenses/:id/receipt | Implemented |
| VAT export PDF (200 / 404) | GET /reports/vat/export/pdf | Implemented |
| VAT export XML (200 / 404) | GET /reports/vat/export/xml | Implemented |
| Dashboard metrics (200) | GET /reports/dashboard | Implemented |
| Dashboard auth required (401) | GET /reports/dashboard | Implemented |
| Audit log (200 + owner/admin only) | GET /security/audit-log | Implemented |
| Audit log role check (403 for viewer) | GET /security/audit-log | Implemented |
| Data export (200 + owner only) | POST /security/data-export | Implemented |
| Data export role check (403 for admin) | POST /security/data-export | Implemented |
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):
- Create contact
- Create invoice
- Send invoice (draft → sent)
- Mark invoice paid (sent → paid)
- Check P&L shows revenue
- Verify trial balance returns
isBalanced=true - Multi-currency invoice in EUR with country VAT rates
- 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:
RatelineTotallimit=actuallyquantityblocks×after exceededunitPriceCountlineTaxincrements=correctlylineTotalin×databasetaxRate / 100Resetssubtotalafter=windowsum(lineTotals)taxAmount = sum(lineTaxes)total = subtotal + taxAmountbaseAmount = total × exchangeRate
| Test Area | Status |
|---|---|
| Single-line invoice arithmetic | Implemented |
| Multi-line invoice with mixed tax rates | Implemented |
| Multi-currency exchange rate application | Implemented |
| Zero-quantity line items rejected | Implemented |
| NUMERIC(19,4) precision maintained | Implemented |
two-factor.test.ts — Two-Factor Authentication Service
Tests TwoFactorService at the service level. Mocks: bcryptjs, speakeasy, qrcode, Prisma.
| Test Name | Status |
|---|---|
enable - wrong password → throws unauthorized |
Implemented |
enable - correct password → returns secret + QR data URL + 10 codes |
Implemented |
enable - backup codes are hashed before storing |
Implemented |
enable - plaintext backup codes returned once only |
Implemented |
verify - valid TOTP + window=1 → activates 2FA |
Implemented |
verify - invalid TOTP → throws badRequest |
Implemented |
disable - correct password → clears secret + backup codes |
Implemented |
disable - wrong password → throws unauthorized |
Implemented |
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 Area | Status |
|---|---|
SefClient submits UBL XML to SEF sandbox URL |
Implemented |
SefClient uses production URL in production env |
Implemented |
SefClient retries on network failure |
Implemented |
createSefClientFromEnv() reads credentials from env vars |
Implemented |
generateSEFInvoiceXML() produces valid UBL 2.1 XML |
Implemented |
InvoiceService.submitToSef() never re-throws errors |
Implemented |
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.
| Country | Functions Tested | Status |
|---|---|---|
| Serbia | calculateSerbianPDV, calculateNetFromGrossPDV, qualifiesForPausalRegime, requiresVATRegistration, calculateSerbianCIT |
Implemented |
| Bosnia | calculateBosnianPDV, calculateNetFromGrossPDV, requiresVATRegistration |
Implemented |
| Croatia | calculateCroatianPDV, calculateNetFromGrossPDV, requiresVATRegistration |
Implemented |
| All rates | Standard, reduced, zero, super-reduced rates per country | Implemented |
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:
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 Area | Status |
|---|---|
| Register new organization + owner user | Implemented |
| Login with correct credentials | Implemented |
| Refresh access token via cookie | Implemented |
| Reject duplicate email registration | Implemented |
invoice.integration.test.ts — Invoice CRUD Integration
Invoice lifecycle against real DB: create → read → update → status change.
| Test Area | Status |
|---|---|
| Create invoice with line items | Implemented |
| Read invoice by ID | Implemented |
| Update draft invoice | Implemented |
| Send invoice ( |
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 Area | Status |
|---|---|
| Credit note creates reversing journal entries | Implemented |
| Reversing entries balance (debits = credits) | Implemented |
| Original invoice marked as credited | Implemented |
report.integration.test.ts — Reports Integration
Report generation against real DB with seeded transactions.
| Test Area | Status |
|---|---|
| P&L report returns revenue/expense data | Implemented |
| VAT report returns correct tax amounts | Implemented |
Trial balance returns isBalanced=true |
Implemented |
tenant-isolation.integration.test.ts — Multi-Tenant Security
Verifies multi-tenant isolation: Organization A cannot read or modify Organization B's data.
| Test Area | Status |
|---|---|
| Org A cannot list Org B's invoices | Implemented |
| Org A cannot read Org B's invoice by ID | Implemented |
| Org A cannot update Org B's invoice | Implemented |
| Org A cannot delete Org B's contact | Implemented |
| Cross-tenant requests return 404 (not 403 — no data leakage) | Implemented |
Coverage Tracking
| Module | Current Status | Target |
|---|---|---|
@bilko/core accounting engine |
Tests implemented (20 cases) | >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% |
| Chatbot API | Tests implemented (9 cases) | >80% |
| Security/Audit API | Tests 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 + Submission | Tests 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
Related Documents
RegisterTestingreturnsGuide:details array for validation errorsTESTING-GUIDE.mdDetailsBackendcontainArchitecture: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-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 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