diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 74f875fe..60bde90c 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,13 +1,18 @@ """Shared fixtures for integration tests.""" from pathlib import Path - from typing import Generator + import pytest +from fastapi import Request + from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.engine import Engine +from authentication.noop import NoopAuthDependency +from authentication.interface import AuthTuple + from configuration import configuration from models.database.base import Base @@ -45,6 +50,23 @@ def test_config_fixture() -> Generator: # Note: Cleanup is handled by the autouse reset_configuration_state fixture +@pytest.fixture(name="current_config", scope="function") +def current_config_fixture() -> Generator: + """Load current configuration for integration tests. + + This fixture loads the actual configuration file from project root (current configuration), + demonstrating integration with the configuration system. + """ + config_path = Path(__file__).parent.parent.parent / "lightspeed-stack.yaml" + assert config_path.exists(), f"Config file not found: {config_path}" + + # Load configuration + configuration.load_configuration(str(config_path)) + + yield configuration + # Note: Cleanup is handled by the autouse reset_configuration_state fixture + + @pytest.fixture(name="test_db_engine", scope="function") def test_db_engine_fixture() -> Generator: """Create an in-memory SQLite database engine for testing. @@ -81,3 +103,26 @@ def test_db_session_fixture(test_db_engine: Engine) -> Generator[Session, None, yield session session.close() + + +@pytest.fixture(name="test_request") +def test_request_fixture() -> Request: + """Create a test FastAPI Request object with proper scope.""" + return Request( + scope={ + "type": "http", + "query_string": b"", + "headers": [], + } + ) + + +@pytest.fixture(name="test_auth") +async def test_auth_fixture(test_request: Request) -> AuthTuple: + """Create authentication using real noop auth module. + + This uses the actual NoopAuthDependency instead of mocking, + making this a true integration test. + """ + noop_auth = NoopAuthDependency() + return await noop_auth(test_request) diff --git a/tests/integration/endpoints/test_config_integration.py b/tests/integration/endpoints/test_config_integration.py new file mode 100644 index 00000000..2df47cdf --- /dev/null +++ b/tests/integration/endpoints/test_config_integration.py @@ -0,0 +1,84 @@ +"""Integration tests for the /config endpoint.""" + +import pytest + +from fastapi import Request + +from authentication.interface import AuthTuple + +from configuration import AppConfig, LogicError +from app.endpoints.config import config_endpoint_handler + + +@pytest.mark.asyncio +async def test_config_endpoint_returns_config( + test_config: AppConfig, + test_request: Request, + test_auth: AuthTuple, +) -> None: + """Test that config endpoint returns test configuration. + + This integration test verifies: + - Endpoint handler integrates with configuration system + - Configuration values are correctly accessed + - Real noop authentication is used + - Response structure matches expected format + + Args: + test_config: Loads test configuration + test_request: FastAPI request + test_auth: noop authentication tuple + """ + response = await config_endpoint_handler(auth=test_auth, request=test_request) + + # Verify that response matches the real configuration + assert response == test_config.configuration + + +@pytest.mark.asyncio +async def test_config_endpoint_returns_current_config( + current_config: AppConfig, + test_request: Request, + test_auth: AuthTuple, +) -> None: + """Test that config endpoint returns current configuration (from root). + + This integration test verifies: + - Endpoint handler integrates with configuration system + - Configuration values are correctly accessed + - Real noop authentication is used + - Response structure matches expected format + + Args: + current_config: Loads root configuration + test_request: FastAPI request + test_auth: noop authentication tuple + """ + response = await config_endpoint_handler(auth=test_auth, request=test_request) + + # Verify that response matches the root configuration + assert response == current_config.configuration + + +@pytest.mark.asyncio +async def test_config_endpoint_fails_without_configuration( + test_request: Request, + test_auth: AuthTuple, +) -> None: + """Test that authorization fails when configuration is not loaded. + + This integration test verifies: + - LogicError is raised when configuration is not loaded + - Error message indicates configuration is not loaded + + Args: + test_request: FastAPI request + test_auth: noop authentication tuple + """ + + # Verify that LogicError is raised when authorization tries to access config + with pytest.raises(LogicError) as exc_info: + await config_endpoint_handler(auth=test_auth, request=test_request) + + # Verify error message + assert "configuration is not loaded" in str(exc_info.value) diff --git a/tests/integration/endpoints/test_info_integration.py b/tests/integration/endpoints/test_info_integration.py index 3d7ead15..c1a3ea4d 100644 --- a/tests/integration/endpoints/test_info_integration.py +++ b/tests/integration/endpoints/test_info_integration.py @@ -7,10 +7,10 @@ from fastapi import HTTPException, Request, status from llama_stack_client import APIConnectionError from llama_stack_client.types import VersionInfo +from authentication.interface import AuthTuple from configuration import AppConfig from app.endpoints.info import info_endpoint_handler -from authentication.noop import NoopAuthDependency from version import __version__ @@ -36,35 +36,12 @@ def mock_llama_stack_client_fixture( yield mock_client -@pytest.fixture(name="test_request") -def test_request_fixture() -> Request: - """Create a test FastAPI Request object with proper scope.""" - return Request( - scope={ - "type": "http", - "query_string": b"", - "headers": [], - } - ) - - -@pytest.fixture(name="test_auth") -async def test_auth_fixture(test_request: Request) -> tuple[str, str, bool, str]: - """Create authentication using real noop auth module. - - This uses the actual NoopAuthDependency instead of mocking, - making this a true integration test. - """ - noop_auth = NoopAuthDependency() - return await noop_auth(test_request) - - @pytest.mark.asyncio async def test_info_endpoint_returns_service_information( test_config: AppConfig, mock_llama_stack_client: AsyncMockType, test_request: Request, - test_auth: tuple[str, str, bool, str], + test_auth: AuthTuple, ) -> None: """Test that info endpoint returns correct service information. @@ -100,7 +77,7 @@ async def test_info_endpoint_handles_connection_error( test_config: AppConfig, mock_llama_stack_client: AsyncMockType, test_request: Request, - test_auth: tuple[str, str, bool, str], + test_auth: AuthTuple, mocker: MockerFixture, ) -> None: """Test that info endpoint properly handles Llama Stack connection errors. @@ -140,7 +117,7 @@ async def test_info_endpoint_uses_configuration_values( test_config: AppConfig, mock_llama_stack_client: AsyncMockType, test_request: Request, - test_auth: tuple[str, str, bool, str], + test_auth: AuthTuple, ) -> None: """Test that info endpoint correctly uses configuration values.