forked from Gitlink/gitlink-cli
121 lines
3.4 KiB
Go
121 lines
3.4 KiB
Go
package interactive
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
|
|
)
|
|
|
|
// makeShortcutForViewport builds a minimal shortcut so formatCommandDisplay has
|
|
// something to render in the display header line of the output viewer.
|
|
func makeShortcutForViewport() *common.Shortcut {
|
|
return &common.Shortcut{
|
|
Name: "list",
|
|
}
|
|
}
|
|
|
|
// TestLongOutputEntersViewport verifies that when command output exceeds the
|
|
// available terminal height, the REPL switches into the scrollable output
|
|
// viewer (stateOutput) instead of falling back to the inline input state.
|
|
func TestLongOutputEntersViewport(t *testing.T) {
|
|
m := newReplModel("owner", "repo")
|
|
// Small terminal: m.height-4 == 1 line of room, so any multi-line output
|
|
// must overflow into the viewport.
|
|
m.height = 5
|
|
m.width = 80
|
|
m.state = stateExecuting
|
|
|
|
longOutput := strings.Repeat("line of output\n", 20)
|
|
msg := execResultMsg{
|
|
group: "issue",
|
|
shortcut: makeShortcutForViewport(),
|
|
args: map[string]string{},
|
|
output: longOutput,
|
|
err: nil,
|
|
}
|
|
|
|
newModel, _ := m.Update(msg)
|
|
repl, ok := newModel.(replModel)
|
|
if !ok {
|
|
t.Fatalf("expected replModel, got %T", newModel)
|
|
}
|
|
|
|
if repl.state != stateOutput {
|
|
t.Fatalf("expected stateOutput for long output, got %v", repl.state)
|
|
}
|
|
if repl.viewport.Height != m.height-2 {
|
|
t.Fatalf("expected viewport height %d, got %d", m.height-2, repl.viewport.Height)
|
|
}
|
|
}
|
|
|
|
// TestShortOutputStaysInput verifies that short command output keeps the
|
|
// existing behaviour: store lastOutput and return to stateInput.
|
|
func TestShortOutputStaysInput(t *testing.T) {
|
|
m := newReplModel("owner", "repo")
|
|
m.height = 40 // plenty of room
|
|
m.width = 80
|
|
m.state = stateExecuting
|
|
|
|
shortOutput := "only one line"
|
|
msg := execResultMsg{
|
|
group: "issue",
|
|
shortcut: makeShortcutForViewport(),
|
|
args: map[string]string{},
|
|
output: shortOutput,
|
|
err: nil,
|
|
}
|
|
|
|
newModel, _ := m.Update(msg)
|
|
repl, ok := newModel.(replModel)
|
|
if !ok {
|
|
t.Fatalf("expected replModel, got %T", newModel)
|
|
}
|
|
|
|
if repl.state != stateInput {
|
|
t.Fatalf("expected stateInput for short output, got %v", repl.state)
|
|
}
|
|
if repl.lastOutput == "" {
|
|
t.Fatalf("expected lastOutput to be set for short output")
|
|
}
|
|
if !strings.Contains(repl.lastOutput, shortOutput) {
|
|
t.Fatalf("expected lastOutput to contain %q, got %q", shortOutput, repl.lastOutput)
|
|
}
|
|
}
|
|
|
|
// TestViewportQuitReturnsToInput verifies that pressing 'q' in the output
|
|
// viewer returns the REPL to the input state.
|
|
func TestViewportQuitReturnsToInput(t *testing.T) {
|
|
m := newReplModel("owner", "repo")
|
|
m.state = stateOutput
|
|
|
|
keyQ := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}}
|
|
newModel, _ := m.Update(keyQ)
|
|
|
|
repl, ok := newModel.(replModel)
|
|
if !ok {
|
|
t.Fatalf("expected replModel, got %T", newModel)
|
|
}
|
|
if repl.state != stateInput {
|
|
t.Fatalf("expected stateInput after pressing 'q', got %v", repl.state)
|
|
}
|
|
}
|
|
|
|
// TestViewportEscReturnsToInput verifies that Esc also exits the output viewer.
|
|
func TestViewportEscReturnsToInput(t *testing.T) {
|
|
m := newReplModel("owner", "repo")
|
|
m.state = stateOutput
|
|
|
|
keyEsc := tea.KeyMsg{Type: tea.KeyEsc}
|
|
newModel, _ := m.Update(keyEsc)
|
|
|
|
repl, ok := newModel.(replModel)
|
|
if !ok {
|
|
t.Fatalf("expected replModel, got %T", newModel)
|
|
}
|
|
if repl.state != stateInput {
|
|
t.Fatalf("expected stateInput after pressing Esc, got %v", repl.state)
|
|
}
|
|
}
|