summaryrefslogtreecommitdiff
path: root/internal/tui/pidpicker/model_test.go
blob: 7347ecafeb9656025e087b4ebfa75e5872a8b884 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package pidpicker

import (
	"ior/internal/tui/messages"
	"strings"
	"testing"

	tea "github.com/charmbracelet/bubbletea"
)

func TestApplyFilterByPIDCommAndCmdline(t *testing.T) {
	m := NewWithKeys(DefaultKeyMap())
	m.processes = []ProcessInfo{
		{Pid: 100, Comm: "bash", Cmdline: "bash -l"},
		{Pid: 200, Comm: "sshd", Cmdline: "/usr/sbin/sshd -D"},
	}

	m.input.SetValue("200")
	m.applyFilter()
	if len(m.filtered) != 1 || m.filtered[0].Pid != 200 {
		t.Fatalf("expected pid filter to keep only 200, got %+v", m.filtered)
	}

	m.input.SetValue("BASH")
	m.applyFilter()
	if len(m.filtered) != 1 || m.filtered[0].Pid != 100 {
		t.Fatalf("expected comm filter to keep only 100, got %+v", m.filtered)
	}

	m.input.SetValue("/usr/sbin")
	m.applyFilter()
	if len(m.filtered) != 1 || m.filtered[0].Pid != 200 {
		t.Fatalf("expected cmdline filter to keep only 200, got %+v", m.filtered)
	}
}

func TestEnterEmitsAllPIDsAndSelectedPID(t *testing.T) {
	m := NewWithKeys(DefaultKeyMap())
	m.processes = []ProcessInfo{{Pid: 7, Comm: "vim"}, {Pid: 9, Comm: "top"}}
	m.applyFilter()

	modelAny, cmdAny := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
	_ = modelAny
	msgAny := cmdAny()
	pidAny, ok := msgAny.(messages.PidSelectedMsg)
	if !ok {
		t.Fatalf("expected PidSelectedMsg for all-pids selection, got %T", msgAny)
	}
	if pidAny.Pid != 0 {
		t.Fatalf("expected all-pids to emit pid 0, got %d", pidAny.Pid)
	}

	m.selectedIndex = 2
	modelOne, cmdOne := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
	_ = modelOne
	msgOne := cmdOne()
	pidOne, ok := msgOne.(messages.PidSelectedMsg)
	if !ok {
		t.Fatalf("expected PidSelectedMsg for concrete selection, got %T", msgOne)
	}
	if pidOne.Pid != 9 {
		t.Fatalf("expected selected pid 9, got %d", pidOne.Pid)
	}
}

func TestEscQuitsAndRefreshTriggersScan(t *testing.T) {
	m := NewWithKeys(DefaultKeyMap())

	_, escCmd := m.Update(tea.KeyMsg{Type: tea.KeyEsc})
	if escCmd == nil {
		t.Fatalf("expected esc to return quit cmd")
	}
	if msg := escCmd(); msg != (tea.QuitMsg{}) {
		t.Fatalf("expected quit msg from esc, got %T", msg)
	}

	_, refreshCmd := m.Update(tea.KeyMsg{Type: tea.KeyCtrlR})
	if refreshCmd == nil {
		t.Fatalf("expected refresh cmd")
	}
	if _, ok := refreshCmd().(processesLoadedMsg); !ok {
		t.Fatalf("expected refresh to emit processesLoadedMsg")
	}
}

func TestRuneRDoesNotTriggerRefreshWhileFilterFocused(t *testing.T) {
	m := NewWithKeys(DefaultKeyMap())

	next, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'r'}})
	if cmd == nil {
		t.Fatalf("expected textinput update cmd")
	}

	updated := next.(Model)
	if got := updated.input.Value(); got != "r" {
		t.Fatalf("expected filter input to contain typed r, got %q", got)
	}
}

func TestRenderRowsKeepsSelectionVisible(t *testing.T) {
	m := NewWithKeys(DefaultKeyMap())
	m.height = 8 // visible rows == 2
	m.processes = []ProcessInfo{
		{Pid: 1, Comm: "p1"},
		{Pid: 2, Comm: "p2"},
		{Pid: 3, Comm: "p3"},
		{Pid: 4, Comm: "p4"},
	}
	m.applyFilter()
	m.selectedIndex = 4

	rows := m.renderRows()
	if !strings.Contains(rows, "> 4  p4") {
		t.Fatalf("expected selected row to remain visible, got:\n%s", rows)
	}
}