Files
superwork/tui/internal/tui/dep_test.go
T
2026-06-23 05:02:15 +08:00

133 lines
4.7 KiB
Go

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])
}
}
}