package tui import ( "testing" "superwork-tui/internal/issue" ) // ── isBlocked truth table ───────────────────────────────────────────────────── func TestIsBlocked_NoPrerequisite(t *testing.T) { it := issue.Issue{Number: 1, Column: issue.ColumnTodo, Prerequisite: 0} if isBlocked(it, []issue.Issue{it}) { t.Error("isBlocked = true, want false when Prerequisite == 0") } } func TestIsBlocked_PrereqInDone(t *testing.T) { prereq := issue.Issue{Number: 2, Column: issue.ColumnDone} it := issue.Issue{Number: 1, Column: issue.ColumnTodo, Prerequisite: 2} if isBlocked(it, []issue.Issue{it, prereq}) { t.Error("isBlocked = true, want false when prerequisite is in ColumnDone") } } func TestIsBlocked_PrereqNotInDone(t *testing.T) { prereq := issue.Issue{Number: 2, Column: issue.ColumnTodo} it := issue.Issue{Number: 1, Column: issue.ColumnTodo, Prerequisite: 2} if !isBlocked(it, []issue.Issue{it, prereq}) { t.Error("isBlocked = false, want true when prerequisite is in ColumnTodo") } } func TestIsBlocked_PrereqInProgress(t *testing.T) { prereq := issue.Issue{Number: 2, Column: issue.ColumnInProgress} it := issue.Issue{Number: 1, Column: issue.ColumnTodo, Prerequisite: 2} if !isBlocked(it, []issue.Issue{it, prereq}) { t.Error("isBlocked = false, want true when prerequisite is in ColumnInProgress") } } func TestIsBlocked_PrereqNotFound(t *testing.T) { it := issue.Issue{Number: 1, Column: issue.ColumnTodo, Prerequisite: 99} if !isBlocked(it, []issue.Issue{it}) { t.Error("isBlocked = false, want true when prerequisite is not found") } } // ── todoDepTree grouping ────────────────────────────────────────────────────── func TestTodoDepTree_NoDeps(t *testing.T) { todos := []issue.Issue{ {Number: 1, Column: issue.ColumnTodo}, {Number: 2, Column: issue.ColumnTodo}, {Number: 3, Column: issue.ColumnTodo}, } entries := todoDepTree(todos) if len(entries) != 3 { t.Fatalf("len = %d, want 3", len(entries)) } for i, e := range entries { if e.indent { t.Errorf("entries[%d].indent = true, want false (no deps)", i) } if e.iss.Number != todos[i].Number { t.Errorf("entries[%d].iss.Number = %d, want %d", i, e.iss.Number, todos[i].Number) } } } func TestTodoDepTree_BlockedChildAfterParent(t *testing.T) { // #2 depends on #1; both in todo. #3 is independent. todos := []issue.Issue{ {Number: 1, Column: issue.ColumnTodo, Prerequisite: 0}, {Number: 2, Column: issue.ColumnTodo, Prerequisite: 1}, {Number: 3, Column: issue.ColumnTodo, Prerequisite: 0}, } entries := todoDepTree(todos) if len(entries) != 3 { t.Fatalf("len = %d, want 3", len(entries)) } // Expected order: #1 (not indented), #2 (indented under #1), #3 (not indented) if entries[0].iss.Number != 1 || entries[0].indent { t.Errorf("entries[0] = {%d, indent=%v}, want {1, false}", entries[0].iss.Number, entries[0].indent) } if entries[1].iss.Number != 2 || !entries[1].indent { t.Errorf("entries[1] = {%d, indent=%v}, want {2, true}", entries[1].iss.Number, entries[1].indent) } if entries[2].iss.Number != 3 || entries[2].indent { t.Errorf("entries[2] = {%d, indent=%v}, want {3, false}", entries[2].iss.Number, entries[2].indent) } } func TestTodoDepTree_ParentNotInTodo(t *testing.T) { // #1 depends on #99 which is not in the todo list → #1 appears at top level. todos := []issue.Issue{ {Number: 1, Column: issue.ColumnTodo, Prerequisite: 99}, {Number: 2, Column: issue.ColumnTodo, Prerequisite: 0}, } entries := todoDepTree(todos) if len(entries) != 2 { t.Fatalf("len = %d, want 2", len(entries)) } if entries[0].iss.Number != 1 || entries[0].indent { t.Errorf("entries[0] = {%d, indent=%v}, want {1, false}", entries[0].iss.Number, entries[0].indent) } if entries[1].iss.Number != 2 || entries[1].indent { t.Errorf("entries[1] = {%d, indent=%v}, want {2, false}", entries[1].iss.Number, entries[1].indent) } } func TestTodoDepTree_AllEmitted(t *testing.T) { // Ensure no duplicates and all issues appear exactly once. todos := []issue.Issue{ {Number: 10, Column: issue.ColumnTodo, Prerequisite: 0}, {Number: 11, Column: issue.ColumnTodo, Prerequisite: 10}, {Number: 12, Column: issue.ColumnTodo, Prerequisite: 10}, } entries := todoDepTree(todos) if len(entries) != 3 { t.Fatalf("len = %d, want 3", len(entries)) } seen := make(map[int]int) for _, e := range entries { seen[e.iss.Number]++ } for _, iss := range todos { if seen[iss.Number] != 1 { t.Errorf("issue #%d appeared %d times, want 1", iss.Number, seen[iss.Number]) } } }