| from pathlib import Path |
|
|
| from src.jobs import cancel_job_safe |
| from src.progress import STEP_LABELS, STEP_ORDER, progress_from_events |
|
|
|
|
| def test_progress_timeline_uses_exact_worker_steps(): |
| assert "pi_verification" in STEP_ORDER |
| assert "metadata_sanitize" in STEP_ORDER |
| assert "generation_smoke" in STEP_ORDER |
| events = [ |
| {"ts": "2026-06-02T10:00:00+00:00", "step": "bootstrap", "status": "started"}, |
| {"ts": "2026-06-02T10:00:01+00:00", "step": "metadata_sanitize", "status": "success"}, |
| {"ts": "2026-06-02T10:00:02+00:00", "step": "generation_smoke", "status": "started"}, |
| ] |
| result = progress_from_events(events) |
| assert result["current_step"] == "generation_smoke" |
| assert any(x["step"] == "metadata_sanitize" and x["label"] == STEP_LABELS["metadata_sanitize"] for x in result["timeline"]) |
| assert any(x["step"] == "generation_smoke" and x["status"] == "running" for x in result["timeline"]) |
|
|
|
|
| def test_frontend_progress_polling_is_no_cache_and_faster(): |
| api_js = Path("web/static/api.js").read_text(encoding="utf-8") |
| app_js = Path("web/static/app.js").read_text(encoding="utf-8") |
| progress_js = Path("web/static/progress.js").read_text(encoding="utf-8") |
| assert 'cache:"no-store"' in api_js |
| assert "withCacheBust" in api_js |
| assert "setInterval(refreshProgress,2000)" in app_js |
| assert "stabilizeProgressPayload" in progress_js |
|
|
|
|
| def test_cancel_endpoint_and_button_exist(): |
| app_py = Path("app.py").read_text(encoding="utf-8") |
| html = Path("web/index.html").read_text(encoding="utf-8") |
| js = Path("web/static/app.js").read_text(encoding="utf-8") |
| assert '"/api/runs/{run_id}/cancel"' in app_py |
| assert "cancel_job_safe" in app_py |
| assert 'id="cancelRun"' in html |
| assert "cancelActiveRun" in js |
| assert "/cancel?bucket_name=" in js |
|
|
|
|
| def test_cancel_job_safe_requires_job_id(): |
| assert cancel_job_safe("", namespace="alice", token="fake")["ok"] is False |
|
|