test: tests unitarios para pantalla de tests del dashboard
Tests para TestMenuOptions, updateTestsScreen (navegacion, seleccion, generacion de intents), viewTests (render, cursor, last run), testKindLabel, testKindIntent, y navegacion desde main/server menus. Issue: 0023 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// ── TestMenuOptions ─────────────────────────────────────────────────────
|
||||
|
||||
func TestTestMenuOptions_Count(t *testing.T) {
|
||||
opts := TestMenuOptions()
|
||||
if len(opts) != 4 {
|
||||
t.Fatalf("expected 4 test menu options, got %d", len(opts))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTestMenuOptions_Labels(t *testing.T) {
|
||||
opts := TestMenuOptions()
|
||||
expected := []string{"Go Tests", "E2E Tests", "E2E Tests (headed)", "All Tests"}
|
||||
for i, want := range expected {
|
||||
if opts[i].Label != want {
|
||||
t.Errorf("option[%d]: expected label %q, got %q", i, want, opts[i].Label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMainMenuOptions_IncludesTests(t *testing.T) {
|
||||
opts := MainMenuOptions()
|
||||
found := false
|
||||
for _, opt := range opts {
|
||||
if opt.Label == "Tests" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Error("MainMenuOptions should include 'Tests'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMainMenuOptions_TestsBeforeQuit(t *testing.T) {
|
||||
opts := MainMenuOptions()
|
||||
testsIdx, quitIdx := -1, -1
|
||||
for i, opt := range opts {
|
||||
if opt.Label == "Tests" {
|
||||
testsIdx = i
|
||||
}
|
||||
if opt.Label == "Quit" {
|
||||
quitIdx = i
|
||||
}
|
||||
}
|
||||
if testsIdx < 0 || quitIdx < 0 {
|
||||
t.Fatal("expected both Tests and Quit in menu")
|
||||
}
|
||||
if testsIdx >= quitIdx {
|
||||
t.Errorf("Tests (index %d) should come before Quit (index %d)", testsIdx, quitIdx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerMenuOptions_NoRunTests(t *testing.T) {
|
||||
for _, running := range []bool{true, false} {
|
||||
opts := ServerMenuOptions(running)
|
||||
for _, opt := range opts {
|
||||
if opt.Label == "Run Tests" {
|
||||
t.Errorf("ServerMenuOptions(running=%v) should not have 'Run Tests', found it", running)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerMenuOptions_HasTests(t *testing.T) {
|
||||
for _, running := range []bool{true, false} {
|
||||
opts := ServerMenuOptions(running)
|
||||
found := false
|
||||
for _, opt := range opts {
|
||||
if opt.Label == "Tests" {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("ServerMenuOptions(running=%v) should have 'Tests'", running)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── updateTestsScreen ───────────────────────────────────────────────────
|
||||
|
||||
func TestUpdateTestsScreen_Navigation(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 0, WindowHeight: 40}
|
||||
|
||||
m, _ = Update(m, KeyMsg{Str: "down"})
|
||||
if m.Cursor != 1 {
|
||||
t.Errorf("expected cursor 1 after down, got %d", m.Cursor)
|
||||
}
|
||||
|
||||
m, _ = Update(m, KeyMsg{Str: "up"})
|
||||
if m.Cursor != 0 {
|
||||
t.Errorf("expected cursor 0 after up, got %d", m.Cursor)
|
||||
}
|
||||
|
||||
// Can't go below 0
|
||||
m, _ = Update(m, KeyMsg{Str: "up"})
|
||||
if m.Cursor != 0 {
|
||||
t.Errorf("expected cursor 0 clamped, got %d", m.Cursor)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestsScreen_Back(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 2}
|
||||
m, _ = Update(m, KeyMsg{Str: "0"})
|
||||
if m.Screen != ScreenMain {
|
||||
t.Errorf("expected ScreenMain, got %d", m.Screen)
|
||||
}
|
||||
if m.Cursor != 0 {
|
||||
t.Errorf("expected cursor reset to 0, got %d", m.Cursor)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestsScreen_SelectGoTests(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 0}
|
||||
m, intents := Update(m, KeyMsg{Str: "enter"})
|
||||
if len(intents) != 1 || intents[0].Kind != IntentRunGoTests {
|
||||
t.Errorf("expected IntentRunGoTests, got %v", intents)
|
||||
}
|
||||
if m.LastTestKind != TestKindGo {
|
||||
t.Errorf("expected LastTestKind=TestKindGo, got %d", m.LastTestKind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestsScreen_SelectE2ETests(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 1}
|
||||
_, intents := Update(m, KeyMsg{Str: "enter"})
|
||||
if len(intents) != 1 || intents[0].Kind != IntentRunE2ETests {
|
||||
t.Errorf("expected IntentRunE2ETests, got %v", intents)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestsScreen_SelectE2EHeaded(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 2}
|
||||
_, intents := Update(m, KeyMsg{Str: "enter"})
|
||||
if len(intents) != 1 || intents[0].Kind != IntentRunE2EHeadTests {
|
||||
t.Errorf("expected IntentRunE2EHeadTests, got %v", intents)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestsScreen_SelectAllTests(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 3}
|
||||
_, intents := Update(m, KeyMsg{Str: "enter"})
|
||||
if len(intents) != 1 || intents[0].Kind != IntentRunAllTests {
|
||||
t.Errorf("expected IntentRunAllTests, got %v", intents)
|
||||
}
|
||||
}
|
||||
|
||||
// ── MsgTestsDone ────────────────────────────────────────────────────────
|
||||
|
||||
func TestMsgTestsDone_SetsKindAndStatus(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests}
|
||||
m, _ = Update(m, MsgTestsDone{Kind: TestKindE2E, Passed: true, Output: []string{"ok"}})
|
||||
if m.Screen != ScreenTestOutput {
|
||||
t.Errorf("expected ScreenTestOutput, got %d", m.Screen)
|
||||
}
|
||||
if m.LastTestKind != TestKindE2E {
|
||||
t.Errorf("expected LastTestKind=TestKindE2E, got %d", m.LastTestKind)
|
||||
}
|
||||
if !strings.Contains(m.StatusMsg, "PASSED") {
|
||||
t.Errorf("expected PASSED in status, got %q", m.StatusMsg)
|
||||
}
|
||||
if !strings.Contains(m.StatusMsg, "E2E") {
|
||||
t.Errorf("expected E2E in status, got %q", m.StatusMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgTestsDone_Failed(t *testing.T) {
|
||||
m := Model{}
|
||||
m, _ = Update(m, MsgTestsDone{Kind: TestKindGo, Passed: false, Output: []string{"FAIL"}})
|
||||
if !strings.Contains(m.StatusMsg, "FAILED") {
|
||||
t.Errorf("expected FAILED in status, got %q", m.StatusMsg)
|
||||
}
|
||||
}
|
||||
|
||||
// ── updateTestOutput ────────────────────────────────────────────────────
|
||||
|
||||
func TestUpdateTestOutput_BackGoesToTests(t *testing.T) {
|
||||
m := Model{Screen: ScreenTestOutput, LastTestKind: TestKindGo}
|
||||
m, _ = Update(m, KeyMsg{Str: "0"})
|
||||
if m.Screen != ScreenTests {
|
||||
t.Errorf("expected ScreenTests, got %d", m.Screen)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestOutput_RerunUsesLastKind(t *testing.T) {
|
||||
m := Model{Screen: ScreenTestOutput, LastTestKind: TestKindE2E, WindowHeight: 40}
|
||||
_, intents := Update(m, KeyMsg{Str: "r"})
|
||||
if len(intents) != 1 || intents[0].Kind != IntentRunE2ETests {
|
||||
t.Errorf("expected IntentRunE2ETests, got %v", intents)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTestOutput_RerunDefaultsToGo(t *testing.T) {
|
||||
m := Model{Screen: ScreenTestOutput, LastTestKind: TestKindNone, WindowHeight: 40}
|
||||
_, intents := Update(m, KeyMsg{Str: "r"})
|
||||
if len(intents) != 1 || intents[0].Kind != IntentRunGoTests {
|
||||
t.Errorf("expected IntentRunGoTests as default, got %v", intents)
|
||||
}
|
||||
}
|
||||
|
||||
// ── viewTests ───────────────────────────────────────────────────────────
|
||||
|
||||
func TestViewTests_ShowsOptions(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 0, WindowWidth: 80, WindowHeight: 40}
|
||||
out := View(m)
|
||||
if !strings.Contains(out, "Go Tests") {
|
||||
t.Error("expected 'Go Tests' in view")
|
||||
}
|
||||
if !strings.Contains(out, "E2E Tests") {
|
||||
t.Error("expected 'E2E Tests' in view")
|
||||
}
|
||||
if !strings.Contains(out, "All Tests") {
|
||||
t.Error("expected 'All Tests' in view")
|
||||
}
|
||||
}
|
||||
|
||||
func TestViewTests_ShowsCursor(t *testing.T) {
|
||||
m := Model{Screen: ScreenTests, Cursor: 1, WindowWidth: 80, WindowHeight: 40}
|
||||
out := View(m)
|
||||
// Cursor on E2E Tests (index 1)
|
||||
lines := strings.Split(out, "\n")
|
||||
foundCursor := false
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "> ") && strings.Contains(line, "E2E Tests") && !strings.Contains(line, "(headed)") {
|
||||
foundCursor = true
|
||||
}
|
||||
}
|
||||
if !foundCursor {
|
||||
t.Error("expected cursor on E2E Tests")
|
||||
}
|
||||
}
|
||||
|
||||
func TestViewTests_ShowsLastRun(t *testing.T) {
|
||||
m := Model{
|
||||
Screen: ScreenTests,
|
||||
Cursor: 0,
|
||||
WindowWidth: 80,
|
||||
WindowHeight: 40,
|
||||
LastTestKind: TestKindGo,
|
||||
StatusMsg: "Go Tests PASSED",
|
||||
}
|
||||
out := View(m)
|
||||
if !strings.Contains(out, "Last run:") {
|
||||
t.Error("expected 'Last run:' in view")
|
||||
}
|
||||
if !strings.Contains(out, "PASSED") {
|
||||
t.Error("expected PASSED in last run")
|
||||
}
|
||||
}
|
||||
|
||||
func TestViewTestOutput_ShowsKindInTitle(t *testing.T) {
|
||||
m := Model{
|
||||
Screen: ScreenTestOutput,
|
||||
LastTestKind: TestKindE2E,
|
||||
StatusMsg: "E2E Tests PASSED",
|
||||
LogLines: []string{"ok"},
|
||||
WindowWidth: 80,
|
||||
WindowHeight: 40,
|
||||
}
|
||||
out := View(m)
|
||||
if !strings.Contains(out, "Test Results — E2E Tests") {
|
||||
t.Errorf("expected 'Test Results — E2E Tests' in view, got:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Main menu Tests navigation ──────────────────────────────────────────
|
||||
|
||||
func TestMainMenu_TestsNavigation(t *testing.T) {
|
||||
m := Model{Screen: ScreenMain, Cursor: 2} // Tests is at index 2
|
||||
m, intents := Update(m, KeyMsg{Str: "enter"})
|
||||
if m.Screen != ScreenTests {
|
||||
t.Errorf("expected ScreenTests, got %d", m.Screen)
|
||||
}
|
||||
if len(intents) != 0 {
|
||||
t.Errorf("expected no intents for Tests nav, got %v", intents)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Server menu Tests navigation ────────────────────────────────────────
|
||||
|
||||
func TestServerMenu_TestsNavigation(t *testing.T) {
|
||||
// "Tests" is the last option in both running/stopped menus
|
||||
opts := ServerMenuOptions(false)
|
||||
testsIdx := -1
|
||||
for i, o := range opts {
|
||||
if o.Label == "Tests" {
|
||||
testsIdx = i
|
||||
}
|
||||
}
|
||||
if testsIdx < 0 {
|
||||
t.Fatal("Tests not found in server menu")
|
||||
}
|
||||
|
||||
m := Model{Screen: ScreenServer, Cursor: testsIdx}
|
||||
m, _ = Update(m, KeyMsg{Str: "enter"})
|
||||
if m.Screen != ScreenTests {
|
||||
t.Errorf("expected ScreenTests, got %d", m.Screen)
|
||||
}
|
||||
}
|
||||
|
||||
// ── testKindLabel ───────────────────────────────────────────────────────
|
||||
|
||||
func TestTestKindLabel(t *testing.T) {
|
||||
cases := []struct {
|
||||
kind TestKind
|
||||
want string
|
||||
}{
|
||||
{TestKindGo, "Go Tests"},
|
||||
{TestKindE2E, "E2E Tests"},
|
||||
{TestKindE2EHead, "E2E Tests (headed)"},
|
||||
{TestKindAll, "All Tests"},
|
||||
{TestKindNone, "Tests"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
got := testKindLabel(tc.kind)
|
||||
if got != tc.want {
|
||||
t.Errorf("testKindLabel(%d) = %q, want %q", tc.kind, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── testKindIntent ──────────────────────────────────────────────────────
|
||||
|
||||
func TestTestKindIntent(t *testing.T) {
|
||||
cases := []struct {
|
||||
kind TestKind
|
||||
want IntentKind
|
||||
}{
|
||||
{TestKindGo, IntentRunGoTests},
|
||||
{TestKindE2E, IntentRunE2ETests},
|
||||
{TestKindE2EHead, IntentRunE2EHeadTests},
|
||||
{TestKindAll, IntentRunAllTests},
|
||||
{TestKindNone, ""},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
got := testKindIntent(tc.kind)
|
||||
if got != tc.want {
|
||||
t.Errorf("testKindIntent(%d) = %q, want %q", tc.kind, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user