diff --git a/bot/arguments.go b/bot/arguments.go index 540e494..0cae6df 100644 --- a/bot/arguments.go +++ b/bot/arguments.go @@ -126,7 +126,7 @@ func getArgumentValueFn(t reflect.Type) (*Argument, error) { } avfn := func(input string) (reflect.Value, error) { - v := reflect.New(t.Elem()) + v := reflect.New(typeI.Elem()) ret := mt.Func.Call([]reflect.Value{ v, reflect.ValueOf(input), @@ -185,9 +185,9 @@ func getArgumentValueFn(t reflect.Type) (*Argument, error) { case reflect.Bool: fn = func(s string) (reflect.Value, error) { switch s { - case "true", "yes", "y", "Y", "1": + case "True", "TRUE", "true", "T", "t", "yes", "y", "Y", "1": return reflect.ValueOf(true), nil - case "false", "no", "n", "N", "0": + case "False", "FALSE", "false", "F", "f", "no", "n", "N", "0": return reflect.ValueOf(false), nil default: return nilV, errors.New("invalid bool [true/false]") diff --git a/bot/arguments_test.go b/bot/arguments_test.go new file mode 100644 index 0000000..dd994a1 --- /dev/null +++ b/bot/arguments_test.go @@ -0,0 +1,51 @@ +package bot + +import ( + "reflect" + "strings" + "testing" +) + +type mockParser string + +func (m *mockParser) Parse(s string) error { + *m = mockParser(s) + return nil +} + +func mockParse(str string) *mockParser { + return (*mockParser)(&str) +} + +func TestArguments(t *testing.T) { + testArgs(t, "string", "string") + testArgs(t, true, "true") + testArgs(t, false, "n") + testArgs(t, int64(69420), "69420") + testArgs(t, uint64(1337), "1337") + testArgs(t, 69.420, "69.420") + testArgs(t, mockParse("testString"), "testString") + testArgs(t, *mockParse("testString"), "testString") + + _, err := getArgumentValueFn(reflect.TypeOf(struct{}{})) + if !strings.HasPrefix(err.Error(), "invalid type: ") { + t.Fatal("Unexpected error:", err) + } + +} + +func testArgs(t *testing.T, expect interface{}, input string) { + f, err := getArgumentValueFn(reflect.TypeOf(expect)) + if err != nil { + t.Fatal("Failed to get argument value function:", err) + } + + v, err := f.fn(input) + if err != nil { + t.Fatal("avfs returned with error:", err) + } + + if v := v.Interface(); !reflect.DeepEqual(v, expect) { + t.Fatal("Value :", v, "\nExpects:", expect) + } +} diff --git a/bot/ctx.go b/bot/ctx.go index ff91220..0e399ba 100644 --- a/bot/ctx.go +++ b/bot/ctx.go @@ -188,7 +188,7 @@ func (ctx *Context) Subcommands() []*Subcommand { func (ctx *Context) FindCommand(structname, methodname string) *CommandContext { if structname == "" { for _, c := range ctx.Commands { - if c.Command == methodname { + if c.MethodName == methodname { return c } } @@ -202,7 +202,7 @@ func (ctx *Context) FindCommand(structname, methodname string) *CommandContext { } for _, c := range sub.Commands { - if c.Command == methodname { + if c.MethodName == methodname { return c } } diff --git a/bot/ctx_test.go b/bot/ctx_test.go index 23f5a80..e72ca72 100644 --- a/bot/ctx_test.go +++ b/bot/ctx_test.go @@ -68,10 +68,14 @@ func TestNewContext(t *testing.T) { Store: state.NewDefaultStore(nil), } - _, err := New(state, &testCommands{}) + c, err := New(state, &testCommands{}) if err != nil { t.Fatal("Failed to create new context:", err) } + + if !reflect.DeepEqual(c.Subcommands(), c.subcommands) { + t.Fatal("Subcommands mismatch.") + } } func TestContext(t *testing.T) { @@ -104,6 +108,22 @@ func TestContext(t *testing.T) { } }) + t.Run("find commands", func(t *testing.T) { + cmd := ctx.FindCommand("", "NoArgs") + if cmd == nil { + t.Fatal("Failed to find NoArgs") + } + }) + + t.Run("help", func(t *testing.T) { + if h := ctx.Help(); h == "" { + t.Fatal("Empty help?") + } + if h := ctx.HelpAdmin(); h == "" { + t.Fatal("Empty admin help?") + } + }) + testReturn := func(expects interface{}, content string) (call error) { // Return channel for testing ret := make(chan interface{}) @@ -215,7 +235,12 @@ func TestContext(t *testing.T) { } if err := testMessage("run testCommands noop"); err != nil { - t.Fatal("unexpected error:", err) + t.Fatal("Unexpected error:", err) + } + + cmd := ctx.FindCommand("testCommands", "Noop") + if cmd == nil { + t.Fatal("Failed to find subcommand Noop") } }) } diff --git a/bot/extras/arguments/emoji.go b/bot/extras/arguments/emoji.go index 7780d35..93349e1 100644 --- a/bot/extras/arguments/emoji.go +++ b/bot/extras/arguments/emoji.go @@ -41,7 +41,7 @@ func (e Emoji) String() string { } func (e Emoji) URL() string { - if e.Custom { + if !e.Custom { return "" } diff --git a/bot/extras/arguments/emoji_test.go b/bot/extras/arguments/emoji_test.go index 7fef1c2..a1fa8f1 100644 --- a/bot/extras/arguments/emoji_test.go +++ b/bot/extras/arguments/emoji_test.go @@ -2,7 +2,7 @@ package arguments import "testing" -func TestEmojiRune(t *testing.T) { +func TestEmojiRuneParsing(t *testing.T) { var emojis = []string{ "🏑", "❄️", @@ -26,3 +26,68 @@ func TestEmojiRune(t *testing.T) { } } } + +func TestEmojiRune(t *testing.T) { + const emoji = "💩" + + e := Emoji{} + if err := e.Parse(emoji); err != nil { + t.Fatal("Failed to parse emoji:", err) + } + + if u := e.URL(); u != "" { + t.Fatal("Unexpected URL:", u) + } + + if s := e.String(); s != emoji { + t.Fatal("Unexpected string:", s) + } + + if s := e.APIString(); s != emoji { + t.Fatal("Unexpected API string:", s) + } +} + +func TestEmojiCustom(t *testing.T) { + const emoji = "<:StareNeutral:612368399732965376>" + const url = "https://cdn.discordapp.com/emojis/612368399732965376.png" + + e := Emoji{} + if err := e.Parse(emoji); err != nil { + t.Fatal("Failed to parse emoji:", err) + } + + if u := e.URL(); u != url { + t.Fatal("Unexpected URL:", u) + } + + if s := e.String(); s != emoji { + t.Fatal("Unexpected string:", s) + } + + if s := e.APIString(); s != "StareNeutral:612368399732965376" { + t.Fatal("Unexpected API string:", s) + } +} + +func TestEmojiAnimated(t *testing.T) { + const emoji = "" + const url = "https://cdn.discordapp.com/emojis/614322540332056577.gif" + + e := Emoji{} + if err := e.Parse(emoji); err != nil { + t.Fatal("Failed to parse emoji:", err) + } + + if u := e.URL(); u != url { + t.Fatal("Unexpected URL:", u) + } + + if s := e.String(); s != emoji { + t.Fatal("Unexpected string:", s) + } + + if s := e.APIString(); s != "StareNodGIF:614322540332056577" { + t.Fatal("Unexpected API string:", s) + } +} diff --git a/bot/extras/arguments/flag_test.go b/bot/extras/arguments/flag_test.go new file mode 100644 index 0000000..bdc5e80 --- /dev/null +++ b/bot/extras/arguments/flag_test.go @@ -0,0 +1,71 @@ +package arguments + +import ( + "reflect" + "strings" + "testing" +) + +func TestFlagSet(t *testing.T) { + fs := NewFlagSet() + + var b bool + fs.BoolVar(&b, "b", false, "Test boolean") + + if usage := fs.Usage(); !strings.Contains(usage, "Test boolean") { + t.Fatal("Unexpected usage:", usage) + } + + if err := fs.Parse([]string{"-b", "asdasd"}); err != nil { + t.Fatal("Failed to parse:", err) + } + + if !b { + t.Fatal("Test boolean is false") + } +} + +func TestFlag(t *testing.T) { + f := Flag{} + + if err := f.ParseContent([]string{"gc", "--now", "1m4s"}); err != nil { + t.Fatal("Failed to parse:", err) + } + + if f.Command() != "gc" { + t.Fatal("Unexpected command:", f.Command()) + } + + if args := f.Args(); !reflect.DeepEqual(args, []string{"--now", "1m4s"}) { + t.Fatal("Unexpected arguments:", args) + } + + if arg := f.Arg(1200); arg != "" { + t.Fatal("Unexpected argument at 1200th:", arg) + } + + if arg := f.Arg(0); arg != "--now" { + t.Fatal("Unexpected argument at 1st:", arg) + } + + if s := f.String(); s != "--now 1m4s" { + t.Fatal("Unexpected string:", s) + } + + fs := NewFlagSet() + + var now bool + fs.BoolVar(&now, "now", false, "Now") + + if err := f.With(fs.FlagSet); err != nil { + t.Fatal("Failed to parse:", err) + } + + if !now { + t.Fatal("now is false") + } + + if arg := fs.FlagSet.Arg(0); arg != "1m4s" { + t.Fatal("Unexpected argument:", arg) + } +} diff --git a/bot/subcommand_test.go b/bot/subcommand_test.go index 6d9ec94..9afe829 100644 --- a/bot/subcommand_test.go +++ b/bot/subcommand_test.go @@ -83,6 +83,12 @@ func TestSubcommand(t *testing.T) { t.Fatal("missing noargs") } }) + + t.Run("help commands", func(t *testing.T) { + if h := sub.Help("", "", false); h == "" { + t.Fatal("Empty subcommand help?") + } + }) } func BenchmarkSubcommandConstructor(b *testing.B) {