package service import ( "encoding/json" "net/http" "net/http/httptest" "path/filepath" "strings" "testing" ) func TestHTTPHandlersCoverServiceRoutes(t *testing.T) { kube := fakeKubeServer(t) harbor := fakeHarborServer(t, true) installKubeFactory(t, kube) app := newTestApp(t) app.settings.Namespace = "maintenance" app.settings.RunnerImageARM64 = "runner:arm64" app.settings.HarborAPIBase = harbor.URL + "/api/v2.0" app.settings.HarborUsername = "admin" app.settings.HarborPassword = "pw" app.settings.HarborProject = "metis" app.settings.HarborRegistry = "registry.example" app.settings.ArtifactStatePath = filepath.Join(t.TempDir(), "artifacts.json") handler := app.Handler() t.Run("health", func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/healthz", nil) resp := httptest.NewRecorder() handler.ServeHTTP(resp, req) if resp.Code != http.StatusOK || !strings.Contains(resp.Body.String(), `"status":"ok"`) { t.Fatalf("health response: %d %s", resp.Code, resp.Body.String()) } }) authHeaders := func(req *http.Request) { req.Header.Set("X-Auth-Request-User", "brad") req.Header.Set("X-Auth-Request-Groups", "admin") } t.Run("devices", func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/api/devices?host=titan-22", nil) authHeaders(req) resp := httptest.NewRecorder() handler.ServeHTTP(resp, req) if resp.Code != http.StatusOK || !strings.Contains(resp.Body.String(), `"/dev/sdz"`) { t.Fatalf("devices response: %d %s", resp.Code, resp.Body.String()) } }) t.Run("build", func(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/api/jobs/build", strings.NewReader(`{"node":"titan-15"}`)) req.Header.Set("Content-Type", "application/json") authHeaders(req) resp := httptest.NewRecorder() handler.ServeHTTP(resp, req) if resp.Code != http.StatusAccepted { t.Fatalf("build response: %d %s", resp.Code, resp.Body.String()) } var job Job if err := json.Unmarshal(resp.Body.Bytes(), &job); err != nil { t.Fatalf("decode build job: %v", err) } waitForJobState(t, app, job.ID, JobDone) }) t.Run("replace", func(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/api/jobs/replace", strings.NewReader(`{"node":"titan-15","host":"titan-22","device":"/dev/sdz"}`)) req.Header.Set("Content-Type", "application/json") authHeaders(req) resp := httptest.NewRecorder() handler.ServeHTTP(resp, req) if resp.Code != http.StatusAccepted { t.Fatalf("replace response: %d %s", resp.Code, resp.Body.String()) } var job Job if err := json.Unmarshal(resp.Body.Bytes(), &job); err != nil { t.Fatalf("decode replace job: %v", err) } waitForJobState(t, app, job.ID, JobDone) }) t.Run("watch", func(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/api/sentinel/watch", nil) authHeaders(req) resp := httptest.NewRecorder() handler.ServeHTTP(resp, req) if resp.Code != http.StatusOK || !strings.Contains(resp.Body.String(), `"kind":"sentinel.watch"`) { t.Fatalf("watch response: %d %s", resp.Code, resp.Body.String()) } }) t.Run("index", func(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) authHeaders(req) resp := httptest.NewRecorder() handler.ServeHTTP(resp, req) if resp.Code != http.StatusOK || !strings.Contains(resp.Body.String(), "