fieldwitness/tests/e2e/test_keys.py
Aaron D. Lee 16318daea3
Some checks failed
CI / lint (push) Failing after 12s
CI / typecheck (push) Failing after 12s
Add comprehensive test suite: integration tests + Playwright e2e
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>
2026-04-02 20:22:12 -04:00

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}"
)