feat: ejecutar tests desde el dashboard TUI

Se añade opción "Run Tests" al menú del servidor en el dashboard TUI.
Ejecuta `go test -tags goolm -count=1 ./...` y muestra los resultados
en una pantalla dedicada (ScreenTestOutput) con scroll y opción de re-ejecutar.

Cambios:
- pkg/tui: nuevo MsgTestsDone, ScreenTestOutput, IntentRunTests, updateTestOutput
- pkg/tui/view.go: viewTestOutput con scroll y controles (↑↓ r 0)
- shell/tui/adapter.go: runTests() ejecuta go test con el env del manager
- shell/process/manager.go: buildEnv → BuildEnv (exportado) para que el adapter
  pueda construir el env completo con las variables de .env

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 02:21:17 +00:00
parent 828eb175fe
commit b6fe4f9135
6 changed files with 114 additions and 5 deletions
+38
View File
@@ -21,6 +21,7 @@ const (
IntentRestartLauncher IntentKind = "restart_launcher"
IntentKillLauncher IntentKind = "kill_launcher"
IntentRebuildRestart IntentKind = "rebuild_restart"
IntentRunTests IntentKind = "run_tests"
)
// Intent is pure data describing a side effect to execute.
@@ -98,6 +99,18 @@ func Update(model Model, msg interface{}) (Model, []Intent) {
model.LogScroll = max(0, len(m.Lines)-visibleLogLines(model))
return model, nil
case MsgTestsDone:
model.Screen = ScreenTestOutput
model.LogLines = m.Output
model.LogScroll = 0
model.Cursor = 0
if m.Passed {
model.StatusMsg = "Tests PASSED"
} else {
model.StatusMsg = "Tests FAILED"
}
return model, nil
case MsgTick:
return model, []Intent{{Kind: IntentLoadAgents}}
@@ -127,6 +140,8 @@ func updateKey(model Model, key KeyMsg) (Model, []Intent) {
return updateLogs(model, key)
case ScreenServer:
return updateServerScreen(model, key)
case ScreenTestOutput:
return updateTestOutput(model, key)
}
return model, nil
}
@@ -283,6 +298,9 @@ 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 "Logs":
model.Screen = ScreenLogs
model.LogLines = nil
@@ -294,6 +312,26 @@ func executeServerAction(model Model, action string) (Model, []Intent) {
return model, nil
}
func updateTestOutput(model Model, key KeyMsg) (Model, []Intent) {
switch key.Str {
case "0":
model.Screen = ScreenServer
model.Cursor = 0
model.LogLines = nil
model.LogScroll = 0
model.StatusMsg = ""
case "up", "k":
model.LogScroll = max(0, model.LogScroll-1)
case "down", "j":
maxScroll := max(0, len(model.LogLines)-visibleLogLines(model))
model.LogScroll = min(model.LogScroll+1, maxScroll)
case "r":
model.StatusMsg = "Running tests..."
return model, []Intent{{Kind: IntentRunTests}}
}
return model, nil
}
// ── pure helpers ─────────────────────────────────────────────────────────
func visibleLogLines(m Model) int {