- Wrap RateLimitMiddleware in Middleware() - bare class broke all requests (500) - Clamp/validate num param - ?num=abc no longer returns 500 - Query length cap (500), result counts clamped to 1..20 - Wire lifespan into Starlette so shared httpx client closes on shutdown - Purge stale per-IP rate limit entries to bound memory growth - URL-encode queries in the Playwright scraper path - Lazy lib imports so the package works without optional playwright - Add pyproject.toml (activates ruff/pytest/bandit in CI), README, LICENSE - Remove committed __pycache__, add .gitignore/.dockerignore - Fix SearXNG healthcheck path (/health -> /healthz) and compose docs
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
|
|
|
|
class TestSearchResultFormatting:
|
|
"""Test SearXNG result formatting."""
|
|
|
|
def test_format_single_result(self):
|
|
results = [
|
|
{
|
|
"title": "Python.org",
|
|
"url": "https://www.python.org/",
|
|
"content": "Python is a programming language",
|
|
}
|
|
]
|
|
lines = []
|
|
for i, r in enumerate(results, 1):
|
|
lines.append(f"{i}. {r.get('title', 'N/A')}")
|
|
lines.append(f" URL: {r.get('url', 'N/A')}")
|
|
snippet = r.get("content", "")[:200]
|
|
if snippet:
|
|
lines.append(f" {snippet}")
|
|
|
|
assert len(lines) == 3
|
|
assert "1. Python.org" in lines[0]
|
|
assert "https://www.python.org/" in lines[1]
|
|
assert "Python is a programming language" in lines[2]
|
|
|
|
def test_format_multiple_results(self):
|
|
results = [
|
|
{"title": f"Result {i}", "url": f"https://example.com/{i}", "content": f"Content {i}"}
|
|
for i in range(5)
|
|
]
|
|
lines = []
|
|
for i, r in enumerate(results, 1):
|
|
lines.append(f"{i}. {r.get('title', 'N/A')}")
|
|
lines.append(f" URL: {r.get('url', 'N/A')}")
|
|
snippet = r.get("content", "")[:200]
|
|
if snippet:
|
|
lines.append(f" {snippet}")
|
|
|
|
assert len(lines) == 15
|
|
|
|
def test_format_missing_fields(self):
|
|
results = [{"title": "No URL", "content": "Some content"}]
|
|
lines = []
|
|
for i, r in enumerate(results, 1):
|
|
lines.append(f"{i}. {r.get('title', 'N/A')}")
|
|
lines.append(f" URL: {r.get('url', 'N/A')}")
|
|
snippet = r.get("content", "")[:200]
|
|
if snippet:
|
|
lines.append(f" {snippet}")
|
|
|
|
assert "URL: N/A" in lines[1]
|
|
|
|
def test_format_empty_results(self):
|
|
results = []
|
|
lines = []
|
|
for i, r in enumerate(results, 1):
|
|
lines.append(f"{i}. {r.get('title', 'N/A')}")
|
|
assert lines == []
|
|
|
|
def test_snippet_truncation(self):
|
|
long_content = "x" * 500
|
|
results = [{"title": "Long", "url": "https://example.com", "content": long_content}]
|
|
lines = []
|
|
for i, r in enumerate(results, 1):
|
|
lines.append(f"{i}. {r.get('title', 'N/A')}")
|
|
lines.append(f" URL: {r.get('url', 'N/A')}")
|
|
snippet = r.get("content", "")[:200]
|
|
if snippet:
|
|
lines.append(f" {snippet}")
|
|
|
|
assert len(lines[2]) <= 203
|