""" Tests to verify that all critical API endpoints are properly registered. This test module serves as a regression prevention mechanism to ensure that endpoints remain accessible after code refactoring or reorganization. """ from unittest.mock import AsyncMock, Mock, patch import pytest # Test constants TEST_URL = "https://example.com/test.pdf" @pytest.mark.unit class TestEndpointRegistration: """Verify that critical API endpoints are registered in the FastAPI app""" @patch("app.api.url_upload.httpx.AsyncClient.stream") @patch("app.api.url_upload.process_document") def test_process_url_endpoint_exists(self, mock_process_document, mock_stream, client): """Verify that /api/process-url endpoint is registered and accessible""" # Mock successful download to prevent actual HTTP requests mock_response = AsyncMock() mock_response.status_code = 200 mock_response.headers = {"Content-Type": "application/pdf", "Content-Length": "1024"} async def mock_aiter_bytes(chunk_size=None): yield b"PDF content" mock_response.aiter_bytes = mock_aiter_bytes mock_response.raise_for_status = Mock() mock_context = AsyncMock() mock_context.__aenter__.return_value = mock_response mock_stream.return_value = mock_context # Mock Celery task mock_task = Mock() mock_task.id = "test-task-id" mock_process_document.delay.return_value = mock_task # Make a request to the endpoint - it should not return 404 response = client.post("/api/process-url", json={"url": TEST_URL}) # The endpoint exists if we don't get a 404 # We may get other errors (401, 400, 500, etc.) due to validation or missing mocks, # but 404 specifically means the endpoint is not registered assert response.status_code != 404, ( "Endpoint /api/process-url returned 404 (not found). " "This indicates the router is not properly registered in the application. " "Verify that url_upload_router is included in app/api/__init__.py" ) @patch("app.api.url_upload.httpx.AsyncClient.stream") @patch("app.api.url_upload.process_document") def test_process_url_endpoint_accepts_post(self, mock_process_document, mock_stream, client): """Verify that /api/process-url accepts POST requests""" # Mock successful download to prevent actual HTTP requests mock_response = AsyncMock() mock_response.status_code = 200 mock_response.headers = {"Content-Type": "application/pdf", "Content-Length": "1024"} async def mock_aiter_bytes(chunk_size=None): yield b"PDF content" mock_response.aiter_bytes = mock_aiter_bytes mock_response.raise_for_status = Mock() mock_context = AsyncMock() mock_context.__aenter__.return_value = mock_response mock_stream.return_value = mock_context # Mock Celery task mock_task = Mock() mock_task.id = "test-task-id" mock_process_document.delay.return_value = mock_task # Try POST request response = client.post("/api/process-url", json={"url": TEST_URL}) # Should not return 405 (Method Not Allowed) assert response.status_code != 405, ( "Endpoint /api/process-url returned 405 (Method Not Allowed) for POST. " "Verify the endpoint is decorated with @router.post()" ) @patch("app.api.url_upload.httpx.AsyncClient.stream") @patch("app.api.url_upload.process_document") def test_api_router_included_in_app(self, mock_process_document, mock_stream, client): """Verify that the main API router is included in the FastAPI app""" # Mock successful download for /api/process-url test mock_response = AsyncMock() mock_response.status_code = 200 mock_response.headers = {"Content-Type": "application/pdf", "Content-Length": "1024"} async def mock_aiter_bytes(chunk_size=None): yield b"PDF content" mock_response.aiter_bytes = mock_aiter_bytes mock_response.raise_for_status = Mock() mock_context = AsyncMock() mock_context.__aenter__.return_value = mock_response mock_stream.return_value = mock_context # Mock Celery task mock_task = Mock() mock_task.id = "test-task-id" mock_process_document.delay.return_value = mock_task # Test a few known API endpoints to ensure the /api prefix works endpoints_to_check = [ ("/api/process-url", "post"), ] for endpoint, method in endpoints_to_check: if method == "get": response = client.get(endpoint) else: response = client.post(endpoint, json={"url": TEST_URL}) # None of these should return 404 assert response.status_code != 404, ( f"Endpoint {endpoint} returned 404. " f"Verify that api_router is included in app/main.py with prefix='/api'" )