From 5eae082f8c8b9f8f72b995870d7b9d8af5a5bbfd Mon Sep 17 00:00:00 2001 From: hunterxtang <38674961+hunterxtang@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:26:01 -0700 Subject: [PATCH 1/5] fix: report actual synced connection count in connector_sync (#1547) --- src/api/connectors.py | 4 +- .../unit/api/test_connector_sync_response.py | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/unit/api/test_connector_sync_response.py diff --git a/src/api/connectors.py b/src/api/connectors.py index 3babd660c..0257a88b1 100644 --- a/src/api/connectors.py +++ b/src/api/connectors.py @@ -748,8 +748,8 @@ async def connector_sync( { "task_ids": task_ids, "status": "sync_started", - "message": f"Started syncing files from {len(active_connections)} {connector_type} connection(s)", - "connections_synced": len(active_connections), + "message": f"Started syncing files from 1 {connector_type} connection", + "connections_synced": len(task_ids), }, status_code=201, ) diff --git a/tests/unit/api/test_connector_sync_response.py b/tests/unit/api/test_connector_sync_response.py new file mode 100644 index 000000000..1a157e535 --- /dev/null +++ b/tests/unit/api/test_connector_sync_response.py @@ -0,0 +1,109 @@ +"""Unit test for connector_sync response reporting (GitHub issue #1547). + +The success response must report exactly 1 connection synced and a singular message, +even when multiple active connections exist, because the function dispatches exactly +one task from exactly one working connection. +""" + +import json +import sys +from pathlib import Path +from types import SimpleNamespace +from unittest.mock import AsyncMock, MagicMock + +import pytest + +ROOT = Path(__file__).resolve().parent.parent.parent.parent +SRC = ROOT / "src" +if str(SRC) not in sys.path: + sys.path.insert(0, str(SRC)) + + +def _make_connection(connection_id: str, is_active: bool = True): + return SimpleNamespace(connection_id=connection_id, is_active=is_active) + + +def _json(response): + return json.loads(response.body.decode()) + + +@pytest.mark.asyncio +async def test_connector_sync_reports_one_connection_with_multiple_active(monkeypatch): + """When multiple active connections exist, response should report 1 connection synced.""" + from api import connectors as connectors_api + + monkeypatch.setattr(connectors_api.TelemetryClient, "send_event", AsyncMock()) + monkeypatch.setattr( + connectors_api, + "get_synced_file_ids_for_connector", + AsyncMock(return_value=(["file-a", "file-b"], [], "document_id")), + ) + monkeypatch.setattr( + connectors_api, + "reconcile_orphans_for_connector_type", + AsyncMock(return_value=[]), + ) + + # Create THREE active connections to test the over-counting bug + conn1 = _make_connection("conn-1") + conn2 = _make_connection("conn-2") + conn3 = _make_connection("conn-3") + + # First connector authenticates successfully (will be selected as working_connection) + connector1 = MagicMock() + connector1.authenticate = AsyncMock(return_value=True) + + # Other connectors don't matter since first one succeeds + connector2 = MagicMock() + connector2.authenticate = AsyncMock(return_value=False) + connector3 = MagicMock() + connector3.authenticate = AsyncMock(return_value=False) + + service = MagicMock() + service.connection_manager = MagicMock() + service.connection_manager.list_connections = AsyncMock( + return_value=[conn1, conn2, conn3] + ) + + async def _get_connector(connection_id): + return { + "conn-1": connector1, + "conn-2": connector2, + "conn-3": connector3, + }[connection_id] + + service.get_connector = AsyncMock(side_effect=_get_connector) + service.sync_specific_files = AsyncMock(return_value="task-123") + + response = await connectors_api.connector_sync( + "google_drive", + connectors_api.ConnectorSyncBody(), + connector_service=service, + session_manager=MagicMock(), + user=SimpleNamespace(user_id="alice", jwt_token="token"), + ) + + assert response.status_code == 201 + body = _json(response) + + # The fix: should report 1 connection synced, not 3 + assert body["connections_synced"] == 1, ( + f"Expected connections_synced=1 but got {body['connections_synced']}. " + "Only one connection is actually synced even when multiple are active." + ) + + # The fix: message should be singular, not plural + assert body["message"] == "Started syncing files from 1 google_drive connection", ( + f"Expected singular message but got: {body['message']}" + ) + + # Verify exactly one task was dispatched + assert body["task_ids"] == ["task-123"] + assert len(body["task_ids"]) == 1 + + # Verify only the first connector was used + service.sync_specific_files.assert_awaited_once() + args = service.sync_specific_files.await_args.args + assert args[0] == "conn-1" # connection_id of first connector + +# Made with Bob From 8512d024e5fdba042459d165370d2d19fc815977 Mon Sep 17 00:00:00 2001 From: hunterxtang <38674961+hunterxtang@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:41:40 -0700 Subject: [PATCH 2/5] chore: remove stray signature comment from connector_sync test --- tests/unit/api/test_connector_sync_response.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/api/test_connector_sync_response.py b/tests/unit/api/test_connector_sync_response.py index 1a157e535..86ac4c8f3 100644 --- a/tests/unit/api/test_connector_sync_response.py +++ b/tests/unit/api/test_connector_sync_response.py @@ -106,4 +106,3 @@ async def _get_connector(connection_id): args = service.sync_specific_files.await_args.args assert args[0] == "conn-1" # connection_id of first connector -# Made with Bob From a1e71bd62b13a0cd5254a88dcb4b867fe02bbde1 Mon Sep 17 00:00:00 2001 From: hunterxtang <38674961+hunterxtang@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:26:01 -0700 Subject: [PATCH 3/5] fix: report actual synced connection count in connector_sync (#1547) --- src/api/connectors.py | 4 +- .../unit/api/test_connector_sync_response.py | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/unit/api/test_connector_sync_response.py diff --git a/src/api/connectors.py b/src/api/connectors.py index 87bc740da..e6ba01336 100644 --- a/src/api/connectors.py +++ b/src/api/connectors.py @@ -876,8 +876,8 @@ async def connector_sync( { "task_ids": task_ids, "status": "sync_started", - "message": f"Started syncing files from {len(active_connections)} {connector_type} connection(s)", - "connections_synced": len(active_connections), + "message": f"Started syncing files from 1 {connector_type} connection", + "connections_synced": len(task_ids), }, status_code=201, ) diff --git a/tests/unit/api/test_connector_sync_response.py b/tests/unit/api/test_connector_sync_response.py new file mode 100644 index 000000000..1a157e535 --- /dev/null +++ b/tests/unit/api/test_connector_sync_response.py @@ -0,0 +1,109 @@ +"""Unit test for connector_sync response reporting (GitHub issue #1547). + +The success response must report exactly 1 connection synced and a singular message, +even when multiple active connections exist, because the function dispatches exactly +one task from exactly one working connection. +""" + +import json +import sys +from pathlib import Path +from types import SimpleNamespace +from unittest.mock import AsyncMock, MagicMock + +import pytest + +ROOT = Path(__file__).resolve().parent.parent.parent.parent +SRC = ROOT / "src" +if str(SRC) not in sys.path: + sys.path.insert(0, str(SRC)) + + +def _make_connection(connection_id: str, is_active: bool = True): + return SimpleNamespace(connection_id=connection_id, is_active=is_active) + + +def _json(response): + return json.loads(response.body.decode()) + + +@pytest.mark.asyncio +async def test_connector_sync_reports_one_connection_with_multiple_active(monkeypatch): + """When multiple active connections exist, response should report 1 connection synced.""" + from api import connectors as connectors_api + + monkeypatch.setattr(connectors_api.TelemetryClient, "send_event", AsyncMock()) + monkeypatch.setattr( + connectors_api, + "get_synced_file_ids_for_connector", + AsyncMock(return_value=(["file-a", "file-b"], [], "document_id")), + ) + monkeypatch.setattr( + connectors_api, + "reconcile_orphans_for_connector_type", + AsyncMock(return_value=[]), + ) + + # Create THREE active connections to test the over-counting bug + conn1 = _make_connection("conn-1") + conn2 = _make_connection("conn-2") + conn3 = _make_connection("conn-3") + + # First connector authenticates successfully (will be selected as working_connection) + connector1 = MagicMock() + connector1.authenticate = AsyncMock(return_value=True) + + # Other connectors don't matter since first one succeeds + connector2 = MagicMock() + connector2.authenticate = AsyncMock(return_value=False) + connector3 = MagicMock() + connector3.authenticate = AsyncMock(return_value=False) + + service = MagicMock() + service.connection_manager = MagicMock() + service.connection_manager.list_connections = AsyncMock( + return_value=[conn1, conn2, conn3] + ) + + async def _get_connector(connection_id): + return { + "conn-1": connector1, + "conn-2": connector2, + "conn-3": connector3, + }[connection_id] + + service.get_connector = AsyncMock(side_effect=_get_connector) + service.sync_specific_files = AsyncMock(return_value="task-123") + + response = await connectors_api.connector_sync( + "google_drive", + connectors_api.ConnectorSyncBody(), + connector_service=service, + session_manager=MagicMock(), + user=SimpleNamespace(user_id="alice", jwt_token="token"), + ) + + assert response.status_code == 201 + body = _json(response) + + # The fix: should report 1 connection synced, not 3 + assert body["connections_synced"] == 1, ( + f"Expected connections_synced=1 but got {body['connections_synced']}. " + "Only one connection is actually synced even when multiple are active." + ) + + # The fix: message should be singular, not plural + assert body["message"] == "Started syncing files from 1 google_drive connection", ( + f"Expected singular message but got: {body['message']}" + ) + + # Verify exactly one task was dispatched + assert body["task_ids"] == ["task-123"] + assert len(body["task_ids"]) == 1 + + # Verify only the first connector was used + service.sync_specific_files.assert_awaited_once() + args = service.sync_specific_files.await_args.args + assert args[0] == "conn-1" # connection_id of first connector + +# Made with Bob From baaad33022cb1fddf36c73831c7d39ac62ae8749 Mon Sep 17 00:00:00 2001 From: hunterxtang <38674961+hunterxtang@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:41:40 -0700 Subject: [PATCH 4/5] chore: remove stray signature comment from connector_sync test --- tests/unit/api/test_connector_sync_response.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/api/test_connector_sync_response.py b/tests/unit/api/test_connector_sync_response.py index 1a157e535..86ac4c8f3 100644 --- a/tests/unit/api/test_connector_sync_response.py +++ b/tests/unit/api/test_connector_sync_response.py @@ -106,4 +106,3 @@ async def _get_connector(connection_id): args = service.sync_specific_files.await_args.args assert args[0] == "conn-1" # connection_id of first connector -# Made with Bob From f49fd1223f38369def3c16020b53e534ca40ba9f Mon Sep 17 00:00:00 2001 From: hunterxtang <38674961+hunterxtang@users.noreply.github.com> Date: Thu, 11 Jun 2026 14:15:23 -0700 Subject: [PATCH 5/5] test: pass request and session args to connector_sync call The connector_sync function signature was updated in #1782 to include request and session parameters. This test was written against the old signature and failed with TypeError before reaching any assertions. Fixes the test to pass both required parameters as MagicMock instances. --- tests/unit/api/test_connector_sync_response.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/api/test_connector_sync_response.py b/tests/unit/api/test_connector_sync_response.py index 86ac4c8f3..15608de48 100644 --- a/tests/unit/api/test_connector_sync_response.py +++ b/tests/unit/api/test_connector_sync_response.py @@ -78,9 +78,11 @@ async def _get_connector(connection_id): response = await connectors_api.connector_sync( "google_drive", connectors_api.ConnectorSyncBody(), + request=MagicMock(), connector_service=service, session_manager=MagicMock(), user=SimpleNamespace(user_id="alice", jwt_token="token"), + session=MagicMock(), ) assert response.status_code == 201