summaryrefslogtreecommitdiff
path: root/internal/handlers/defer_atom_test.go
blob: 1a626d50f4d1ccb8e3eb95a17bb787e024b1a198 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package handlers

import (
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"task-dashboard/internal/config"
	"task-dashboard/internal/models"
)

func TestHandleDeferAtom_ReturnsActiveBucketItemToDormant(t *testing.T) {
	db, cleanup := setupTestDB(t)
	defer cleanup()
	h := &Handler{store: db, config: &config.Config{}}

	// pick_n=1 plus a reserve item added after the cycle runs, so deferring
	// task-1 backfills with the reserve rather than immediately re-picking
	// task-1 itself (the only-item-in-pool case is a degenerate edge case
	// covered at the store layer).
	bucket, err := h.store.CreateBucket("Gutters", 30, 1)
	if err != nil {
		t.Fatal(err)
	}
	if err := h.store.CreateNativeTask(models.Task{ID: "task-1", Content: "Clean gutters", Priority: 1}); err != nil {
		t.Fatal(err)
	}
	if err := h.store.AddBucketItem(bucket.ID, "task-1"); err != nil {
		t.Fatal(err)
	}
	if _, err := h.store.RunBucketCycles(time.Now()); err != nil {
		t.Fatal(err)
	}
	if err := h.store.CreateNativeTask(models.Task{ID: "reserve", Content: "reserve", Priority: 1}); err != nil {
		t.Fatal(err)
	}
	if err := h.store.AddBucketItem(bucket.ID, "reserve"); err != nil {
		t.Fatal(err)
	}

	req := httptest.NewRequest("POST", "/defer-atom", nil)
	req.Form = map[string][]string{"id": {"task-1"}}
	w := httptest.NewRecorder()
	h.HandleDeferAtom(w, req)

	if w.Code != http.StatusOK {
		t.Fatalf("status = %d, want 200, body=%s", w.Code, w.Body.String())
	}
	if w.Header().Get("HX-Trigger") != "refresh-tasks" {
		t.Errorf("HX-Trigger = %q, want refresh-tasks", w.Header().Get("HX-Trigger"))
	}
	updated, err := h.store.GetNativeTaskByID("task-1")
	if err != nil {
		t.Fatal(err)
	}
	if updated.BucketState != "dormant" {
		t.Errorf("BucketState = %q, want dormant", updated.BucketState)
	}
}

func TestHandleDeferAtom_MissingID_Returns400(t *testing.T) {
	db, cleanup := setupTestDB(t)
	defer cleanup()
	h := &Handler{store: db, config: &config.Config{}}

	req := httptest.NewRequest("POST", "/defer-atom", nil)
	req.Form = map[string][]string{"id": {""}}
	w := httptest.NewRecorder()
	h.HandleDeferAtom(w, req)

	if w.Code != http.StatusBadRequest {
		t.Fatalf("status = %d, want 400", w.Code)
	}
}

func TestHandleDeferAtom_NotABucketItem_Returns500(t *testing.T) {
	db, cleanup := setupTestDB(t)
	defer cleanup()
	h := &Handler{store: db, config: &config.Config{}}

	if err := h.store.CreateNativeTask(models.Task{ID: "task-1", Content: "Plain task", Priority: 1}); err != nil {
		t.Fatal(err)
	}

	req := httptest.NewRequest("POST", "/defer-atom", nil)
	req.Form = map[string][]string{"id": {"task-1"}}
	w := httptest.NewRecorder()
	h.HandleDeferAtom(w, req)

	if w.Code != http.StatusInternalServerError {
		t.Fatalf("status = %d, want 500", w.Code)
	}
}