diff --git a/surfsense_backend/tests/integration/composio/conftest.py b/surfsense_backend/tests/integration/composio/conftest.py index 779e7bdb2..44d707ec3 100644 --- a/surfsense_backend/tests/integration/composio/conftest.py +++ b/surfsense_backend/tests/integration/composio/conftest.py @@ -1,13 +1,11 @@ """Composio route integration fixtures. -The sys.modules hijack happens at module import time, before importing -app.app, so production `from composio import Composio` bindings resolve to -the strict E2E fake in this pytest process too. +The `composio` sys.modules hijack lives in the parent integration conftest +so it runs before any sibling suite imports `app.routes`. """ from __future__ import annotations -import sys from collections.abc import AsyncGenerator import httpx @@ -16,19 +14,15 @@ import pytest_asyncio from httpx import ASGITransport from sqlalchemy.ext.asyncio import AsyncSession -from tests.e2e.fakes import composio_module as _fake_composio - -sys.modules["composio"] = _fake_composio - -from app.app import app, limiter # noqa: E402 -from app.config import config # noqa: E402 -from app.db import ( # noqa: E402 +from app.app import app, limiter +from app.config import config +from app.db import ( SearchSourceConnector, SearchSourceConnectorType, User, get_async_session, ) -from app.users import current_active_user # noqa: E402 +from app.users import current_active_user pytestmark = pytest.mark.integration diff --git a/surfsense_backend/tests/integration/conftest.py b/surfsense_backend/tests/integration/conftest.py index d9d7cacae..2f4b3fe9a 100644 --- a/surfsense_backend/tests/integration/conftest.py +++ b/surfsense_backend/tests/integration/conftest.py @@ -1,3 +1,5 @@ +import importlib +import sys import uuid from unittest.mock import AsyncMock, MagicMock @@ -7,17 +9,27 @@ from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.pool import NullPool -from app.config import config as app_config -from app.db import ( - Base, - DocumentType, - SearchSourceConnector, - SearchSourceConnectorType, - SearchSpace, - User, -) -from app.indexing_pipeline.connector_document import ConnectorDocument -from tests.conftest import TEST_DATABASE_URL +# Hijack `composio` before any `from app.*` import; the `from composio import +# Composio` in app.services.composio_service binds once at first import. +from tests.e2e.fakes import composio_module as _fake_composio + +sys.modules["composio"] = _fake_composio + +app_config = importlib.import_module("app.config").config +app_db = importlib.import_module("app.db") +Base = app_db.Base +DocumentType = app_db.DocumentType +SearchSourceConnector = app_db.SearchSourceConnector +SearchSourceConnectorType = app_db.SearchSourceConnectorType +SearchSpace = app_db.SearchSpace +User = app_db.User +ConnectorDocument = importlib.import_module( + "app.indexing_pipeline.connector_document" +).ConnectorDocument +create_default_roles_and_membership = importlib.import_module( + "app.routes.search_spaces_routes" +).create_default_roles_and_membership +TEST_DATABASE_URL = importlib.import_module("tests.conftest").TEST_DATABASE_URL _EMBEDDING_DIM = app_config.embedding_model_instance.dimension @@ -105,6 +117,9 @@ async def db_search_space(db_session: AsyncSession, db_user: User) -> SearchSpac ) db_session.add(space) await db_session.flush() + # Mirror POST /searchspaces so routes guarded by check_permission find a membership. + await create_default_roles_and_membership(db_session, space.id, db_user.id) + await db_session.flush() return space