test(backend): generalize native Google E2E fakes for Gmail

This commit is contained in:
Anish Sarkar 2026-05-07 04:22:59 +05:30
parent 92dd967bf1
commit a5c04cb38d
3 changed files with 90 additions and 14 deletions

View file

@ -1,12 +1,13 @@
"""Strict native Google Drive fakes for Playwright E2E.
"""Strict native Google SDK fakes for Playwright E2E.
This module patches the production Google OAuth and Drive SDK bindings used by
the native ``GOOGLE_DRIVE_CONNECTOR`` happy path. It deliberately does not
replace the whole Google package; unmodelled service methods fail loudly.
the native Google connector happy paths. It deliberately does not replace the
whole Google package; unmodelled service methods fail loudly.
"""
from __future__ import annotations
import base64
import json
from datetime import UTC, datetime, timedelta
from pathlib import Path
@ -17,6 +18,7 @@ from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
from google.oauth2.credentials import Credentials
_DRIVE_FIXTURE_PATH = Path(__file__).parent / "fixtures" / "drive_files.json"
_GMAIL_FIXTURE_PATH = Path(__file__).parent / "fixtures" / "gmail_messages.json"
def _load_drive_fixture() -> dict[str, Any]:
@ -27,14 +29,22 @@ def _load_drive_fixture() -> dict[str, Any]:
_DRIVE_FIXTURE = _load_drive_fixture()
def _load_gmail_fixture() -> dict[str, Any]:
with _GMAIL_FIXTURE_PATH.open() as f:
return json.load(f)
_GMAIL_FIXTURE = _load_gmail_fixture()
class _StrictFakeMixin:
_component_name: str = "<unknown>"
def __getattr__(self, name: str) -> Any:
raise NotImplementedError(
f"E2E native Google Drive fake missing surface: "
f"E2E native Google fake missing surface: "
f"{self._component_name}.{name!r}. Add it to "
f"surfsense_backend/tests/e2e/fakes/native_google_drive.py."
f"surfsense_backend/tests/e2e/fakes/native_google.py."
)
@ -149,7 +159,7 @@ class _FakeDriveFiles(_StrictFakeMixin):
content = _DRIVE_FIXTURE.get("_file_contents", {}).get(file_id)
if content is None:
raise NotImplementedError(
f"E2E native Google Drive fake has no content for fileId={file_id!r}."
f"E2E native Google fake has no content for fileId={file_id!r}."
)
return _FakeMediaRequest(content.encode("utf-8"))
@ -158,7 +168,7 @@ class _FakeDriveFiles(_StrictFakeMixin):
content = _DRIVE_FIXTURE.get("_file_contents", {}).get(file_id)
if content is None:
raise NotImplementedError(
f"E2E native Google Drive fake has no export content for fileId={file_id!r}."
f"E2E native Google fake has no export content for fileId={file_id!r}."
)
return _FakeRequest(content.encode("utf-8"))
@ -194,6 +204,46 @@ class _FakeGmailUsers(_StrictFakeMixin):
raise NotImplementedError(f"Unexpected fake Gmail profile userId={user_id!r}")
return _FakeRequest({"emailAddress": "native-drive-e2e@surfsense.example"})
def messages(self) -> _FakeGmailMessages:
return _FakeGmailMessages()
class _FakeGmailMessages(_StrictFakeMixin):
_component_name = "gmail.messages"
def list(self, **kwargs: Any) -> _FakeRequest:
user_id = kwargs.get("userId")
if user_id != "me":
raise NotImplementedError(f"Unexpected fake Gmail list userId={user_id!r}")
max_results = int(kwargs.get("maxResults", 10) or 10)
messages = list(_GMAIL_FIXTURE.get("messages", []))[:max_results]
return _FakeRequest(
{
"messages": [
{
"id": message["id"],
"threadId": message.get("threadId"),
}
for message in messages
],
"resultSizeEstimate": len(messages),
}
)
def get(self, **kwargs: Any) -> _FakeRequest:
user_id = kwargs.get("userId")
if user_id != "me":
raise NotImplementedError(f"Unexpected fake Gmail get userId={user_id!r}")
message_id = kwargs.get("id")
detail = _GMAIL_FIXTURE.get("details", {}).get(message_id)
if detail is None:
raise NotImplementedError(
f"E2E native Gmail fake has no message detail for id={message_id!r}."
)
return _FakeRequest(_gmail_detail_to_native_message(detail))
class _FakeGmailService(_StrictFakeMixin):
_component_name = "gmail_service"
@ -208,7 +258,7 @@ def _fake_build(service_name: str, version: str, **_: Any) -> Any:
if service_name == "gmail" and version == "v1":
return _FakeGmailService()
raise NotImplementedError(
f"E2E native Google Drive fake cannot build {service_name!r} {version!r}."
f"E2E native Google fake cannot build {service_name!r} {version!r}."
)
@ -256,14 +306,40 @@ def _drive_get_metadata(file_id: str | None) -> dict[str, Any]:
if entry.get("id") == file_id:
return dict(entry)
raise NotImplementedError(
f"E2E native Google Drive fake has no metadata for fileId={file_id!r}."
f"E2E native Google fake has no metadata for fileId={file_id!r}."
)
def _gmail_detail_to_native_message(detail: dict[str, Any]) -> dict[str, Any]:
message_text = detail.get("messageText", "")
encoded_body = base64.urlsafe_b64encode(message_text.encode("utf-8")).decode("ascii")
return {
"id": detail.get("id"),
"threadId": detail.get("threadId"),
"labelIds": ["INBOX", "IMPORTANT"],
"snippet": message_text[:160],
"payload": {
"mimeType": "text/plain",
"headers": [
{"name": "Subject", "value": detail.get("subject", "No Subject")},
{"name": "From", "value": detail.get("from", "Unknown Sender")},
{"name": "To", "value": detail.get("to", "Unknown Recipient")},
{"name": "Date", "value": detail.get("date", "Unknown Date")},
],
"body": {
"data": encoded_body,
"size": len(message_text),
},
},
}
def install(active_patches: list[Any]) -> None:
"""Patch production bindings to use native Google Drive fakes."""
"""Patch production bindings to use native Google SDK fakes."""
targets = [
("app.routes.google_drive_add_connector_route.Flow", _FakeFlow),
("app.routes.google_gmail_add_connector_route.Flow", _FakeFlow),
("app.connectors.google_drive.client.build", _fake_build),
("app.connectors.google_gmail_connector.build", _fake_build),
("googleapiclient.http.MediaIoBaseDownload", _FakeMediaIoBaseDownload),

View file

@ -81,7 +81,7 @@ from unittest.mock import patch # noqa: E402
from app.app import app # noqa: E402
from tests.e2e.fakes import ( # noqa: E402
embeddings as _fake_embeddings,
native_google_drive as _fake_native_google_drive,
native_google as _fake_native_google,
)
from tests.e2e.fakes.chat_llm import ( # noqa: E402
fake_create_chat_litellm_from_agent_config,
@ -148,7 +148,7 @@ def _patch_llm_bindings() -> None:
_patch_llm_bindings()
_fake_embeddings.install(_active_patches)
_fake_native_google_drive.install(_active_patches)
_fake_native_google.install(_active_patches)
# ---------------------------------------------------------------------------

View file

@ -66,7 +66,7 @@ from unittest.mock import patch # noqa: E402
from app.celery_app import celery_app # noqa: E402
from tests.e2e.fakes import ( # noqa: E402
embeddings as _fake_embeddings,
native_google_drive as _fake_native_google_drive,
native_google as _fake_native_google,
)
from tests.e2e.fakes.chat_llm import ( # noqa: E402
fake_create_chat_litellm_from_agent_config,
@ -132,7 +132,7 @@ def _patch_llm_bindings() -> None:
_patch_llm_bindings()
_fake_embeddings.install(_active_patches)
_fake_native_google_drive.install(_active_patches)
_fake_native_google.install(_active_patches)
# ---------------------------------------------------------------------------