summaryrefslogtreecommitdiff
path: root/internal/tui/flamegraph/model_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-06 14:44:34 +0200
committerPaul Buetow <paul@buetow.org>2026-03-06 14:44:34 +0200
commit479f399aae8d3b28d9714214ea624d4a8cc0e886 (patch)
tree0609eee6378d170b3e6a4601560f58e98bf09cc8 /internal/tui/flamegraph/model_test.go
parent3e08a3d199fdf603b7c0a4002ca9822b6ecf2575 (diff)
flamegraph: keep non-matches visible in filter and add pgup/pgdn selection jumps
Diffstat (limited to 'internal/tui/flamegraph/model_test.go')
-rw-r--r--internal/tui/flamegraph/model_test.go70
1 files changed, 70 insertions, 0 deletions
diff --git a/internal/tui/flamegraph/model_test.go b/internal/tui/flamegraph/model_test.go
index e253c76..093bf34 100644
--- a/internal/tui/flamegraph/model_test.go
+++ b/internal/tui/flamegraph/model_test.go
@@ -193,6 +193,37 @@ func TestHorizontalTraversalFallbackFromRoot(t *testing.T) {
}
}
+func TestPageUpJumpsSelectionToTopMostDepth(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: 40, Path: "root" + pathSeparator + "B"},
+ {Name: "A1", Depth: 2, Col: 0, Path: "root" + pathSeparator + "A" + pathSeparator + "A1"},
+ {Name: "B1", Depth: 2, Col: 40, Path: "root" + pathSeparator + "B" + pathSeparator + "B1"},
+ {Name: "A2", Depth: 3, Col: 0, Path: "root" + pathSeparator + "A" + pathSeparator + "A1" + pathSeparator + "A2"},
+ {Name: "B2", Depth: 3, Col: 40, Path: "root" + pathSeparator + "B" + pathSeparator + "B1" + pathSeparator + "B2"},
+ }
+ m.selectedIdx = mustFrameIndex(t, m.frames, "root"+pathSeparator+"B"+pathSeparator+"B1")
+
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: tea.KeyPgUp})
+ if got, want := m.frames[m.selectedIdx].Path, "root"+pathSeparator+"B"+pathSeparator+"B1"+pathSeparator+"B2"; got != want {
+ t.Fatalf("expected pgup to jump to deepest top frame %q, got %q", want, got)
+ }
+}
+
+func TestPageDownJumpsSelectionToCurrentViewRoot(t *testing.T) {
+ m := newZoomModel()
+ m.selectedIdx = mustFrameIndex(t, m.frames, "root"+pathSeparator+"A")
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: tea.KeyEnter})
+ m.selectedIdx = mustFrameIndex(t, m.frames, "root"+pathSeparator+"A"+pathSeparator+"A1")
+
+ m = pressFlameKey(t, m, tea.KeyPressMsg{Code: tea.KeyPgDown})
+ if got, want := m.frames[m.selectedIdx].Path, "root"+pathSeparator+"A"; got != want {
+ t.Fatalf("expected pgdn to jump to current zoom root %q, got %q", want, got)
+ }
+}
+
func TestPausedStateStillAllowsNavigation(t *testing.T) {
m := NewModel(nil)
m.frames = []tuiFrame{
@@ -635,6 +666,45 @@ func TestViewIncludesSelectionStatusBar(t *testing.T) {
}
}
+func TestViewFilterSelectionStatusUsesFilteredTotalAndKeepsContextVisible(t *testing.T) {
+ snapshot := &snapshotNode{
+ Name: "root",
+ Total: 100,
+ Children: []*snapshotNode{
+ {
+ Name: "keep",
+ Total: 60,
+ Children: []*snapshotNode{
+ {Name: "needle", Total: 60},
+ },
+ },
+ {
+ Name: "drop",
+ Total: 40,
+ Children: []*snapshotNode{
+ {Name: "noise", Total: 40},
+ },
+ },
+ },
+ }
+ m := NewModel(nil)
+ m.width = 220
+ m.height = 12
+ m.frames = BuildTerminalLayout(snapshot, m.width, m.height)
+ m.globalTotal = 100
+ m.selectedIdx = mustFrameIndex(t, m.frames, "root"+pathSeparator+"keep"+pathSeparator+"needle")
+ m.searchQuery = "needle"
+ m.recomputeFilterState()
+
+ view := m.View().Content
+ if !strings.Contains(view, "100.00% filter") {
+ t.Fatalf("expected filtered selection share in status line, got %q", view)
+ }
+ if !strings.Contains(view, "drop") || !strings.Contains(view, "noise") {
+ t.Fatalf("expected non-matching branches to remain visible while filtering, got %q", view)
+ }
+}
+
func TestControlCycleFieldOrderReconfiguresLiveTrie(t *testing.T) {
liveTrie := coreflamegraph.NewLiveTrie([]string{"comm", "path", "tracepoint"}, "count")
m := NewModel(liveTrie)