""" e2e tests for general navigation and page health. These tests verify that: - The homepage loads after authentication. - All primary navigation links resolve without 5xx errors. - The layout is accessible at a mobile viewport width. """ from __future__ import annotations import pytest from playwright.sync_api import Page, expect PRIMARY_NAV_HREFS = [ "/", "/encode", "/decode", "/generate", "/attest", "/verify", "/keys/", "/fieldkit/", "/dropbox/admin", "/federation/", ] @pytest.mark.e2e def test_homepage_loads(live_server: str, authenticated_page: Page) -> None: """The index page loads after login.""" page = authenticated_page page.goto(f"{live_server}/") page.wait_for_load_state("networkidle") # At least one of the feature card links is visible expect(page.locator("a[href='/encode']")).to_be_visible() @pytest.mark.e2e def test_all_nav_links_no_server_error(live_server: str, authenticated_page: Page) -> None: """Every primary navigation link returns a non-5xx response.""" page = authenticated_page errors: list[str] = [] for href in PRIMARY_NAV_HREFS: url = f"{live_server}{href}" response = page.goto(url) page.wait_for_load_state("networkidle") status = response.status if response else None if status is not None and status >= 500: errors.append(f"{href} → HTTP {status}") assert not errors, "Navigation links returned server errors:\n" + "\n".join(errors) @pytest.mark.e2e def test_health_endpoint_authenticated(live_server: str, authenticated_page: Page) -> None: """The /health endpoint returns JSON with status when authenticated.""" page = authenticated_page result = page.evaluate( """async (baseUrl) => { const resp = await fetch(baseUrl + '/health'); return {status: resp.status, body: await resp.json()}; }""", live_server, ) assert result["status"] == 200, f"Health check failed: {result['status']}" assert "status" in result["body"] @pytest.mark.e2e def test_health_endpoint_unauthenticated(live_server: str, page: Page, admin_user: None) -> None: """The /health endpoint returns minimal JSON for anonymous callers.""" # Navigate to the server first so fetch() has a proper origin page.goto(f"{live_server}/login") page.wait_for_load_state("networkidle") result = page.evaluate( """async () => { const resp = await fetch('/health'); return {status: resp.status, body: await resp.json()}; }""" ) assert result["status"] == 200 assert "status" in result["body"] @pytest.mark.e2e def test_responsive_layout_mobile(live_server: str, authenticated_page: Page) -> None: """The index page renders without horizontal overflow at 375px viewport.""" page = authenticated_page page.set_viewport_size({"width": 375, "height": 812}) page.goto(f"{live_server}/") page.wait_for_load_state("networkidle") overflow = page.evaluate("""() => { return document.documentElement.scrollWidth > document.documentElement.clientWidth; }""") assert not overflow, "Page has horizontal overflow at 375px — layout breaks on mobile" @pytest.mark.e2e def test_page_titles_are_set(live_server: str, authenticated_page: Page) -> None: """Key pages have non-empty title elements.""" page = authenticated_page # Just verify titles are not empty/default — don't assert specific text # since templates may use varying title patterns for href in ["/", "/attest", "/verify", "/keys/"]: page.goto(f"{live_server}{href}") page.wait_for_load_state("networkidle") title = page.title() assert len(title.strip()) > 0, f"Page {href} has empty title" @pytest.mark.e2e def test_logout_link_present_when_authenticated( live_server: str, authenticated_page: Page ) -> None: """The navigation shows a logout affordance when logged in.""" page = authenticated_page page.goto(f"{live_server}/") page.wait_for_load_state("networkidle") # Logout is a POST form inside a Bootstrap dropdown — check page source content = page.content() assert "/logout" in content, "No logout action found in page HTML when authenticated"