package webui import ( "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" ) func TestRootRendersLatestSnapshot(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "audit.json") exportDir := filepath.Join(dir, "export") if err := os.MkdirAll(exportDir, 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(path, []byte(`{"collected_at":"2026-03-15T00:00:00Z","hardware":{"board":{"serial_number":"SERIAL-OLD"}}}`), 0644); err != nil { t.Fatal(err) } handler := NewHandler(HandlerOptions{ Title: "Bee Hardware Audit", AuditPath: path, ExportDir: exportDir, }) first := httptest.NewRecorder() handler.ServeHTTP(first, httptest.NewRequest(http.MethodGet, "/", nil)) if first.Code != http.StatusOK { t.Fatalf("first status=%d", first.Code) } if !strings.Contains(first.Body.String(), "SERIAL-OLD") { t.Fatalf("first body missing old serial: %s", first.Body.String()) } if !strings.Contains(first.Body.String(), "/export/support.tar.gz") { t.Fatalf("first body missing support bundle link: %s", first.Body.String()) } if got := first.Header().Get("Cache-Control"); got != "no-store" { t.Fatalf("first cache-control=%q", got) } if err := os.WriteFile(path, []byte(`{"collected_at":"2026-03-15T00:05:00Z","hardware":{"board":{"serial_number":"SERIAL-NEW"}}}`), 0644); err != nil { t.Fatal(err) } second := httptest.NewRecorder() handler.ServeHTTP(second, httptest.NewRequest(http.MethodGet, "/", nil)) if second.Code != http.StatusOK { t.Fatalf("second status=%d", second.Code) } if !strings.Contains(second.Body.String(), "SERIAL-NEW") { t.Fatalf("second body missing new serial: %s", second.Body.String()) } if strings.Contains(second.Body.String(), "SERIAL-OLD") { t.Fatalf("second body still contains old serial: %s", second.Body.String()) } } func TestAuditJSONServesLatestSnapshot(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "audit.json") body := `{"hardware":{"board":{"serial_number":"SERIAL-API"}}}` if err := os.WriteFile(path, []byte(body), 0644); err != nil { t.Fatal(err) } handler := NewHandler(HandlerOptions{AuditPath: path}) rec := httptest.NewRecorder() handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/audit.json", nil)) if rec.Code != http.StatusOK { t.Fatalf("status=%d", rec.Code) } if got := strings.TrimSpace(rec.Body.String()); got != body { t.Fatalf("body=%q want %q", got, body) } if got := rec.Header().Get("Content-Type"); !strings.Contains(got, "application/json") { t.Fatalf("content-type=%q", got) } } func TestMissingAuditJSONReturnsNotFound(t *testing.T) { handler := NewHandler(HandlerOptions{AuditPath: "/missing/audit.json"}) rec := httptest.NewRecorder() handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/audit.json", nil)) if rec.Code != http.StatusNotFound { t.Fatalf("status=%d want %d", rec.Code, http.StatusNotFound) } } func TestSupportBundleEndpointReturnsArchive(t *testing.T) { dir := t.TempDir() exportDir := filepath.Join(dir, "export") if err := os.MkdirAll(exportDir, 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(exportDir, "bee-audit.log"), []byte("audit log"), 0644); err != nil { t.Fatal(err) } handler := NewHandler(HandlerOptions{ExportDir: exportDir}) rec := httptest.NewRecorder() handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/export/support.tar.gz", nil)) if rec.Code != http.StatusOK { t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String()) } if got := rec.Header().Get("Content-Disposition"); !strings.Contains(got, "attachment;") { t.Fatalf("content-disposition=%q", got) } if rec.Body.Len() == 0 { t.Fatal("empty archive body") } } func TestRuntimeHealthEndpointReturnsJSON(t *testing.T) { dir := t.TempDir() exportDir := filepath.Join(dir, "export") if err := os.MkdirAll(exportDir, 0755); err != nil { t.Fatal(err) } body := `{"status":"PARTIAL","checked_at":"2026-03-16T10:00:00Z"}` if err := os.WriteFile(filepath.Join(exportDir, "runtime-health.json"), []byte(body), 0644); err != nil { t.Fatal(err) } handler := NewHandler(HandlerOptions{ExportDir: exportDir}) rec := httptest.NewRecorder() handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/runtime-health.json", nil)) if rec.Code != http.StatusOK { t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String()) } if strings.TrimSpace(rec.Body.String()) != body { t.Fatalf("body=%q want %q", strings.TrimSpace(rec.Body.String()), body) } }