Merge pull request #555 from christianlouis/copilot/restructure-help-page

feat(help): replace MkDocs redirect with user-facing Help Center + Zammad integration
This commit is contained in:
Christian Krakau-Louis
2026-03-08 18:58:02 +01:00
committed by GitHub
10 changed files with 789 additions and 50 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ class TestHealthEndpoints:
def test_docs_endpoint(self, client: TestClient):
"""Test that API documentation is accessible."""
response = client.get("/docs")
response = client.get("/admin/api-docs")
assert response.status_code == 200
assert "swagger" in response.text.lower() or "openapi" in response.text.lower()
+116 -29
View File
@@ -1,33 +1,50 @@
"""Tests for app/views/help.py module."""
"""Tests for app/views/help.py module user-facing Help Center."""
import pytest
@pytest.mark.integration
class TestHelpViews:
"""Tests for the help documentation view routes."""
"""Tests for the Help Center view routes."""
def test_help_redirect(self, client):
"""GET /help should redirect permanently to /help/."""
response = client.get("/help", follow_redirects=False)
assert response.status_code == 301
assert response.headers["location"] in ("/help/", "http://testserver/help/")
def test_help_returns_200(self, client):
"""GET /help should return the Help Center page."""
response = client.get("/help")
assert response.status_code == 200
def test_help_redirect_follows(self, client):
"""Following /help redirect leads to /help/ (docs served or 404 if not built)."""
# In test environments docs_build/ is not present, so /help/ may 404.
# We only verify the initial redirect works; the final landing page depends
# on whether the docs have been built (they are built only in Docker images).
response = client.get("/help", follow_redirects=False)
assert response.status_code == 301
# Redirect target must be /help/
location = response.headers.get("location", "")
assert location.endswith("/help/")
def test_help_contains_help_center_title(self, client):
"""The page should contain the Help Center heading."""
response = client.get("/help")
assert b"Help Center" in response.content
def test_help_contains_quick_start_section(self, client):
"""The page should contain the Quick Start section."""
response = client.get("/help")
assert b"Quick Start" in response.content
def test_help_contains_sources_section(self, client):
"""The page should contain the Sources section."""
response = client.get("/help")
assert b"Sources" in response.content
def test_help_contains_destinations_section(self, client):
"""The page should contain the Destinations section."""
response = client.get("/help")
assert b"Destinations" in response.content
def test_help_contains_faq_section(self, client):
"""The page should contain the FAQ section."""
response = client.get("/help")
assert b"Frequently Asked Questions" in response.content
def test_help_contains_support_section(self, client):
"""The page should contain the Contact Support section."""
response = client.get("/help")
assert b"Contact Support" in response.content
def test_help_route_is_registered(self, client):
"""Verify the /help route exists in the app router."""
# A GET to /help must not return 405 Method Not Allowed
response = client.get("/help", follow_redirects=False)
response = client.get("/help")
assert response.status_code != 405
@@ -35,31 +52,52 @@ class TestHelpViews:
class TestHelpViewUnit:
"""Unit tests for the help view module."""
def test_help_redirect_returns_301(self):
"""Verify the redirect is HTTP 301 (permanent)."""
def test_help_returns_200(self):
"""Verify the help center returns HTTP 200."""
from fastapi import FastAPI
from fastapi.testclient import TestClient
from starlette.middleware.sessions import SessionMiddleware
from app.views.help import router
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="test-secret")
app.include_router(router)
with TestClient(app) as tc:
resp = tc.get("/help", follow_redirects=False)
assert resp.status_code == 301
resp = tc.get("/help")
assert resp.status_code == 200
def test_help_redirect_target(self):
"""Verify the redirect points to /help/."""
def test_help_page_has_seo_meta(self):
"""Verify SEO meta tags are present in the response."""
from fastapi import FastAPI
from fastapi.testclient import TestClient
from starlette.middleware.sessions import SessionMiddleware
from app.views.help import router
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="test-secret")
app.include_router(router)
with TestClient(app) as tc:
resp = tc.get("/help", follow_redirects=False)
assert resp.headers["location"].rstrip("/").endswith("help") or resp.headers["location"].endswith("/help/")
resp = tc.get("/help")
assert b'name="description"' in resp.content
assert b'name="robots"' in resp.content
def test_help_page_has_structured_data(self):
"""Verify JSON-LD structured data is present."""
from fastapi import FastAPI
from fastapi.testclient import TestClient
from starlette.middleware.sessions import SessionMiddleware
from app.views.help import router
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="test-secret")
app.include_router(router)
with TestClient(app) as tc:
resp = tc.get("/help")
assert b"application/ld+json" in resp.content
assert b"FAQPage" in resp.content
def test_docs_build_path_constant(self):
"""Verify _DOCS_BUILD_DIR is resolved relative to the app package."""
@@ -71,6 +109,38 @@ class TestHelpViewUnit:
# Should point to <repo_root>/docs_build
assert _DOCS_BUILD_DIR.name == "docs_build"
def test_zammad_chat_hidden_when_disabled(self):
"""Chat widget markup should not appear when Zammad chat is disabled."""
from fastapi import FastAPI
from fastapi.testclient import TestClient
from starlette.middleware.sessions import SessionMiddleware
from app.views.help import router
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="test-secret")
app.include_router(router)
with TestClient(app) as tc:
resp = tc.get("/help")
# Default settings: zammad_chat_enabled=False → no chat script
assert b"ZammadChat" not in resp.content
def test_zammad_form_hidden_when_disabled(self):
"""Ticket form markup should not appear when Zammad form is disabled."""
from fastapi import FastAPI
from fastapi.testclient import TestClient
from starlette.middleware.sessions import SessionMiddleware
from app.views.help import router
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="test-secret")
app.include_router(router)
with TestClient(app) as tc:
resp = tc.get("/help")
# Default settings: zammad_form_enabled=False → no form script
assert b"ZammadForm" not in resp.content
@pytest.mark.integration
class TestHelpNavigationLink:
@@ -81,12 +151,29 @@ class TestHelpNavigationLink:
response = client.get("/about")
assert response.status_code == 200
# The Help link should be present somewhere in the rendered page
assert b"/help/" in response.content
assert b"/help" in response.content
def test_help_link_has_accessible_text(self, client):
"""The Help link should have visible text for accessibility."""
response = client.get("/about")
assert response.status_code == 200
content = response.text
# Should include the word "Help" associated with /help/
# Should include the word "Help" associated with /help
assert "Help" in content
@pytest.mark.integration
class TestAdminDocsLinks:
"""Tests that admin doc links are in the admin menu markup."""
def test_api_docs_link_in_admin_menu(self, client):
"""The admin menu HTML should contain the API Docs link."""
response = client.get("/about")
assert response.status_code == 200
assert b"/admin/api-docs" in response.content
def test_developer_docs_link_in_admin_menu(self, client):
"""The admin menu HTML should contain the Developer Docs link."""
response = client.get("/about")
assert response.status_code == 200
assert b"/developer-docs/" in response.content