mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-17 00:34:01 -04:00
207 lines
6.0 KiB
Go
207 lines
6.0 KiB
Go
package tui
|
|
|
|
import (
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/config"
|
|
"testing"
|
|
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/deps"
|
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/distros"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
func archModel() Model {
|
|
m := NewModel("test", "")
|
|
m.osInfo = &distros.OSInfo{
|
|
Distribution: distros.DistroInfo{ID: "arch"},
|
|
PrettyName: "Arch Linux",
|
|
Architecture: "amd64",
|
|
}
|
|
m.isLoading = false
|
|
return m
|
|
}
|
|
|
|
func pressKey(t *testing.T, m Model, key tea.KeyMsg) Model {
|
|
t.Helper()
|
|
updated, _ := m.Update(key)
|
|
next, ok := updated.(Model)
|
|
if !ok {
|
|
t.Fatalf("Update returned %T, want Model", updated)
|
|
}
|
|
return next
|
|
}
|
|
|
|
var enterKey = tea.KeyMsg{Type: tea.KeyEnter}
|
|
var downKey = tea.KeyMsg{Type: tea.KeyDown}
|
|
var escKey = tea.KeyMsg{Type: tea.KeyEsc}
|
|
|
|
func TestWelcomeEnterAdvances(t *testing.T) {
|
|
m := archModel()
|
|
m = pressKey(t, m, enterKey)
|
|
if m.state != StateSelectWindowManager {
|
|
t.Fatalf("state = %v, want StateSelectWindowManager", m.state)
|
|
}
|
|
}
|
|
|
|
func TestWelcomeEnterBlockedWithoutOSInfo(t *testing.T) {
|
|
m := NewModel("test", "")
|
|
m = pressKey(t, m, enterKey)
|
|
if m.state != StateWelcome {
|
|
t.Fatalf("state = %v, want StateWelcome", m.state)
|
|
}
|
|
}
|
|
|
|
func TestWelcomeEnterBlockedOnUnsupportedDistro(t *testing.T) {
|
|
m := archModel()
|
|
m.osInfo.Distribution.ID = "ubuntu"
|
|
m.osInfo.VersionID = "22.04"
|
|
m = pressKey(t, m, enterKey)
|
|
if m.state != StateWelcome {
|
|
t.Fatalf("state = %v, want StateWelcome", m.state)
|
|
}
|
|
}
|
|
|
|
func TestSelectionFlowAndEscape(t *testing.T) {
|
|
m := archModel()
|
|
m = pressKey(t, m, enterKey)
|
|
m = pressKey(t, m, downKey)
|
|
if m.selectedWM != 1 {
|
|
t.Fatalf("selectedWM = %d, want 1", m.selectedWM)
|
|
}
|
|
if m.chosenWindowManager() != deps.WindowManagerHyprland {
|
|
t.Fatalf("chosenWindowManager = %v, want Hyprland", m.chosenWindowManager())
|
|
}
|
|
|
|
m = pressKey(t, m, enterKey)
|
|
if m.state != StateSelectTerminal {
|
|
t.Fatalf("state = %v, want StateSelectTerminal", m.state)
|
|
}
|
|
m = pressKey(t, m, downKey)
|
|
if m.chosenTerminal() != deps.TerminalKitty {
|
|
t.Fatalf("chosenTerminal = %v, want Kitty", m.chosenTerminal())
|
|
}
|
|
|
|
m = pressKey(t, m, escKey)
|
|
if m.state != StateSelectWindowManager {
|
|
t.Fatalf("state = %v, want StateSelectWindowManager after esc", m.state)
|
|
}
|
|
}
|
|
|
|
func TestWindowManagerChoicesOmitHyprlandOnDebian(t *testing.T) {
|
|
m := archModel()
|
|
m.osInfo.Distribution.ID = "debian"
|
|
for _, c := range m.windowManagerChoices() {
|
|
if c.wm == deps.WindowManagerHyprland {
|
|
t.Fatal("debian choices include Hyprland")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTerminalChoicesOmitGhosttyOnGentoo(t *testing.T) {
|
|
m := archModel()
|
|
m.osInfo.Distribution.ID = "gentoo"
|
|
choices := m.terminalChoices()
|
|
if len(choices) != 2 || choices[0].terminal != deps.TerminalKitty {
|
|
t.Fatalf("gentoo terminal choices = %+v, want kitty first without ghostty", choices)
|
|
}
|
|
if m.chosenTerminal() != deps.TerminalKitty {
|
|
t.Fatalf("chosenTerminal = %v, want Kitty default on gentoo", m.chosenTerminal())
|
|
}
|
|
}
|
|
|
|
func TestToggleSelectedDependency(t *testing.T) {
|
|
m := archModel()
|
|
m.dependencies = []deps.Dependency{
|
|
{Name: dmsDepName, Required: true, Status: deps.StatusMissing},
|
|
{Name: "quickshell", Required: true, Status: deps.StatusInstalled},
|
|
{Name: "matugen", Required: true, Status: deps.StatusMissing},
|
|
}
|
|
|
|
m.selectedDep = 0
|
|
m.toggleSelectedDependency()
|
|
if m.disabledItems[dmsDepName] || m.reinstallItems[dmsDepName] {
|
|
t.Fatal("dms must not be toggleable")
|
|
}
|
|
|
|
m.selectedDep = 1
|
|
m.toggleSelectedDependency()
|
|
if !m.reinstallItems["quickshell"] {
|
|
t.Fatal("toggling an installed dep should mark reinstall")
|
|
}
|
|
|
|
m.selectedDep = 2
|
|
m.toggleSelectedDependency()
|
|
if !m.disabledItems["matugen"] {
|
|
t.Fatal("toggling a missing dep should mark disabled")
|
|
}
|
|
}
|
|
|
|
func TestDetectedDepsPartitionAndOptOut(t *testing.T) {
|
|
m := archModel()
|
|
m.state = StateDetectingDeps
|
|
updated, _ := m.Update(depsDetectedMsg{deps: []deps.Dependency{
|
|
{Name: "dms-greeter", Required: false},
|
|
{Name: "quickshell", Required: true},
|
|
}})
|
|
m = updated.(Model)
|
|
|
|
if m.state != StateDependencyReview {
|
|
t.Fatalf("state = %v, want StateDependencyReview", m.state)
|
|
}
|
|
if m.dependencies[0].Name != "quickshell" {
|
|
t.Fatal("required deps should sort before optional")
|
|
}
|
|
if !m.disabledItems["dms-greeter"] {
|
|
t.Fatal("optional deps should default to disabled")
|
|
}
|
|
}
|
|
|
|
func TestPasswordPromptValidation(t *testing.T) {
|
|
m := archModel()
|
|
m.state = StatePasswordPrompt
|
|
|
|
updated, _ := m.Update(passwordValidMsg{valid: false})
|
|
m = updated.(Model)
|
|
if !m.authFailed || m.state != StatePasswordPrompt {
|
|
t.Fatalf("invalid password: authFailed=%v state=%v", m.authFailed, m.state)
|
|
}
|
|
|
|
updated, _ = m.Update(passwordValidMsg{password: "hunter2", valid: true})
|
|
m = updated.(Model)
|
|
if m.state != StateInstallingPackages || m.sudoPassword != "hunter2" || m.authFailed {
|
|
t.Fatalf("valid password: state=%v sudoPassword set=%v", m.state, m.sudoPassword != "")
|
|
}
|
|
}
|
|
|
|
func TestConfigCheckDefaultsToReplace(t *testing.T) {
|
|
m := archModel()
|
|
m.state = StateConfigConfirmation
|
|
updated, _ := m.Update(configCheckResult{configs: []ExistingConfigInfo{
|
|
{ConfigType: "Niri", Path: "/tmp/niri.kdl", Exists: false},
|
|
{ConfigType: "Ghostty", Path: "/tmp/ghostty", Exists: true},
|
|
}})
|
|
m = updated.(Model)
|
|
|
|
if m.state != StateConfigConfirmation {
|
|
t.Fatalf("state = %v, want StateConfigConfirmation while configs exist", m.state)
|
|
}
|
|
if !m.replaceConfigs["Ghostty"] {
|
|
t.Fatal("existing config should default to replace")
|
|
}
|
|
if m.selectedConfig != 1 {
|
|
t.Fatalf("selectedConfig = %d, want first existing config", m.selectedConfig)
|
|
}
|
|
}
|
|
|
|
func TestConfigCheckKeepsBindsByDefault(t *testing.T) {
|
|
m := archModel()
|
|
m.state = StateConfigConfirmation
|
|
updated, _ := m.Update(configCheckResult{configs: []ExistingConfigInfo{
|
|
{ConfigType: "Mango", Path: "/tmp/config.conf", Exists: true},
|
|
{ConfigType: config.BindsConfigType, Path: "/tmp/binds.conf", Exists: true},
|
|
}})
|
|
m = updated.(Model)
|
|
if !m.replaceConfigs["Mango"] || m.replaceConfigs[config.BindsConfigType] {
|
|
t.Fatalf("replaceConfigs = %v, want Mango replaced and its binds kept", m.replaceConfigs)
|
|
}
|
|
}
|