fffiloni commited on
Commit
bf2fa25
·
verified ·
1 Parent(s): 5d50517

Upload 17 files

Browse files
tests/test_bucket_urls.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from src.bucket import summarize_run_bundle
2
+ from src.view_models import build_run_view_model
3
+ import app
4
+
5
+
6
+ def test_bucket_artifact_tree_url_has_no_main_segment():
7
+ url = app._run_artifacts_url("gist-20260602-120645-a145824d", "fffiloni/space-factory-runs")
8
+ assert url == "https://huggingface.co/buckets/fffiloni/space-factory-runs/tree/runs/gist-20260602-120645-a145824d"
9
+ assert "/tree/main/runs/" not in url
10
+
11
+
12
+ def test_run_summary_artifact_url_has_no_main_segment():
13
+ summary = summarize_run_bundle(
14
+ "run-launch",
15
+ {"state": {"status": "running"}, "launch": {}, "summary_file": {}},
16
+ bucket_source="user/space-factory-runs",
17
+ )
18
+ assert summary["artifacts_url"] == "https://huggingface.co/buckets/user/space-factory-runs/tree/runs/run-launch"
19
+
20
+
21
+ def test_view_model_artifact_url_has_no_main_segment():
22
+ bundle = {
23
+ "summary": {"status": "running", "created_at": "2026-06-02T12:00:00+00:00"},
24
+ "state": {},
25
+ "launch": {"status": "running"},
26
+ "events": [],
27
+ }
28
+ view = build_run_view_model("run-launch", bundle, bucket_source="user/space-factory-runs")
29
+ assert view["links"]["artifacts_url"] == "https://huggingface.co/buckets/user/space-factory-runs/tree/runs/run-launch"
tests/test_custom_ui_shell.py CHANGED
@@ -1,242 +1,100 @@
1
  from pathlib import Path
2
 
3
 
4
- def test_custom_ui_assets_exist():
5
- root = Path(__file__).resolve().parents[1]
6
- assert (root / "web" / "index.html").exists()
7
- assert (root / "web" / "static" / "app.css").exists()
8
- assert (root / "web" / "static" / "app.js").exists()
9
- assert (root / "web" / "static" / "progress.js").exists()
10
-
11
-
12
- def test_app_registers_custom_routes():
13
- root = Path(__file__).resolve().parents[1]
14
- content = (root / "app.py").read_text()
15
- assert "def register_custom_routes" in content
16
- assert '"/custom"' in content
17
- assert '"/api/progress/from-events"' in content
18
- assert '"/api/runs"' in content
19
 
20
 
21
- def test_custom_ui_contains_core_product_sections():
22
- root = Path(__file__).resolve().parents[1]
23
- html = (root / "web" / "index.html").read_text()
24
- for text in [
25
- "New Build",
26
- "Space Test",
27
- "Run Explorer",
28
- "Run storage",
29
- "Live job progress",
30
- "Run details",
31
- "Validation & metrics",
32
- "Latest events",
33
- ]:
34
- assert text in html
35
 
36
 
37
- def test_custom_ui_bridge_endpoints_are_registered():
38
- root = Path(__file__).resolve().parents[1]
39
- content = (root / "app.py").read_text()
40
  for route in [
 
41
  '"/api/me"',
42
  '"/api/bucket/status"',
43
  '"/api/bucket/create"',
44
  '"/api/build"',
45
  '"/api/validate"',
 
46
  '"/api/runs/{run_id}/progress"',
 
 
47
  ]:
48
  assert route in content
49
- assert "_oauth_context_from_request" in content
50
 
51
 
52
- def test_custom_ui_calls_real_bridge_endpoints():
53
- root = Path(__file__).resolve().parents[1]
54
- js = (root / "web" / "static" / "app.js").read_text()
55
- for endpoint in ["/api/me", "/api/build", "/api/validate", "/api/bucket/status", "/api/bucket/create"]:
56
- assert endpoint in js
57
- assert "Custom UI shell is ready" not in js
58
- assert "functional Gradio controls" not in js
59
-
60
-
61
- def test_custom_ui_has_validate_form():
62
- root = Path(__file__).resolve().parents[1]
63
- html = (root / "web" / "index.html").read_text()
64
- for element_id in ["validateSpace", "validateApi", "expectedOutput", "testArgs", "testKwargs", "launchValidate"]:
65
- assert element_id in html
66
-
67
-
68
- def test_custom_ui_has_run_detail_explorer():
69
- root = Path(__file__).resolve().parents[1]
70
- html = (root / "web" / "index.html").read_text()
71
- for element_id in ["selectedRunId", "selectedModelId", "artifactList", "reportPreview", "runDetailStatus"]:
72
- assert element_id in html
73
- js = (root / "web" / "static" / "runs.js").read_text()
74
- assert "selectRun" in js
75
- assert "renderRunDetail" in js
76
- assert "/api/runs/" in js
77
-
78
-
79
- def test_custom_ui_renders_metrics_from_progress():
80
- root = Path(__file__).resolve().parents[1]
81
- js = (root / "web" / "static" / "app.js").read_text()
82
- assert "function renderMetrics" in js
83
- assert "generation_smoke" in js
84
- assert "recommended_zerogpu_duration" in js
85
 
86
- def test_custom_ui_has_selected_run_actions_and_manual_hardware_panel():
87
- root = Path(__file__).resolve().parents[1]
88
- html = (root / "web" / "index.html").read_text()
89
- for element_id in ["manualActionPanel", "manualOpenSettings", "manualGoValidate", "selectedValidateBtn", "selectedOpenSettings", "selectedBlockers"]:
90
- assert element_id in html
91
- app_js = (root / "web" / "static" / "app.js").read_text()
92
- assert "prepareValidationFromActiveRun" in app_js
93
- assert "renderManualAction" in app_js
94
- runs_js = (root / "web" / "static" / "runs.js").read_text()
95
- assert "renderSelectedLinks" in runs_js
96
- assert "renderBlockers" in runs_js
97
 
98
- def test_custom_ui_has_run_filters_and_resilient_polling():
99
- root = Path(__file__).resolve().parents[1]
100
- html = (root / "web" / "index.html").read_text()
101
- js = (root / "web" / "static" / "app.js").read_text()
102
- runs_js = (root / "web" / "static" / "runs.js").read_text()
103
- css = (root / "web" / "static" / "app.css").read_text()
104
- for element_id in ["runFilters", "refreshRuns", "pollWarning"]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  assert element_id in html
106
- assert "runStatusFilter" in js
107
- assert "localStorage.setItem('asf.activeRun'" in js
108
- assert "restoreActiveRun" in js
109
- assert "Progress polling failed" in js
110
- assert "renderRunsFromCache" in runs_js
111
- assert "state.runsCache" in runs_js
112
- assert ".run-row.selected" in css
113
-
114
- def test_custom_ui_has_oauth_status_panel_and_login_link():
115
- root = Path(__file__).resolve().parents[1]
116
- html = (root / "web" / "index.html").read_text()
117
- js = (root / "web" / "static" / "app.js").read_text()
118
- app_py = (root / "app.py").read_text()
119
- assert "authPanel" in html
120
- assert "renderAuthWarnings" in js
121
- assert "/oauth/huggingface/login" in js
122
- assert '"/api/oauth/diagnostics"' in app_py
123
- assert "public_oauth_context" in app_py
124
-
125
- def test_custom_ui_v30_bucket_gate_and_zerogpu_toggle():
126
- root = Path(__file__).resolve().parents[1]
127
- html = (root / "web" / "index.html").read_text()
128
- js = (root / "web" / "static" / "app.js").read_text()
129
- assert 'id="tryZeroGpu"' in html
130
- assert 'disabled /> Try ZeroGPU first' not in html
131
- assert 'id="launchBuild" disabled' in html
132
- assert 'buildGateText' in html
133
- assert 'effectivePreferredHardware' in js
134
- assert 'setBucketReady' in js
135
- assert 'Create or check your private run bucket before launching a build' in js
136
-
137
-
138
- def test_custom_ui_v30_css_has_overflow_and_duplicate_cleanup():
139
- root = Path(__file__).resolve().parents[1]
140
- css = (root / "web" / "static" / "app.css").read_text()
141
- assert '.app-shell{min-height:100vh;max-width:1540px' in css
142
- assert '.top-tabs{display:flex' in css
143
- assert '.runs-table{border:1px solid var(--line);border-radius:14px;padding:0;overflow:hidden' in css
144
- assert 'font-family:ui-monospace' in css
145
- assert '.auth-panel,.operation-status{' in css
146
-
147
- def test_custom_ui_v31_feedback_and_loading_states():
148
- root = Path(__file__).resolve().parents[1]
149
- html = (root / "web" / "index.html").read_text()
150
- js = (root / "web" / "static" / "app.js").read_text()
151
- css = (root / "web" / "static" / "app.css").read_text()
152
- api_js = (root / "web" / "static" / "api.js").read_text()
153
- progress_js = (root / "web" / "static" / "progress.js").read_text()
154
- assert "operationStatus" in html
155
- assert "lastPolled" in html
156
- assert "setOperation" in js
157
- assert "setBusy" in js
158
- assert "validateBuildForm" in js
159
- assert "validateValidationForm" in js
160
- assert "TERMINAL_STATUSES" in js
161
- assert "Run bucket is not ready" in Path(root / "app.py").read_text()
162
- assert ".operation-status" in css
163
- assert "parseApiError" in api_js
164
- assert "lastPolled" in progress_js
165
-
166
-
167
- def test_v33_root_custom_ui_not_iframe_preview():
168
- root = Path(__file__).resolve().parents[1]
169
- app_py = (root / "app.py").read_text()
170
- readme = (root / "README.md").read_text()
171
- assert '@fastapi_app.get("/", response_class=HTMLResponse)' in app_py
172
- assert 'attach_huggingface_oauth(fastapi_app)' in app_py
173
- assert '<iframe src="/custom"' not in app_py
174
- assert 'Custom UI preview' not in app_py
175
- assert 'The product root (`/`) is the custom dashboard' in readme
176
 
177
 
178
- def test_v34_no_explicit_uvicorn_launcher():
179
- root = Path(__file__).resolve().parents[1]
180
- app_py = (root / "app.py").read_text()
181
- assert "uvicorn.run(" not in app_py
182
- assert 'if __name__ == "__main__"' not in app_py
183
- assert "app = create_app()" in app_py
184
-
185
-
186
- def test_v37_simplified_navigation_and_artifact_path():
187
- root = Path(__file__).resolve().parents[1]
188
- html = (root / "web" / "index.html").read_text()
189
- js = (root / "web" / "static" / "app.js").read_text()
190
- assert 'data-view="build"' in html
191
- assert 'data-view="validate"' in html
192
- assert 'data-view="runs"' not in html
193
- assert 'data-view="storage"' not in html
194
- assert 'data-view="about"' not in html
195
- assert 'tree/main/runs/${runId}' in js
196
-
197
-
198
- def test_v38_new_build_mode_and_local_run_filtering():
199
- root = Path(__file__).resolve().parents[1]
200
- html = (root / "web" / "index.html").read_text()
201
- js = (root / "web" / "static" / "app.js").read_text()
202
- runs_js = (root / "web" / "static" / "runs.js").read_text()
203
- css = (root / "web" / "static" / "app.css").read_text()
204
- assert "prepareNewBuild" in html
205
- assert "buildModePanel" in html
206
- assert "Preparing a new build" in html
207
- assert "function prepareNewBuild" in js
208
- assert "setBuildModeInspecting" in js
209
- assert "filteredRuns" in runs_js
210
- assert "apiGet(`/api/runs?limit=100" in runs_js
211
- assert "status=${encodeURIComponent(status)}" not in runs_js
212
- assert ".build-mode-panel" in css
213
-
214
-
215
- def test_v40_tabbed_ui_logout_and_compact_progress():
216
- root = Path(__file__).resolve().parents[1]
217
- html = (root / "web" / "index.html").read_text()
218
- css = (root / "web" / "static" / "app.css").read_text()
219
- js = (root / "web" / "static" / "app.js").read_text()
220
- runs_js = (root / "web" / "static" / "runs.js").read_text()
221
- assert 'class="top-tabs"' in html
222
- assert 'data-view="progress"' in html
223
- assert 'id="logoutLink"' in html
224
- assert 'class="sidebar"' not in html
225
- assert 'max-height:330px' not in css
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
 
1
  from pathlib import Path
2
 
3
 
4
+ def root() -> Path:
5
+ return Path(__file__).resolve().parents[1]
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
 
8
+ def test_custom_ui_assets_exist():
9
+ base = root()
10
+ assert (base / "web" / "index.html").exists()
11
+ assert (base / "web" / "static" / "app.css").exists()
12
+ assert (base / "web" / "static" / "app.js").exists()
13
+ assert (base / "web" / "static" / "progress.js").exists()
14
+ assert (base / "web" / "static" / "runs.js").exists()
 
 
 
 
 
 
 
15
 
16
 
17
+ def test_app_registers_custom_routes_and_bridge_endpoints():
18
+ content = (root() / "app.py").read_text(encoding="utf-8")
19
+ assert "def register_custom_routes" in content
20
  for route in [
21
+ '"/custom"',
22
  '"/api/me"',
23
  '"/api/bucket/status"',
24
  '"/api/bucket/create"',
25
  '"/api/build"',
26
  '"/api/validate"',
27
+ '"/api/runs"',
28
  '"/api/runs/{run_id}/progress"',
29
+ '"/api/runs/resumable"',
30
+ '"/api/runs/{run_id}/view"',
31
  ]:
32
  assert route in content
 
33
 
34
 
35
+ def test_one_page_workspace_contains_core_sections():
36
+ html = (root() / "web" / "index.html").read_text(encoding="utf-8")
37
+ for text in [
38
+ "New Build",
39
+ "Active Run",
40
+ "Runs Explorer",
41
+ "Selected run",
42
+ "Space Test",
43
+ "Validation result",
44
+ "Raw events",
45
+ "Full report",
46
+ "Artifacts",
47
+ "Run storage",
48
+ ]:
49
+ assert text in html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
+ def test_one_page_workspace_keeps_required_ids_for_live_bridge():
53
+ html = (root() / "web" / "index.html").read_text(encoding="utf-8")
54
+ required_ids = [
55
+ "launchBuild",
56
+ "checkBucket",
57
+ "createBucket",
58
+ "launchValidate",
59
+ "progressStatus",
60
+ "timeline",
61
+ "activityFeed",
62
+ "runFilters",
63
+ "runsTable",
64
+ "selectedRunId",
65
+ "artifactList",
66
+ "reportPreview",
67
+ "eventsPanel",
68
+ "spaceTestPreview",
69
+ "metricsList",
70
+ "manualActionPanel",
71
+ "selectedValidateBtn",
72
+ "resumeLatestRun",
73
+ ]
74
+ for element_id in required_ids:
75
  assert element_id in html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
 
78
+ def test_frontend_calls_real_bridge_endpoints_and_keeps_run_logic():
79
+ app_js = (root() / "web" / "static" / "app.js").read_text(encoding="utf-8")
80
+ runs_js = (root() / "web" / "static" / "runs.js").read_text(encoding="utf-8")
81
+ progress_js = (root() / "web" / "static" / "progress.js").read_text(encoding="utf-8")
82
+ for endpoint in ["/api/me", "/api/build", "/api/validate", "/api/bucket/status", "/api/bucket/create"]:
83
+ assert endpoint in app_js
84
+ assert "selectRun" in runs_js
85
+ assert "renderRunDetail" in runs_js
86
+ assert "renderRunViewModel" in progress_js
87
+ assert "renderActivityFeed" in progress_js
88
+ assert "renderDiagnostics" in progress_js
89
+
90
+
91
+ def test_css_contains_one_page_responsive_layout():
92
+ css = (root() / "web" / "static" / "app.css").read_text(encoding="utf-8")
93
+ for snippet in [
94
+ ".workspace-grid{display:grid;grid-template-columns:360px minmax(0,1fr) 340px",
95
+ ".space-test-grid{display:grid;grid-template-columns:minmax(0,1.15fr) 360px",
96
+ "word-break:normal",
97
+ ".run-row.selected",
98
+ "@media (max-width: 860px)",
99
+ ]:
100
+ assert snippet in css.replace(" ", "") if "word-break:normal" == snippet else snippet in css
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_pass46_ui_regressions.py CHANGED
@@ -1,16 +1,15 @@
1
  from pathlib import Path
2
 
3
 
4
- def test_selecting_run_does_not_force_tab_switch():
5
  text = Path("web/static/runs.js").read_text(encoding="utf-8")
6
- select_run = text.split("async function selectRun", 1)[1].split("function renderRunDetail", 1)[0]
7
  assert "switchView(" not in select_run
8
  assert "Keep the user on the current tab" in select_run
9
 
10
 
11
- def test_mobile_css_prevents_letter_by_letter_wrapping():
12
  css = Path("web/static/app.css").read_text(encoding="utf-8")
13
- assert "Pass 46: mobile framing" in css
14
- assert "word-break: normal" in css
15
- assert "grid-template-columns:1fr!important" in css
16
- assert ".nav-item{flex:0 0 auto" in css
 
1
  from pathlib import Path
2
 
3
 
4
+ def test_selecting_run_still_does_not_force_hidden_navigation():
5
  text = Path("web/static/runs.js").read_text(encoding="utf-8")
6
+ select_run = text.split("async function selectRun", 1)[1].split("function renderSelectedLinks", 1)[0]
7
  assert "switchView(" not in select_run
8
  assert "Keep the user on the current tab" in select_run
9
 
10
 
11
+ def test_mobile_css_prevents_letter_by_letter_wrapping_in_one_page_layout():
12
  css = Path("web/static/app.css").read_text(encoding="utf-8")
13
+ assert "word-break:normal" in css.replace(" ", "")
14
+ assert "@media (max-width: 860px)" in css
15
+ assert ".workspace-grid,.space-test-grid,.editor-grid,.two-cols,.summary-meta-grid,.diagnostic-list,.bottom-split,.three-way,.run-storage,.test-top-row{grid-template-columns:1fr}".replace(" ", "") in css.replace(" ", "")
 
tests/test_pass47_simple_spec_reset.py CHANGED
@@ -1,41 +1,30 @@
1
  from pathlib import Path
2
 
3
 
4
- def test_pass47_has_only_three_public_tabs():
5
  html = Path("web/index.html").read_text(encoding="utf-8")
6
- assert 'data-view="build"' in html
7
- assert 'data-view="progress"' in html
8
- assert 'data-view="validate"' in html
9
- assert 'data-view="about-page"' not in html
10
- assert html.count('class="nav-item') == 3
11
 
12
 
13
- def test_build_tab_is_launch_focused_without_visible_run_list():
14
  html = Path("web/index.html").read_text(encoding="utf-8")
15
- build_section = html.split('data-section="build"', 1)[1].split('data-section="progress"', 1)[0]
16
- assert "New Build" in build_section
17
- assert "Run storage" in build_section
18
- assert "Launch result" in build_section
19
- assert "runsTableHome" not in build_section
20
- assert "Run Explorer" not in build_section
21
 
22
 
23
- def test_runs_tab_is_the_single_run_inspection_surface():
24
  html = Path("web/index.html").read_text(encoding="utf-8")
25
- runs_section = html.split('data-section="progress"', 1)[1].split('data-section="validate"', 1)[0]
26
- for required in ["Inspect existing runs", "runsTable", "timeline", "Latest events", "Report preview", "Artifacts"]:
27
- assert required in runs_section
28
 
29
 
30
- def test_launching_does_not_force_runs_tab():
31
- js = Path("web/static/app.js").read_text(encoding="utf-8")
32
- set_active = js.split("function setActiveRun", 1)[1].split("async function loadAppInfo", 1)[0]
33
- assert "switchView(" not in set_active
34
- assert "renderLaunchResult" in js
35
-
36
-
37
- def test_pass47_mobile_layout_is_single_column_safe():
38
- css = Path("web/static/app.css").read_text(encoding="utf-8")
39
- assert "Pass 47: deliberately simple three-tab interface" in css
40
- assert ".simple-build-grid,.simple-runs-grid,.simple-validate-grid,.simple-storage-card{grid-template-columns:1fr!important}" in css
41
- assert "word-break: normal" in css
 
1
  from pathlib import Path
2
 
3
 
4
+ def test_one_page_workspace_has_no_public_tabs_anymore():
5
  html = Path("web/index.html").read_text(encoding="utf-8")
6
+ assert 'data-view="build"' not in html
7
+ assert 'data-view="progress"' not in html
8
+ assert 'data-view="validate"' not in html
9
+ assert "Runs Explorer" in html
10
+ assert "Active Run" in html
11
 
12
 
13
+ def test_new_build_panel_is_left_column_and_launch_focused():
14
  html = Path("web/index.html").read_text(encoding="utf-8")
15
+ assert 'id="newBuildCard"' in html
16
+ for text in ["Launch a private Space", "Run storage", "Build private Space", "Launch result"]:
17
+ assert text in html
 
 
 
18
 
19
 
20
+ def test_runs_explorer_and_selected_run_are_integrated_on_same_page():
21
  html = Path("web/index.html").read_text(encoding="utf-8")
22
+ for text in ["Runs Explorer", "Search runs by ID, model, or space", "Selected run", "Prefill Space Test"]:
23
+ assert text in html
 
24
 
25
 
26
+ def test_space_test_panel_is_inline_not_tabbed():
27
+ html = Path("web/index.html").read_text(encoding="utf-8")
28
+ assert 'id="spaceTestSection"' in html
29
+ assert "Validate an existing Space" in html
30
+ assert "Launch validation" in html
 
 
 
 
 
 
 
tests/test_run_bundle_details.py CHANGED
@@ -42,7 +42,7 @@ def test_summarize_run_bundle_recovers_launch_only_running_job():
42
  assert summary["target_space"] == "alice/z-image"
43
  assert summary["job_id"] == "abc123"
44
  assert summary["job_url"].endswith("/abc123")
45
- assert summary["artifacts_url"].endswith("/tree/main/runs/run-launch")
46
 
47
 
48
  def test_summarize_run_bundle_uses_summary_file_fallback():
 
42
  assert summary["target_space"] == "alice/z-image"
43
  assert summary["job_id"] == "abc123"
44
  assert summary["job_url"].endswith("/abc123")
45
+ assert summary["artifacts_url"].endswith("/tree/runs/run-launch")
46
 
47
 
48
  def test_summarize_run_bundle_uses_summary_file_fallback():