diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 8137b5c..71990cf 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -302,3 +302,107 @@ def mock_minio_stat(monkeypatch): except ImportError: pass # storage module not yet available — patch is best-effort yield mock + + +# ── Phase 5 cloud storage fixtures ─────────────────────────────────────────── + + +@pytest.fixture +def mock_google_drive_creds(): + """Return a fake Google Drive OAuth credential dict for unit tests. + + Shape mirrors what google-auth-oauthlib stores in credentials.to_json(). + Expiry is far in the future so tests never hit a token-refresh branch. + """ + return { + "access_token": "ya29.test_access", + "refresh_token": "1//test_refresh", + "expiry": "2099-12-31T23:59:59", + "token_uri": "https://oauth2.googleapis.com/token", + "client_id": "test_client_id", + "client_secret": "test_client_secret", + } + + +@pytest.fixture +def mock_onedrive_creds(): + """Return a fake OneDrive MSAL credential dict for unit tests. + + Shape mirrors what msal.PublicClientApplication.acquire_token_by_auth_code_flow + returns (simplified subset required by cloud_utils). + """ + return { + "access_token": "test_ms_access", + "refresh_token": "test_ms_refresh", + "expires_at": "2099-12-31T23:59:59", + } + + +@pytest.fixture +def mock_webdav_client(): + """Return a MagicMock simulating a webdavclient3 Client instance. + + All four methods the DocuVault cloud layer calls are pre-wired to return None + so tests can assert call counts without making real network connections. + """ + from unittest.mock import MagicMock + + client = MagicMock() + client.upload_to = MagicMock(return_value=None) + client.download_from = MagicMock(return_value=None) + client.list = MagicMock(return_value=None) + client.check = MagicMock(return_value=None) + return client + + +@pytest_asyncio.fixture +async def cloud_connection_factory(db_session: AsyncSession): + """Factory fixture that creates CloudConnection ORM rows in the test db_session. + + Usage:: + + async def test_something(cloud_connection_factory, auth_user): + conn = await cloud_connection_factory( + db_session, auth_user["user"].id, provider="google_drive" + ) + assert conn.status == "ACTIVE" + + Parameters + ---------- + session : AsyncSession + The async SQLAlchemy session to use (typically db_session). + user_id : uuid.UUID | str + Owner of the cloud connection. + provider : str + Provider slug, e.g. "google_drive", "onedrive", "webdav". + status : str + Connection status string, default "ACTIVE". + display_name : str | None + Human-readable label; defaults to " account". + credentials_enc : str + Encrypted credential blob (use a placeholder in unit tests). + """ + import uuid as _uuid + from db.models import CloudConnection + + async def _factory( + session: AsyncSession, + user_id, + provider: str = "google_drive", + status: str = "ACTIVE", + display_name: str | None = None, + credentials_enc: str = "fake_encrypted_creds", + ) -> CloudConnection: + conn = CloudConnection( + id=_uuid.uuid4(), + user_id=user_id if isinstance(user_id, _uuid.UUID) else _uuid.UUID(str(user_id)), + provider=provider, + display_name=display_name or f"{provider} account", + credentials_enc=credentials_enc, + status=status, + ) + session.add(conn) + await session.flush() + return conn + + return _factory