Skip to content

Commit 188e9fd

Browse files
committed
feat: enhance README with schema compatibility tests and validation strategy for Rust HTTP API
1 parent d47958d commit 188e9fd

File tree

1 file changed

+102
-4
lines changed

1 file changed

+102
-4
lines changed

specs/191-rust-http-api-test-suite/README.md

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,18 @@ rust/leanspec-http/tests/
5454
├── common/
5555
│ ├── mod.rs # Test utilities
5656
│ ├── fixtures.rs # Test fixtures (sample specs)
57-
│ └── server.rs # Test server setup
57+
│ ├── server.rs # Test server setup
58+
│ └── schema_validator.rs # Schema validation utilities
5859
├── integration/
5960
│ ├── projects_test.rs # Project management APIs
6061
│ ├── specs_test.rs # Spec operations
6162
│ ├── search_test.rs # Search functionality
6263
│ ├── stats_test.rs # Statistics
6364
│ ├── deps_test.rs # Dependencies
6465
│ └── validate_test.rs # Validation
66+
├── schemas/
67+
│ ├── nextjs_reference.rs # Reference schemas from Next.js API
68+
│ └── compatibility_test.rs # Schema compatibility tests
6569
└── scenarios/
6670
├── multi_project_test.rs # Multi-project scenarios
6771
└── error_cases_test.rs # Error handling
@@ -75,6 +79,12 @@ rust/leanspec-http/tests/
7579
- Verify responses match expected format
7680
- Test error conditions and edge cases
7781

82+
**Schema Compatibility Tests** (NEW):
83+
- Validate Rust response schemas match Next.js API schemas
84+
- Ensure field names match (camelCase vs snake_case)
85+
- Verify response structure compatibility
86+
- Test serialization consistency
87+
7888
**Test Fixtures**:
7989
- Reusable test projects with known spec structure
8090
- Sample specs with various statuses, priorities, tags
@@ -84,6 +94,7 @@ rust/leanspec-http/tests/
8494
- `axum-test` or raw Axum router testing
8595
- `reqwest` for HTTP client
8696
- `serde_json` for response validation
97+
- `schemars` for JSON Schema generation and validation
8798
- `tempfile` for temporary test projects
8899
- `tokio::test` for async tests
89100

@@ -94,10 +105,14 @@ rust/leanspec-http/tests/
94105
- [ ] Create test fixture generator (sample specs)
95106
- [ ] Create test server helper (spawn with temp registry)
96107
- [ ] Add test utilities (assertions, matchers)
108+
- [ ] Set up schema validation utilities
109+
- [ ] Document reference Next.js API schemas
97110

98111
### Phase 2: Project Management Tests (Day 2)
99112
- [ ] Test GET `/api/projects` (list all, empty state, multi-project)
113+
- [ ] Validate response schema matches Next.js `/api/local-projects`
100114
- [ ] Test POST `/api/projects` (add valid, invalid path, duplicate)
115+
- [ ] Validate request/response schema compatibility
101116
- [ ] Test GET `/api/projects/{id}` (existing, not found)
102117
- [ ] Test PATCH `/api/projects/{id}` (update name, favorite, color)
103118
- [ ] Test DELETE `/api/projects/{id}` (remove, not found, current project)
@@ -107,16 +122,23 @@ rust/leanspec-http/tests/
107122

108123
### Phase 3: Spec Operations Tests (Day 3)
109124
- [ ] Test GET `/api/specs` (list all, empty, with filters)
125+
- [ ] Validate response schema matches Next.js `/api/projects/[id]/specs`
126+
- [ ] Compare field serialization: camelCase vs snake_case
110127
- [ ] Test GET `/api/specs` with query params (status, priority, tags, assignee)
111128
- [ ] Test GET `/api/specs/{spec}` (by number, by name, not found)
112129
- [ ] Test GET `/api/specs/{spec}` (verify required_by computed)
130+
- [ ] Validate SpecDetail schema matches Next.js spec detail
113131
- [ ] Test POST `/api/search` (query, filters, empty results)
132+
- [ ] Validate SearchResponse schema compatibility
114133
- [ ] Test POST `/api/search` (ranking by relevance)
115134

116135
### Phase 4: Stats & Dependencies Tests (Day 4)
117136
- [ ] Test GET `/api/stats` (empty project, various statuses)
137+
- [ ] Validate StatsResponse schema matches Next.js `/api/projects/[id]/stats`
138+
- [ ] Compare field names: byStatus, byPriority, byTag
118139
- [ ] Test GET `/api/stats` (verify counts by status, priority, tags)
119140
- [ ] Test GET `/api/deps/{spec}` (simple dependency)
141+
- [ ] Validate DependencyResponse schema
120142
- [ ] Test GET `/api/deps/{spec}` (transitive dependencies)
121143
- [ ] Test GET `/api/deps/{spec}` (circular dependencies)
122144
- [ ] Test GET `/api/deps/{spec}` (spec not found)
@@ -150,6 +172,8 @@ rust/leanspec-http/tests/
150172
- [ ] All happy path scenarios tested
151173
- [ ] All error conditions tested
152174
- [ ] Multi-project switching tested
175+
- [ ] **Schema compatibility validated with Next.js APIs**
176+
- [ ] **All response fields use camelCase serialization**
153177
- [ ] Tests run in CI
154178
- [ ] Tests pass consistently
155179

@@ -158,9 +182,41 @@ rust/leanspec-http/tests/
158182
- [ ] Concurrent request testing
159183
- [ ] Large dataset testing (100+ specs)
160184
- [ ] Test documentation/examples
185+
- [ ] JSON Schema exports for documentation
161186

162187
## Test Examples
163188

189+
### Schema Validation Test
190+
191+
```rust
192+
#[tokio::test]
193+
async fn test_spec_response_schema_compatibility() {
194+
let app = test_server_with_fixtures().await;
195+
196+
// Get spec from Rust API
197+
let res = app.get("/api/specs/001-test-spec").send().await;
198+
assert_eq!(res.status(), 200);
199+
200+
let spec: SpecDetail = res.json().await;
201+
202+
// Validate required fields exist and use camelCase
203+
assert!(spec.spec_number.is_some());
204+
assert!(!spec.spec_name.is_empty());
205+
assert!(!spec.title.is_none());
206+
assert!(!spec.status.is_empty());
207+
assert!(!spec.content_md.is_empty());
208+
assert!(!spec.file_path.is_empty());
209+
210+
// Validate field serialization matches Next.js format
211+
let json = serde_json::to_value(&spec).unwrap();
212+
assert!(json.get("specNumber").is_some()); // camelCase
213+
assert!(json.get("specName").is_some()); // camelCase
214+
assert!(json.get("contentMd").is_some()); // camelCase
215+
assert!(json.get("filePath").is_some()); // camelCase
216+
assert!(json.get("createdAt").is_some()); // camelCase
217+
}
218+
```
219+
164220
### Project Management Test
165221

166222
```rust
@@ -182,6 +238,11 @@ async fn test_list_projects() {
182238
let body: ProjectsListResponse = res.json().await;
183239
assert_eq!(body.projects.len(), 1);
184240
assert!(body.current_project_id.is_some());
241+
242+
// Validate schema matches Next.js /api/local-projects
243+
let json = serde_json::to_value(&body).unwrap();
244+
assert!(json.get("projects").is_some());
245+
assert!(json.get("currentProjectId").is_some()); // camelCase
185246
}
186247

187248
#[tokio::test]
@@ -271,19 +332,56 @@ async fn test_search_relevance_ranking() {
271332

272333
## Notes
273334

335+
### Schema Compatibility Strategy
336+
337+
**Reference Implementation**: Next.js API routes in `packages/ui/src/app/api/`
338+
- `/api/local-projects` → Rust `/api/projects`
339+
- `/api/projects/[id]/specs` → Rust `/api/specs`
340+
- `/api/projects/[id]/stats` → Rust `/api/stats`
341+
- `/api/projects/[id]/dependencies` → Rust `/api/deps/{spec}`
342+
343+
**Validation Approach**:
344+
1. Extract sample responses from Next.js API routes
345+
2. Compare field names and structure
346+
3. Validate camelCase serialization in Rust responses
347+
4. Document any intentional differences
348+
5. Create compatibility tests that would fail on schema drift
349+
350+
**Key Fields to Validate**:
351+
- `specNumber` (not `spec_number`)
352+
- `specName` (not `spec_name`)
353+
- `contentMd` (not `content_md`)
354+
- `filePath` (not `file_path`)
355+
- `createdAt`, `updatedAt`, `completedAt` (not snake_case)
356+
- `dependsOn`, `requiredBy` (not snake_case)
357+
- `byStatus`, `byPriority`, `byTag` in stats (not snake_case)
358+
359+
**Current Status**: ✅ Rust types already use `#[serde(rename_all = "camelCase")]` - tests will validate this continues working.
360+
274361
### Why Integration Tests First?
275362

276363
1. **Verify current state**: Ensure existing APIs work before adding new ones
277364
2. **Regression prevention**: Catch breaking changes immediately
278-
3. **Documentation**: Tests serve as API usage examples
279-
4. **Confidence**: Safe to refactor with comprehensive tests
280-
5. **Prerequisites**: Spec 190 backend work needs this foundation
365+
3. **Schema validation**: Ensure compatibility with Next.js APIs
366+
4. **Documentation**: Tests serve as API usage examples
367+
5. **Confidence**: Safe to refactor with comprehensive tests
368+
6. **Prerequisites**: Spec 190 backend work needs this foundation
369+
370+
### Why Schema Alignment Matters
371+
372+
**API Compatibility** is critical because:
373+
- **@leanspec/ui-vite** expects exact same response format as Next.js APIs
374+
- Field names must match (camelCase in JSON, not snake_case)
375+
- Frontend code should work unchanged when switching backends
376+
- Type safety: TypeScript types in frontend must match Rust serialization
377+
- No adapter layer needed if schemas are identical
281378

282379
### Testing Philosophy
283380

284381
**Focus on behavior, not implementation**:
285382
- Test HTTP responses, not internal state
286383
- Verify response formats match frontend expectations
384+
- **Validate schema compatibility with Next.js APIs**
287385
- Test edge cases and error conditions
288386
- Use realistic fixtures that mirror production data
289387

0 commit comments

Comments
 (0)