package installer import ( "os" "strings" "testing" "gitgud.io/mike/mpv-manager/pkg/constants" "github.com/stretchr/testify/assert" ) func containsAppIDInCommands(commands [][]string, appID string) bool { for _, cmd := range commands { for _, arg := range cmd { if arg == appID { return true } } } return false } func TestNewPackageManager(t *testing.T) { tests := []struct { name string family string wantCmd string wantFamily string }{ { name: "Debian family", family: constants.PMFamilyDebian, wantCmd: constants.CommandApt, wantFamily: constants.PMFamilyDebian, }, { name: "RHEL family", family: constants.PMFamilyRHEL, wantCmd: constants.CommandDnf, wantFamily: constants.PMFamilyRHEL, }, { name: "Arch family", family: constants.PMFamilyArch, wantCmd: constants.CommandPacman, wantFamily: constants.PMFamilyArch, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := NewPackageManager(tt.family) assert.Equal(t, tt.wantCmd, got.cmd) assert.Equal(t, tt.wantFamily, got.family) }) } } func TestBuildInstallCommand(t *testing.T) { tests := []struct { name string family string packageName string withPrivilege bool containsCmd string containsSudo bool }{ { name: "Debian install with privilege", family: constants.PMFamilyDebian, packageName: "mpv", withPrivilege: true, containsCmd: "apt install -y", containsSudo: true, }, { name: "Debian install without privilege", family: constants.PMFamilyDebian, packageName: "mpv", withPrivilege: false, containsCmd: "apt install -y", containsSudo: false, }, { name: "RHEL install with privilege", family: constants.PMFamilyRHEL, packageName: "mpv", withPrivilege: true, containsCmd: "dnf install -y", containsSudo: true, }, { name: "RHEL install without privilege", family: constants.PMFamilyRHEL, packageName: "mpv", withPrivilege: false, containsCmd: "dnf install -y", containsSudo: false, }, { name: "Arch install with privilege", family: constants.PMFamilyArch, packageName: "mpv", withPrivilege: true, containsCmd: "pacman -S --noconfirm", containsSudo: true, }, { name: "Arch install without privilege", family: constants.PMFamilyArch, packageName: "mpv", withPrivilege: false, containsCmd: "pacman -S --noconfirm", containsSudo: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pm := NewPackageManager(tt.family) got := pm.BuildInstallCommand(tt.packageName, tt.withPrivilege) assert.NotNil(t, got) // Check if expected command parts are in result result := strings.Join(got, " ") assert.Contains(t, result, tt.containsCmd) assert.Contains(t, result, tt.packageName) if tt.withPrivilege && os.Geteuid() != 0 { assert.Contains(t, result, "sudo") } }) } } func TestBuildUpdateCommand(t *testing.T) { tests := []struct { name string family string withPrivilege bool containsCmd string containsSudo bool }{ { name: "Debian update with privilege", family: constants.PMFamilyDebian, withPrivilege: true, containsCmd: "apt update", containsSudo: true, }, { name: "Debian update without privilege", family: constants.PMFamilyDebian, withPrivilege: false, containsCmd: "apt update", containsSudo: false, }, { name: "RHEL update with privilege", family: constants.PMFamilyRHEL, withPrivilege: true, containsCmd: "dnf makecache", containsSudo: true, }, { name: "RHEL update without privilege", family: constants.PMFamilyRHEL, withPrivilege: false, containsCmd: "dnf makecache", containsSudo: false, }, { name: "RHEL update without privilege", family: constants.PMFamilyRHEL, withPrivilege: false, containsCmd: "dnf makecache", containsSudo: false, }, { name: "Arch update with privilege", family: constants.PMFamilyArch, withPrivilege: true, containsCmd: "pacman -Sy", containsSudo: true, }, { name: "Arch update without privilege", family: constants.PMFamilyArch, withPrivilege: false, containsCmd: "pacman -Sy", containsSudo: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pm := NewPackageManager(tt.family) got := pm.BuildUpdateCommand(tt.withPrivilege) assert.NotNil(t, got) result := strings.Join(got, " ") assert.Contains(t, result, tt.containsCmd) if tt.withPrivilege && os.Geteuid() != 0 { assert.Contains(t, result, "sudo") } }) } } func TestBuildUpgradeCommand(t *testing.T) { tests := []struct { name string family string packageName string withPrivilege bool containsCmd string containsSudo bool }{ { name: "Debian upgrade with privilege and package", family: constants.PMFamilyDebian, packageName: "mpv", withPrivilege: true, containsCmd: "apt upgrade -y", containsSudo: true, }, { name: "Debian upgrade without privilege and package", family: constants.PMFamilyDebian, packageName: "mpv", withPrivilege: false, containsCmd: "apt upgrade -y", containsSudo: false, }, { name: "Debian upgrade without package", family: constants.PMFamilyDebian, packageName: "", withPrivilege: true, containsCmd: "apt upgrade -y", containsSudo: true, }, { name: "Arch upgrade with privilege", family: constants.PMFamilyArch, packageName: "mpv", withPrivilege: true, containsCmd: "pacman -Sy --noconfirm", containsSudo: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pm := NewPackageManager(tt.family) got := pm.BuildUpgradeCommand(tt.packageName, tt.withPrivilege) assert.NotNil(t, got) result := strings.Join(got, " ") assert.Contains(t, result, tt.containsCmd) if tt.packageName != "" { assert.Contains(t, result, tt.packageName) } if tt.withPrivilege && os.Geteuid() != 0 { assert.Contains(t, result, "sudo") } }) } } func TestBuildRemoveCommand(t *testing.T) { tests := []struct { name string family string packageName string withPrivilege bool containsCmd string containsSudo bool }{ { name: "Debian remove with privilege", family: constants.PMFamilyDebian, packageName: "mpv", withPrivilege: true, containsCmd: "apt remove -y", containsSudo: true, }, { name: "Debian remove without privilege", family: constants.PMFamilyDebian, packageName: "mpv", withPrivilege: false, containsCmd: "apt remove -y", containsSudo: false, }, { name: "RHEL remove with privilege", family: constants.PMFamilyRHEL, packageName: "mpv", withPrivilege: true, containsCmd: "dnf remove -y", containsSudo: true, }, { name: "Arch remove with privilege", family: constants.PMFamilyArch, packageName: "mpv", withPrivilege: true, containsCmd: "pacman -Rn", containsSudo: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pm := NewPackageManager(tt.family) got := pm.BuildRemoveCommand(tt.packageName, tt.withPrivilege) assert.NotNil(t, got) result := strings.Join(got, " ") assert.Contains(t, result, tt.containsCmd) assert.Contains(t, result, tt.packageName) if tt.withPrivilege && os.Geteuid() != 0 { assert.Contains(t, result, "sudo") } }) } } func TestGetCommandName(t *testing.T) { tests := []struct { name string family string wantCmd string }{ { name: "Debian family command name", family: constants.PMFamilyDebian, wantCmd: constants.CommandApt, }, { name: "RHEL family command name", family: constants.PMFamilyRHEL, wantCmd: constants.CommandDnf, }, { name: "Arch family command name", family: constants.PMFamilyArch, wantCmd: constants.CommandPacman, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pm := NewPackageManager(tt.family) got := pm.GetCommandName() assert.Equal(t, tt.wantCmd, got) }) } } func TestGetFamily(t *testing.T) { tests := []struct { name string family string wantFamily string }{ { name: "Debian family getter", family: constants.PMFamilyDebian, wantFamily: constants.PMFamilyDebian, }, { name: "RHEL family getter", family: constants.PMFamilyRHEL, wantFamily: constants.PMFamilyRHEL, }, { name: "Arch family getter", family: constants.PMFamilyArch, wantFamily: constants.PMFamilyArch, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { pm := NewPackageManager(tt.family) got := pm.GetFamily() assert.Equal(t, tt.wantFamily, got) }) } } func TestNewFlatpakManager(t *testing.T) { t.Run("Create Flatpak manager", func(t *testing.T) { fm := NewFlatpakManager() assert.NotNil(t, fm) }) } func TestFlatpakBuildInstallCommands(t *testing.T) { tests := []struct { name string appID string enableFlathub bool expectedCount int containsFlathub bool containsInstall bool }{ { name: "Install with Flathub enabled", appID: "io.mpv.Mpv", enableFlathub: true, expectedCount: 2, containsFlathub: true, containsInstall: true, }, { name: "Install without Flathub", appID: "io.mpv.Mpv", enableFlathub: false, expectedCount: 1, containsFlathub: false, containsInstall: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { fm := NewFlatpakManager() got := fm.BuildInstallCommands(tt.appID, tt.enableFlathub) assert.Equal(t, tt.expectedCount, len(got)) assert.True(t, containsAppIDInCommands(got, tt.appID)) assert.Equal(t, tt.containsFlathub, containsCommandArray(got, "flatpak", "remote-add", "--if-not-exists", "flathub")) assert.Equal(t, tt.containsInstall, containsCommandArray(got, "flatpak", "install")) }) } } func TestFlatpakBuildUpdateCommand(t *testing.T) { tests := []struct { name string appID string contains bool }{ { name: "Update with app ID", appID: "io.mpv.Mpv", contains: true, }, { name: "Update without app ID", appID: "", contains: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { fm := NewFlatpakManager() got := fm.BuildUpdateCommand(tt.appID) assert.NotNil(t, got) assert.Contains(t, got, "flatpak") assert.Contains(t, got, "update") assert.Equal(t, tt.contains, containsItem(got, tt.appID)) }) } } func TestFlatpakBuildRemoveCommand(t *testing.T) { t.Run("Build Flatpak remove command", func(t *testing.T) { fm := NewFlatpakManager() appID := "io.mpv.Mpv" got := fm.BuildRemoveCommand(appID) assert.NotNil(t, got) assert.Contains(t, got, "flatpak") assert.Contains(t, got, "uninstall") assert.Contains(t, got, appID) }) } func TestFlatpakBuildOverrideCommand(t *testing.T) { t.Run("Build Flatpak override command", func(t *testing.T) { fm := NewFlatpakManager() override := "--filesystem=xdg-config/mpv:ro" appID := "io.mpv.Mpv" got := fm.BuildOverrideCommand(override, appID) assert.NotNil(t, got) assert.Contains(t, got, "flatpak") assert.Contains(t, got, "override") assert.Contains(t, got, override) assert.Contains(t, got, appID) }) } // Helper functions for tests func containsItem(cmds []string, item string) bool { for _, cmd := range cmds { if cmd == item { return true } } return false } func containsCommandArray(cmdSets [][]string, parts ...string) bool { for _, cmds := range cmdSets { allMatch := true for _, part := range parts { if !containsItem(cmds, part) { allMatch = false break } } if allMatch { return true } } return false }