diff --git a/tests/test_memory_extended.py b/tests/test_memory_extended.py index 62c0f33..6f2a86b 100644 --- a/tests/test_memory_extended.py +++ b/tests/test_memory_extended.py @@ -1318,3 +1318,51 @@ def test_store_memory_valid_from_combined_with_other_fields(self, client, mock_r assert req_body.get("tags") == ["history"] assert req_body.get("session_id") == "sess-1" assert req_body.get("ttl_seconds") == 86400 + + +class TestAsyncExportVectorsCursor: + """AsyncDakeraClient.export_vectors() cursor pagination parity (DAK-7424 follow-up).""" + + async def test_async_export_vectors_forwards_cursor(self): + """Async variant forwards cursor in the request body for pagination.""" + from unittest.mock import patch + + from dakera import AsyncDakeraClient + + client = AsyncDakeraClient("http://localhost:3000") + captured: dict = {} + + async def fake_request(method, path, data=None, **kwargs): + captured["method"] = method + captured["path"] = path + captured["data"] = data or {} + return {"vectors": [{"id": "v-1", "values": [0.1, 0.2]}], "next_cursor": "cursor-page2"} + + with patch.object(client, "_request", side_effect=fake_request): + result = await client.export_vectors("test-ns", cursor="cursor-abc", limit=50) + + assert captured["method"] == "POST" + assert "test-ns" in captured["path"] + assert captured["data"]["cursor"] == "cursor-abc" + assert captured["data"]["limit"] == 50 + assert result["next_cursor"] == "cursor-page2" + assert len(result["vectors"]) == 1 + + async def test_async_export_vectors_omits_cursor_when_none(self): + """Async variant does not include cursor in request body when not provided.""" + from unittest.mock import patch + + from dakera import AsyncDakeraClient + + client = AsyncDakeraClient("http://localhost:3000") + captured: dict = {} + + async def fake_request(method, path, data=None, **kwargs): + captured["data"] = data or {} + return {"vectors": [], "next_cursor": None} + + with patch.object(client, "_request", side_effect=fake_request): + await client.export_vectors("test-ns", limit=10) + + assert "cursor" not in captured["data"] + assert captured["data"]["limit"] == 10 diff --git a/tests/test_ops.py b/tests/test_ops.py index 9bc7cda..0c9970c 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -617,3 +617,53 @@ def test_debug_config_forbidden_raises(self, client, mock_responses): ) with pytest.raises(AuthorizationError): client.debug_config() + + +class TestAsyncDebugConfig: + """AsyncDakeraClient.debug_config() parity tests (DAK-7477).""" + + async def test_async_debug_config_returns_env_map(self): + """Async variant GETs /debug/config and returns the env-var dict.""" + from unittest.mock import patch + + from dakera import AsyncDakeraClient + + client = AsyncDakeraClient("http://localhost:3000") + captured: dict = {} + fake_response = { + "DAKERA_ENABLE_BM25": "true", + "DAKERA_RERANKER_ENABLED": "true", + "_version": "0.11.102", + "_build_sha": "abc1234", + } + + async def fake_request(method, path, **kwargs): + captured["method"] = method + captured["path"] = path + return fake_response + + with patch.object(client, "_request", side_effect=fake_request): + result = await client.debug_config() + + assert captured["method"] == "GET" + assert captured["path"] == "/debug/config" + assert result["_version"] == "0.11.102" + assert "DAKERA_ENABLE_BM25" in result + + async def test_async_debug_config_forbidden_raises(self): + """Async variant surfaces AuthorizationError on 403 (no Admin scope).""" + from unittest.mock import patch + + from dakera import AsyncDakeraClient + from dakera.exceptions import AuthorizationError + + client = AsyncDakeraClient("http://localhost:3000") + + async def fake_request(method, path, **kwargs): + raise AuthorizationError("Forbidden: Admin scope required", status_code=403) + + with ( + patch.object(client, "_request", side_effect=fake_request), + pytest.raises(AuthorizationError), + ): + await client.debug_config()