Refactor TestLabelCommands and TestReopenCommand to reduce complexity
- TestLabelCommands: 67 → <10 using labelTestHelper - TestReopenCommand: 37 → <10 using reopenTestHelper - All tests pass - Progress on bd-55 Amp-Thread-ID: https://ampcode.com/threads/T-0a5a623d-42f0-4b36-96ed-809285a748cb Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -10,6 +10,89 @@ import (
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
)
|
||||
|
||||
type reopenTestHelper struct {
|
||||
s *sqlite.SQLiteStorage
|
||||
ctx context.Context
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) createIssue(title string, issueType types.IssueType, priority int) *types.Issue {
|
||||
issue := &types.Issue{
|
||||
Title: title,
|
||||
Priority: priority,
|
||||
IssueType: issueType,
|
||||
Status: types.StatusOpen,
|
||||
}
|
||||
if err := h.s.CreateIssue(h.ctx, issue, "test-user"); err != nil {
|
||||
h.t.Fatalf("Failed to create issue: %v", err)
|
||||
}
|
||||
return issue
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) closeIssue(issueID, reason string) {
|
||||
if err := h.s.CloseIssue(h.ctx, issueID, "test-user", reason); err != nil {
|
||||
h.t.Fatalf("Failed to close issue: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) reopenIssue(issueID string) {
|
||||
updates := map[string]interface{}{
|
||||
"status": string(types.StatusOpen),
|
||||
}
|
||||
if err := h.s.UpdateIssue(h.ctx, issueID, updates, "test-user"); err != nil {
|
||||
h.t.Fatalf("Failed to reopen issue: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) getIssue(issueID string) *types.Issue {
|
||||
issue, err := h.s.GetIssue(h.ctx, issueID)
|
||||
if err != nil {
|
||||
h.t.Fatalf("Failed to get issue: %v", err)
|
||||
}
|
||||
return issue
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) addComment(issueID, comment string) {
|
||||
if err := h.s.AddComment(h.ctx, issueID, "test-user", comment); err != nil {
|
||||
h.t.Fatalf("Failed to add comment: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) assertStatus(issueID string, expected types.Status) {
|
||||
issue := h.getIssue(issueID)
|
||||
if issue.Status != expected {
|
||||
h.t.Errorf("Expected status %s, got %s", expected, issue.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) assertClosedAtSet(issueID string) {
|
||||
issue := h.getIssue(issueID)
|
||||
if issue.ClosedAt == nil {
|
||||
h.t.Error("Expected ClosedAt to be set")
|
||||
}
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) assertClosedAtNil(issueID string) {
|
||||
issue := h.getIssue(issueID)
|
||||
if issue.ClosedAt != nil {
|
||||
h.t.Errorf("Expected ClosedAt to be nil, got %v", issue.ClosedAt)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *reopenTestHelper) assertCommentEvent(issueID, comment string) {
|
||||
events, err := h.s.GetEvents(h.ctx, issueID, 100)
|
||||
if err != nil {
|
||||
h.t.Fatalf("Failed to get events: %v", err)
|
||||
}
|
||||
|
||||
for _, e := range events {
|
||||
if e.EventType == types.EventCommented && e.Comment != nil && *e.Comment == comment {
|
||||
return
|
||||
}
|
||||
}
|
||||
h.t.Errorf("Expected to find comment event with reason '%s'", comment)
|
||||
}
|
||||
|
||||
func TestReopenCommand(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "bd-test-reopen-*")
|
||||
if err != nil {
|
||||
@@ -25,187 +108,42 @@ func TestReopenCommand(t *testing.T) {
|
||||
defer s.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
h := &reopenTestHelper{s: s, ctx: ctx, t: t}
|
||||
|
||||
t.Run("reopen closed issue", func(t *testing.T) {
|
||||
issue := &types.Issue{
|
||||
Title: "Test Issue",
|
||||
Description: "Test description",
|
||||
Priority: 1,
|
||||
IssueType: types.TypeBug,
|
||||
Status: types.StatusOpen,
|
||||
}
|
||||
|
||||
if err := s.CreateIssue(ctx, issue, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to create issue: %v", err)
|
||||
}
|
||||
|
||||
if err := s.CloseIssue(ctx, issue.ID, "test-user", "Closing for test"); err != nil {
|
||||
t.Fatalf("Failed to close issue: %v", err)
|
||||
}
|
||||
|
||||
closed, err := s.GetIssue(ctx, issue.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get closed issue: %v", err)
|
||||
}
|
||||
if closed.Status != types.StatusClosed {
|
||||
t.Errorf("Expected status to be closed, got %s", closed.Status)
|
||||
}
|
||||
if closed.ClosedAt == nil {
|
||||
t.Error("Expected ClosedAt to be set")
|
||||
}
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"status": string(types.StatusOpen),
|
||||
}
|
||||
if err := s.UpdateIssue(ctx, issue.ID, updates, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to reopen issue: %v", err)
|
||||
}
|
||||
|
||||
reopened, err := s.GetIssue(ctx, issue.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get reopened issue: %v", err)
|
||||
}
|
||||
if reopened.Status != types.StatusOpen {
|
||||
t.Errorf("Expected status to be open, got %s", reopened.Status)
|
||||
}
|
||||
if reopened.ClosedAt != nil {
|
||||
t.Errorf("Expected ClosedAt to be nil, got %v", reopened.ClosedAt)
|
||||
}
|
||||
issue := h.createIssue("Test Issue", types.TypeBug, 1)
|
||||
h.closeIssue(issue.ID, "Closing for test")
|
||||
h.assertStatus(issue.ID, types.StatusClosed)
|
||||
h.assertClosedAtSet(issue.ID)
|
||||
h.reopenIssue(issue.ID)
|
||||
h.assertStatus(issue.ID, types.StatusOpen)
|
||||
h.assertClosedAtNil(issue.ID)
|
||||
})
|
||||
|
||||
t.Run("reopen with reason adds comment", func(t *testing.T) {
|
||||
issue := &types.Issue{
|
||||
Title: "Test Issue 2",
|
||||
Description: "Test description",
|
||||
Priority: 1,
|
||||
IssueType: types.TypeTask,
|
||||
Status: types.StatusOpen,
|
||||
}
|
||||
|
||||
if err := s.CreateIssue(ctx, issue, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to create issue: %v", err)
|
||||
}
|
||||
|
||||
if err := s.CloseIssue(ctx, issue.ID, "test-user", "Done"); err != nil {
|
||||
t.Fatalf("Failed to close issue: %v", err)
|
||||
}
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"status": string(types.StatusOpen),
|
||||
}
|
||||
if err := s.UpdateIssue(ctx, issue.ID, updates, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to reopen issue: %v", err)
|
||||
}
|
||||
|
||||
issue := h.createIssue("Test Issue 2", types.TypeTask, 1)
|
||||
h.closeIssue(issue.ID, "Done")
|
||||
h.reopenIssue(issue.ID)
|
||||
reason := "Found a regression"
|
||||
if err := s.AddComment(ctx, issue.ID, "test-user", reason); err != nil {
|
||||
t.Fatalf("Failed to add comment: %v", err)
|
||||
}
|
||||
|
||||
events, err := s.GetEvents(ctx, issue.ID, 100)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get events: %v", err)
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, e := range events {
|
||||
if e.EventType == types.EventCommented && e.Comment != nil && *e.Comment == reason {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("Expected to find comment event with reason '%s'", reason)
|
||||
}
|
||||
h.addComment(issue.ID, reason)
|
||||
h.assertCommentEvent(issue.ID, reason)
|
||||
})
|
||||
|
||||
t.Run("reopen multiple issues", func(t *testing.T) {
|
||||
issue1 := &types.Issue{
|
||||
Title: "Multi Test 1",
|
||||
Priority: 1,
|
||||
IssueType: types.TypeBug,
|
||||
Status: types.StatusOpen,
|
||||
}
|
||||
issue2 := &types.Issue{
|
||||
Title: "Multi Test 2",
|
||||
Priority: 1,
|
||||
IssueType: types.TypeBug,
|
||||
Status: types.StatusOpen,
|
||||
}
|
||||
|
||||
if err := s.CreateIssue(ctx, issue1, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to create issue1: %v", err)
|
||||
}
|
||||
if err := s.CreateIssue(ctx, issue2, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to create issue2: %v", err)
|
||||
}
|
||||
|
||||
if err := s.CloseIssue(ctx, issue1.ID, "test-user", "Done"); err != nil {
|
||||
t.Fatalf("Failed to close issue1: %v", err)
|
||||
}
|
||||
if err := s.CloseIssue(ctx, issue2.ID, "test-user", "Done"); err != nil {
|
||||
t.Fatalf("Failed to close issue2: %v", err)
|
||||
}
|
||||
|
||||
updates1 := map[string]interface{}{
|
||||
"status": string(types.StatusOpen),
|
||||
}
|
||||
if err := s.UpdateIssue(ctx, issue1.ID, updates1, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to reopen issue1: %v", err)
|
||||
}
|
||||
|
||||
updates2 := map[string]interface{}{
|
||||
"status": string(types.StatusOpen),
|
||||
}
|
||||
if err := s.UpdateIssue(ctx, issue2.ID, updates2, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to reopen issue2: %v", err)
|
||||
}
|
||||
|
||||
reopened1, err := s.GetIssue(ctx, issue1.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get issue1: %v", err)
|
||||
}
|
||||
reopened2, err := s.GetIssue(ctx, issue2.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get issue2: %v", err)
|
||||
}
|
||||
|
||||
if reopened1.Status != types.StatusOpen {
|
||||
t.Errorf("Expected issue1 status to be open, got %s", reopened1.Status)
|
||||
}
|
||||
if reopened2.Status != types.StatusOpen {
|
||||
t.Errorf("Expected issue2 status to be open, got %s", reopened2.Status)
|
||||
}
|
||||
issue1 := h.createIssue("Multi Test 1", types.TypeBug, 1)
|
||||
issue2 := h.createIssue("Multi Test 2", types.TypeBug, 1)
|
||||
h.closeIssue(issue1.ID, "Done")
|
||||
h.closeIssue(issue2.ID, "Done")
|
||||
h.reopenIssue(issue1.ID)
|
||||
h.reopenIssue(issue2.ID)
|
||||
h.assertStatus(issue1.ID, types.StatusOpen)
|
||||
h.assertStatus(issue2.ID, types.StatusOpen)
|
||||
})
|
||||
|
||||
t.Run("reopen already open issue is no-op", func(t *testing.T) {
|
||||
issue := &types.Issue{
|
||||
Title: "Already Open",
|
||||
Priority: 1,
|
||||
IssueType: types.TypeTask,
|
||||
Status: types.StatusOpen,
|
||||
}
|
||||
|
||||
if err := s.CreateIssue(ctx, issue, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to create issue: %v", err)
|
||||
}
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"status": string(types.StatusOpen),
|
||||
}
|
||||
if err := s.UpdateIssue(ctx, issue.ID, updates, "test-user"); err != nil {
|
||||
t.Fatalf("Failed to update issue: %v", err)
|
||||
}
|
||||
|
||||
updated, err := s.GetIssue(ctx, issue.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get issue: %v", err)
|
||||
}
|
||||
if updated.Status != types.StatusOpen {
|
||||
t.Errorf("Expected status to remain open, got %s", updated.Status)
|
||||
}
|
||||
if updated.ClosedAt != nil {
|
||||
t.Errorf("Expected ClosedAt to remain nil, got %v", updated.ClosedAt)
|
||||
}
|
||||
issue := h.createIssue("Already Open", types.TypeTask, 1)
|
||||
h.reopenIssue(issue.ID)
|
||||
h.assertStatus(issue.ID, types.StatusOpen)
|
||||
h.assertClosedAtNil(issue.ID)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user