summaryrefslogtreecommitdiff
path: root/internal/storage/epic_test.go
blob: dfd5be146bc3d69d7ed79501c7c735b8e1905525 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package storage

import (
	"testing"

	"github.com/thepeterstone/claudomator/internal/story"
)

func TestCreateEpic_AndGetEpic(t *testing.T) {
	db := testDB(t)

	e := &story.Epic{
		ID:              "epic-1",
		Name:            "Bigger Auth Rework",
		Description:     "Overhaul the auth flow.",
		DiscoverySource: "human",
	}
	if err := db.CreateEpic(e); err != nil {
		t.Fatalf("CreateEpic: %v", err)
	}
	// CreateEpic defaults Status to OPEN when unset.
	if e.Status != "OPEN" {
		t.Errorf("Status after create: want OPEN, got %q", e.Status)
	}

	got, err := db.GetEpic("epic-1")
	if err != nil {
		t.Fatalf("GetEpic: %v", err)
	}
	if got.Name != "Bigger Auth Rework" {
		t.Errorf("Name: want %q, got %q", "Bigger Auth Rework", got.Name)
	}
	if got.Description != "Overhaul the auth flow." {
		t.Errorf("Description: want %q, got %q", "Overhaul the auth flow.", got.Description)
	}
	if got.Status != "OPEN" {
		t.Errorf("Status: want OPEN, got %q", got.Status)
	}
	if got.DiscoverySource != "human" {
		t.Errorf("DiscoverySource: want human, got %q", got.DiscoverySource)
	}
	if got.CreatedAt.IsZero() || got.UpdatedAt.IsZero() {
		t.Errorf("expected CreatedAt/UpdatedAt to be set, got %+v", got)
	}
}

func TestGetEpic_NotFound(t *testing.T) {
	db := testDB(t)
	if _, err := db.GetEpic("nope"); err == nil {
		t.Fatal("expected error for missing epic, got nil")
	}
}

func TestListEpics(t *testing.T) {
	db := testDB(t)

	for _, e := range []*story.Epic{
		{ID: "e1", Name: "alpha", Status: "OPEN"},
		{ID: "e2", Name: "beta", Status: "CLOSED"},
		{ID: "e3", Name: "gamma", Status: "OPEN"},
	} {
		if err := db.CreateEpic(e); err != nil {
			t.Fatalf("CreateEpic(%s): %v", e.ID, err)
		}
	}

	all, err := db.ListEpics("")
	if err != nil {
		t.Fatalf("ListEpics: %v", err)
	}
	if len(all) != 3 {
		t.Errorf("want 3 epics, got %d", len(all))
	}

	open, err := db.ListEpics("OPEN")
	if err != nil {
		t.Fatalf("ListEpics(OPEN): %v", err)
	}
	if len(open) != 2 {
		t.Errorf("want 2 OPEN epics, got %d", len(open))
	}
	for _, e := range open {
		if e.Status != "OPEN" {
			t.Errorf("expected only OPEN epics, got %q", e.Status)
		}
	}
}

func TestUpdateEpic(t *testing.T) {
	db := testDB(t)

	e := &story.Epic{ID: "e1", Name: "original", Status: "OPEN"}
	if err := db.CreateEpic(e); err != nil {
		t.Fatalf("CreateEpic: %v", err)
	}
	e.Name = "updated"
	e.Description = "now with a description"
	e.Status = "CLOSED"
	if err := db.UpdateEpic(e); err != nil {
		t.Fatalf("UpdateEpic: %v", err)
	}
	got, err := db.GetEpic("e1")
	if err != nil {
		t.Fatalf("GetEpic: %v", err)
	}
	if got.Name != "updated" {
		t.Errorf("Name after update: want updated, got %q", got.Name)
	}
	if got.Description != "now with a description" {
		t.Errorf("Description after update: want %q, got %q", "now with a description", got.Description)
	}
	// UpdateEpic performs no status-machine validation — CLOSED is accepted
	// as a plain pass-through write, matching UpdateProject's trust level.
	if got.Status != "CLOSED" {
		t.Errorf("Status after update: want CLOSED, got %q", got.Status)
	}
}