1+ package cmd
2+
3+ import (
4+ "bytes"
5+ "os"
6+ "path/filepath"
7+ "testing"
8+
9+ "github.com/spf13/cobra"
10+ "github.com/spf13/viper"
11+ "github.com/stretchr/testify/assert"
12+ )
13+
14+ func TestExecute (t * testing.T ) {
15+ // Save original args
16+ originalArgs := os .Args
17+ defer func () { os .Args = originalArgs }()
18+
19+ tests := []struct {
20+ name string
21+ args []string
22+ expectError bool
23+ }{
24+ {
25+ name : "Help command" ,
26+ args : []string {"--help" },
27+ expectError : false ,
28+ },
29+ {
30+ name : "Unknown subcommand" ,
31+ args : []string {"invalid-command" },
32+ expectError : false , // Unknown subcommands just show help, don't error
33+ },
34+ }
35+
36+ for _ , tt := range tests {
37+ t .Run (tt .name , func (t * testing.T ) {
38+ // Create a test version of the root command to avoid affecting global state
39+ testRootCmd := & cobra.Command {
40+ Use : "tagit" ,
41+ Short : "Update consul services with dynamic tags coming from a script" ,
42+ }
43+ testRootCmd .PersistentFlags ().StringP ("consul-addr" , "c" , "127.0.0.1:8500" , "consul address" )
44+ testRootCmd .PersistentFlags ().StringP ("service-id" , "s" , "" , "consul service id" )
45+ testRootCmd .PersistentFlags ().StringP ("script" , "x" , "" , "path to script used to generate tags" )
46+ testRootCmd .PersistentFlags ().StringP ("tag-prefix" , "p" , "tagged" , "prefix to be added to tags" )
47+ testRootCmd .PersistentFlags ().StringP ("interval" , "i" , "60s" , "interval to run the script" )
48+ testRootCmd .PersistentFlags ().StringP ("token" , "t" , "" , "consul token" )
49+
50+ var buf bytes.Buffer
51+ testRootCmd .SetOut (& buf )
52+ testRootCmd .SetErr (& buf )
53+ testRootCmd .SetArgs (tt .args )
54+
55+ err := testRootCmd .Execute ()
56+
57+ if tt .expectError {
58+ assert .Error (t , err )
59+ } else {
60+ assert .NoError (t , err )
61+ }
62+ })
63+ }
64+ }
65+
66+ func TestInitConfig (t * testing.T ) {
67+ // Save original environment
68+ originalHome := os .Getenv ("HOME" )
69+ defer func () {
70+ if originalHome != "" {
71+ os .Setenv ("HOME" , originalHome )
72+ } else {
73+ os .Unsetenv ("HOME" )
74+ }
75+ }()
76+
77+ tests := []struct {
78+ name string
79+ setupConfig func () (string , func ()) // Returns config file path and cleanup function
80+ expectError bool
81+ expectedVals map [string ]string
82+ }{
83+ {
84+ name : "No config file" ,
85+ setupConfig : func () (string , func ()) {
86+ // Create a temporary home directory
87+ tempDir , err := os .MkdirTemp ("" , "tagit-test-home" )
88+ if err != nil {
89+ t .Fatalf ("Failed to create temp dir: %v" , err )
90+ }
91+ os .Setenv ("HOME" , tempDir )
92+ return "" , func () { os .RemoveAll (tempDir ) }
93+ },
94+ expectError : false ,
95+ },
96+ {
97+ name : "Valid config file" ,
98+ setupConfig : func () (string , func ()) {
99+ // Create a temporary home directory
100+ tempDir , err := os .MkdirTemp ("" , "tagit-test-home" )
101+ if err != nil {
102+ t .Fatalf ("Failed to create temp dir: %v" , err )
103+ }
104+ os .Setenv ("HOME" , tempDir )
105+
106+ // Create a config file
107+ configPath := filepath .Join (tempDir , ".tagit.yaml" )
108+ configContent := `consul-addr: "localhost:8500"
109+ service-id: "test-service"
110+ script: "/tmp/test.sh"
111+ tag-prefix: "test"
112+ interval: "30s"
113+ token: "test-token"
114+ `
115+ err = os .WriteFile (configPath , []byte (configContent ), 0644 )
116+ if err != nil {
117+ t .Fatalf ("Failed to create config file: %v" , err )
118+ }
119+
120+ return configPath , func () { os .RemoveAll (tempDir ) }
121+ },
122+ expectError : false ,
123+ expectedVals : map [string ]string {
124+ "consul-addr" : "localhost:8500" ,
125+ "service-id" : "test-service" ,
126+ "script" : "/tmp/test.sh" ,
127+ "tag-prefix" : "test" ,
128+ "interval" : "30s" ,
129+ "token" : "test-token" ,
130+ },
131+ },
132+ }
133+
134+ for _ , tt := range tests {
135+ t .Run (tt .name , func (t * testing.T ) {
136+ // Reset viper for each test
137+ viper .Reset ()
138+
139+ configPath , cleanup := tt .setupConfig ()
140+ defer cleanup ()
141+
142+ // Set config file if provided
143+ if configPath != "" {
144+ viper .SetConfigFile (configPath )
145+ }
146+
147+ // Call initConfig
148+ initConfig ()
149+
150+ // Verify expected values
151+ for key , expectedVal := range tt .expectedVals {
152+ actualVal := viper .GetString (key )
153+ assert .Equal (t , expectedVal , actualVal , "Config value for %q should be %q but got %q" , key , expectedVal , actualVal )
154+ }
155+ })
156+ }
157+ }
158+
159+ func TestRootCmdFlags (t * testing.T ) {
160+ // Test that all expected flags are defined
161+ expectedFlags := []struct {
162+ name string
163+ shorthand string
164+ defaultValue string
165+ required bool
166+ }{
167+ {"consul-addr" , "c" , "127.0.0.1:8500" , false },
168+ {"service-id" , "s" , "" , true },
169+ {"script" , "x" , "" , true },
170+ {"tag-prefix" , "p" , "tagged" , false },
171+ {"interval" , "i" , "60s" , false },
172+ {"token" , "t" , "" , false },
173+ }
174+
175+ for _ , flag := range expectedFlags {
176+ t .Run (flag .name , func (t * testing.T ) {
177+ f := rootCmd .PersistentFlags ().Lookup (flag .name )
178+ assert .NotNil (t , f , "Flag %q should be defined" , flag .name )
179+
180+ if f != nil {
181+ assert .Equal (t , flag .shorthand , f .Shorthand , "Flag %q shorthand should be %q" , flag .name , flag .shorthand )
182+ assert .Equal (t , flag .defaultValue , f .DefValue , "Flag %q default value should be %q" , flag .name , flag .defaultValue )
183+ }
184+ })
185+ }
186+ }
187+
188+ func TestRootCmdHelp (t * testing.T ) {
189+ var buf bytes.Buffer
190+ rootCmd .SetOut (& buf )
191+ rootCmd .SetArgs ([]string {"--help" })
192+
193+ err := rootCmd .Execute ()
194+ assert .NoError (t , err )
195+
196+ output := buf .String ()
197+ assert .Contains (t , output , "Update consul services with dynamic tags" )
198+ assert .Contains (t , output , "Usage:" )
199+ assert .Contains (t , output , "Available Commands:" )
200+ assert .Contains (t , output , "Flags:" )
201+
202+ // Check that our subcommands are listed
203+ assert .Contains (t , output , "cleanup" )
204+ assert .Contains (t , output , "run" )
205+ assert .Contains (t , output , "systemd" )
206+ }
0 commit comments