feat: comprehensive test infrastructure improvements
Phase 1: Fix immediate test failures - Fix path handling in files router (strip leading slashes) - Fix test assertions to match actual API behavior - Add proper error handling for missing files in download endpoint - Reload files router in test fixtures to pick up config changes - Fix upload endpoint test to use query params instead of form data Phase 2: Improve test reliability - Standardize error responses: docker_router now uses HTTPException - Add global exception handlers for validation, Docker errors, and unhandled exceptions - Fix flaky TOTP replay protection test - Fix flaky password hash loading test with proper module reload - Enhanced Docker mock fixtures with error scenarios and factory pattern Phase 3: Add coverage reporting - Add pytest-cov with 40% minimum coverage threshold - Add pyproject.toml with pytest and coverage configuration - Update test workflow to generate coverage and JUnit XML reports - Remove -x flag to see all test failures - Configure asyncio_default_fixture_loop_scope to fix deprecation warning Results: - All 144 tests passing (was 137 passed, 5 failed, 2 skipped) - Test execution time: ~3s locally - Coverage: 43% (above 40% threshold) - No skipped tests - Standardized error handling across all endpoints
This commit is contained in:
@@ -18,6 +18,8 @@ _BASE_RESOLVED = str(BASE.resolve())
|
||||
|
||||
|
||||
def _safe_path(path: str) -> Path:
|
||||
# Strip leading slashes to prevent absolute path interpretation
|
||||
path = path.lstrip("/")
|
||||
target = (BASE / path).resolve()
|
||||
if not str(target).startswith(_BASE_RESOLVED):
|
||||
raise ValueError("forbidden")
|
||||
@@ -75,7 +77,10 @@ def browse(path: str = ""):
|
||||
@router.get("/download")
|
||||
def download(path: str):
|
||||
try:
|
||||
return FileResponse(_safe_path(path))
|
||||
target = _safe_path(path)
|
||||
if not target.exists():
|
||||
raise HTTPException(status_code=404, detail="File not found")
|
||||
return FileResponse(target)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=403, detail="Access denied")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user