hugin/server/tests/test_docs.py
2026-10-27 08:33:21 +01:00

82 lines
3.1 KiB
Python

"""Online-Hilfe (→ KONZEPT.md 13): alle Themen, Links, Suche, Linter-Regeln."""
import re
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from hugin_app import docs
from hugin_core.linter.rules import RULES
from test_app import env # noqa: F401 (Fixture)
from test_web import browser, csp_clean
@pytest.mark.parametrize("topic", [t.slug for t in docs.TOPICS])
def test_each_topic_without_and_with_login(env, topic):
for c in (TestClient(env.client.app), browser(env, "shop-lesen")):
response = c.get(f"/help/{topic}")
assert response.status_code == 200
assert "[[" not in response.text, "Platzhalter nicht ersetzt"
assert csp_clean(response.text) == []
assert docs.BY_SLUG[topic].title in response.text
def test_all_help_links_resolve(env):
c = browser(env, "pub-autor")
seen = set()
for t in docs.TOPICS:
page = c.get(f"/help/{t.slug}").text
article = page[page.index('<article'):page.index('</article>')]
for href in re.findall(r'href="([^"]+)"', article):
if href.startswith("http") or href in seen:
continue
seen.add(href)
response = c.get(href, follow_redirects=True)
assert response.status_code in (200, 403), f"{t.slug}: Link {href} → {response.status_code}"
assert "/help/teams" in seen and "/catalog" in seen
def test_each_linter_rule_is_described():
sources = (Path(__file__).parents[1] / "src").rglob("*.py")
in_code = {k for p in sources for k in re.findall(r'(?:_error|_hint|Finding)\("(H\d{3})"', p.read_text())}
described = {k for k, _, _ in RULES}
assert in_code == described, f"fehlt in REGELN: {in_code - described}, überzählig: {described - in_code}"
def test_rules_table_in_help(env):
page = TestClient(env.client.app).get("/help/linter").text
for code, _, _ in RULES:
assert f"<code>{code}</code>" in page
def test_search(env):
c = TestClient(env.client.app)
page = c.get("/help?q=probe").text
assert "Programm hugin" in page and "Pakete schreiben" in page
assert "Nichts gefunden" in c.get("/help?q=quantenkuchen").text
def test_server_address_inserted(env):
assert "hugin init --server http://testserver" in TestClient(env.client.app).get("/help/teams").text
def test_html_in_text_not_executed(monkeypatch):
monkeypatch.setattr(docs, "source_text", lambda slug: "# T\n\n<script>alert(1)</script> [x](javascript:alert(1))")
output = docs.html("start", "http://x", lambda h: h)
assert "<script>" not in output and "&lt;script&gt;" in output and 'href="javascript:' not in output
def test_each_role_explained(env):
from hugin_app.auth import ROLES
text = env.client.get("/help/roles").text
for role in ROLES:
assert f"<code>{role}</code>" in text, role
def test_each_kind_explained(env):
"""Jede Art aus dem Manifest hat einen Abschnitt in der Hilfe „Arten von Paketen“."""
from hugin_core.package import Kind
text = docs.source_text("kinds")
for kind in Kind:
assert f"(`{kind.value}`)" in text, f"Art {kind.value} fehlt in kinds.md"