package cqrs_test import ( "context" "errors" "log" "reflect" "testing" "gitstormr.dev/code-raider/gravity-wells/cqrs" ) type testEvent struct { Echo string } type testCommand struct { Echo string } type testQuery struct { Echo string } type successCommandHandler struct { SendEvent bool } func (s *successCommandHandler) Handle( ctx context.Context, cmd cqrs.Command, ) ([]cqrs.Event, error) { command, _ := cmd.(*testCommand) log.Printf("Processing command: %s\n", command.Echo) if s.SendEvent { return []cqrs.Event{testEvent{Echo: command.Echo}}, nil } else { return nil, nil } } type successEventHandler struct{} func (e *successEventHandler) Handle( ctx context.Context, evt cqrs.Event, ) error { event, _ := evt.(testEvent) log.Printf("Processing event: %s\n", event.Echo) return nil } type failureCommandHandler struct{} func (e *failureCommandHandler) Handle( ctx context.Context, cmd cqrs.Command, ) ([]cqrs.Event, error) { return nil, errors.New("failed") } type successQueryHandler struct{} func (e *successQueryHandler) Handle( ctx context.Context, query cqrs.Query, ) (interface{}, error) { return query, nil } type failureQueryHandler struct{} func (e *failureQueryHandler) Handle( ctx context.Context, query cqrs.Query, ) (interface{}, error) { return nil, errors.New("failed") } type failureEventHandler struct{} func (e *failureEventHandler) Handle( ctx context.Context, evt cqrs.Event, ) error { return errors.New("failed") } func logTestCommandMiddleware(next cqrs.CommandHandler) cqrs.CommandHandler { return cqrs.CommandHandlerFunc( func(ctx context.Context, cmd cqrs.Command) ([]cqrs.Event, error) { log.Printf("Received command: %s\n", cmd) return next.Handle(ctx, cmd) }, ) } func logTestQueryMiddleware(next cqrs.QueryHandler) cqrs.QueryHandler { return cqrs.QueryHandlerFunc( func(ctx context.Context, query cqrs.Query) (cqrs.Query, error) { log.Printf("Received query: %s\n", query) return next.Handle(ctx, query) }, ) } func logTestEventMiddleware(next cqrs.EventHandler) cqrs.EventHandler { return cqrs.EventHandlerFunc( func(ctx context.Context, evt cqrs.Event) error { log.Printf("Received event: %s\n", evt) return next.Handle(ctx, evt) }, ) } func TestNewRuneBringer(t *testing.T) { bus := cqrs.NewSingularity() if bus == nil { t.Error("RuneBringer should not be nil") } busType := reflect.TypeOf(bus) if busType.Kind() == reflect.Ptr { busType = busType.Elem() } if busType.Name() != "singularity" { t.Errorf( "RuneBringer should be of type RuneBringer, got %s", busType.Name(), ) } } func TestRuneBringer_CommandHandle(t *testing.T) { tests := []struct { SendEvent bool }{ {true}, {false}, } for _, tt := range tests { bus := cqrs.NewSingularity() bus.UseCommandMiddleware(logTestCommandMiddleware) bus.UseEventMiddleware(logTestEventMiddleware) bus.RegisterCommandHandler( &testCommand{}, &successCommandHandler{SendEvent: tt.SendEvent}, ) bus.RegisterEventHandler(&testEvent{}, &successEventHandler{}) events, err := bus.ExecuteCommand( context.Background(), &testCommand{Echo: "Hello"}, ) if err != nil { t.Error("Error should be nil") } if tt.SendEvent { if len(events) == 0 { t.Errorf("Expected 1 event, got %d", len(events)) } } else { if len(events) != 0 { t.Errorf("Expected 0 events, got %d", len(events)) } } } } func TestRuneBringer_CommandHandleFailure(t *testing.T) { bus := cqrs.NewSingularity() bus.UseCommandMiddleware(logTestCommandMiddleware) bus.RegisterCommandHandler( &testCommand{}, &failureCommandHandler{}, ) _, err := bus.ExecuteCommand( context.Background(), &testCommand{Echo: "Hello"}, ) if err == nil { t.Error("Error should not be nil") } } func TestRuneBringer_CommandMissingHandler(t *testing.T) { bus := cqrs.NewSingularity() bus.UseCommandMiddleware(logTestCommandMiddleware) _, err := bus.ExecuteCommand( context.Background(), &testCommand{Echo: "Hello"}, ) if err == nil { t.Error("Error should not be nil") } } func TestRuneBringer_CommandHandleEventFailure(t *testing.T) { tests := []struct { SendEvent bool EventHandler cqrs.EventHandler }{ {true, &failureEventHandler{}}, {true, nil}, {false, nil}, } for _, tt := range tests { bus := cqrs.NewSingularity() bus.UseCommandMiddleware(logTestCommandMiddleware) bus.RegisterCommandHandler( &testCommand{}, &successCommandHandler{SendEvent: tt.SendEvent}, ) if tt.EventHandler != nil { bus.RegisterEventHandler(&testEvent{}, tt.EventHandler) } _, err := bus.ExecuteCommand( context.Background(), &testCommand{Echo: "Hello"}, ) bus.RegisterEventHandler(&testEvent{}, tt.EventHandler) if tt.SendEvent && tt.EventHandler != nil { if err == nil { t.Error("Error should not be nil") } } else { if err != nil { t.Error("Error should be nil") } } } } func TestRuneBringer_QueryHandle(t *testing.T) { bus := cqrs.NewSingularity() bus.UseQueryMiddleware(logTestQueryMiddleware) bus.RegisterQueryHandler( &testQuery{}, &successQueryHandler{}, ) result, err := bus.ExecuteQuery( context.Background(), &testQuery{Echo: "Hello"}, ) if err != nil { t.Error("Error should be nil") } if result == nil { t.Error("Result should not be nil") } } func TestRuneBringer_QueryHandleFailure(t *testing.T) { bus := cqrs.NewSingularity() bus.UseQueryMiddleware(logTestQueryMiddleware) bus.RegisterQueryHandler( &testQuery{}, &failureQueryHandler{}, ) _, err := bus.ExecuteQuery( context.Background(), &testQuery{Echo: "Hello"}, ) if err == nil { t.Error("Error should not be nil") } } func TestRuneBringer_QueryMissingHandler(t *testing.T) { bus := cqrs.NewSingularity() bus.UseQueryMiddleware(logTestQueryMiddleware) _, err := bus.ExecuteQuery( context.Background(), &testQuery{Echo: "Hello"}, ) if err == nil { t.Error("Error should not be nil") } }