Integration tests (350 passing): - test_evidence_summary.py: HTML/PDF generation, XSS safety, anchor rendering - test_tor.py: Tor module unit tests (mocked, no Tor needed) - test_c2pa_importer.py: Import result dataclass, trust evaluation, graceful degradation - test_file_attestation.py: All file types (PNG, PDF, CSV, empty, large), determinism - test_paths.py: Registry correctness, env var override, all paths under BASE_DIR - test_killswitch_coverage.py: Tor keys, trusted keys, carrier history destruction Playwright e2e infrastructure: - tests/e2e/ with conftest (live server, auth fixtures), helpers (test file generators) - test_auth.py: Setup flow, login/logout, protected routes - test_attest.py: Image/PDF/CSV attestation, verify, attestation log - test_dropbox.py: Token creation, source upload, branding check - test_keys.py: Identity display, trust store - test_fieldkit.py: Status dashboard, killswitch page - test_navigation.py: All nav links, responsive layout Run: pytest (unit/integration) or pytest -m e2e tests/e2e/ (browser) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
113 lines
4.0 KiB
Python
113 lines
4.0 KiB
Python
"""
|
|
e2e tests for the key management pages (/keys/*).
|
|
|
|
These tests verify that:
|
|
- The key management dashboard loads and displays identity/channel key state.
|
|
- Generating a channel key succeeds (idempotent — second call is a no-op or success).
|
|
- Generating an identity key succeeds.
|
|
|
|
We do NOT test key export (download) in the browser because Playwright's
|
|
download handling requires additional setup and the export route is tested
|
|
by the unit tests. The export button presence is verified instead.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from playwright.sync_api import Page, expect
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_keys_page_loads(live_server: str, authenticated_page: Page) -> None:
|
|
"""The /keys/ dashboard loads and shows both key sections."""
|
|
page = authenticated_page
|
|
page.goto(f"{live_server}/keys/")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
# Two key sections must be present
|
|
expect(page.locator("body")).to_contain_text("Channel Key")
|
|
expect(page.locator("body")).to_contain_text("Identity")
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_generate_identity_key(live_server: str, authenticated_page: Page) -> None:
|
|
"""If no identity key exists, generating one succeeds and shows a fingerprint."""
|
|
page = authenticated_page
|
|
page.goto(f"{live_server}/keys/")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
gen_button = page.locator("form[action*='generate_identity'] button")
|
|
|
|
if gen_button.count() > 0:
|
|
# No identity — generate one
|
|
gen_button.click()
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
# Success flash or fingerprint visible
|
|
body = page.locator("body").inner_text()
|
|
assert any(word in body.lower() for word in ("generated", "fingerprint", "identity")), (
|
|
f"Expected identity generation confirmation, got: {body[:300]}"
|
|
)
|
|
else:
|
|
# Identity already exists — fingerprint should be displayed
|
|
expect(page.locator("body")).to_contain_text("Fingerprint")
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_generate_channel_key(live_server: str, authenticated_page: Page) -> None:
|
|
"""If no channel key exists, generating one succeeds."""
|
|
page = authenticated_page
|
|
page.goto(f"{live_server}/keys/")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
gen_button = page.locator("form[action*='generate_channel'] button")
|
|
|
|
if gen_button.count() > 0:
|
|
gen_button.click()
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
body = page.locator("body").inner_text()
|
|
assert any(word in body.lower() for word in ("generated", "fingerprint", "channel")), (
|
|
f"Expected channel key generation confirmation, got: {body[:300]}"
|
|
)
|
|
else:
|
|
# Channel key already configured
|
|
expect(page.locator("body")).to_contain_text("Fingerprint")
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_keys_page_shows_fingerprints_after_generation(
|
|
live_server: str, authenticated_page: Page
|
|
) -> None:
|
|
"""After generating both keys the dashboard shows non-empty fingerprints."""
|
|
page = authenticated_page
|
|
|
|
# Ensure both keys exist
|
|
page.goto(f"{live_server}/keys/")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
for action in ("generate_identity", "generate_channel"):
|
|
btn = page.locator(f"form[action*='{action}'] button")
|
|
if btn.count() > 0:
|
|
btn.click()
|
|
page.wait_for_load_state("networkidle")
|
|
page.goto(f"{live_server}/keys/")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
# Both fingerprints should now be visible
|
|
fingerprints = page.locator("code")
|
|
assert fingerprints.count() >= 2, (
|
|
f"Expected at least 2 fingerprint <code> elements, got {fingerprints.count()}"
|
|
)
|
|
|
|
|
|
@pytest.mark.e2e
|
|
def test_keys_page_requires_auth(live_server: str, page: Page) -> None:
|
|
"""Unauthenticated access to /keys/ redirects to /login."""
|
|
page.goto(f"{live_server}/keys/")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
assert "/login" in page.url or "/setup" in page.url, (
|
|
f"Expected auth redirect, got {page.url}"
|
|
)
|