| 1 | package cli |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | |
| 7 | "github.com/charmbracelet/x/ansi" |
| 8 | "reasonix/internal/event" |
| 9 | ) |
| 10 | |
| 11 | // TestRenderTodoPanelIsFlat proves retired hierarchy fields do not affect the |
| 12 | // pinned task panel. |
| 13 | func TestRenderTodoPanelIsFlat(t *testing.T) { |
| 14 | m := newTestChatTUI() |
| 15 | m.width = 60 |
| 16 | m.todos = []event.Todo{ |
| 17 | {Content: "Phase A", Status: "in_progress"}, |
| 18 | {Content: "sub one", Status: "pending"}, |
| 19 | } |
| 20 | |
| 21 | out := ansi.Strip(m.renderTodoPanel()) |
| 22 | if !strings.Contains(out, "Phase A") { |
| 23 | t.Fatalf("panel missing phase:\n%s", out) |
| 24 | } |
| 25 | if !strings.Contains(out, " ○ sub one") { |
| 26 | t.Fatalf("todo should render at the same flat depth:\n%s", out) |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | func TestRenderTodoPanelScrollsToInProgressTodo(t *testing.T) { |
| 31 | m := newTestChatTUI() |
| 32 | m.width = 72 |
| 33 | m.todos = []event.Todo{ |
| 34 | {Content: "Item 01", Status: "completed"}, {Content: "Item 02", Status: "completed"}, |
| 35 | {Content: "Item 03", Status: "completed"}, {Content: "Item 04", Status: "completed"}, |
| 36 | {Content: "Item 05", Status: "completed"}, {Content: "Item 06", Status: "completed"}, |
| 37 | {Content: "Item 07", Status: "completed"}, {Content: "Item 08", Status: "completed"}, |
| 38 | {Content: "Item 09", Status: "in_progress"}, {Content: "Item 10", Status: "pending"}, |
| 39 | } |
| 40 | |
| 41 | out := ansi.Strip(m.renderTodoPanel()) |
| 42 | if !strings.Contains(out, "Item 09") { |
| 43 | t.Fatalf("panel should keep the in-progress todo visible:\n%s", out) |
| 44 | } |
| 45 | if strings.Contains(out, "Item 01") { |
| 46 | t.Fatalf("panel should window around the active todo instead of pinning the first rows:\n%s", out) |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | func TestRenderTodoPanelKeepsCompletedListVisible(t *testing.T) { |
| 51 | m := newTestChatTUI() |
| 52 | m.width = 60 |
| 53 | m.todos = []event.Todo{{Content: "Verified", Status: "completed"}} |
| 54 | if out := ansi.Strip(m.renderTodoPanel()); !strings.Contains(out, "1/1") || !strings.Contains(out, "Verified") { |
| 55 | t.Fatalf("completed current-turn list must remain inspectable:\n%s", out) |
| 56 | } |
| 57 | } |
| 58 |