@@ -46,40 +46,41 @@ func TestStudioUIInteraction(t *testing.T) {
4646 ts := httptest .NewServer (srv .Handler ())
4747 defer ts .Close ()
4848
49+ // --- Fetch index.html and discover asset paths ---
50+ htmlPath , jsPath , cssPath := discoverAssets (t , ts .URL )
51+
4952 // --- Static UI assets used by Live ---
50- for _ , path := range []string {"/" , "/app.jsx" , "/styles.css" , "/index.html" } {
51- resp , err := http .Get (ts .URL + path )
53+ for _ , entry := range []struct {
54+ path string
55+ markers []string
56+ }{
57+ {"/" , []string {"SLMCode Studio" , "id=\" root\" " , "<title>" }},
58+ {htmlPath , []string {"SLMCode Studio" , "id=\" root\" " , "<title>" }},
59+ {jsPath , []string {
60+ "/api/events" , "/runs" , "/runs/stop" , "/runs/latest" ,
61+ "/agents" , "/board" , "/config" , "/skills" ,
62+ "/pipeline" , "/tasks" , "/stacks" ,
63+ "/health" , "/auth" , "/mcp" ,
64+ "pipeline" , "autoScroll" ,
65+ }},
66+ {cssPath , []string {
67+ "--color-surface" ,
68+ }},
69+ } {
70+ resp , err := http .Get (ts .URL + entry .path )
5271 if err != nil {
5372 t .Fatal (err )
5473 }
5574 body , _ := io .ReadAll (resp .Body )
5675 resp .Body .Close ()
5776 if resp .StatusCode != 200 {
58- t .Fatalf ("%s → %d" , path , resp .StatusCode )
77+ t .Fatalf ("%s → %d" , entry . path , resp .StatusCode )
5978 }
60- if path == "/app.jsx" {
79+ if len ( entry . markers ) > 0 {
6180 src := string (body )
62- for _ , marker := range []string {
63- "renderMarkdown" , "DepGraph" , "PROVIDER_PRESETS" , "/api/runs" ,
64- "/api/runs/stop" , "/api/events" , "file_change" , "autoScroll" ,
65- `id: "queries"` , "/api/queries" , "openQuery" , "queryDocTab" ,
66- "openAgent" , "showDebugEvents" , "/api/agents/" ,
67- "intervention" , "turnMeter" , "intervention-banner" ,
68- "LiveLogs" , "LiveStatusCard" , "LiveEnrichBox" , "live-overview" , "live-logs-panel" ,
69- "PipelineHeader" , "PIPE_GROUPS" , "pipeline-header" , "pipeline-groups" ,
70- "continueAsk" , "/api/continue/answer" , "polish" , "Keep precise flags" ,
71- "escalateAsk" , "/api/escalate/answer" , "Human review needed" , "Retry now" ,
72- } {
81+ for _ , marker := range entry .markers {
7382 if ! strings .Contains (src , marker ) {
74- t .Fatalf ("app.jsx missing %q" , marker )
75- }
76- }
77- }
78- if path == "/styles.css" {
79- css := string (body )
80- for _ , marker := range []string {"--accent" , "pipeline-header" , "pipeline-groups" , "live-logs-panel" } {
81- if ! strings .Contains (css , marker ) {
82- t .Fatalf ("styles.css missing %q" , marker )
83+ t .Fatalf ("%s missing %q" , entry .path , marker )
8384 }
8485 }
8586 }
@@ -225,6 +226,69 @@ func TestStudioUIInteraction(t *testing.T) {
225226 }
226227}
227228
229+ // discoverAssets fetches the index page and extracts paths to JS and CSS bundles.
230+ func discoverAssets (t * testing.T , baseURL string ) (htmlPath , jsPath , cssPath string ) {
231+ t .Helper ()
232+
233+ resp , err := http .Get (baseURL + "/" )
234+ if err != nil {
235+ t .Fatal (err )
236+ }
237+ body , _ := io .ReadAll (resp .Body )
238+ resp .Body .Close ()
239+ html := string (body )
240+
241+ // Extract JS bundle path from <script type="module" ... src="...">
242+ idx := strings .Index (html , `<script type="module"` )
243+ if idx >= 0 {
244+ rest := html [idx :]
245+ start := strings .Index (rest , `src="` )
246+ if start >= 0 {
247+ start += 5
248+ end := strings .Index (rest [start :], `"` )
249+ if end >= 0 {
250+ jsPath = rest [start : start + end ]
251+ }
252+ }
253+ }
254+
255+ // Extract local CSS path: find <link rel="stylesheet" ... href="/assets/...">
256+ // Skip the Google Fonts stylesheet (which uses href before rel).
257+ search := html
258+ for {
259+ idx := strings .Index (search , `rel="stylesheet"` )
260+ if idx < 0 {
261+ break
262+ }
263+ // Look for href= within this link element's scope
264+ seg := search [max (0 , idx - 200 ):min (len (search ), idx + 200 )]
265+ hrefIdx := strings .Index (seg , `href="` )
266+ if hrefIdx >= 0 {
267+ hrefStart := hrefIdx + 6
268+ hrefEnd := strings .Index (seg [hrefStart :], `"` )
269+ if hrefEnd >= 0 {
270+ candidate := seg [hrefStart : hrefStart + hrefEnd ]
271+ if strings .HasPrefix (candidate , "/assets/" ) {
272+ cssPath = candidate
273+ break
274+ }
275+ }
276+ }
277+ search = search [idx + len (`rel="stylesheet"` ):]
278+ }
279+
280+ // Try /index.html as well
281+ htmlPath = "/index.html"
282+ if jsPath == "" {
283+ t .Fatal ("could not discover JS bundle path from index.html" )
284+ }
285+ if cssPath == "" {
286+ t .Fatal ("could not discover CSS bundle path from index.html" )
287+ }
288+
289+ return htmlPath , jsPath , cssPath
290+ }
291+
228292func findRepoRoot (t * testing.T ) string {
229293 t .Helper ()
230294 wd , err := os .Getwd ()
0 commit comments