package webui import ( "regexp" "strings" "testing" ) func appJS(t *testing.T) string { t.Helper() b, err := embedded.ReadFile("assets/app.js") if err != nil { t.Fatalf("read embedded app.js: %v", err) } return string(b) } func TestRenderDispatcherFunctionsExist(t *testing.T) { js := appJS(t) start := strings.Index(js, "function render(){") if start < 0 { t.Fatal("render dispatcher not found") } end := strings.Index(js[start:], "}\n") if end < 0 { t.Fatal("render dispatcher end not found") } body := js[start : start+end+1] calls := regexp.MustCompile(`\b(render[A-Z][A-Za-z0-9_]*)\(`).FindAllStringSubmatch(body, -1) if len(calls) == 0 { t.Fatal("render dispatcher contains no render function calls") } seen := map[string]bool{} for _, call := range calls { name := call[1] if seen[name] { continue } seen[name] = true if !strings.Contains(js, "function "+name+"(") { t.Errorf("render dispatcher calls %s but app.js does not define it", name) } } } func TestPlacementUIHelpersExist(t *testing.T) { js := appJS(t) for _, name := range []string{ "placementRule", "placementRows", "placementCell", "placementSourceLabel", "renderPlacement", "placementCellHTML", "placementWorkerCard", "loadPlacement", "openPlacementDialog", "lines", "installedForWorker", "savePlacementRule", "placementExactAction", } { if !strings.Contains(js, "function "+name+"(") { t.Errorf("missing placement UI helper %s", name) } } } func appCSS(t *testing.T) string { t.Helper() b, err := embedded.ReadFile("assets/app.css") if err != nil { t.Fatalf("read embedded app.css: %v", err) } return string(b) } func indexHTML(t *testing.T) string { t.Helper() b, err := embedded.ReadFile("assets/index.html") if err != nil { t.Fatalf("read embedded index.html: %v", err) } return string(b) } func TestProfessionalLightThemeIsEmbedded(t *testing.T) { css := appCSS(t) for _, want := range []string{ "color-scheme:light", "--bg:#eef2f6", "--surface:#ffffff", "--text:#253345", "--font-mono:", "Checkpoint 24 — SCMDB-inspired professional light control-plane theme", ".live-flow-stage,.cluster-map-stage", } { if !strings.Contains(css, want) { t.Errorf("light theme marker %q missing from app.css", want) } } if strings.Contains(indexHTML(t), `name="color-scheme" content="dark light"`) { t.Fatal("index still advertises dark color scheme") } if !strings.Contains(indexHTML(t), `name="color-scheme" content="light"`) { t.Fatal("index does not advertise light color scheme") } } func TestCanvasThemeUsesLightNodeSurfaces(t *testing.T) { js := appJS(t) for _, want := range []string{ "rgba(255,255,255,.97)", "rgba(37,51,69,.94)", "const liveColor=(v,a=1,l=44)", } { if !strings.Contains(js, want) { t.Errorf("light canvas marker %q missing from app.js", want) } } for _, legacy := range []string{ "rgba(10,18,25,.96)", "rgba(11,20,27,.94)", } { if strings.Contains(js, legacy) { t.Errorf("legacy dark canvas color %q still present", legacy) } } } func TestPolicyDialogCloseControlsBypassFormValidation(t *testing.T) { html := indexHTML(t) if strings.Contains(html, `
`) { t.Fatal("policy dialog still uses method=dialog; required fields can block cancel controls") } for _, want := range []string{ ``, ``, ``, } { if !strings.Contains(html, want) { t.Errorf("policy dialog control missing or unsafe: %s", want) } } js := appJS(t) if !strings.Contains(js, `document.getElementById(b.dataset.closeDialog)?.close()`) { t.Fatal("generic data-close-dialog handler missing") } if strings.Contains(js, `if(e.submitter?.value==='cancel')return;e.preventDefault();`) { t.Fatal("policy submit handler still depends on cancel submit semantics") } } func TestDialogCloseTargetsExist(t *testing.T) { html := indexHTML(t) dialogIDs := map[string]bool{} for _, m := range regexp.MustCompile(``) block := pattern.FindString(html) if block == "" { t.Fatalf("dialog %s not found", dialogID) } if !strings.Contains(block, `required`) { t.Fatalf("test assumption failed: dialog %s has no required field", dialogID) } if !strings.Contains(block, `type="button"`) || !strings.Contains(block, `data-close-dialog="`+dialogID+`"`) { t.Errorf("dialog %s lacks a validation-independent close control", dialogID) } } } func TestModelTableExposesDistinctContextWindows(t *testing.T) { js := appJS(t) for _, want := range []string{"Modell-Max", "Konfig.", "Geladen", "configured_context_length", "loaded_context_length"} { if !strings.Contains(js, want) { t.Errorf("model context UI marker %q missing", want) } } }