From 93de9fead0557f526229aa394b631bb0922d15e2 Mon Sep 17 00:00:00 2001 From: Eva Micankova Date: Thu, 30 Oct 2025 10:56:14 +0100 Subject: [PATCH 1/3] Adding intehration tests of /config endpoint. Moving auth and request fixtures to conftest.py. --- tests/integration/conftest.py | 45 ++++++++++ .../endpoints/test_config_integration.py | 82 +++++++++++++++++++ .../endpoints/test_info_integration.py | 24 ------ 3 files changed, 127 insertions(+), 24 deletions(-) create mode 100644 tests/integration/endpoints/test_config_integration.py diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 74f875fe..492e8830 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -2,6 +2,9 @@ from pathlib import Path +from fastapi import Request +from authentication.noop import NoopAuthDependency + from typing import Generator import pytest from sqlalchemy import create_engine @@ -45,6 +48,25 @@ 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) -> 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) diff --git a/tests/integration/endpoints/test_config_integration.py b/tests/integration/endpoints/test_config_integration.py new file mode 100644 index 00000000..717a78c0 --- /dev/null +++ b/tests/integration/endpoints/test_config_integration.py @@ -0,0 +1,82 @@ +"""Integration tests for the /config endpoint.""" + +import pytest + +from fastapi import Request + +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: tuple[str, str, bool, str], +) -> 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: tuple[str, str, bool, str], +) -> 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: tuple[str, str, bool, str], +) -> 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..0ed71fc3 100644 --- a/tests/integration/endpoints/test_info_integration.py +++ b/tests/integration/endpoints/test_info_integration.py @@ -10,7 +10,6 @@ from configuration import AppConfig from app.endpoints.info import info_endpoint_handler -from authentication.noop import NoopAuthDependency from version import __version__ @@ -36,29 +35,6 @@ 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, From 50fcb590e3624b30b9f81e955c03c11a2ca4429b Mon Sep 17 00:00:00 2001 From: Eva Micankova Date: Thu, 30 Oct 2025 12:27:30 +0100 Subject: [PATCH 2/3] Resolving black and Pylint errors --- tests/integration/conftest.py | 11 +++++------ .../integration/endpoints/test_config_integration.py | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 492e8830..ac57359c 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,16 +1,17 @@ """Shared fixtures for integration tests.""" from pathlib import Path +from typing import Generator +import pytest from fastapi import Request -from authentication.noop import NoopAuthDependency -from typing import Generator -import pytest from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.engine import Engine +from authentication.noop import NoopAuthDependency + from configuration import configuration from models.database.base import Base @@ -55,9 +56,7 @@ def current_config_fixture() -> Generator: 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" - ) + config_path = Path(__file__).parent.parent.parent / "lightspeed-stack.yaml" assert config_path.exists(), f"Config file not found: {config_path}" # Load configuration diff --git a/tests/integration/endpoints/test_config_integration.py b/tests/integration/endpoints/test_config_integration.py index 717a78c0..4160e722 100644 --- a/tests/integration/endpoints/test_config_integration.py +++ b/tests/integration/endpoints/test_config_integration.py @@ -53,7 +53,7 @@ async def test_config_endpoint_returns_current_config( 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 @@ -73,7 +73,7 @@ async def test_config_endpoint_fails_without_configuration( 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) From 1c8f2524801b67112c73c543e8c79b59e31a9d0a Mon Sep 17 00:00:00 2001 From: Eva Micankova Date: Thu, 30 Oct 2025 12:33:55 +0100 Subject: [PATCH 3/3] Correcting variable and return types to be AuthTuple. --- tests/integration/conftest.py | 3 ++- tests/integration/endpoints/test_config_integration.py | 8 +++++--- tests/integration/endpoints/test_info_integration.py | 7 ++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index ac57359c..60bde90c 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -11,6 +11,7 @@ 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 @@ -117,7 +118,7 @@ def test_request_fixture() -> Request: @pytest.fixture(name="test_auth") -async def test_auth_fixture(test_request: Request) -> tuple[str, str, bool, str]: +async def test_auth_fixture(test_request: Request) -> AuthTuple: """Create authentication using real noop auth module. This uses the actual NoopAuthDependency instead of mocking, diff --git a/tests/integration/endpoints/test_config_integration.py b/tests/integration/endpoints/test_config_integration.py index 4160e722..2df47cdf 100644 --- a/tests/integration/endpoints/test_config_integration.py +++ b/tests/integration/endpoints/test_config_integration.py @@ -4,6 +4,8 @@ from fastapi import Request +from authentication.interface import AuthTuple + from configuration import AppConfig, LogicError from app.endpoints.config import config_endpoint_handler @@ -12,7 +14,7 @@ async def test_config_endpoint_returns_config( test_config: AppConfig, test_request: Request, - test_auth: tuple[str, str, bool, str], + test_auth: AuthTuple, ) -> None: """Test that config endpoint returns test configuration. @@ -37,7 +39,7 @@ async def test_config_endpoint_returns_config( async def test_config_endpoint_returns_current_config( current_config: AppConfig, test_request: Request, - test_auth: tuple[str, str, bool, str], + test_auth: AuthTuple, ) -> None: """Test that config endpoint returns current configuration (from root). @@ -61,7 +63,7 @@ async def test_config_endpoint_returns_current_config( @pytest.mark.asyncio async def test_config_endpoint_fails_without_configuration( test_request: Request, - test_auth: tuple[str, str, bool, str], + test_auth: AuthTuple, ) -> None: """Test that authorization fails when configuration is not loaded. diff --git a/tests/integration/endpoints/test_info_integration.py b/tests/integration/endpoints/test_info_integration.py index 0ed71fc3..c1a3ea4d 100644 --- a/tests/integration/endpoints/test_info_integration.py +++ b/tests/integration/endpoints/test_info_integration.py @@ -7,6 +7,7 @@ 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 @@ -40,7 +41,7 @@ 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. @@ -76,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. @@ -116,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.