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>
108 lines
3.3 KiB
Python
108 lines
3.3 KiB
Python
"""
|
|
Test helpers for e2e tests — generate in-memory test files.
|
|
|
|
All helpers return raw bytes suitable for use with page.set_input_files().
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import io
|
|
import struct
|
|
import zlib
|
|
|
|
|
|
def create_test_image(width: int = 64, height: int = 64) -> bytes:
|
|
"""Generate a minimal valid PNG image in memory.
|
|
|
|
Returns raw PNG bytes. Does not require Pillow — builds a PNG manually
|
|
using only the stdlib so that helpers.py has zero external dependencies.
|
|
"""
|
|
# PNG signature
|
|
png_sig = b"\x89PNG\r\n\x1a\n"
|
|
|
|
def make_chunk(chunk_type: bytes, data: bytes) -> bytes:
|
|
length = struct.pack(">I", len(data))
|
|
crc = struct.pack(">I", zlib.crc32(chunk_type + data) & 0xFFFFFFFF)
|
|
return length + chunk_type + data + crc
|
|
|
|
# IHDR: width, height, bit depth=8, color type=2 (RGB), compression=0,
|
|
# filter=0, interlace=0
|
|
ihdr_data = struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0)
|
|
ihdr = make_chunk(b"IHDR", ihdr_data)
|
|
|
|
# IDAT: raw scanlines (filter byte 0 per row, then RGB pixels)
|
|
raw_rows = []
|
|
for y in range(height):
|
|
row = b"\x00" # filter type None
|
|
for x in range(width):
|
|
# Vary pixel color so the image is non-trivial
|
|
r = (x * 4) & 0xFF
|
|
g = (y * 4) & 0xFF
|
|
b = ((x + y) * 2) & 0xFF
|
|
row += bytes([r, g, b])
|
|
raw_rows.append(row)
|
|
|
|
compressed = zlib.compress(b"".join(raw_rows))
|
|
idat = make_chunk(b"IDAT", compressed)
|
|
|
|
iend = make_chunk(b"IEND", b"")
|
|
|
|
return png_sig + ihdr + idat + iend
|
|
|
|
|
|
def create_test_pdf() -> bytes:
|
|
"""Generate a minimal valid single-page PDF in memory.
|
|
|
|
The PDF is structurally valid (Acrobat/browsers will accept it) but
|
|
contains only a blank page with a text label.
|
|
"""
|
|
body = b"""%PDF-1.4
|
|
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
|
|
2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
|
|
3 0 obj<</Type/Page/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 4 0 R>>>>>>endobj
|
|
4 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj
|
|
5 0 obj<</Length 44>>
|
|
stream
|
|
BT /F1 12 Tf 100 700 Td (FieldWitness test PDF) Tj ET
|
|
endstream
|
|
endobj
|
|
"""
|
|
xref_offset = len(body)
|
|
body += (
|
|
b"xref\n"
|
|
b"0 6\n"
|
|
b"0000000000 65535 f \n"
|
|
b"0000000009 00000 n \n"
|
|
b"0000000058 00000 n \n"
|
|
b"0000000115 00000 n \n"
|
|
b"0000000266 00000 n \n"
|
|
b"0000000346 00000 n \n"
|
|
b"trailer<</Size 6/Root 1 0 R>>\n"
|
|
b"startxref\n"
|
|
)
|
|
body += str(xref_offset).encode() + b"\n%%EOF\n"
|
|
return body
|
|
|
|
|
|
def create_test_csv() -> bytes:
|
|
"""Generate a simple CSV file in memory."""
|
|
lines = [
|
|
"timestamp,sensor_id,value,unit",
|
|
"2024-01-15T10:00:00Z,TEMP-001,23.5,celsius",
|
|
"2024-01-15T10:01:00Z,TEMP-001,23.7,celsius",
|
|
"2024-01-15T10:02:00Z,TEMP-001,23.6,celsius",
|
|
"2024-01-15T10:03:00Z,HUMID-001,65.2,percent",
|
|
]
|
|
return "\n".join(lines).encode("utf-8")
|
|
|
|
|
|
def create_test_txt() -> bytes:
|
|
"""Generate a plain-text file in memory."""
|
|
content = (
|
|
"FieldWitness e2e test document\n"
|
|
"===============================\n\n"
|
|
"This file was generated by the automated test suite.\n"
|
|
"It contains no sensitive information.\n"
|
|
)
|
|
return content.encode("utf-8")
|