fix(cmd): export variables for test accessibility

Export rootCmd->RootCmd and appVersion->AppVersion to fix test compilation errors. Update all references across cmd package and tests.
This commit is contained in:
Gu1llaum-3 2025-09-10 11:07:11 +02:00
parent 9bb44da18b
commit aa6be1d92d
9 changed files with 61 additions and 57 deletions

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/Gu1llaum-3/sshm/internal/ui" "github.com/Gu1llaum-3/sshm/internal/ui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -26,5 +27,5 @@ var addCmd = &cobra.Command{
} }
func init() { func init() {
rootCmd.AddCommand(addCmd) RootCmd.AddCommand(addCmd)
} }

View File

@ -38,7 +38,7 @@ func TestAddCommand(t *testing.T) {
func TestAddCommandRegistration(t *testing.T) { func TestAddCommandRegistration(t *testing.T) {
// Check that add command is registered with root command // Check that add command is registered with root command
found := false found := false
for _, cmd := range rootCmd.Commands() { for _, cmd := range RootCmd.Commands() {
if cmd.Name() == "add" { if cmd.Name() == "add" {
found = true found = true
break break
@ -74,8 +74,8 @@ func TestAddCommandHelp(t *testing.T) {
func contains(s, substr string) bool { func contains(s, substr string) bool {
return len(s) >= len(substr) && (s == substr || len(substr) == 0 || return len(s) >= len(substr) && (s == substr || len(substr) == 0 ||
(len(s) > len(substr) && (s[:len(substr)] == substr || (len(s) > len(substr) && (s[:len(substr)] == substr ||
s[len(s)-len(substr):] == substr || s[len(s)-len(substr):] == substr ||
containsSubstring(s, substr)))) containsSubstring(s, substr))))
} }
func containsSubstring(s, substr string) bool { func containsSubstring(s, substr string) bool {

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/Gu1llaum-3/sshm/internal/ui" "github.com/Gu1llaum-3/sshm/internal/ui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -23,5 +24,5 @@ var editCmd = &cobra.Command{
} }
func init() { func init() {
rootCmd.AddCommand(editCmd) RootCmd.AddCommand(editCmd)
} }

View File

@ -37,7 +37,7 @@ func TestEditCommand(t *testing.T) {
func TestEditCommandRegistration(t *testing.T) { func TestEditCommandRegistration(t *testing.T) {
// Check that edit command is registered with root command // Check that edit command is registered with root command
found := false found := false
for _, cmd := range rootCmd.Commands() { for _, cmd := range RootCmd.Commands() {
if cmd.Name() == "edit" { if cmd.Name() == "edit" {
found = true found = true
break break

View File

@ -24,5 +24,5 @@ var moveCmd = &cobra.Command{
} }
func init() { func init() {
rootCmd.AddCommand(moveCmd) RootCmd.AddCommand(moveCmd)
} }

View File

@ -15,13 +15,14 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// appVersion will be set at build time via -ldflags // AppVersion will be set at build time via -ldflags
var appVersion = "dev" var AppVersion = "dev"
// configFile holds the path to the SSH config file // configFile holds the path to the SSH config file
var configFile string var configFile string
var rootCmd = &cobra.Command{ // RootCmd is the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "sshm", Use: "sshm",
Short: "SSH Manager - A modern SSH connection manager", Short: "SSH Manager - A modern SSH connection manager",
Long: `SSHM is a modern SSH manager for your terminal. Long: `SSHM is a modern SSH manager for your terminal.
@ -32,7 +33,7 @@ Main usage:
You can also use sshm in CLI mode for direct operations. You can also use sshm in CLI mode for direct operations.
Hosts are read from your ~/.ssh/config file by default.`, Hosts are read from your ~/.ssh/config file by default.`,
Version: appVersion, Version: AppVersion,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// If no arguments provided, run interactive mode // If no arguments provided, run interactive mode
if len(args) == 0 { if len(args) == 0 {
@ -88,7 +89,7 @@ func runInteractiveMode() {
} }
// Run the interactive TUI // Run the interactive TUI
if err := ui.RunInteractiveMode(hosts, configFile, appVersion); err != nil { if err := ui.RunInteractiveMode(hosts, configFile, AppVersion); err != nil {
log.Fatalf("Error running interactive mode: %v", err) log.Fatalf("Error running interactive mode: %v", err)
} }
} }
@ -141,13 +142,13 @@ func connectToHost(hostName string) {
// getVersionWithUpdateCheck returns a custom version string with update check // getVersionWithUpdateCheck returns a custom version string with update check
func getVersionWithUpdateCheck() string { func getVersionWithUpdateCheck() string {
versionText := fmt.Sprintf("sshm version %s", appVersion) versionText := fmt.Sprintf("sshm version %s", AppVersion)
// Check for updates // Check for updates
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
updateInfo, err := version.CheckForUpdates(ctx, appVersion) updateInfo, err := version.CheckForUpdates(ctx, AppVersion)
if err != nil { if err != nil {
// Return just version if check fails // Return just version if check fails
return versionText + "\n" return versionText + "\n"
@ -165,7 +166,7 @@ func getVersionWithUpdateCheck() string {
// Execute adds all child commands to the root command and sets flags appropriately. // Execute adds all child commands to the root command and sets flags appropriately.
func Execute() { func Execute() {
if err := rootCmd.Execute(); err != nil { if err := RootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err) fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1) os.Exit(1)
} }
@ -173,8 +174,8 @@ func Execute() {
func init() { func init() {
// Add the config file flag // Add the config file flag
rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "", "SSH config file to use (default: ~/.ssh/config)") RootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "", "SSH config file to use (default: ~/.ssh/config)")
// Set custom version template with update check // Set custom version template with update check
rootCmd.SetVersionTemplate(getVersionWithUpdateCheck()) RootCmd.SetVersionTemplate(getVersionWithUpdateCheck())
} }

View File

@ -8,27 +8,28 @@ import (
func TestRootCommand(t *testing.T) { func TestRootCommand(t *testing.T) {
// Test that the root command is properly configured // Test that the root command is properly configured
if rootCmd.Use != "sshm" { if RootCmd.Use != "sshm" {
t.Errorf("Expected Use 'sshm', got '%s'", rootCmd.Use) t.Errorf("Expected Use 'sshm', got '%s'", RootCmd.Use)
} }
if rootCmd.Short != "SSH Manager - A modern SSH connection manager" { if RootCmd.Short != "SSH Manager - A modern SSH connection manager" {
t.Errorf("Expected Short description, got '%s'", rootCmd.Short) t.Errorf("Expected Short description, got '%s'", RootCmd.Short)
} }
if rootCmd.Version != version { if RootCmd.Version != AppVersion {
t.Errorf("Expected Version '%s', got '%s'", version, rootCmd.Version) t.Errorf("Expected Version '%s', got '%s'", AppVersion, RootCmd.Version)
} }
} }
func TestRootCommandFlags(t *testing.T) { func TestRootCommandFlags(t *testing.T) {
// Test that persistent flags are properly configured // Test that persistent flags are properly configured
flags := rootCmd.PersistentFlags() flags := RootCmd.PersistentFlags()
// Check config flag // Check config flag
configFlag := flags.Lookup("config") configFlag := flags.Lookup("config")
if configFlag == nil { if configFlag == nil {
t.Error("Expected --config flag to be defined") t.Error("Expected --config flag to be defined")
return
} }
if configFlag.Shorthand != "c" { if configFlag.Shorthand != "c" {
t.Errorf("Expected config flag shorthand 'c', got '%s'", configFlag.Shorthand) t.Errorf("Expected config flag shorthand 'c', got '%s'", configFlag.Shorthand)
@ -40,7 +41,7 @@ func TestRootCommandSubcommands(t *testing.T) {
// Note: completion and help are automatically added by Cobra and may not always appear in Commands() // Note: completion and help are automatically added by Cobra and may not always appear in Commands()
expectedCommands := []string{"add", "edit", "search"} expectedCommands := []string{"add", "edit", "search"}
commands := rootCmd.Commands() commands := RootCmd.Commands()
commandNames := make(map[string]bool) commandNames := make(map[string]bool)
for _, cmd := range commands { for _, cmd := range commands {
commandNames[cmd.Name()] = true commandNames[cmd.Name()] = true
@ -61,11 +62,11 @@ func TestRootCommandSubcommands(t *testing.T) {
func TestRootCommandHelp(t *testing.T) { func TestRootCommandHelp(t *testing.T) {
// Test help output // Test help output
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
rootCmd.SetOut(buf) RootCmd.SetOut(buf)
rootCmd.SetArgs([]string{"--help"}) RootCmd.SetArgs([]string{"--help"})
// This should not return an error for help // This should not return an error for help
err := rootCmd.Execute() err := RootCmd.Execute()
if err != nil { if err != nil {
t.Errorf("Expected no error for help command, got %v", err) t.Errorf("Expected no error for help command, got %v", err)
} }
@ -82,16 +83,16 @@ func TestRootCommandHelp(t *testing.T) {
func TestRootCommandVersion(t *testing.T) { func TestRootCommandVersion(t *testing.T) {
// Test that version command executes without error // Test that version command executes without error
// Note: Cobra handles version output internally, so we just check for no error // Note: Cobra handles version output internally, so we just check for no error
rootCmd.SetArgs([]string{"--version"}) RootCmd.SetArgs([]string{"--version"})
// This should not return an error for version // This should not return an error for version
err := rootCmd.Execute() err := RootCmd.Execute()
if err != nil { if err != nil {
t.Errorf("Expected no error for version command, got %v", err) t.Errorf("Expected no error for version command, got %v", err)
} }
// Reset args for other tests // Reset args for other tests
rootCmd.SetArgs([]string{}) RootCmd.SetArgs([]string{})
} }
func TestExecuteFunction(t *testing.T) { func TestExecuteFunction(t *testing.T) {
@ -124,8 +125,8 @@ func TestConfigFileVariable(t *testing.T) {
defer func() { configFile = originalConfigFile }() defer func() { configFile = originalConfigFile }()
// Set config file through flag // Set config file through flag
rootCmd.SetArgs([]string{"--config", "/tmp/test-config"}) RootCmd.SetArgs([]string{"--config", "/tmp/test-config"})
rootCmd.ParseFlags([]string{"--config", "/tmp/test-config"}) RootCmd.ParseFlags([]string{"--config", "/tmp/test-config"})
// The configFile variable should be updated by the flag parsing // The configFile variable should be updated by the flag parsing
// Note: This test verifies the flag binding works // Note: This test verifies the flag binding works
@ -133,12 +134,12 @@ func TestConfigFileVariable(t *testing.T) {
func TestVersionVariable(t *testing.T) { func TestVersionVariable(t *testing.T) {
// Test that version variable has a default value // Test that version variable has a default value
if version == "" { if AppVersion == "" {
t.Error("version variable should have a default value") t.Error("AppVersion variable should have a default value")
} }
// Test that version is set to "dev" by default // Test that version is set to "dev" by default
if version != "dev" { if AppVersion != "dev" {
t.Logf("version is set to '%s' (expected 'dev' for development)", version) t.Logf("AppVersion is set to '%s' (expected 'dev' for development)", AppVersion)
} }
} }

View File

@ -235,7 +235,7 @@ func escapeJSON(s string) string {
func init() { func init() {
// Add search command to root // Add search command to root
rootCmd.AddCommand(searchCmd) RootCmd.AddCommand(searchCmd)
// Add flags // Add flags
searchCmd.Flags().StringVarP(&outputFormat, "format", "f", "table", "Output format (table, json, simple)") searchCmd.Flags().StringVarP(&outputFormat, "format", "f", "table", "Output format (table, json, simple)")

View File

@ -36,7 +36,7 @@ func TestSearchCommand(t *testing.T) {
func TestSearchCommandRegistration(t *testing.T) { func TestSearchCommandRegistration(t *testing.T) {
// Check that search command is registered with root command // Check that search command is registered with root command
found := false found := false
for _, cmd := range rootCmd.Commands() { for _, cmd := range RootCmd.Commands() {
if cmd.Name() == "search" { if cmd.Name() == "search" {
found = true found = true
break break