/ dispatcher_test.go
dispatcher_test.go
1 package dispatch2_test 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "codeberg.org/vlbeaudoin/dispatch2" 9 ) 10 11 func TestSimple(t *testing.T) { 12 type Config struct { 13 Verbose bool 14 } 15 16 d := dispatch2.NewDispatcher[Config]() 17 18 if err := d.RegisterFunc("basic", "basic command", "", []string{"b"}, func(ctx context.Context, cfg *Config, args []string) error { 19 select { 20 case <-ctx.Done(): 21 return ctx.Err() 22 default: 23 t.Log("inside basic executer") 24 if cfg.Verbose { 25 t.Log("basic: verbose mode is on") 26 } 27 return nil 28 } 29 }); err != nil { 30 t.Error(err) 31 } 32 33 for _, command := range d.Commands() { 34 t.Run( 35 fmt.Sprintf("exec: %q", command), 36 func(t *testing.T) { 37 if err := command.Execute(context.TODO(), d.Config(), []string{}); err != nil { 38 t.Error(err) 39 } 40 }) 41 } 42 43 t.Run("dispatch basic", func(t *testing.T) { 44 if err := d.Dispatch(context.TODO(), []string{"basic"}); err != nil { 45 t.Error(err) 46 } 47 }) 48 49 t.Run("dispatch empty string", func(t *testing.T) { 50 if err := d.Dispatch(context.TODO(), nil); err != nil { 51 if err != dispatch2.ErrCommandRequired { 52 t.Error(err) 53 } 54 } 55 }) 56 57 t.Run("dispatch invalid", func(t *testing.T) { 58 if err := d.Dispatch(context.TODO(), []string{"invalid"}); err != nil { 59 if err != dispatch2.ErrCommandNotFound { 60 t.Error(err) 61 } 62 } 63 }) 64 65 t.Run("help", func(t *testing.T) { 66 if err := d.RegisterFunc( 67 "help", 68 "show help", 69 "help COMMAND [SUBCOMMAND...]", 70 nil, 71 func(ctx context.Context, cfg *Config, args []string) error { 72 t.Log("help command executed") 73 return nil 74 }, 75 ); err != nil { 76 t.Error(err) 77 } 78 79 if err := d.Dispatch(context.TODO(), []string{"help"}); err != nil { 80 t.Error(err) 81 } 82 83 if err := d.Dispatch(context.TODO(), []string{"help", "invalid"}); err != nil { 84 t.Error(err) 85 } 86 }) 87 88 t.Run("subcommand", func(t *testing.T) { 89 deepCmd := dispatch2.NewCommandFunc( 90 "deep", 91 "deep command", 92 "deep SUBCOMMAND...", 93 nil, 94 func(ctx context.Context, cfg *Config, args []string) error { 95 t.Log("executed 'deep' command") 96 t.Log("remaining args:", args) 97 return nil 98 }) 99 100 if err := deepCmd.RegisterFunc( 101 "deeper", 102 "deeper command", 103 "deeper SUBCOMMAND...", 104 nil, 105 func(ctx context.Context, cfg *Config, args []string) error { 106 t.Log("executed 'deep deeper' command") 107 return nil 108 }, 109 ); err != nil { 110 t.Error(err) 111 } 112 113 if err := d.RegisterCommand(deepCmd); err != nil { 114 t.Error(err) 115 } 116 117 t.Run("deep deeper", func(t *testing.T) { 118 if err := d.Dispatch(context.TODO(), []string{"deep", "deeper"}); err != nil { 119 t.Log(d.Commands()) 120 for _, cmd := range d.Commands() { 121 t.Logf("%s subcommands: %d", cmd.Name(), cmd.NSubcommands()) 122 if cmd.NSubcommands() != 0 { 123 for _, cmd := range cmd.Subcommands() { 124 t.Log("inner command: ", cmd) 125 } 126 } 127 } 128 t.Error(err) 129 } 130 }) 131 132 t.Run("deep", func(t *testing.T) { 133 if err := d.Dispatch(context.TODO(), []string{"deep"}); err != nil { 134 t.Error(err) 135 } 136 }) 137 138 t.Run("deep invalid", func(t *testing.T) { 139 if err := d.Dispatch(context.TODO(), []string{"deep", "invalid"}); err != nil { 140 t.Error(err) 141 } 142 }) 143 144 t.Run("deep with helloworld middleware", func(t *testing.T) { 145 /* 146 f := dispatch2.MiddlewareHelloWorld[Config]()(dispatch2.WrapExecuter(deepCmd.Executer())) 147 if err := f(); err != nil { 148 t.Error(err) 149 } 150 */ 151 152 /* 153 mw := dispatch2.WrapMiddleware(func(e dispatch2.Executer[Config]) dispatch2.Executer[Config] { 154 // return dispatch2.ExecuterFunc[Config](func(ctx context.Context, cfg *Config, args []string) error { 155 // return e.Execute(ctx, cfg, args) 156 // }) 157 return deepCmd 158 }) 159 160 executer := mw(deepCmd.Execute) 161 162 if err := executer(context.TODO(), &Config{}, []string{}); err != nil { 163 t.Error(err) 164 } 165 */ 166 167 if err := dispatch2.MiddlewareHelloWorld[Config]()( 168 dispatch2.ExecuterFunc[Config](deepCmd.Execute))( 169 context.TODO(), d.Config(), []string{}); err != nil { 170 t.Error(err) 171 } 172 }) 173 }) 174 } 175 176 func TestDispatcherMiddleware(t *testing.T) { 177 type Config struct{} 178 179 d := dispatch2.NewDispatcher[Config]() 180 181 d.Before(dispatch2.MiddlewarePrinter[Config]("dispatch middleware before 1")) 182 d.Before(dispatch2.MiddlewarePrinter[Config]("dispatch middleware before 2")) 183 d.After(dispatch2.MiddlewarePrinter[Config]("dispatch middleware after 1")) 184 d.After(dispatch2.MiddlewarePrinter[Config]("dispatch middleware after 2")) 185 186 c := dispatch2.NewCommand( 187 "foo", 188 "foo command for TestDispatcherMiddleware", 189 "foo", 190 nil, 191 dispatch2.EmptyExecuter[Config]()) 192 193 c.Before(dispatch2.MiddlewarePrinter[Config]("command middleware before 1")) 194 c.Before(dispatch2.MiddlewarePrinter[Config]("command middleware before 2")) 195 c.After(dispatch2.MiddlewarePrinter[Config]("command middleware after 1")) 196 c.After(dispatch2.MiddlewarePrinter[Config]("command middleware after 2")) 197 198 if err := d.RegisterCommand(c); err != nil { 199 t.Error(err) 200 } 201 202 if err := d.Dispatch(context.TODO(), []string{"foo"}); err != nil { 203 t.Error(err) 204 } 205 }