package api_test import ( "bytes" "context" "encoding/json" "net/http" "net/http/httptest" "path/filepath" "strconv" "testing" "testing/fstest" "havenllo/internal/api" "havenllo/internal/app" "havenllo/internal/database" ) func newHandler(t *testing.T) http.Handler { t.Helper() db, err := database.Open(context.Background(), filepath.Join(t.TempDir(), "havenllo.db")) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = db.Close() }) return api.NewHandler(app.New(db), fstest.MapFS{"index.html": {Data: []byte("")}}) } func request(t *testing.T, handler http.Handler, method, path, body string, jsonBody bool) *httptest.ResponseRecorder { t.Helper() r := httptest.NewRequest(method, path, bytes.NewBufferString(body)) if jsonBody { r.Header.Set("Content-Type", "application/json") } w := httptest.NewRecorder() handler.ServeHTTP(w, r) return w } func TestBoardAndHealth(t *testing.T) { t.Parallel() handler := newHandler(t) for _, path := range []string{"/api/health", "/api/board"} { response := request(t, handler, http.MethodGet, path, "", false) if response.Code != http.StatusOK { t.Fatalf("%s status = %d, body %s", path, response.Code, response.Body) } } var snapshot struct { Lists []json.RawMessage `json:"lists"` } if err := json.Unmarshal(request(t, handler, http.MethodGet, "/api/board", "", false).Body.Bytes(), &snapshot); err != nil { t.Fatal(err) } if len(snapshot.Lists) != 3 { t.Fatalf("snapshot lists = %d, want 3", len(snapshot.Lists)) } } func TestJSONValidationAndLastListConflict(t *testing.T) { t.Parallel() handler := newHandler(t) if got := request(t, handler, http.MethodPost, "/api/lists", `{"name":"later","unknown":true}`, true); got.Code != http.StatusBadRequest { t.Fatalf("unknown field status = %d", got.Code) } if got := request(t, handler, http.MethodPost, "/api/lists", `{"name":"later"}`, false); got.Code != http.StatusUnsupportedMediaType { t.Fatalf("content type status = %d", got.Code) } response := request(t, handler, http.MethodGet, "/api/lists", "", false) var lists struct { Lists []struct { ID int64 `json:"id"` } `json:"lists"` } if err := json.Unmarshal(response.Body.Bytes(), &lists); err != nil { t.Fatal(err) } for _, list := range lists.Lists[:2] { if got := request(t, handler, http.MethodDelete, "/api/lists/"+strconv.FormatInt(list.ID, 10), "", false); got.Code != http.StatusNoContent { t.Fatalf("delete list status = %d", got.Code) } } if got := request(t, handler, http.MethodDelete, "/api/lists/"+strconv.FormatInt(lists.Lists[2].ID, 10), "", false); got.Code != http.StatusConflict { t.Fatalf("last list status = %d", got.Code) } }