order sagas
Build and Publish / BuildAndDeployArm64 (push) Failing after 5s
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled

This commit is contained in:
2026-06-21 11:33:20 +02:00
parent 484f2364fb
commit 1a365de071
25 changed files with 4224 additions and 1 deletions
+96
View File
@@ -0,0 +1,96 @@
package order
import (
"context"
"encoding/json"
"slices"
"strings"
"testing"
"git.k6n.net/mats/go-cart-actor/pkg/flow"
)
func fullRegistry(t *testing.T, pub Publisher) *flow.Registry {
t.Helper()
reg := flow.NewRegistry()
flow.RegisterBuiltinHooks(reg)
RegisterFlowActions(reg, newPool(t), NewMockProvider())
RegisterEmitHook(reg, pub)
return reg
}
func TestCapabilitiesIncludesPredicatesAndEmit(t *testing.T) {
caps := fullRegistry(t, nil).Capabilities()
for _, want := range []string{"has_customer_email", "has_items", "is_captured", "not_captured", "has_open_balance"} {
if !slices.Contains(caps.Predicates, want) {
t.Errorf("predicates missing %q (got %v)", want, caps.Predicates)
}
}
if !slices.Contains(caps.Hooks, "amqp_emit") {
t.Errorf("hooks missing amqp_emit (got %v)", caps.Hooks)
}
}
func TestIsCapturedPredicateGatesStep(t *testing.T) {
pool := newPool(t)
reg := flow.NewRegistry()
flow.RegisterBuiltinHooks(reg)
RegisterFlowActions(reg, pool, NewMockProvider())
eng := flow.NewEngine(reg, nil)
ran := false
reg.Action("mark", func(_ context.Context, _ *flow.State, _ json.RawMessage) error { ran = true; return nil })
// Capture order 9001 via place-and-pay.
def, _ := EmbeddedFlow("place-and-pay")
paid := flow.NewState(9001, nil)
paid.Vars[PlaceOrderVar] = placeMsg()
if _, err := eng.Run(context.Background(), def, paid); err != nil {
t.Fatal(err)
}
gated := &flow.Definition{Name: "g", Steps: []flow.Step{{Name: "m", Action: "mark", When: "is_captured"}}}
if _, err := eng.Run(context.Background(), gated, flow.NewState(9001, nil)); err != nil {
t.Fatal(err)
}
if !ran {
t.Fatal("is_captured should pass for a captured order")
}
// Fresh (unplaced) order → is_captured false → step skipped.
ran = false
if _, err := eng.Run(context.Background(), gated, flow.NewState(9999, nil)); err != nil {
t.Fatal(err)
}
if ran {
t.Fatal("is_captured should skip for a new order")
}
}
type fakePublisher struct{ msgs []string }
func (f *fakePublisher) Publish(_, routingKey string, body []byte) error {
f.msgs = append(f.msgs, routingKey+":"+string(body))
return nil
}
func TestAmqpEmitHookPublishes(t *testing.T) {
fp := &fakePublisher{}
reg := flow.NewRegistry()
RegisterEmitHook(reg, fp)
reg.Action("noopact", func(_ context.Context, _ *flow.State, _ json.RawMessage) error { return nil })
eng := flow.NewEngine(reg, nil)
def := &flow.Definition{Name: "e", Steps: []flow.Step{{
Name: "s",
Action: "noopact",
Hooks: flow.Hooks{After: []flow.HookRef{{Type: "amqp_emit", Params: json.RawMessage(`{"routingKey":"k"}`)}}},
}}}
if _, err := eng.Run(context.Background(), def, flow.NewState(7, nil)); err != nil {
t.Fatal(err)
}
if len(fp.msgs) != 1 || !strings.HasPrefix(fp.msgs[0], "k:") {
t.Fatalf("expected one message routed to k, got %v", fp.msgs)
}
}