package tui import ( "strings" "testing" tea "charm.land/bubbletea/v2" "gitgud.io/mike/mpv-manager/pkg/config" ) // newConfigOptionsModel sandboxes the user config, reloads it, and returns a // model in the config options state with an installed app tracked. func newConfigOptionsModel(t *testing.T) *Model { t.Helper() sandboxConfigHome(t) if _, err := config.Reload(); err != nil { t.Fatalf("failed to reload config: %v", err) } if err := config.AddInstalledApp(config.InstalledApp{ AppName: "mpv", AppType: "exe-binary", InstallMethod: "mpv-binary", }); err != nil { t.Fatalf("failed to add installed app: %v", err) } m := NewModel() m.setupConfigOptionsList() m.state = StateConfigOptions return m } // selectConfigOption selects the config options item with the given ID and // presses Enter. func selectConfigOption(t *testing.T, m *Model, id string) *Model { t.Helper() for i, item := range m.configOptionsList.Items() { if item.(menuItem).id == id { m.configOptionsList.Select(i) return pressKey(t, m, tea.KeyPressMsg{Code: tea.KeyEnter}) } } t.Fatalf("config option %q not found", id) return m } func TestConfigOptionsContainsResetManagerData(t *testing.T) { sandboxConfigHome(t) if _, err := config.Reload(); err != nil { t.Fatalf("failed to reload config: %v", err) } m := NewModel() m.setupConfigOptionsList() found := false for _, item := range m.configOptionsList.Items() { if item.(menuItem).id == "reset-manager-data" { found = true } } if !found { t.Error("expected reset-manager-data entry in config options") } } func TestResetManagerDataConfirmResetsConfig(t *testing.T) { m := newConfigOptionsModel(t) if len(config.GetInstalledApps()) != 1 { t.Fatalf("expected 1 installed app before reset, got %d", len(config.GetInstalledApps())) } // Selecting the action opens the confirmation sub-state. m = selectConfigOption(t, m, "reset-manager-data") if m.state != StateResetManagerData { t.Fatalf("expected StateResetManagerData, got %v", m.state) } if view := m.resetManagerDataView(); !strings.Contains(view, "Reset MPV Manager Data") { t.Errorf("confirmation view missing title: %q", view) } else if strings.Contains(view, "includes installed app tracking, language preferences") { t.Errorf("confirmation view incorrectly claims language preferences are reset: %q", view) } else if !strings.Contains(view, "Language preferences in mpv.conf are not affected") { t.Errorf("confirmation view does not explain the language preference scope: %q", view) } // y confirms: config is reset and we land back on config options. m = pressKey(t, m, keyRunes("y")) if m.state != StateConfigOptions { t.Fatalf("expected StateConfigOptions after confirm, got %v", m.state) } if !strings.HasPrefix(m.resetManagerDataStatusMsg, "✓") { t.Errorf("expected success status, got %q", m.resetManagerDataStatusMsg) } if apps := config.GetInstalledApps(); len(apps) != 0 { t.Errorf("expected installed apps cleared after reset, got %d", len(apps)) } // The status is rendered on the config options screen. if view := m.configOptionsListView(); !strings.Contains(view, "reset to defaults") { t.Errorf("expected status in config options view, got %q", view) } } func TestResetManagerDataCancelKeepsConfig(t *testing.T) { for _, cancel := range []tea.KeyPressMsg{keyRunes("n"), {Code: tea.KeyEsc}} { m := newConfigOptionsModel(t) m = selectConfigOption(t, m, "reset-manager-data") if m.state != StateResetManagerData { t.Fatalf("expected StateResetManagerData, got %v", m.state) } m = pressKey(t, m, cancel) if m.state != StateConfigOptions { t.Fatalf("expected StateConfigOptions after cancel, got %v", m.state) } if apps := config.GetInstalledApps(); len(apps) != 1 { t.Errorf("expected installed apps kept after cancel, got %d", len(apps)) } if m.resetManagerDataStatusMsg != "" { t.Errorf("expected no status message after cancel, got %q", m.resetManagerDataStatusMsg) } } }