package widgetapi import ( "context" "github.com/itworx/pulse/internal/widget" "net/http" "net/http/httptest" "strings" "testing" ) func TestCatalogAndPreviewContract(t *testing.T) { registry, err := widget.NewRegistry(widget.DefaultDefinitions()) if err != nil { t.Fatal(err) } h := Handler{Registry: registry} request := httptest.NewRequest(http.MethodGet, "/api/v1/widgets/catalog", nil) response := httptest.NewRecorder() h.ServeHTTP(response, request) if response.Code != http.StatusOK { t.Fatalf("catalog=%d", response.Code) } request = httptest.NewRequest(http.MethodPost, "/api/v1/widgets/preview", nil) response = httptest.NewRecorder() h.ServeHTTP(response, request) if response.Code != http.StatusBadRequest { t.Fatalf("invalid preview=%d", response.Code) } } func TestPreviewValidatesBoundaries(t *testing.T) { registry, err := widget.NewRegistry(widget.DefaultDefinitions()) if err != nil { t.Fatal(err) } h := Handler{Registry: registry} tests := []struct { name string method string path string contentType string body string want int }{ {name: "valid", method: http.MethodPost, path: "/api/v1/widgets/preview", contentType: "application/json", body: `{"widget":{"id":"cpu","type":"stat","title":"CPU","data":{"sourceType":"semantic-metric","metric":"host.cpu.utilization"}}}`, want: http.StatusOK}, {name: "trailing json", method: http.MethodPost, path: "/api/v1/widgets/preview", contentType: "application/json", body: `{"widget":{}} {}`, want: http.StatusBadRequest}, {name: "unknown envelope field", method: http.MethodPost, path: "/api/v1/widgets/preview", contentType: "application/json", body: `{"widget":{},"surprise":true}`, want: http.StatusBadRequest}, {name: "wrong content type", method: http.MethodPost, path: "/api/v1/widgets/preview", contentType: "text/plain", body: `{}`, want: http.StatusUnsupportedMediaType}, {name: "known path wrong method", method: http.MethodDelete, path: "/api/v1/widgets/catalog", want: http.StatusMethodNotAllowed}, {name: "unknown path", method: http.MethodGet, path: "/api/v1/widgets/missing", want: http.StatusNotFound}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { request := httptest.NewRequest(test.method, test.path, strings.NewReader(test.body)) if test.contentType != "" { request.Header.Set("Content-Type", test.contentType) } response := httptest.NewRecorder() h.ServeHTTP(response, request) if response.Code != test.want { t.Fatalf("status=%d want=%d body=%s", response.Code, test.want, response.Body.String()) } }) } } func TestCanceledRequestDoesNotWrite(t *testing.T) { registry, err := widget.NewRegistry(widget.DefaultDefinitions()) if err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(context.Background()) cancel() request := httptest.NewRequest(http.MethodGet, "/api/v1/widgets/catalog", nil).WithContext(ctx) response := httptest.NewRecorder() (Handler{Registry: registry}).ServeHTTP(response, request) if response.Body.Len() != 0 { t.Fatalf("canceled request wrote %q", response.Body.String()) } }