okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

dawntui: tree and context inspector on listView, shared confirm for agent delete78011da

main
3.1 KiB81 linesraw
1// The context inspector shows the prepared request's standing and each
2// section's facts without enter, filters sections by typing, and scrolls a
3// section's content in its own reader. The reader's body height is only known
4// to the frame, so these drive View first and then assert the scroll it allows.
5package tui
6
7import (
8	"albedo/cli/internal/daemon"
9	"strings"
10	"testing"
11
12	tea "charm.land/bubbletea/v2"
13	"github.com/charmbracelet/x/ansi"
14)
15
16func contextFixture(t *testing.T) ContextInspectorModel {
17	t.Helper()
18	m := NewContextInspectorModel(nil, "s")
19	m.SetSize(120, 30)
20	m, _ = m.Update(contextSnapshotLoadedMsg{Gen: m.Generation, Snapshot: &daemon.ContextSnapshot{
21		State: "ready", Provider: "claude", Model: "claude-x", Protocol: "messages",
22		Sections: []daemon.ContextSection{
23			{ID: "history", Label: "History", Kind: "history", Source: "transcript", Pages: 2, ByteCount: 4096, Preview: "user: hello"},
24			{ID: "system", Label: "System", Kind: "system", Source: "instructions"},
25		},
26	}})
27	if m.Snapshot == nil || len(m.shown) != 2 {
28		t.Fatal("fixture snapshot did not load")
29	}
30	return m
31}
32
33func TestContextShowsRequestAndSectionFactsWithoutEnter(t *testing.T) {
34	m := contextFixture(t)
35	view := ansi.Strip(m.View())
36	if !strings.Contains(view, "claude · claude-x · messages") || !strings.Contains(view, "read-only") {
37		t.Fatalf("the prepared request should show above the sections:\n%s", view)
38	}
39	if !strings.Contains(view, "2 pages") || !strings.Contains(view, "transcript") {
40		t.Fatalf("the highlighted section's facts should show without opening it:\n%s", view)
41	}
42}
43
44func TestContextFilterSectionsByTyping(t *testing.T) {
45	m := contextFixture(t)
46	for _, r := range "sys" {
47		m, _ = m.Update(tea.KeyPressMsg{Code: r, Text: string(r)})
48	}
49	view := ansi.Strip(m.View())
50	if strings.Contains(view, "History") || !strings.Contains(view, "System") {
51		t.Fatalf("typing should filter the sections:\n%s", view)
52	}
53	if row, _ := m.highlighted(); row.key != "system" {
54		t.Fatalf("the filter left %q under the cursor", row.key)
55	}
56}
57
58func TestContextReaderScrollsAndReturnsOnEsc(t *testing.T) {
59	m := contextFixture(t)
60	m, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
61	if m.Detail == nil {
62		t.Fatal("enter should open the section reader")
63	}
64	content := strings.Repeat("history line\n", 80)
65	m, _ = m.Update(contextPageLoadedMsg{Gen: m.Generation, SectionID: "history", Data: &daemon.ContextPage{Content: content}})
66	m.View()
67	m, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyDown})
68	m, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyDown})
69	m, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyDown})
70	if m.Detail.Scroll != 3 {
71		t.Fatalf("down should scroll one line each press, got %d", m.Detail.Scroll)
72	}
73	m, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyPgDown})
74	if m.Detail.Scroll <= 3 || m.Detail.Scroll > len(m.Detail.wrapped) {
75		t.Fatalf("pgdown should jump by a body of rows, stayed inside the content: %d", m.Detail.Scroll)
76	}
77	m, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyEscape})
78	if m.Detail != nil || !strings.Contains(ansi.Strip(m.View()), "claude-x") {
79		t.Fatal("esc should return to the sections")
80	}
81}