Search the indexed library. Results are ranked by
+ embedding distance; filter by collection, chunk kind, docket or year, and
+ follow “similar” to find neighbours of a cited item.
+
+
+
+
+
diff --git a/tests/llm/test_api.py b/tests/llm/test_api.py
index 26c0aba..1b220c7 100644
--- a/tests/llm/test_api.py
+++ b/tests/llm/test_api.py
@@ -1,10 +1,11 @@
"""llm.api — FastAPI chat app."""
+import re
from unittest.mock import patch
from fastapi.testclient import TestClient
-from llm.api import app
+from llm.api import _COLLECTION_CHOICES, _KIND_CHOICES, app
client = TestClient(app)
@@ -74,6 +75,76 @@ class TestIndex:
assert "innerHTML = ''" in html and "innerHTML = text" not in html
+class TestSearchPage:
+ """``GET /ui/search`` — the framework-free search UI (refs #578)."""
+
+ def test_serves_search_page(self):
+ r = client.get("/ui/search")
+ assert r.status_code == 200
+ assert "text/html" in r.headers["content-type"]
+ html = r.text
+ assert "Library Search" in html
+ # the form: query box + every filter the API accepts
+ assert 'id="search"' in html
+ assert 'id="q"' in html
+ for field in ("collection", "kind", "docket", "year"):
+ assert 'id="%s"' % field in html
+ for value in sorted(_COLLECTION_CHOICES):
+ assert 'value="%s"' % value in html
+ for value in sorted(_KIND_CHOICES):
+ assert 'value="%s"' % value in html
+ # llm: tags aren't indexed yet — a placeholder, not a dead filter
+ assert "#575" in html and 'id="tag"' not in html
+
+ def test_trailing_slash_also_serves_the_page(self):
+ """The headless probe's readiness check appends "/"; a 307 there
+ would read as "service not responding"."""
+ r = client.get("/ui/search/")
+ assert r.status_code == 200
+ assert "Library Search" in r.text
+
+ def test_renders_results_similar_and_pagination(self):
+ html = client.get("/ui/search").text
+ # results: label link, snippet, docket/comment id, similar
+ assert "function hitEl(r)" in html
+ assert "r.snippet" in html and "r.docket" in html and "r.comment_id" in html
+ assert "if (r.url)" in html # no empty href for an unlinked label
+ # /similar is keyed by the bib item key the result carries
+ assert "function showSimilar" in html
+ assert "r.item_key" in html
+ assert "'/similar/' + encodeURIComponent(key)" in html
+ # pagination + shareable URL
+ assert 'id="prev"' in html and 'id="next"' in html
+ assert "offset += LIMIT" in html
+ assert "window.history.pushState" in html
+ assert "new URLSearchParams(window.location.search)" in html
+ # loading + error states, with the API's own 400 detail
+ assert "'Searching…'" in html
+ assert "body.detail" in html
+ assert "setStatus('Error: ' + e.message, true)" in html
+
+ def test_no_external_script_or_style_urls(self):
+ """Framework-free and CDN-free: behind oauth2-proxy the page has
+ no outbound access, so every byte of CSS/JS is inline."""
+ html = client.get("/ui/search").text
+ assert re.search(r"