summaryrefslogtreecommitdiff
path: root/internal/tui/flamegraph/model_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-05 22:35:56 +0200
committerPaul Buetow <paul@buetow.org>2026-03-05 22:35:56 +0200
commit3307447e4ae159b11bbe262ad161d6e3c571ee4c (patch)
tree69f508b120715e102f8508ca88e4cbc8adf74a23 /internal/tui/flamegraph/model_test.go
parent6948ab9b8880b318e43590bba8ecab77552348c3 (diff)
task 358: add flamegraph keyboard navigation
Diffstat (limited to 'internal/tui/flamegraph/model_test.go')
-rw-r--r--internal/tui/flamegraph/model_test.go83
1 files changed, 83 insertions, 0 deletions
diff --git a/internal/tui/flamegraph/model_test.go b/internal/tui/flamegraph/model_test.go
index 1e472ae..4569296 100644
--- a/internal/tui/flamegraph/model_test.go
+++ b/internal/tui/flamegraph/model_test.go
@@ -3,6 +3,8 @@ package flamegraph
import (
coreflamegraph "ior/internal/flamegraph"
"testing"
+
+ tea "charm.land/bubbletea/v2"
)
func TestNewModelDefaults(t *testing.T) {
@@ -48,3 +50,84 @@ func TestRefreshFromLiveTrieTracksVersionAndSnapshot(t *testing.T) {
t.Fatalf("expected no refresh when version is unchanged")
}
}
+
+func TestKeyboardNavigationDeepNarrowTree(t *testing.T) {
+ m := NewModel(nil)
+ m.frames = []tuiFrame{
+ {Name: "root", Depth: 0, Col: 0, Path: "root"},
+ {Name: "child", Depth: 1, Col: 0, Path: "root" + pathSeparator + "child"},
+ {Name: "leaf", Depth: 2, Col: 0, Path: "root" + pathSeparator + "child" + pathSeparator + "leaf"},
+ }
+
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'k'}[0], Text: "k"})
+ if m.selectedIdx != 1 {
+ t.Fatalf("expected selection to move deeper to idx 1, got %d", m.selectedIdx)
+ }
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'k'}[0], Text: "k"})
+ if m.selectedIdx != 2 {
+ t.Fatalf("expected selection to move deeper to idx 2, got %d", m.selectedIdx)
+ }
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'j'}[0], Text: "j"})
+ if m.selectedIdx != 1 {
+ t.Fatalf("expected selection to move shallower to idx 1, got %d", m.selectedIdx)
+ }
+}
+
+func TestKeyboardNavigationShallowWideSiblings(t *testing.T) {
+ m := NewModel(nil)
+ m.frames = []tuiFrame{
+ {Name: "root", Depth: 0, Col: 0, Path: "root"},
+ {Name: "A", Depth: 1, Col: 0, Path: "root" + pathSeparator + "A"},
+ {Name: "B", Depth: 1, Col: 30, Path: "root" + pathSeparator + "B"},
+ {Name: "C", Depth: 1, Col: 60, Path: "root" + pathSeparator + "C"},
+ }
+
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'k'}[0], Text: "k"})
+ if m.selectedIdx != 1 {
+ t.Fatalf("expected first deeper frame to be A, got idx %d", m.selectedIdx)
+ }
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'l'}[0], Text: "l"})
+ if m.selectedIdx != 2 {
+ t.Fatalf("expected next sibling B, got idx %d", m.selectedIdx)
+ }
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'l'}[0], Text: "l"})
+ if m.selectedIdx != 3 {
+ t.Fatalf("expected next sibling C, got idx %d", m.selectedIdx)
+ }
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'l'}[0], Text: "l"})
+ if m.selectedIdx != 3 {
+ t.Fatalf("expected selection to clamp at last sibling, got idx %d", m.selectedIdx)
+ }
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: []rune{'h'}[0], Text: "h"})
+ if m.selectedIdx != 2 {
+ t.Fatalf("expected previous sibling B, got idx %d", m.selectedIdx)
+ }
+}
+
+func TestKeyboardNavigationSingleNodeClamped(t *testing.T) {
+ m := NewModel(nil)
+ m.frames = []tuiFrame{{Name: "root", Depth: 0, Col: 0, Path: "root"}}
+
+ keys := []tea.KeyPressMsg{
+ {Code: []rune{'j'}[0], Text: "j"},
+ {Code: []rune{'k'}[0], Text: "k"},
+ {Code: []rune{'h'}[0], Text: "h"},
+ {Code: []rune{'l'}[0], Text: "l"},
+ {Code: tea.KeyDown},
+ {Code: tea.KeyUp},
+ {Code: tea.KeyLeft},
+ {Code: tea.KeyRight},
+ }
+ for _, keyMsg := range keys {
+ m = pressFlameKey(t, m, keyMsg)
+ if m.selectedIdx != 0 {
+ t.Fatalf("expected single-node selection to stay at idx 0, got %d", m.selectedIdx)
+ }
+ }
+}
+
+func pressFlameKey(t *testing.T, m Model, keyMsg tea.KeyPressMsg) Model {
+ t.Helper()
+ next, _ := m.Update(keyMsg)
+ return next.(Model)
+}