feat: pantalla de tests en el dashboard TUI
Nueva seccion "Tests" en el menu principal del dashboard que permite ejecutar Go tests, E2E tests (headless y headed), y todos secuencialmente. - ScreenTests con menu de seleccion de tipo de test - TestKind enum para identificar el tipo de test ejecutado - Nuevos intents: IntentRunGoTests, IntentRunE2ETests, IntentRunE2EHeadTests, IntentRunAllTests - LastTestKind en Model para re-ejecucion con "r" - runGoTests, runE2ETests, runAllTests en adapter - "Run Tests" en Server menu reemplazado por navegacion a ScreenTests - Test output muestra tipo de test en titulo y vuelve a ScreenTests con "0" Issue: 0023 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+101
-7
@@ -23,6 +23,10 @@ const (
|
||||
IntentKillLauncher IntentKind = "kill_launcher"
|
||||
IntentRebuildRestart IntentKind = "rebuild_restart"
|
||||
IntentRunTests IntentKind = "run_tests"
|
||||
IntentRunGoTests IntentKind = "run_go_tests"
|
||||
IntentRunE2ETests IntentKind = "run_e2e_tests"
|
||||
IntentRunE2EHeadTests IntentKind = "run_e2e_head_tests"
|
||||
IntentRunAllTests IntentKind = "run_all_tests"
|
||||
)
|
||||
|
||||
// Intent is pure data describing a side effect to execute.
|
||||
@@ -107,10 +111,12 @@ func Update(model Model, msg interface{}) (Model, []Intent) {
|
||||
model.LogLines = m.Output
|
||||
model.LogScroll = 0
|
||||
model.Cursor = 0
|
||||
model.LastTestKind = m.Kind
|
||||
label := testKindLabel(m.Kind)
|
||||
if m.Passed {
|
||||
model.StatusMsg = "Tests PASSED"
|
||||
model.StatusMsg = label + " PASSED"
|
||||
} else {
|
||||
model.StatusMsg = "Tests FAILED"
|
||||
model.StatusMsg = label + " FAILED"
|
||||
}
|
||||
return model, nil
|
||||
|
||||
@@ -143,6 +149,8 @@ func updateKey(model Model, key KeyMsg) (Model, []Intent) {
|
||||
return updateLogs(model, key)
|
||||
case ScreenServer:
|
||||
return updateServerScreen(model, key)
|
||||
case ScreenTests:
|
||||
return updateTestsScreen(model, key)
|
||||
case ScreenTestOutput:
|
||||
return updateTestOutput(model, key)
|
||||
}
|
||||
@@ -167,6 +175,11 @@ func updateMainScreen(model Model, key KeyMsg) (Model, []Intent) {
|
||||
model.Cursor = 0
|
||||
model.StatusMsg = ""
|
||||
return model, []Intent{{Kind: IntentLoadAgents}}
|
||||
case "Tests":
|
||||
model.Screen = ScreenTests
|
||||
model.Cursor = 0
|
||||
model.StatusMsg = ""
|
||||
return model, nil
|
||||
case "Quit":
|
||||
return model, []Intent{{Kind: IntentQuit}}
|
||||
}
|
||||
@@ -304,9 +317,11 @@ func executeServerAction(model Model, action string) (Model, []Intent) {
|
||||
case "Rebuild & Restart":
|
||||
model.StatusMsg = "Building & restarting..."
|
||||
return model, []Intent{{Kind: IntentRebuildRestart}}
|
||||
case "Run Tests":
|
||||
model.StatusMsg = "Running tests..."
|
||||
return model, []Intent{{Kind: IntentRunTests}}
|
||||
case "Tests":
|
||||
model.Screen = ScreenTests
|
||||
model.Cursor = 0
|
||||
model.StatusMsg = ""
|
||||
return model, nil
|
||||
case "Logs":
|
||||
model.Screen = ScreenLogs
|
||||
model.LogLines = nil
|
||||
@@ -321,7 +336,7 @@ func executeServerAction(model Model, action string) (Model, []Intent) {
|
||||
func updateTestOutput(model Model, key KeyMsg) (Model, []Intent) {
|
||||
switch key.Str {
|
||||
case "0":
|
||||
model.Screen = ScreenServer
|
||||
model.Screen = ScreenTests
|
||||
model.Cursor = 0
|
||||
model.LogLines = nil
|
||||
model.LogScroll = 0
|
||||
@@ -332,12 +347,91 @@ func updateTestOutput(model Model, key KeyMsg) (Model, []Intent) {
|
||||
maxScroll := max(0, len(model.LogLines)-visibleLogLines(model))
|
||||
model.LogScroll = min(model.LogScroll+1, maxScroll)
|
||||
case "r":
|
||||
intent := testKindIntent(model.LastTestKind)
|
||||
if intent == "" {
|
||||
intent = IntentRunGoTests
|
||||
}
|
||||
model.StatusMsg = "Running tests..."
|
||||
return model, []Intent{{Kind: IntentRunTests}}
|
||||
model.LogLines = nil
|
||||
model.LogScroll = 0
|
||||
return model, []Intent{{Kind: intent}}
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func updateTestsScreen(model Model, key KeyMsg) (Model, []Intent) {
|
||||
opts := TestMenuOptions()
|
||||
|
||||
switch key.Str {
|
||||
case "0":
|
||||
model.Screen = ScreenMain
|
||||
model.Cursor = 0
|
||||
model.StatusMsg = ""
|
||||
case "up", "k":
|
||||
model.Cursor = clamp(model.Cursor-1, 0, len(opts)-1)
|
||||
case "down", "j":
|
||||
model.Cursor = clamp(model.Cursor+1, 0, len(opts)-1)
|
||||
case "enter":
|
||||
if model.Cursor < len(opts) {
|
||||
return executeTestAction(model, opts[model.Cursor].Label)
|
||||
}
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func executeTestAction(model Model, action string) (Model, []Intent) {
|
||||
model.StatusMsg = "Running tests..."
|
||||
model.LogLines = nil
|
||||
model.LogScroll = 0
|
||||
switch action {
|
||||
case "Go Tests":
|
||||
model.LastTestKind = TestKindGo
|
||||
return model, []Intent{{Kind: IntentRunGoTests}}
|
||||
case "E2E Tests":
|
||||
model.LastTestKind = TestKindE2E
|
||||
return model, []Intent{{Kind: IntentRunE2ETests}}
|
||||
case "E2E Tests (headed)":
|
||||
model.LastTestKind = TestKindE2EHead
|
||||
return model, []Intent{{Kind: IntentRunE2EHeadTests}}
|
||||
case "All Tests":
|
||||
model.LastTestKind = TestKindAll
|
||||
return model, []Intent{{Kind: IntentRunAllTests}}
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
|
||||
// testKindIntent maps a TestKind to its corresponding IntentKind.
|
||||
func testKindIntent(k TestKind) IntentKind {
|
||||
switch k {
|
||||
case TestKindGo:
|
||||
return IntentRunGoTests
|
||||
case TestKindE2E:
|
||||
return IntentRunE2ETests
|
||||
case TestKindE2EHead:
|
||||
return IntentRunE2EHeadTests
|
||||
case TestKindAll:
|
||||
return IntentRunAllTests
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// testKindLabel returns a human-readable label for a TestKind.
|
||||
func testKindLabel(k TestKind) string {
|
||||
switch k {
|
||||
case TestKindGo:
|
||||
return "Go Tests"
|
||||
case TestKindE2E:
|
||||
return "E2E Tests"
|
||||
case TestKindE2EHead:
|
||||
return "E2E Tests (headed)"
|
||||
case TestKindAll:
|
||||
return "All Tests"
|
||||
default:
|
||||
return "Tests"
|
||||
}
|
||||
}
|
||||
|
||||
// ── pure helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
func visibleLogLines(m Model) int {
|
||||
|
||||
Reference in New Issue
Block a user