File size: 5,596 Bytes
db4ba8d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# TradeFlow AI Test Suite

## Overview

Comprehensive test suite covering critical security and reliability fixes implemented in the audit remediation.

## Test Files

### `conftest.py`
Shared fixtures for all tests:
- `test_client`: FastAPI test client
- `mock_current_user`: Authenticated operator user
- `mock_admin_user`: Authenticated admin user  
- `mock_supabase`: Mocked Supabase AsyncClient
- Sample file bytes (PDF, PNG, malicious)

### `test_config.py`

Configuration and environment variable tests:

- ✅ `GEMINI_API_KEY` is required (not hardcoded)

- ✅ `GEMINI_API_KEY` must come from environment variable

- ✅ CORS origins are controlled (not wildcard)



### `test_routers_batches.py`

File upload validation tests:

- File magic number validation (detects spoofed files)

- File size limits (50MB max)

- MIME type validation

- Filename path traversal protection

- Batch creation with invalid files (rollback)

- Maximum 3 files per batch

- doc_types validation

### `test_routers_blockchain.py`
Authorization and access control tests:
- ✅ Authentication required for blockchain endpoints
- ✅ Users can only access their company's batches
- ✅ Admins can access any batch
- ✅ Non-existent batch handling
- ✅ Batch ownership verification

### `test_ai_nodes_extract.py`

AI node error handling tests:

- ✅ Validates required document fields (doc_id, pages)
- ✅ Handles empty document lists
- ✅ Catches only specific exceptions (ValueError, KeyError)
- ✅ Re-raises unexpected exceptions
- ✅ Correctly combines data from multiple documents

### `test_dependencies.py`

JWT and authentication tests:

- ✅ Keycloak JWKS cached with TTL (1 hour)

- ✅ JWKS refreshes after TTL expires

- ✅ HTTP errors in JWKS fetch are handled

- ✅ CurrentUser stores all required fields



### `test_storage_service.py`

Storage security tests:

- ✅ MinIO bucket created with private policy

- ✅ Bucket policy denies public access

- ✅ Existing buckets are handled correctly

- ✅ File upload paths are sanitized



## Running Tests



```bash

# Install dev dependencies

pip install -e ".[dev]"



# Run all tests

pytest tests/



# Run with coverage

pytest tests/ --cov=src --cov-report=html



# Run specific test file

pytest tests/test_config.py -v

# Run specific test
pytest tests/test_config.py::test_gemini_api_key_required -v

```



## Coverage Goals



Target: **70% code coverage** (as per pyproject.toml)



Current coverage baseline: 0% → Target: 70%+ after implementation



## Critical Security Tests (Must Pass)



1. **Config Tests** - Ensure API keys are not hardcoded

   ```bash

   pytest tests/test_config.py -v
   ```



2. **Authorization Tests** - Ensure cross-company access is blocked

   ```bash

   pytest tests/test_routers_blockchain.py::test_get_blockchain_receipt_requires_ownership -v

   ```

3. **File Validation Tests** - Ensure spoofed files are rejected
   ```bash

   pytest tests/test_routers_batches.py::test_file_magic_number_validation -v

   ```

4. **Error Handling Tests** - Ensure exceptions are properly caught
   ```bash

   pytest tests/test_ai_nodes_extract.py::test_extraction_node_reraises_unknown_exceptions -v

   ```

5. **Storage Security Tests** - Ensure bucket policy is private
   ```bash

   pytest tests/test_storage_service.py::test_minio_bucket_policy_denies_public_access -v

   ```

## Next Steps

1. **Implement missing test bodies** - The test structure is in place, implementation code needs to be added
2. **Add integration tests** - Test full pipeline (upload → extract → validate → blockchain)
3. **Add performance tests** - Ensure large file uploads are handled efficiently
4. **Add stress tests** - Test behavior under load (rate limiting, timeouts)
5. **CI/CD integration** - Add to GitHub Actions for automatic testing on PRs

## Integration Testing

- Integration tests are marked with `@pytest.mark.integration` and should run against real service instances.
- Use `docker-compose.integration.yml` to start the required local services: Redis, MinIO, and ChromaDB.
- Run integration tests with:

```bash

cd apps/api

.venv/bin/python -m pytest -m integration tests/integration -q

```

## Deterministic E2E Testing

When you want reliable end-to-end pipeline validation without external LLM variability, enable deterministic mode:

```bash

set DETERMINISTIC_E2E=1&&set RUN_KEYCLOAK=1&&set RUN_FULL_E2E=1&&python -m pytest tests/integration -q

```

The deterministic mode uses a stable LLM stub for `apps/api/src/ai/nodes/extract.py`, so the extraction and review flow can be validated without Gemini or other external model dependencies.

## Keycloak E2E Provisioning

The repo includes `scripts/keycloak/provision_e2e.py` to provision a Keycloak E2E client/user and emit a `.env.e2e` file with an `E2E_BEARER_TOKEN`.

```bash

set KEYCLOAK_SERVER_URL=http://localhost:8080

set KEYCLOAK_ADMIN=admin

set KEYCLOAK_ADMIN_PASSWORD=admin1234

python scripts\keycloak\provision_e2e.py

```

Then run the guarded auth/E2E tests:

```bash

set RUN_KEYCLOAK=1&&set RUN_FULL_E2E=1&&python -m pytest tests/integration -q

```

> The CI workflow `.github/workflows/e2e.yml` runs the full E2E flow with `DETERMINISTIC_E2E=1` so the test pipeline remains stable without requiring a live LLM.



## Notes



- All tests use `pytest` with `pytest-asyncio` for async support

- Tests use mocks to avoid external dependencies (Supabase, Gemini API)

- Tests follow AAA pattern: Arrange, Act, Assert