# Test Inventory

# Bilko — Test Inventory

**Status:** NO TESTS EXIST YET — This document tracks planned tests and implementation status.

This inventory catalogs all tests planned for Bilko, organized by category and priority.

---

## Test Coverage Summary

| Category | Total Planned | Implemented | Coverage Target |
|----------|---------------|-------------|-----------------|
| **Unit Tests** | 45 | 0 | >80% |
| **Integration Tests** | 35 | 0 | >80% |
| **E2E Tests** | 12 | 0 | Critical flows |
| **TOTAL** | **92** | **0** | — |

```mermaid
graph TD
    subgraph COVERAGE["Test Coverage Matrix — 92 Tests Planned"]
        subgraph UNIT["Unit Tests — 45"]
            FIN["Financial Calculations<br/>12 tests — P0<br/>VAT, invoice totals, precision"]
            DE["Double-Entry Validation<br/>6 tests — P0<br/>debit=credit enforcement"]
            CUR["Currency Conversion<br/>8 tests — P0<br/>exchange rate locking"]
            DATE["Date Utilities<br/>6 tests — P1<br/>due dates, fiscal year"]
            FMT["Number Formatting<br/>5 tests — P1<br/>RSD, EUR, BAM display"]
            AUTH_U["Authentication Utils<br/>8 tests — P0<br/>bcrypt, JWT, tokens"]
        end

        subgraph INTEG["Integration Tests — 35"]
            AUTH_API["Auth API<br/>10 tests — P0<br/>register/login/refresh/logout"]
            INV_API["Invoices API<br/>10 tests — P0<br/>CRUD + status + org-scope"]
            EXP_API["Expenses API<br/>8 tests — P1<br/>CRUD + approve/pay"]
            REP_API["Reports API<br/>7 tests — P1<br/>P&L / BS / VAT reports"]
        end

        subgraph E2E_["E2E Tests — 12"]
            INV_E2E["Invoice Flow<br/>4 tests — P0<br/>Create → Send → Paid"]
            EXP_E2E["Expense Flow<br/>3 tests — P1<br/>Add → Approve → Pay"]
            REP_E2E["Report Flow<br/>2 tests — P1<br/>Generate → Export PDF"]
            SET_E2E["Settings Flow<br/>2 tests — P2<br/>Org settings + Invite user"]
            AUTH_E2E["Auth Flow<br/>1 test — P1<br/>Register → Login → 2FA → Logout"]
        end
    end

    style FIN fill:#dc3545,color:#fff
    style DE fill:#dc3545,color:#fff
    style CUR fill:#dc3545,color:#fff
    style AUTH_U fill:#dc3545,color:#fff
    style AUTH_API fill:#dc3545,color:#fff
    style INV_API fill:#dc3545,color:#fff
    style INV_E2E fill:#dc3545,color:#fff
    style DATE fill:#fd7e14,color:#fff
    style FMT fill:#fd7e14,color:#fff
    style EXP_API fill:#fd7e14,color:#fff
    style REP_API fill:#fd7e14,color:#fff
    style EXP_E2E fill:#fd7e14,color:#fff
    style REP_E2E fill:#fd7e14,color:#fff
    style AUTH_E2E fill:#fd7e14,color:#fff
    style SET_E2E fill:#6c757d,color:#fff
```

---

## Priority Legend

- **P0** — Critical (MVP blocker, financial logic)
- **P1** — High (core features, security)
- **P2** — Medium (nice-to-have, edge cases)
- **P3** — Low (future enhancements)

---

## Unit Tests (45 total)

### Financial Calculations (12 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `vat.test.ts` | `calculateVAT - Serbia 20%` | VAT calculation for Serbia | P0 | ❌ Not implemented |
| `vat.test.ts` | `calculateVAT - BiH 17%` | VAT calculation for BiH | P0 | ❌ Not implemented |
| `vat.test.ts` | `calculateVAT - Croatia 25%` | VAT calculation for Croatia | P0 | ❌ Not implemented |
| `vat.test.ts` | `calculateVAT - zero rate` | VAT at 0% (exports) | P0 | ❌ Not implemented |
| `vat.test.ts` | `calculateVAT - decimal amounts` | VAT on €123.45 | P0 | ❌ Not implemented |
| `vat.test.ts` | `calculateVAT - rounding` | Rounds to 2 decimal places | P0 | ❌ Not implemented |
| `invoice-calc.test.ts` | `calculateInvoiceTotal - subtotal` | Sum of line items | P0 | ❌ Not implemented |
| `invoice-calc.test.ts` | `calculateInvoiceTotal - tax` | Sum of tax amounts | P0 | ❌ Not implemented |
| `invoice-calc.test.ts` | `calculateInvoiceTotal - discount` | Subtract discount from subtotal | P0 | ❌ Not implemented |
| `invoice-calc.test.ts` | `calculateInvoiceTotal - total` | Subtotal + tax - discount | P0 | ❌ Not implemented |
| `invoice-calc.test.ts` | `calculateInvoiceTotal - multi-item` | Multiple line items with different tax rates | P0 | ❌ Not implemented |
| `invoice-calc.test.ts` | `calculateInvoiceTotal - precision` | NUMERIC(19,4) precision maintained | P0 | ❌ Not implemented |

---

### Double-Entry Validation (6 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `double-entry.test.ts` | `validateTransaction - debit equals credit` | Debit amount = Credit amount | P0 | ❌ Not implemented |
| `double-entry.test.ts` | `validateTransaction - rejects unbalanced` | Throws error if debit ≠ credit | P0 | ❌ Not implemented |
| `double-entry.test.ts` | `validateTransaction - requires both accounts` | Throws if missing debit or credit account | P0 | ❌ Not implemented |
| `double-entry.test.ts` | `validateTransaction - multi-currency` | Validates amounts in base currency | P0 | ❌ Not implemented |
| `double-entry.test.ts` | `validateTransaction - precision` | NUMERIC precision preserved | P0 | ❌ Not implemented |
| `double-entry.test.ts` | `validateTransaction - zero amount` | Rejects zero-amount transactions | P1 | ❌ Not implemented |

---

### Currency Conversion (8 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `currency.test.ts` | `convertCurrency - EUR to RSD` | Convert at locked exchange rate | P0 | ❌ Not implemented |
| `currency.test.ts` | `convertCurrency - RSD to EUR` | Reverse conversion | P0 | ❌ Not implemented |
| `currency.test.ts` | `convertCurrency - same currency` | Rate = 1.0 when currency matches | P0 | ❌ Not implemented |
| `currency.test.ts` | `convertCurrency - precision` | NUMERIC(19,4) preserved | P0 | ❌ Not implemented |
| `currency.test.ts` | `convertCurrency - large amounts` | €999,999,999.9999 | P0 | ❌ Not implemented |
| `currency.test.ts` | `convertCurrency - rounding` | Rounds to 4 decimal places | P1 | ❌ Not implemented |
| `currency.test.ts` | `lockExchangeRate - historical rate` | Uses rate from transaction date, not today | P0 | ❌ Not implemented |
| `currency.test.ts` | `lockExchangeRate - missing rate` | Throws if no rate available for date | P1 | ❌ Not implemented |

---

### Date Utilities (6 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `date.test.ts` | `calculateDueDate - 30 days` | Invoice date + 30 days | P1 | ❌ Not implemented |
| `date.test.ts` | `calculateDueDate - custom terms` | Invoice date + custom days | P1 | ❌ Not implemented |
| `date.test.ts` | `isOverdue - past due date` | Returns true if today > due date | P1 | ❌ Not implemented |
| `date.test.ts` | `isOverdue - not overdue` | Returns false if today <= due date | P1 | ❌ Not implemented |
| `date.test.ts` | `getFiscalYear - starts Jan 1` | Fiscal year 2026 = Jan 1 - Dec 31 | P2 | ❌ Not implemented |
| `date.test.ts` | `getFiscalYear - custom start` | Fiscal year starts on custom date | P2 | ❌ Not implemented |

---

### Number Formatting (5 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `format.test.ts` | `formatCurrency - RSD` | "50,000.00 RSD" format | P1 | ❌ Not implemented |
| `format.test.ts` | `formatCurrency - EUR` | "€50,000.00" format | P1 | ❌ Not implemented |
| `format.test.ts` | `formatCurrency - BAM` | "50,000.00 BAM" format | P1 | ❌ Not implemented |
| `format.test.ts` | `formatCurrency - decimal places` | Respects currency decimal places (0-4) | P1 | ❌ Not implemented |
| `format.test.ts` | `formatCurrency - null` | Returns "-" for null/undefined | P2 | ❌ Not implemented |

---

### Authentication (8 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `auth.test.ts` | `hashPassword - bcrypt 12 rounds` | Password hashed with bcrypt | P0 | ❌ Not implemented |
| `auth.test.ts` | `hashPassword - unique salt` | Each hash is different | P0 | ❌ Not implemented |
| `auth.test.ts` | `verifyPassword - correct password` | Returns true for correct password | P0 | ❌ Not implemented |
| `auth.test.ts` | `verifyPassword - incorrect password` | Returns false for wrong password | P0 | ❌ Not implemented |
| `auth.test.ts` | `generateJWT - valid payload` | JWT contains user ID, org ID, role | P0 | ❌ Not implemented |
| `auth.test.ts` | `generateJWT - expiry 15 min` | Access token expires in 15 min | P0 | ❌ Not implemented |
| `auth.test.ts` | `generateRefreshToken - expiry 7 days` | Refresh token expires in 7 days | P0 | ❌ Not implemented |
| `auth.test.ts` | `verifyJWT - expired token` | Throws error if token expired | P1 | ❌ Not implemented |

---

## Integration Tests (35 total)

### Auth API (10 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `auth-api.test.ts` | `POST /auth/register - success` | Creates user, returns 201 | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/register - duplicate email` | Returns 400 if email exists | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/register - weak password` | Returns 400 if password < 8 chars | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/login - success` | Returns access + refresh tokens | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/login - wrong password` | Returns 401 | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/login - non-existent user` | Returns 401 | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/refresh - success` | Returns new access token | P0 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/refresh - expired token` | Returns 401 | P1 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/logout - success` | Deletes refresh token from DB | P1 | ❌ Not implemented |
| `auth-api.test.ts` | `POST /auth/logout - already logged out` | Returns 204 (idempotent) | P2 | ❌ Not implemented |

---

### Invoices API (10 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `invoices-api.test.ts` | `POST /invoices - success` | Creates invoice, returns 201 | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `POST /invoices - validates required fields` | Returns 400 if missing customer | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `POST /invoices - validates currency` | Returns 400 if invalid currency code | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `POST /invoices - org scoping` | Returns 403 if customer in different org | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `GET /invoices - list` | Returns paginated invoices | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `GET /invoices - filter by status` | Returns only "paid" invoices | P1 | ❌ Not implemented |
| `invoices-api.test.ts` | `GET /invoices/:id - success` | Returns invoice by ID | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `GET /invoices/:id - not found` | Returns 404 if ID doesn't exist | P1 | ❌ Not implemented |
| `invoices-api.test.ts` | `PATCH /invoices/:id - update status` | Changes status to "sent" | P0 | ❌ Not implemented |
| `invoices-api.test.ts` | `DELETE /invoices/:id - soft delete` | Marks as deleted (not hard delete) | P1 | ❌ Not implemented |

---

### Expenses API (8 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `expenses-api.test.ts` | `POST /expenses - success` | Creates expense, returns 201 | P0 | ❌ Not implemented |
| `expenses-api.test.ts` | `POST /expenses - validates required fields` | Returns 400 if missing amount | P0 | ❌ Not implemented |
| `expenses-api.test.ts` | `POST /expenses - org scoping` | Returns 403 if vendor in different org | P0 | ❌ Not implemented |
| `expenses-api.test.ts` | `GET /expenses - list` | Returns paginated expenses | P0 | ❌ Not implemented |
| `expenses-api.test.ts` | `PATCH /expenses/:id/approve - success` | Changes status to "approved" | P1 | ❌ Not implemented |
| `expenses-api.test.ts` | `PATCH /expenses/:id/approve - requires admin` | Returns 403 if user is viewer | P1 | ❌ Not implemented |
| `expenses-api.test.ts` | `PATCH /expenses/:id/reject - success` | Changes status to "rejected" | P1 | ❌ Not implemented |
| `expenses-api.test.ts` | `DELETE /expenses/:id - soft delete` | Marks as deleted | P1 | ❌ Not implemented |

---

### Reports API (7 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `reports-api.test.ts` | `GET /reports/profit-loss - success` | Returns P&L with revenue, expenses, net | P1 | ❌ Not implemented |
| `reports-api.test.ts` | `GET /reports/profit-loss - date range` | Filters by start/end date | P1 | ❌ Not implemented |
| `reports-api.test.ts` | `GET /reports/balance-sheet - success` | Returns assets, liabilities, equity | P1 | ❌ Not implemented |
| `reports-api.test.ts` | `GET /reports/cash-flow - success` | Returns operating, investing, financing | P1 | ❌ Not implemented |
| `reports-api.test.ts` | `GET /reports/vat - success` | Returns sales VAT, purchase VAT, net VAT | P1 | ❌ Not implemented |
| `reports-api.test.ts` | `GET /reports/vat - Serbia 20%` | Calculates Serbian VAT correctly | P1 | ❌ Not implemented |
| `reports-api.test.ts` | `GET /reports/vat - export PDF` | Returns PDF file | P2 | ❌ Not implemented |

---

## E2E Tests (12 total)

### Invoice Flow (4 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `invoice-flow.spec.ts` | `Create invoice via 6-step wizard` | Full invoice creation flow | P0 | ❌ Not implemented |
| `invoice-flow.spec.ts` | `Preview invoice before sending` | Preview modal shows correct totals | P0 | ❌ Not implemented |
| `invoice-flow.spec.ts` | `Send invoice to customer` | Email sent, status changed to "sent" | P0 | ❌ Not implemented |
| `invoice-flow.spec.ts` | `Mark invoice as paid` | Status changed to "paid", paidAt timestamp | P0 | ❌ Not implemented |

---

### Expense Flow (3 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `expense-flow.spec.ts` | `Add expense with receipt upload` | Create expense, upload JPG | P1 | ❌ Not implemented |
| `expense-flow.spec.ts` | `Approve expense` | Admin approves, status changed | P1 | ❌ Not implemented |
| `expense-flow.spec.ts` | `Mark expense as paid` | Status changed to "paid" | P1 | ❌ Not implemented |

---

### Report Flow (2 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `report-flow.spec.ts` | `Generate P&L report` | Select date range, view report | P1 | ❌ Not implemented |
| `report-flow.spec.ts` | `Export P&L to PDF` | Download PDF file | P1 | ❌ Not implemented |

---

### Settings Flow (2 tests)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `settings-flow.spec.ts` | `Update organization settings` | Change org name, tax settings | P2 | ❌ Not implemented |
| `settings-flow.spec.ts` | `Invite user to organization` | Send invite email, user accepts | P2 | ❌ Not implemented |

---

### Auth Flow (1 test)

| Test File | Test Name | What It Tests | Priority | Status |
|-----------|-----------|---------------|----------|--------|
| `auth-flow.spec.ts` | `Register → Login → 2FA → Logout` | Full auth flow with 2FA | P1 | ❌ Not implemented |

---

## Critical Path Testing Flow

```mermaid
flowchart TD
    START(["Start: No Tests"]) --> P1

    subgraph P1["Phase 1 — MVP Critical (25 tests)"]
        P1_FIN["Financial Calculations<br/>12 unit tests<br/>VAT RS/BA/HR, invoice totals"]
        P1_DE["Double-Entry Validation<br/>6 unit tests<br/>debit=credit, balanced=true"]
        P1_AUTH["Auth API<br/>7 integration tests<br/>register, login, refresh"]
        P1_FIN --> P1_DE --> P1_AUTH
    end

    P1 --> P1_GATE{"Coverage<br/>>=50%?"}
    P1_GATE -->|Yes| P2
    P1_GATE -->|No| P1

    subgraph P2["Phase 2 — Core Features (35 tests)"]
        P2_CUR["Currency Conversion<br/>8 unit tests"]
        P2_INV["Invoices API<br/>10 integration tests"]
        P2_E2E["Invoice + Auth + Expense E2E<br/>8 E2E tests"]
        P2_REP["Reports API<br/>7 integration tests"]
        P2_CUR --> P2_INV --> P2_E2E --> P2_REP
    end

    P2 --> P2_GATE{"Coverage<br/>>=70%?"}
    P2_GATE -->|Yes| P3
    P2_GATE -->|No| P2

    subgraph P3["Phase 3 — Polish (32 tests)"]
        P3_DATE["Date + Formatting<br/>11 unit tests"]
        P3_EXP["Expenses API<br/>8 integration tests"]
        P3_EDGE["Edge cases<br/>8 tests"]
        P3_SET["Settings flow<br/>5 tests"]
        P3_DATE --> P3_EXP --> P3_EDGE --> P3_SET
    end

    P3 --> DONE(["Production Ready<br/>>80% coverage<br/>All critical paths tested"])

    style START fill:#6c757d,color:#fff
    style DONE fill:#198754,color:#fff
    style P1_GATE fill:#ffc107,stroke:#e0a800
    style P2_GATE fill:#ffc107,stroke:#e0a800
```

## Test Implementation Roadmap

### Phase 1 (MVP Critical) — 25 tests
- ✅ **Financial calculations** (12 unit tests)
- ✅ **Double-entry validation** (6 unit tests)
- ✅ **Auth API** (7 integration tests: register, login, refresh)

**Target:** Before backend MVP launch

---

### Phase 2 (Core Features) — 35 tests
- ✅ **Currency conversion** (8 unit tests)
- ✅ **Invoices API** (10 integration tests)
- ✅ **Invoice E2E flow** (4 E2E tests)
- ✅ **Auth E2E flow** (1 E2E test)
- ✅ **Expense flow** (3 E2E tests)
- ✅ **Reports API** (7 integration tests)
- ✅ **Report E2E flow** (2 E2E tests)

**Target:** 1 month after MVP launch

---

### Phase 3 (Polish) — 32 tests
- ✅ **Date utilities** (6 unit tests)
- ✅ **Number formatting** (5 unit tests)
- ✅ **Expenses API** (8 integration tests)
- ✅ **Settings flow** (2 E2E tests)
- ✅ **Remaining auth tests** (3 integration tests)
- ✅ **Edge cases** (8 tests across categories)

**Target:** 3 months after MVP launch

---

## Test Execution Commands

### Run All Tests
```bash
npm run test        # All tests (unit + integration + E2E)
```

### Run by Category
```bash
npm run test:unit           # Unit tests only
npm run test:integration    # Integration tests only
npm run test:e2e            # E2E tests only
```

### Run Specific Test File
```bash
npm run test:unit -- vat.test.ts
npm run test:integration -- invoices-api.test.ts
npm run test:e2e -- invoice-flow.spec.ts
```

### Run with Coverage
```bash
npm run test:unit -- --coverage
```

### Watch Mode
```bash
npm run test:unit -- --watch
```

---

## Coverage Tracking

### Current Coverage (as of 2026-02-20)

| Category | Coverage | Target | Status |
|----------|----------|--------|--------|
| **Financial Logic** | 0% | >95% | ❌ Not started |
| **API Endpoints** | 0% | >80% | ❌ Not started |
| **Utilities** | 0% | >90% | ❌ Not started |
| **Overall** | 0% | >80% | ❌ Not started |

**Next Milestone:** 50% coverage (25 critical tests)

---

## Related Documents
- Testing Guide: [TESTING-GUIDE.md](/books/bilko-balkan-accounting-saas/page/testing-guide)
- CI/CD Pipeline: [../infrastructure/CI-CD.md](/books/bilko-balkan-accounting-saas/page/cicd-pipeline)
- Security Testing: [../security/SECURITY-ARCHITECTURE.md](/books/bilko-balkan-accounting-saas/page/security-architecture)

---

**Last Updated:** 2026-02-20
**Status:** NO TESTS IMPLEMENTED YET
**Total Tests Planned:** 92 (45 unit + 35 integration + 12 E2E)
**Next Action:** Implement Phase 1 financial calculation tests (12 tests)