package web import ( "context" "encoding/json" "io" "net/http" "net/http/httptest" "net/url" "strings" "testing" "gardomatic.kleiax.de/lib/client" "github.com/julienschmidt/httprouter" ) func taskWebRequest(request *http.Request, apiClient *client.Client, params httprouter.Params) *http.Request { ctx := context.WithValue(request.Context(), httprouter.ParamsKey, params) ctx = client.NewContext(ctx, apiClient) return request.WithContext(ctx) } func TestTaskListAndCreateWebFlow(t *testing.T) { var created client.TaskInput apiHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") switch { case r.Method == http.MethodGet && r.URL.Path == "/v1/gardens/3": _, _ = w.Write([]byte(`{"garden":{"id":3,"name":"Hinterhof"}}`)) case r.Method == http.MethodGet && r.URL.Path == "/v1/gardens/3/tasks": _, _ = w.Write([]byte(`{"tasks":[{"id":7,"garden_id":3,"title":"Tomaten gießen","plant_id":5,"location_id":6,"priority":5},{"id":9,"garden_id":3,"title":"Bereits erledigt","completed_at":"2026-09-01T10:00:00Z"}]}`)) case r.Method == http.MethodGet && r.URL.Path == "/v1/gardens/3/plants": _, _ = w.Write([]byte(`{"plants":[{"id":5,"garden_id":3,"name":"Tomate"}]}`)) case r.Method == http.MethodGet && r.URL.Path == "/v1/gardens/3/locations": _, _ = w.Write([]byte(`{"locations":[{"id":6,"garden_id":3,"name":"Beet"}]}`)) case r.Method == http.MethodGet && r.URL.Path == "/v1/task-priorities": _, _ = w.Write([]byte(`{"priorities":[{"id":1,"name":"Normal","value":0,"active":true},{"id":2,"name":"Hoch","value":5,"active":true}]}`)) case r.Method == http.MethodPost && r.URL.Path == "/v1/gardens/3/tasks": body, _ := io.ReadAll(r.Body) if err := json.Unmarshal(body, &created); err != nil { t.Fatal(err) } w.WriteHeader(http.StatusCreated) _, _ = w.Write([]byte(`{"task":{"id":8,"garden_id":3,"title":"Ernten"}}`)) default: http.NotFound(w, r) } }) app := newAPIBackedTestApplication(t, apiHandler) params := httprouter.Params{{Key: "gardenID", Value: "3"}} listRequest := taskWebRequest(httptest.NewRequest(http.MethodGet, "/g/3/tasks", nil), app.apiClient, params) listResponse := httptest.NewRecorder() app.tasks(listResponse, listRequest) if listResponse.Code != http.StatusOK || !strings.Contains(listResponse.Body.String(), "Tomaten gießen") || !strings.Contains(listResponse.Body.String(), "Pflanze: Tomate") || strings.Contains(listResponse.Body.String(), "Bereits erledigt") { t.Fatalf("task list: status=%d body=%s", listResponse.Code, listResponse.Body.String()) } form := url.Values{"title": {"Ernten"}, "plant_id": {"5"}, "location_id": {"6"}, "priority": {"3"}, "due_at_start": {"2026-09-03T08:00"}, "due_at_end": {"2026-09-03T18:00"}, "recurrence": {"weekly"}, "recurrence_interval": {"2"}} createRequest := httptest.NewRequest(http.MethodPost, "/g/3/tasks/new", strings.NewReader(form.Encode())) createRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded") createRequest = taskWebRequest(createRequest, app.apiClient, params) createResponse := httptest.NewRecorder() app.taskSave(createResponse, createRequest) if createResponse.Code != http.StatusSeeOther || createResponse.Header().Get("Location") != "/g/3/tasks" { t.Fatalf("create redirect: status=%d location=%q body=%s", createResponse.Code, createResponse.Header().Get("Location"), createResponse.Body.String()) } if created.Title == nil || *created.Title != "Ernten" || created.PlantID == nil || *created.PlantID != 5 || created.DueAtEnd == nil || created.Recurrence == nil || *created.Recurrence != "weekly" || created.RecurrenceInterval == nil || *created.RecurrenceInterval != 2 { t.Errorf("created task input: %+v", created) } } func TestCollectionPageSizeUsesValidatedUserPreference(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "/g/3/tasks", nil) request = request.WithContext(context.WithValue(request.Context(), userContextKey, client.User{ID: 7})) request.AddCookie(&http.Cookie{Name: "gardomatic.entries-per-page.7", Value: "50"}) if got := collectionPageSize(request); got != 50 { t.Fatalf("collectionPageSize = %d, want 50", got) } request = httptest.NewRequest(http.MethodGet, "/g/3/tasks", nil) request.AddCookie(&http.Cookie{Name: "gardomatic.entries-per-page", Value: "17"}) if got := collectionPageSize(request); got != 20 { t.Fatalf("invalid collectionPageSize = %d, want default 20", got) } }