package ui import ( "strings" "testing" tea "github.com/charmbracelet/bubbletea" "motd-assist/internal/motd" "motd-assist/internal/preset" ) func mustUpdate(m Model, msg tea.Msg) Model { next, _ := m.Update(msg) return next.(Model) } func newTestModel(t *testing.T) Model { t.Helper() m := New(t.TempDir()) m = mustUpdate(m, tea.WindowSizeMsg{Width: 120, Height: 40}) return m } func TestViewRendersAllPanes(t *testing.T) { m := newTestModel(t) scripts := []motd.Script{ {Name: "00-header", Path: "/x/00-header", Enabled: true}, {Name: "10-sysinfo", Path: "/x/10-sysinfo", Enabled: false}, } m = mustUpdate(m, discoverMsg{scripts: scripts, host: motd.HostInfo{Hostname: "myhost", Distro: "Ubuntu 24.04", PAM: true}}) m = mustUpdate(m, previewMsg{version: m.previewVersion, text: "Willkommen auf myhost"}) view := m.View() for _, want := range []string{"Presets", "Scripte", "Live-Vorschau", "00-header", "10-sysinfo", "Willkommen auf myhost", "myhost"} { if !strings.Contains(view, want) { t.Errorf("View enthält %q nicht", want) } } } func TestToggleAndPlan(t *testing.T) { m := newTestModel(t) scripts := []motd.Script{ {Name: "00-header", Path: "/x/00-header", Enabled: true}, {Name: "10-sysinfo", Path: "/x/10-sysinfo", Enabled: false}, } m = mustUpdate(m, discoverMsg{scripts: scripts}) // Fokus auf Scripte wechseln und erstes Script ausschalten. m = mustUpdate(m, tea.KeyMsg{Type: tea.KeyTab}) m = mustUpdate(m, tea.KeyMsg{Type: tea.KeySpace}) plan := m.currentPlan() if len(plan.Chmod) != 1 || plan.Chmod[0].Name != "00-header" || plan.Chmod[0].Enable { t.Errorf("Chmod = %+v, want 00-header aus", plan.Chmod) } if markers := m.markersByRow(); markers["00-header"] != "aus" { t.Errorf("Marker = %q, want aus", markers["00-header"]) } } func TestMoveRowChangesOrder(t *testing.T) { m := newTestModel(t) scripts := []motd.Script{ {Name: "00-header", Path: "/x", Enabled: true}, {Name: "10-sysinfo", Path: "/x", Enabled: true}, } m = mustUpdate(m, discoverMsg{scripts: scripts}) m = mustUpdate(m, tea.KeyMsg{Type: tea.KeyTab}) m = mustUpdate(m, tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("d")}) // nach unten if m.working[0].Name != "10-sysinfo" || m.working[1].Name != "00-header" { t.Errorf("Reihenfolge = %v, %v", m.working[0].Name, m.working[1].Name) } if plan := m.currentPlan(); len(plan.Renames) != 2 { t.Errorf("Renames = %+v, want 2", plan.Renames) } } func TestLoadPresetMarksPending(t *testing.T) { m := newTestModel(t) scripts := []motd.Script{{Name: "00-header", Path: "/x", Enabled: false}} m = mustUpdate(m, discoverMsg{scripts: scripts}) m = mustUpdate(m, presetsMsg{presets: []preset.Preset{{Name: "p1", Scripts: []preset.Entry{{Name: "00-header", Enabled: true}}}}}) m = mustUpdate(m, tea.KeyMsg{Type: tea.KeyEnter}) // erstes Preset laden if plan := m.currentPlan(); len(plan.Chmod) != 1 || !plan.Chmod[0].Enable { t.Errorf("Plan = %+v, want 00-header an", plan) } if m.status == "" { t.Error("Statusmeldung nach Preset-Laden erwartet") } } func TestDiscardResetsWorking(t *testing.T) { m := newTestModel(t) scripts := []motd.Script{{Name: "00-header", Path: "/x", Enabled: true}} m = mustUpdate(m, discoverMsg{scripts: scripts}) m = mustUpdate(m, tea.KeyMsg{Type: tea.KeyTab}) m = mustUpdate(m, tea.KeyMsg{Type: tea.KeySpace}) // ausschalten if m.currentPlan().Empty() { t.Fatal("Plan sollte Änderungen haben") } m = mustUpdate(m, tea.KeyMsg{Type: tea.KeyEsc}) if !m.currentPlan().Empty() { t.Errorf("nach esc sollte der Plan leer sein, ist %+v", m.currentPlan()) } }