fffiloni commited on
Commit
b23082b
·
verified ·
1 Parent(s): ba599cf

Upload 14 files

Browse files
tests/test_custom_ui_shell.py CHANGED
@@ -226,3 +226,17 @@ def test_v40_tabbed_ui_logout_and_compact_progress():
226
  assert 'overflow:auto;padding-right' not in css
227
  assert "switchView('progress')" in js
228
  assert 'inferredJobUrl' in runs_js
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  assert 'overflow:auto;padding-right' not in css
227
  assert "switchView('progress')" in js
228
  assert 'inferredJobUrl' in runs_js
229
+
230
+
231
+ def test_v43_run_view_model_contract_is_exposed_to_custom_ui():
232
+ root = Path(__file__).resolve().parents[1]
233
+ app_py = (root / "app.py").read_text()
234
+ html = (root / "web" / "index.html").read_text()
235
+ js = (root / "web" / "static" / "app.js").read_text() + (root / "web" / "static" / "progress.js").read_text()
236
+ assert '"/api/runs/resumable"' in app_py
237
+ assert '"/api/runs/{run_id}/view"' in app_py
238
+ assert "build_run_view_model" in app_py
239
+ for element_id in ["runSummaryCard", "activityFeed", "zeroGpuChecklist", "issueCard", "spaceTestPreview"]:
240
+ assert element_id in html
241
+ assert "bootstrapRunRecovery" in js
242
+ assert "renderRunViewModel" in js
tests/test_view_models.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime, timezone
2
+
3
+ from src.view_models import build_run_view_model, find_latest_resumable_run, normalize_run_status
4
+
5
+
6
+ def _bundle(status="running", events=None, **extra):
7
+ bundle = {
8
+ "summary": {
9
+ "run_id": "run-1",
10
+ "status": status,
11
+ "model_id": "org/model",
12
+ "target_space": "alice/demo",
13
+ "target_space_url": "https://huggingface.co/spaces/alice/demo",
14
+ "created_at": "2026-06-03T10:00:00+00:00",
15
+ "updated_at": "2026-06-03T10:01:00+00:00",
16
+ "selected_hardware": "zero-a10g",
17
+ },
18
+ "state": {"status": status},
19
+ "launch": {"status": status, "job_id": "job-1", "created_by": "alice"},
20
+ "events": events or [],
21
+ "inference_gate": {},
22
+ "generation_smoke": {},
23
+ "hardware_strategy": {},
24
+ "technical_blockers": {},
25
+ }
26
+ bundle.update(extra)
27
+ return bundle
28
+
29
+
30
+ def test_view_model_maps_running_run_to_product_pipeline():
31
+ bundle = _bundle(
32
+ events=[
33
+ {"ts": "2026-06-03T10:00:10+00:00", "step": "model_analysis", "status": "success", "message": "Analyzed model"},
34
+ {"ts": "2026-06-03T10:00:20+00:00", "step": "pi_run", "status": "running", "message": "Generating files"},
35
+ ]
36
+ )
37
+ view = build_run_view_model("run-1", bundle, bucket_source="alice/space-factory-runs", now=datetime(2026, 6, 3, 10, 2, tzinfo=timezone.utc))
38
+ assert view["header"]["status"] == "running"
39
+ assert view["header"]["current_phase"] == "generate_files"
40
+ assert [step["label"] for step in view["pipeline"]][:3] == ["Plan", "Generate Files", "Push to Hub"]
41
+ assert any(item["agent"] == "Coder Agent" for item in view["activity"])
42
+
43
+
44
+ def test_view_model_manual_hardware_is_waiting_manual_action():
45
+ bundle = _bundle(status="manual_hardware_required", hardware_strategy={"manual_action_required": True})
46
+ view = build_run_view_model("run-1", bundle, bucket_source="alice/space-factory-runs", now=datetime(2026, 6, 3, 10, 2, tzinfo=timezone.utc))
47
+ assert view["header"]["status"] == "waiting_manual_action"
48
+ assert view["actions"]["requires_manual_action"] is True
49
+ assert view["diagnostics"]["issue"]["status"] == "action_required"
50
+
51
+
52
+ def test_view_model_success_marks_pipeline_completed_and_live_test_passed():
53
+ bundle = _bundle(status="full_inference_success", generation_smoke={"ok": True, "latency_seconds": 12.4})
54
+ view = build_run_view_model("run-1", bundle, bucket_source="alice/space-factory-runs", now=datetime(2026, 6, 3, 10, 2, tzinfo=timezone.utc))
55
+ assert view["header"]["status"] == "succeeded"
56
+ assert all(step["status"] == "completed" for step in view["pipeline"])
57
+ assert view["space_test"]["status"] == "passed"
58
+
59
+
60
+ def test_view_model_marks_old_non_terminal_run_as_stale():
61
+ bundle = _bundle(status="running")
62
+ status = normalize_run_status(bundle, now=datetime(2026, 6, 4, 10, 2, tzinfo=timezone.utc))
63
+ assert status["global_status"] == "stale"
64
+ assert status["is_stale"] is True
65
+
66
+
67
+ def test_find_latest_resumable_run_ignores_terminal_and_manual():
68
+ runs = [
69
+ {"run_id": "old-success", "status": "full_inference_success", "updated_at": "2026-06-03T10:00:00+00:00"},
70
+ {"run_id": "manual", "status": "manual_hardware_required", "updated_at": "2026-06-03T10:03:00+00:00"},
71
+ {"run_id": "active", "status": "running", "updated_at": "2026-06-03T10:02:00+00:00"},
72
+ ]
73
+ picked = find_latest_resumable_run(runs, now=datetime(2026, 6, 3, 10, 4, tzinfo=timezone.utc))
74
+ assert picked["run_id"] == "active"