diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go index 9aaba96..4a15ff3 100644 --- a/cmd/web/handlers.go +++ b/cmd/web/handlers.go @@ -14,7 +14,7 @@ type createElectionRequestWithValidator struct { func (app *application) createElection(w http.ResponseWriter, r *http.Request) { var request createElectionRequestWithValidator - err := app.decodePostForm(r, &request) + err := app.unmarshalRequest(r, &request) if err != nil { app.clientError(w, http.StatusBadRequest, err.Error()) return diff --git a/cmd/web/handlers_test.go b/cmd/web/handlers_test.go new file mode 100644 index 0000000..f7176c5 --- /dev/null +++ b/cmd/web/handlers_test.go @@ -0,0 +1,54 @@ +package main + +import ( + "bytes" + api "code.dlmw.ch/dlmw/qv/internal" + "encoding/json" + "net/http" + "testing" + "time" +) + +var ( + validCreateElectionRequest = api.CreateElectionRequest{ + Choices: []string{"Gandhi", "Buddha"}, + ExpiresAt: time.Now().Add(24 * time.Hour), + IsAnonymous: false, + MaxVoters: nil, + Name: "Guy of the year", + Tokens: 100, + } // TODO: try to find a way to generate test data +) + +func TestCreateElection(t *testing.T) { + app := newTestApplication(t) + server := newTestServer(t, app.routes()) + defer server.Close() + + tests := []struct { + name string + urlPath string + expectedCode int + expectedBody string + }{ + { + name: "Valid request", + urlPath: "/election", + expectedCode: http.StatusOK, + expectedBody: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + requestBody, err := json.Marshal(validCreateElectionRequest) + if err != nil { + t.Fatal(err) + } + + code, _, body := server.post(t, tt.urlPath, bytes.NewReader(requestBody)) + + t.Logf("Code was %v and body %v", code, body) + }) + } +} diff --git a/cmd/web/helpers.go b/cmd/web/helpers.go index 70b7c8a..17bd588 100644 --- a/cmd/web/helpers.go +++ b/cmd/web/helpers.go @@ -4,8 +4,7 @@ import ( api "code.dlmw.ch/dlmw/qv/internal" "code.dlmw.ch/dlmw/qv/internal/validator" "encoding/json" - "errors" - "github.com/go-playground/form/v4" + "io" "net/http" ) @@ -43,19 +42,14 @@ func (app *application) unprocessableEntityError(w http.ResponseWriter, v valida json.NewEncoder(w).Encode(response) } -func (app *application) decodePostForm(r *http.Request, dst any) error { - err := r.ParseForm() +func (app *application) unmarshalRequest(r *http.Request, dst any) error { + body, err := io.ReadAll(r.Body) if err != nil { return err } - err = app.formDecoder.Decode(dst, r.PostForm) + err = json.Unmarshal(body, &dst) if err != nil { - var invalidDecoderError *form.InvalidDecoderError - if errors.As(err, &invalidDecoderError) { - panic(err) - } - return err } diff --git a/cmd/web/testutils_test.go b/cmd/web/testutils_test.go new file mode 100644 index 0000000..cc05bdc --- /dev/null +++ b/cmd/web/testutils_test.go @@ -0,0 +1,45 @@ +package main + +import ( + "code.dlmw.ch/dlmw/qv/internal/models" + "github.com/go-playground/form/v4" + "io" + "log/slog" + "net/http" + "net/http/httptest" + "testing" +) + +func newTestApplication(t *testing.T) *application { + formDecoder := form.NewDecoder() + + return &application{ + logger: slog.New(slog.NewTextHandler(io.Discard, nil)), + elections: &models.ElectionModel{}, + formDecoder: formDecoder, + } +} + +type testServer struct { + *httptest.Server +} + +func newTestServer(t *testing.T, h http.Handler) *testServer { + server := httptest.NewServer(h) + return &testServer{server} +} + +func (ts *testServer) post(t *testing.T, urlPath string, body io.Reader) (int, http.Header, string) { + res, err := ts.Client().Post(ts.URL+urlPath, "application/json", body) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + + responseBody, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + + return res.StatusCode, res.Header, string(responseBody) +}