package main import ( "strings" "testing" "github.com/spf13/cobra" ) // `info`, `enable`, `disable` and `list` take nothing. Without a declared // arity cobra applies arbitraryArgs, so a stray token yielded exit 0 and the // command looked like it had done its work — a caller could believe a // lighting change happened when the argument was silently dropped. func TestZeroArgCommandsRejectStrayTokens(t *testing.T) { cmds := map[string]*cobra.Command{ "info": NewInfoCmd(), "enable": NewEnableCmd(), "disable": NewDisableCmd(), "list": NewProfileListCmd(), } for name, cmd := range cmds { t.Run(name, func(t *testing.T) { err := cmd.ValidateArgs([]string{"unexpected-arg"}) if err == nil { t.Errorf("%s accepted an argument, want it rejected", name) return } if !strings.Contains(err.Error(), "unexpected-arg") { t.Errorf("%s error = %q, want it to name the offending argument", name, err) } }) } } // Rejecting extras must not break the no-argument case. func TestZeroArgCommandsAcceptNoArgs(t *testing.T) { cmds := map[string]*cobra.Command{ "info": NewInfoCmd(), "enable": NewEnableCmd(), "disable": NewDisableCmd(), "list": NewProfileListCmd(), } for name, cmd := range cmds { t.Run(name, func(t *testing.T) { if err := cmd.ValidateArgs(nil); err != nil { t.Errorf("%s rejected the empty argument list: %v", name, err) } }) } } // Commands that do take an argument must keep accepting exactly one. func TestOneArgCommandsKeepTheirArity(t *testing.T) { cmds := map[string]*cobra.Command{ "brightness": NewBrightnessCmd(), "speed": NewSpeedCmd(), "color": NewColorCmd(), "mode": NewModeCmd(), } for name, cmd := range cmds { t.Run(name, func(t *testing.T) { if err := cmd.ValidateArgs([]string{"160"}); err != nil { t.Errorf("%s rejected its argument: %v", name, err) } if err := cmd.ValidateArgs([]string{"1", "2"}); err == nil { t.Errorf("%s accepted two arguments, want exactly one", name) } }) } }