Files
photoanalyzer/tests/e2e/test_analysis_browser.py

59 lines
2.0 KiB
Python

"""Phase B browser journey (US02-07): start a content-analysis job from the Analyze
view and watch live progress arrive over the real SSE adapter, against a real server
and durable worker. The frontend's SSE→polling event adapter and the worker are
exercised end to end; the vision edge is the recording fake.
"""
from __future__ import annotations
import pytest
from playwright.sync_api import expect
from tests.e2e._pipeline_harness import Server, seed_library, start_worker
pytestmark = pytest.mark.phase_b
@pytest.fixture
def running_stack(tmp_path):
seeded = seed_library(tmp_path, {"beach": 1}, {"beach": "sfw"})
log = tmp_path / "vision.log"
server = Server(seeded).start()
worker = start_worker(seeded, fake_vision_log=log)
try:
yield server
finally:
worker.terminate()
server.stop()
def test_analyze_start_shows_live_progress_and_completes(page, running_stack):
errors = []
page.on("console", lambda m: errors.append(m.text) if m.type == "error" else None)
page.goto(f"{running_stack.base}/app/#/analyze")
run = page.get_by_test_id("run-analysis")
run.wait_for()
assert run.is_enabled() # one confirmed-SFW asset is eligible
run.click()
# Live progress streams into the activity log via the browser's SSE adapter.
log = page.get_by_test_id("analyze-log")
log.get_by_text("Started analysis job").wait_for()
# On completion the view re-renders with the updated counts: the SFW asset is
# now analysed. Waiting on this observable state (not a sleep) proves the whole
# start → worker → SSE → done round trip worked.
analyzed_value = (
page.get_by_test_id("analyze-counts")
.locator(".stat")
.filter(has_text="Analyzed")
.locator(".stat-value")
)
# ``expect`` re-queries the locator each poll, so it survives the re-render that
# replaces the counts DOM when the job completes.
expect(analyzed_value).to_have_text("1", timeout=15000)
assert errors == [], f"console errors: {errors}"