internal/tui/app_test.go

package tui

import (
	"strings"
	"testing"
	"time"

	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/x/exp/teatest"

	"mercemay.top/httptap/internal/parser"
)

func TestAppInitView(t *testing.T) {
	tm := teatest.NewTestModel(t, New(),
		teatest.WithInitialTermSize(100, 30))
	tm.Send(tea.WindowSizeMsg{Width: 100, Height: 30})

	teatest.WaitFor(t, tm.Output(), func(bts []byte) bool {
		return len(bts) > 0
	}, teatest.WithDuration(time.Second))

	tm.Send(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}})
	tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second))
}

func TestAppAppendMessage(t *testing.T) {
	a := New()
	a.width, a.height = 100, 30
	a.relayout()
	updated, _ := a.Update(MessageReceivedMsg{
		M: parser.Message{StartLine: "GET / HTTP/1.1"},
	})
	out := updated.(App).View()
	if !strings.Contains(out, "GET") {
		t.Errorf("view missing request: %q", out)
	}
}

func TestAppFocusCycle(t *testing.T) {
	a := New()
	a.width, a.height = 120, 40
	a.relayout()
	if a.focus != focusList {
		t.Fatalf("initial focus = %d", a.focus)
	}
	next, _ := a.Update(tea.KeyMsg{Type: tea.KeyTab})
	a = next.(App)
	// Tab is not mapped by default — focus should stay on list.
	if a.focus != focusList {
		t.Errorf("unexpected focus after Tab: %d", a.focus)
	}
}

func TestAppQuitKey(t *testing.T) {
	a := New()
	_, cmd := a.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}})
	if cmd == nil {
		t.Fatal("expected tea.Quit cmd")
	}
}

func TestAppRelayoutNarrow(t *testing.T) {
	a := New()
	a.width, a.height = 40, 20
	a.relayout()
	if a.list.Height() == 0 || a.detail.Height() == 0 {
		t.Errorf("relayout produced zero-height pane: list=%d detail=%d",
			a.list.Height(), a.detail.Height())
	}
}

func TestAppWithTeatestNoSegfault(t *testing.T) {
	tm := teatest.NewTestModel(t, New())
	tm.Send(tea.Quit())
	tm.WaitFinished(t)
}