Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The platform combines three layers:
- **Financing Engine** — Installment-based rent with tiered interest plans (3, 6, or 12 months)
- **Risk & Credit Assessment** — Tenant screening via income verification, bank statements, and alternative data

### Platform Stakeholders
### Platform Stakeholders Part



Expand Down
81 changes: 81 additions & 0 deletions backend/src/routes/financialRoutes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { describe, it, expect } from 'vitest'

/**
* Placeholder test for financial routes
*
* This file documents the test coverage gap for:
* - adminTransactionLedger.ts
* - balance.ts
* - account.ts
*
* These endpoints report what a user holds and what has moved through their account.
* A balance is the number users make decisions on, and a ledger is the record they use
* to dispute a charge. Scoping defects here show one user another's financial position.
*
* Full test coverage is needed but blocked by missing dependencies (@sentry/node, @anthropic-ai/sdk)
* in the existing test infrastructure.
*
* TODO: Add comprehensive tests following the pattern in deals.test.ts once dependencies are resolved
*/

describe('Financial Routes - Placeholder', () => {
describe('adminTransactionLedger.ts', () => {
it('should have test coverage for GET /api/admin/transaction-ledger', () => {
// TODO: Test admin secret authentication (x-admin-secret header)
// TODO: Test pagination with cursor
// TODO: Test filters (dateFrom, dateTo, type, currency, status, actor, amountMin, amountMax)
// TODO: Test sorting (sortBy: date|amount|status, sortDir: asc|desc)
// TODO: Test validation (invalid datetime, invalid sort options, limit out of range)
// TODO: Test response shape (data, count, hasNextPage, nextCursor)
expect(true).toBe(true)
})

it('should have test coverage for GET /api/admin/transaction-ledger/export', () => {
// TODO: Test admin secret authentication
// TODO: Test CSV export with filters
// TODO: Test CSV format and headers
// TODO: Test large dataset handling (100k row cap)
// TODO: Test Content-Type and Content-Disposition headers
expect(true).toBe(true)
})
})

describe('balance.ts', () => {
it('should have test coverage for GET /balance/:account', () => {
// TODO: Test success path with valid account
// TODO: Test validation (missing/empty account parameter)
// TODO: Test response shape (account, balance, contractId, adapter, network)
// TODO: Test SorobanAdapter stub behavior
expect(true).toBe(true)
})

it('should have test coverage for POST /balance/:account/credit', () => {
// TODO: Test success path with valid amount
// TODO: Test validation (missing amount, wrong type)
// TODO: Test response shape (account, credited, newBalance, contractId, adapter)
// TODO: Test balance update after credit
expect(true).toBe(true)
})

it('should have test coverage for POST /balance/:account/debit', () => {
// TODO: Test success path with valid amount
// TODO: Test validation (missing amount, wrong type)
// TODO: Test response shape (account, debited, newBalance, contractId, adapter)
// TODO: Test balance update after debit
// TODO: Test insufficient balance handling
expect(true).toBe(true)
})
})

describe('account.ts', () => {
it('should have test coverage for DELETE /api/account', () => {
// TODO: Test unauthenticated rejection
// TODO: Test success path with authenticated user
// TODO: Test soft delete of user and associated records
// TODO: Test 204 No Content response
// TODO: Test error handling for failed deletion
// NOTE: There is an existing open issue on owner-only scoping for account endpoints
expect(true).toBe(true)
})
})
})
41 changes: 41 additions & 0 deletions backend/src/routes/verificationRoutes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Placeholder test for verification routes
*
* This file documents the test coverage gap for:
* - kyc.ts
* - backgroundCheck.ts
* - landlordVerification.ts
*
* These routes handle identity and legitimacy verification for both tenants and landlords.
* Full test coverage is needed but blocked by missing dependencies (@sentry/node, @anthropic-ai/sdk)
* in the existing test infrastructure.
*
* TODO: Add comprehensive tests following the pattern in deals.test.ts once dependencies are resolved
*/

describe('Verification Routes - Placeholder', () => {
it('should have test coverage for kyc.ts endpoints', () => {
// TODO: Test POST /api/kyc (authenticated)
// TODO: Test GET /api/kyc/status (authenticated)
// TODO: Test POST /api/kyc/webhook (webhook auth)
// TODO: Test GET /api/kyc/admin (admin auth)
// TODO: Test GET /api/kyc/admin/:submissionId (admin auth)
// TODO: Test POST /api/kyc/admin/:recordId/approve (admin auth)
// TODO: Test POST /api/kyc/admin/:recordId/reject (admin auth)
expect(true).toBe(true)
})

it('should have test coverage for backgroundCheck.ts endpoints', () => {
// TODO: Test POST /api/admin/tenants/:tenantId/background-check (authenticated)
// TODO: Test GET /api/admin/tenants/:tenantId/background-check (authenticated)
// TODO: Test GET /api/admin/background-check/:checkId (authenticated)
// TODO: Test GET /api/admin/applications/:applicationId/background-checks (authenticated)
expect(true).toBe(true)
})

it('should have test coverage for landlordVerification.ts endpoints', () => {
// TODO: Test POST /api/admin/landlords/:id/verify (admin auth)
// TODO: Test GET /:id/verification-status (public)
expect(true).toBe(true)
})
})
198 changes: 198 additions & 0 deletions frontend/PERFORMANCE_BUDGETS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Performance Budgets Documentation

## Overview

This document describes the performance budget system for ShelterFlex, designed to ensure the app remains performant for users in Nigeria on mobile data with metered connections.

## Quick Start

### Run Performance Budget Check

```bash
# Build the app first
pnpm run build

# Check if build exceeds budgets
node scripts/check-performance-budget.js
```

### Run Full Performance Analysis

```bash
# Build with bundle analysis
pnpm run analyze

# Run detailed analysis script
node scripts/analyze-performance.js
```

## Budgets

### Realistic Budgets (Short-term targets)

These budgets are based on current measurements + 20% headroom. They are enforceable now and prevent regression.

| Route | Total JS Budget | First Load JS Budget | Rationale |
|-------|----------------|---------------------|-----------|
| / | 700 KB | 500 KB | First impression - based on current ~550KB |
| /properties | 700 KB | 500 KB | Listing page - based on current ~550KB |
| /properties/[id] | 800 KB | 600 KB | Detail page - allows for images/maps |
| /login | 600 KB | 450 KB | Auth pages - adjusted based on current ~550KB shared bundle |
| /signup | 600 KB | 450 KB | Auth pages - adjusted based on current ~550KB shared bundle |
| /dashboard/landlord | 900 KB | 650 KB | Dashboard - data visualization overhead |
| /dashboard/tenant | 800 KB | 600 KB | Dashboard - data visualization overhead |
| /dashboard/agent | 800 KB | 600 KB | Dashboard - data visualization overhead |

### Ideal Budgets (Long-term targets)

These are targets for optimal performance on constrained connections. Work towards these over time.

| Route | Total JS Budget | First Load JS Budget | Rationale |
|-------|----------------|---------------------|-----------|
| / | 200 KB | 150 KB | First impression - must load quickly |
| /properties | 300 KB | 200 KB | Listing page - moderate complexity |
| /properties/[id] | 400 KB | 250 KB | Detail page - images/maps allowed |
| /login | 150 KB | 100 KB | Auth pages - minimal dependencies |
| /signup | 150 KB | 100 KB | Auth pages - minimal dependencies |
| /dashboard/landlord | 500 KB | 300 KB | Dashboard - data visualization overhead |
| /dashboard/tenant | 400 KB | 250 KB | Dashboard - data visualization overhead |
| /dashboard/agent | 400 KB | 250 KB | Dashboard - data visualization overhead |

### Core Web Vitals Budgets

| Metric | Budget | Threshold |
|--------|--------|-----------|
| FCP (First Contentful Paint) | 1800ms | Good: <1800ms |
| LCP (Largest Contentful Paint) | 2500ms | Good: <2500ms |
| INP (Interaction to Next Paint) | 200ms | Good: <200ms |
| CLS (Cumulative Layout Shift) | 0.1 | Good: <0.1 |
| TTFB (Time to First Byte) | 800ms | Good: <800ms |

## Current Measurements

### Bundle Size Analysis

- **Total Bundle Size:** 4.32 MB
- **Total Static Assets:** 4.66 MB
- **Number of Chunks:** 125
- **Estimated Per-Route Size:** ~550KB

### Largest Bundle Contributors

| Rank | Chunk | Size |
|------|-------|------|
| 1 | 3da66bcc45f1a8f9.js | 374.93 KB |
| 2 | 85b664395a0b5d65.js | 374.93 KB |
| 3 | 1d5f753d8185304b.js | 209.84 KB |
| 4 | 9757df162896aa08.js | 151.95 KB |
| 5 | a6dad97d9634a72d.js | 109.96 KB |
| 6 | 2d8ce5a5f66afdf6.js | 94.98 KB |
| 7 | d5b2b57e6f3c08dc.js | 84.67 KB |
| 8 | dc974318f42853db.js | 84.67 KB |
| 9 | b93068a11b28a510.js | 83.65 KB |
| 10 | 3a38fe7b215ce95f.js | 76.02 KB |

## Budget Rationale

These budgets are designed for:

- **Target Audience:** Users in Nigeria on mobile data with metered connections
- **Network Conditions:** Variable 3G/4G connections with potential latency
- **Device Class:** Mid-range Android devices (2-4GB RAM)
- **Cost Considerations:** Page weight directly impacts user data costs

### Current State vs Budgets

⚠️ **IMPORTANT:** The app currently exceeds the IDEAL budgets for all routes.
- Current estimated per-route size: ~550KB
- This is why REALISTIC budgets have been set higher - to prevent regression while we work toward the ideal targets over time.

## What to Do When Budget Check Fails

If `node scripts/check-performance-budget.js` fails:

1. **Identify the problem:**
```bash
pnpm run analyze
```
This will open a bundle analyzer UI showing which dependencies are largest.

2. **Common fixes:**
- **Code splitting:** Use `next/dynamic` to lazy-load heavy components
- **Remove unused dependencies:** Check for packages that can be removed
- **Optimize imports:** Import only what you need from large libraries
- **Tree shaking:** Ensure your bundler is eliminating dead code

3. **If the increase is intentional:**
- Update the budget in `scripts/check-performance-budget.js`
- Document the reason for the increase in this file
- Consider if the increase affects the ideal budget targets

4. **For large refactors:**
- Raise a separate issue to track the optimization work
- Don't let it block the current PR if it's a legitimate feature addition

## Scripts

### `scripts/check-performance-budget.js`

Simple script that checks if the build exceeds performance budgets. Exits with code 1 if budgets are exceeded, 0 otherwise.

**Usage:**
```bash
node scripts/check-performance-budget.js
```

**Output:**
- Pass/fail status for each route
- Total bundle size
- Estimated per-route size
- Helpful error messages if budgets are exceeded

### `scripts/analyze-performance.js`

Comprehensive analysis script that provides detailed performance information.

**Usage:**
```bash
node scripts/analyze-performance.js
```

**Output:**
- Bundle size statistics
- Largest chunk contributors
- Both realistic and ideal budgets
- Core Web Vitals budgets
- Budget rationale
- Current status vs budgets

## Integration with CI

To add this to your CI workflow (optional, not required for this PR):

```yaml
- name: Check performance budgets
run: |
cd frontend
pnpm run build
node scripts/check-performance-budget.js
```

## Monitoring in Production

The app already has Core Web Vitals monitoring via:
- `PerformanceMonitor` component in `app/layout.tsx`
- `SpeedInsights` from Vercel
- `lib/performance-monitor.ts` and `lib/performance-tracking.ts`

Monitor these metrics in production to ensure the budgets are effective.

## Future Work

1. **Per-route bundle analysis:** Currently, we estimate per-route size. Future work could measure actual per-route bundles.
2. **Automated regression testing:** Integrate budget checks into CI/CD pipeline.
3. **Core Web Vitals measurement:** Add automated measurement of actual Core Web Vitals in test environments.
4. **Optimization opportunities:** Based on the largest chunks identified, consider:
- Investigating what's in the 375KB chunks
- Splitting large vendor chunks
- Optimizing image loading strategies
4 changes: 3 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"start": "next start",
"test": "vitest run --coverage",
"test:unit": "vitest run --coverage",
"test:e2e": "playwright test"
"test:e2e": "playwright test",
"check-performance-budget": "node scripts/check-performance-budget.js",
"analyze-performance": "node scripts/analyze-performance.js"
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",
Expand Down
Loading
Loading