Files
ss-tools/agent/tests/test_agent/test_persistence_prefetch.py
busya e291ba757f fix(agent): full-catalog dashboard search and working LLM retry
- search_dashboards: call /api/dashboards with page_context=other and
  page_size=100 so the profile 'My Dashboards Only' filter can no longer
  hide the whole catalog; parse available_total/effective_profile_filter
  and report hidden-by-filter instead of a false 'no dashboards' answer
- prefetch_dashboards: same full-catalog context; fix dead code where
  data=resp.json() sat after return '' inside the error branch, making
  every 200 response raise NameError and the prefetch always return ''
- llm-status: ?force=1 bypasses the 30s health cache so the 'Retry now'
  button performs a fresh probe instead of re-reading the stale status;
  frontend keeps a single retry interval (previously stacked intervals
  decayed the countdown faster than 1/s and fired duplicate probes)
- tests: agent tool/prefetch, backend route bypass + force param,
  frontend retry/force coverage
2026-08-19 19:21:00 +03:00

100 lines
3.8 KiB
Python

# #region Test.Agent.Persistence.PrefetchDashboards [C:3] [TYPE Module] [SEMANTICS test,agent,persistence,prefetch,dashboards]
# @BRIEF Tests for prefetch_dashboards — full-catalog context injection for the LLM.
# @RELATION BINDS_TO -> [AgentChat.Persistence]
# @TEST_EDGE: http_error -> non-200 returns empty string
# @TEST_EDGE: empty_catalog -> "No dashboards found." text
# @TEST_EDGE: full_catalog -> lists dashboards and requests page_context=other (profile filter bypass)
import os
from pathlib import Path
import sys
from unittest.mock import AsyncMock, MagicMock, patch
sys.path.append(str(Path(__file__).resolve().parent.parent.parent / "src"))
import httpx
import pytest
os.environ.setdefault("FASTAPI_URL", "http://test-backend:8000")
os.environ.setdefault("SERVICE_JWT", "test-service-jwt")
os.environ.setdefault("AUTH_SECRET_KEY", "test-secret-key-for-jwt-testing")
def _mock_response(status_code=200, json_data=None):
resp = MagicMock(spec=httpx.Response)
resp.status_code = status_code
resp.json.return_value = json_data or {}
return resp
@pytest.mark.anyio
async def test_prefetch_dashboards_uses_full_catalog_context():
"""prefetch_dashboards must request page_context=other + page_size=100 so the
"My Dashboards Only" profile filter cannot hide the whole catalog."""
from ss_tools.agent.context import set_service_jwt, set_user_jwt
from ss_tools.agent._persistence import prefetch_dashboards
set_user_jwt("jwt")
set_service_jwt("svc-jwt")
payload = {
"dashboards": [
{"id": i, "title": f"Dash {i}", "slug": f"dash-{i}", "last_modified": "2026-01-01T00:00:00"}
for i in range(1, 12)
],
"total": 11,
"available_total": 11,
"effective_profile_filter": {"applied": False, "username": None},
}
mock_resp = _mock_response(200, payload)
mock_client = AsyncMock(spec=httpx.AsyncClient)
mock_client.get = AsyncMock(return_value=mock_resp)
with patch("ss_tools.agent._persistence.get_shared_http_client", return_value=mock_client):
result = await prefetch_dashboards("ss-dev")
call_kwargs = mock_client.get.call_args
assert call_kwargs is not None
_, kwargs = call_kwargs
params = kwargs.get("params", {})
assert params.get("page_context") == "other"
assert params.get("page_size") == 100
# The previous dead-code bug made every 200 response raise NameError and return "".
assert result != ""
assert "11 total" in result
assert "Dash 1" in result
assert "Dash 11" in result
@pytest.mark.anyio
async def test_prefetch_dashboards_http_error_returns_empty():
"""Non-200 response must degrade to an empty string, not raise."""
from ss_tools.agent._persistence import prefetch_dashboards
mock_client = AsyncMock(spec=httpx.AsyncClient)
mock_client.get = AsyncMock(return_value=_mock_response(500, {}))
with patch("ss_tools.agent._persistence.get_shared_http_client", return_value=mock_client):
result = await prefetch_dashboards("ss-dev")
assert result == ""
@pytest.mark.anyio
async def test_prefetch_dashboards_empty_catalog():
"""A genuinely empty catalog returns the explicit no-dashboards marker."""
from ss_tools.agent._persistence import prefetch_dashboards
payload = {
"dashboards": [],
"total": 0,
"available_total": 0,
"effective_profile_filter": {"applied": False, "username": None},
}
mock_client = AsyncMock(spec=httpx.AsyncClient)
mock_client.get = AsyncMock(return_value=_mock_response(200, payload))
with patch("ss_tools.agent._persistence.get_shared_http_client", return_value=mock_client):
result = await prefetch_dashboards("ss-dev")
assert result == "No dashboards found."
# #endregion Test.Agent.Persistence.PrefetchDashboards