github.com/alecthomas/kong@v0.9.1-0.20240410131203-2ab5733f1179/tag_test.go (about) 1 package kong_test 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/alecthomas/assert/v2" 8 9 "github.com/alecthomas/kong" 10 ) 11 12 func TestDefaultValueForOptionalArg(t *testing.T) { 13 var cli struct { 14 Arg string `kong:"arg,optional,default='\"\\'👌\\'\"'"` 15 } 16 p := mustNew(t, &cli) 17 _, err := p.Parse(nil) 18 assert.NoError(t, err) 19 assert.Equal(t, "\"'👌'\"", cli.Arg) 20 } 21 22 func TestNoValueInTag(t *testing.T) { 23 var cli struct { 24 Empty1 string `kong:"default"` 25 Empty2 string `kong:"default="` 26 } 27 p := mustNew(t, &cli) 28 _, err := p.Parse(nil) 29 assert.NoError(t, err) 30 assert.Equal(t, "", cli.Empty1) 31 assert.Equal(t, "", cli.Empty2) 32 } 33 34 func TestCommaInQuotes(t *testing.T) { 35 var cli struct { 36 Numbers string `kong:"default='1,2'"` 37 } 38 p := mustNew(t, &cli) 39 _, err := p.Parse(nil) 40 assert.NoError(t, err) 41 assert.Equal(t, "1,2", cli.Numbers) 42 } 43 44 func TestBadString(t *testing.T) { 45 var cli struct { 46 Numbers string `kong:"default='yay'n"` 47 } 48 _, err := kong.New(&cli) 49 assert.Error(t, err) 50 } 51 52 func TestNoQuoteEnd(t *testing.T) { 53 var cli struct { 54 Numbers string `kong:"default='yay"` 55 } 56 _, err := kong.New(&cli) 57 assert.Error(t, err) 58 } 59 60 func TestEscapedQuote(t *testing.T) { 61 var cli struct { 62 DoYouKnow string `kong:"default='i don\\'t know'"` 63 } 64 p := mustNew(t, &cli) 65 _, err := p.Parse(nil) 66 assert.NoError(t, err) 67 assert.Equal(t, "i don't know", cli.DoYouKnow) 68 } 69 70 func TestEscapingInQuotedTags(t *testing.T) { 71 var cli struct { 72 Regex1 string `kong:"default='\\d+\n'"` 73 Regex2 string `default:"\\d+\n"` 74 } 75 p := mustNew(t, &cli) 76 _, err := p.Parse(nil) 77 assert.NoError(t, err) 78 assert.Equal(t, "\\d+\n", cli.Regex1) 79 assert.Equal(t, "\\d+\n", cli.Regex2) 80 } 81 82 func TestBareTags(t *testing.T) { 83 var cli struct { 84 Cmd struct { 85 Arg string `arg` 86 Flag string `required default:"👌"` 87 } `cmd` 88 } 89 90 p := mustNew(t, &cli) 91 _, err := p.Parse([]string{"cmd", "arg", "--flag=hi"}) 92 assert.NoError(t, err) 93 assert.Equal(t, "hi", cli.Cmd.Flag) 94 assert.Equal(t, "arg", cli.Cmd.Arg) 95 } 96 97 func TestBareTagsWithJsonTag(t *testing.T) { 98 var cli struct { 99 Cmd struct { 100 Arg string `json:"-" optional arg` 101 Flag string `json:"best_flag" default:"\"'👌'\""` 102 } `cmd json:"CMD"` 103 } 104 105 p := mustNew(t, &cli) 106 _, err := p.Parse([]string{"cmd"}) 107 assert.NoError(t, err) 108 assert.Equal(t, "\"'👌'\"", cli.Cmd.Flag) 109 assert.Equal(t, "", cli.Cmd.Arg) 110 } 111 112 func TestManySeps(t *testing.T) { 113 var cli struct { 114 Arg string `arg optional default:"hi"` 115 } 116 117 p := mustNew(t, &cli) 118 _, err := p.Parse([]string{}) 119 assert.NoError(t, err) 120 assert.Equal(t, "hi", cli.Arg) 121 } 122 123 func TestTagSetOnEmbeddedStruct(t *testing.T) { 124 type Embedded struct { 125 Key string `help:"A key from ${where}."` 126 } 127 var cli struct { 128 Embedded `set:"where=somewhere"` 129 } 130 buf := &strings.Builder{} 131 p := mustNew(t, &cli, kong.Writers(buf, buf), kong.Exit(func(int) {})) 132 _, err := p.Parse([]string{"--help"}) 133 assert.NoError(t, err) 134 assert.Contains(t, buf.String(), `A key from somewhere.`) 135 } 136 137 func TestTagSetOnCommand(t *testing.T) { 138 type Command struct { 139 Key string `help:"A key from ${where}."` 140 } 141 var cli struct { 142 Command Command `set:"where=somewhere" cmd:""` 143 } 144 buf := &strings.Builder{} 145 p := mustNew(t, &cli, kong.Writers(buf, buf), kong.Exit(func(int) {})) 146 _, err := p.Parse([]string{"command", "--help"}) 147 assert.NoError(t, err) 148 assert.Contains(t, buf.String(), `A key from somewhere.`) 149 } 150 151 func TestTagSetOnFlag(t *testing.T) { 152 var cli struct { 153 Flag string `set:"where=somewhere" help:"A key from ${where}."` 154 } 155 buf := &strings.Builder{} 156 p := mustNew(t, &cli, kong.Writers(buf, buf), kong.Exit(func(int) {})) 157 _, err := p.Parse([]string{"--help"}) 158 assert.NoError(t, err) 159 assert.Contains(t, buf.String(), `A key from somewhere.`) 160 } 161 162 func TestTagAliases(t *testing.T) { 163 type Command struct { 164 Arg string `arg help:"Some arg"` 165 } 166 var cli struct { 167 Cmd Command `cmd aliases:"alias1, alias2"` 168 } 169 p := mustNew(t, &cli) 170 _, err := p.Parse([]string{"alias1", "arg"}) 171 assert.NoError(t, err) 172 assert.Equal(t, "arg", cli.Cmd.Arg) 173 _, err = p.Parse([]string{"alias2", "arg"}) 174 assert.NoError(t, err) 175 assert.Equal(t, "arg", cli.Cmd.Arg) 176 } 177 178 func TestTagAliasesConflict(t *testing.T) { 179 type Command struct { 180 Arg string `arg help:"Some arg"` 181 } 182 var cli struct { 183 Cmd Command `cmd hidden aliases:"other-cmd"` 184 OtherCmd Command `cmd` 185 } 186 p := mustNew(t, &cli) 187 _, err := p.Parse([]string{"other-cmd", "arg"}) 188 assert.NoError(t, err) 189 assert.Equal(t, "arg", cli.OtherCmd.Arg) 190 } 191 192 func TestTagAliasesSub(t *testing.T) { 193 type SubCommand struct { 194 Arg string `arg help:"Some arg"` 195 } 196 type Command struct { 197 SubCmd SubCommand `cmd aliases:"other-sub-cmd"` 198 } 199 var cli struct { 200 Cmd Command `cmd hidden` 201 } 202 p := mustNew(t, &cli) 203 _, err := p.Parse([]string{"cmd", "other-sub-cmd", "arg"}) 204 assert.NoError(t, err) 205 assert.Equal(t, "arg", cli.Cmd.SubCmd.Arg) 206 } 207 208 func TestInvalidRuneErrors(t *testing.T) { 209 cli := struct { 210 Flag bool `short:"invalid"` 211 }{} 212 _, err := kong.New(&cli) 213 assert.EqualError(t, err, "<anonymous struct>.Flag: invalid short flag name \"invalid\": invalid rune") 214 }