Files
library-desk/tests/test_wikijs_pagination.py
T
jpmschweitzerandClaude Fable 5 a66d801abd test: add offline unit tests for Phase A reliability fixes
Mock-based tests (no live services) covering:
- ollama_llm_model resolution under the OLLAMA_MODEL env collision
- per-leg retrieval failure -> source_status/degraded signaling
- Phase 0/Phase 4 LLM timeout fallbacks
- /stats wiki page count using the users/{user} path prefix
- Wiki.js list_all_pages limit-growth pagination and
  list_pages limit-after-filter behavior

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 10:05:51 +02:00

104 lines
3.5 KiB
Python

"""
Unit tests for WikiJSClient page listing and pagination (offline).
Wiki.js 2.x `pages.list` supports only a `limit` argument (no offset), so
exhaustive listing works by growing the limit until the API returns fewer
pages than requested. These tests mock the GraphQL layer.
"""
import pytest
from src.clients.wikijs_client import WikiJSClient
def make_pages(count_other: int, count_user: int):
"""Build a fake TITLE-ordered page listing: 'other/' pages sort before 'users/jp/' pages."""
pages = [
{"id": i, "path": f"other/p{i:03d}", "title": f"A{i:03d}", "tags": []}
for i in range(count_other)
]
pages += [
{"id": count_other + i, "path": f"users/jp/p{i:03d}", "title": f"Z{i:03d}", "tags": ["projects"]}
for i in range(count_user)
]
return pages
@pytest.fixture
def client():
"""WikiJSClient with a mocked GraphQL layer serving 138 pages (100 other + 38 user)."""
client = WikiJSClient("http://wiki.test", "")
client._all_pages = make_pages(100, 38)
client._requested_limits = []
async def fake_execute(query, variables=None):
limit = variables["limit"]
client._requested_limits.append(limit)
return {"pages": {"list": client._all_pages[:limit]}}
client._execute_query = fake_execute
return client
@pytest.mark.unit
class TestListAllPagesPagination:
"""list_all_pages must exhaust the listing via a limit-growth loop."""
async def test_grows_limit_until_exhausted(self, client):
pages = await client.list_all_pages(batch_size=50)
# 50 -> full batch, 100 -> full batch, 200 -> 138 < 200 done
assert client._requested_limits == [50, 100, 200]
assert len(pages) == 138
async def test_single_call_when_first_batch_not_full(self, client):
pages = await client.list_all_pages(batch_size=500)
assert client._requested_limits == [500]
assert len(pages) == 138
async def test_path_prefix_filter_after_exhaustion(self, client):
"""All 38 user pages are returned even though they sort last (beyond batch_size)."""
pages = await client.list_all_pages(path_prefix="users/jp", batch_size=50)
assert len(pages) == 38
assert all(p["path"].startswith("users/jp") for p in pages)
async def test_empty_wiki(self, client):
client._all_pages = []
pages = await client.list_all_pages(batch_size=100)
assert pages == []
@pytest.mark.unit
class TestListPagesLimitAfterFilter:
"""list_pages must apply `limit` AFTER client-side filters, not before."""
async def test_prefix_filter_with_small_limit(self, client):
"""Old defect: API limit=5 returned 5 'other/' pages, filter dropped all -> 0 results."""
pages = await client.list_pages(path_prefix="users/jp", limit=5)
assert len(pages) == 5
assert all(p["path"].startswith("users/jp") for p in pages)
async def test_tag_filter_with_small_limit(self, client):
pages = await client.list_pages(tags=["projects"], limit=10)
assert len(pages) == 10
assert all("projects" in p["tags"] for p in pages)
async def test_unfiltered_passes_limit_to_api(self, client):
pages = await client.list_pages(limit=7)
assert client._requested_limits == [7]
assert len(pages) == 7
async def test_tags_normalized_to_list(self, client):
client._all_pages = [{"id": 1, "path": "home", "title": "Home", "tags": None}]
pages = await client.list_pages(limit=10)
assert pages[0]["tags"] == []