File size: 4,854 Bytes
53e1531 | 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 | """
Shortlist — API Endpoint Tests
Tests for the FastAPI application endpoints.
Uses TestClient for synchronous testing.
"""
import pytest
from fastapi.testclient import TestClient
from app.main import app
@pytest.fixture
def client():
"""Create a test client for the FastAPI app."""
return TestClient(app)
class TestHealthCheck:
"""Tests for the /health endpoint."""
def test_health_returns_200(self, client):
response = client.get("/health")
assert response.status_code == 200
def test_health_returns_status(self, client):
response = client.get("/health")
data = response.json()
assert data["status"] == "healthy"
assert "version" in data
assert "environment" in data
def test_health_has_security_headers(self, client):
response = client.get("/health")
assert response.headers.get("X-Content-Type-Options") == "nosniff"
assert response.headers.get("X-Frame-Options") == "DENY"
assert response.headers.get("X-XSS-Protection") == "1; mode=block"
class TestCORS:
"""Tests for CORS configuration."""
def test_cors_allows_configured_origin(self, client):
response = client.options(
"/health",
headers={
"Origin": "http://localhost:3000",
"Access-Control-Request-Method": "GET",
},
)
assert response.headers.get("access-control-allow-origin") == "http://localhost:3000"
def test_cors_blocks_unknown_origin(self, client):
response = client.options(
"/health",
headers={
"Origin": "http://evil.com",
"Access-Control-Request-Method": "GET",
},
)
# Unknown origins should not get CORS headers
assert response.headers.get("access-control-allow-origin") != "http://evil.com"
class TestAuthRequiredEndpoints:
"""Tests that protected endpoints require authentication."""
def test_jd_analyze_requires_auth(self, client):
response = client.post("/api/v1/jd/analyze", json={
"jd_text": "x" * 100,
"role": "Backend Engineer",
"company_type": "startup",
})
assert response.status_code == 401
def test_capstone_generate_requires_auth(self, client):
response = client.post("/api/v1/capstone/generate", json={
"analysis_id": "test-id",
})
assert response.status_code == 401
def test_repo_analyze_requires_auth(self, client):
response = client.post("/api/v1/repo/analyze", json={
"github_url": "https://github.com/test/repo",
})
assert response.status_code == 401
def test_scaffold_generate_requires_auth(self, client):
response = client.post("/api/v1/scaffold/generate", json={
"project_title": "Test Project",
"project_description": "A test project description here",
})
assert response.status_code == 401
def test_portfolio_optimize_requires_auth(self, client):
response = client.post("/api/v1/portfolio/optimize", json={
"project_title": "Test",
"project_description": "A test project description here",
})
assert response.status_code == 401
class TestInputValidation:
"""Tests for request validation (Pydantic enforcement)."""
def test_jd_rejects_short_text(self, client):
"""JD text under 50 chars should be rejected (auth blocks first with fake token)."""
response = client.post(
"/api/v1/jd/analyze",
json={
"jd_text": "too short",
"role": "Engineer",
"company_type": "startup",
},
headers={"Authorization": "Bearer fake-token"},
)
# Auth runs before validation, so we get 401 with fake token
assert response.status_code in (401, 422)
def test_jd_rejects_invalid_company_type(self, client):
"""Invalid company type should be rejected (auth blocks first with fake token)."""
response = client.post(
"/api/v1/jd/analyze",
json={
"jd_text": "x" * 100,
"role": "Engineer",
"company_type": "invalid_type",
},
headers={"Authorization": "Bearer fake-token"},
)
assert response.status_code in (401, 422)
def test_repo_rejects_invalid_github_url(self, client):
"""Non-GitHub URLs should be rejected (auth blocks first with fake token)."""
response = client.post(
"/api/v1/repo/analyze",
json={"github_url": "https://gitlab.com/user/repo"},
headers={"Authorization": "Bearer fake-token"},
)
assert response.status_code in (401, 422)
|