package bookings import ( "context" "testing" "bookra/apps/backend/internal/db" ) const activityTenantID = "5d6b3551-0a3e-4b86-bdf0-e9df20a47148" var activitySessionID = "4bf74c12-44dd-45ca-86bb-b104f16f2435" func seedSessionBooking(t *testing.T, repo *db.MemoryRepository, name, status string) db.BookingRecord { t.Helper() created, err := repo.CreateBooking(context.Background(), db.CreateBookingParams{ TenantID: activityTenantID, ClassSessionID: &activitySessionID, CustomerName: name, CustomerEmail: name + "@example.com", Status: status, Reference: "BK-" + name, ManageToken: "tok-" + name, }) if err != nil { t.Fatalf("seed booking: %v", err) } booking, err := repo.GetBookingByReference(context.Background(), created.Reference) if err != nil { t.Fatalf("get booking: %v", err) } return booking } func TestCustomerCancelWritesActivityEvent(t *testing.T) { repo := db.NewMemoryRepository() booking := newBookingFixture(t, repo) svc := NewCustomerService(repo, nil, "http://localhost:3000") if err := svc.CancelBooking(context.Background(), booking.Reference, "secret-manage-token"); err != nil { t.Fatalf("cancel booking: %v", err) } events, err := repo.ListActivityEvents(context.Background(), activityTenantID, 1) if err != nil { t.Fatalf("list activity: %v", err) } if len(events) != 1 { t.Fatalf("expected 1 event, got %d", len(events)) } event := events[0] if event.Action != "booking.cancelled" { t.Fatalf("expected booking.cancelled, got %s", event.Action) } if event.ActorKind != "customer" || event.ActorName != "Test Customer" { t.Fatalf("expected customer actor Test Customer, got %s %q", event.ActorKind, event.ActorName) } if event.EntityID == nil || *event.EntityID != booking.ID { t.Fatalf("expected entity id %s, got %v", booking.ID, event.EntityID) } } func TestPromoteWaitlistWritesSystemEvent(t *testing.T) { repo := db.NewMemoryRepository() // Demo session capacity is 4 — three confirmed leaves exactly one seat. for _, name := range []string{"fill-a", "fill-b", "fill-c"} { seedSessionBooking(t, repo, name, "confirmed") } waiting := seedSessionBooking(t, repo, "queued", "waitlisted") promoted, err := PromoteWaitlist(context.Background(), repo, activityTenantID, activitySessionID) if err != nil { t.Fatalf("promote waitlist: %v", err) } if len(promoted) != 1 || promoted[0].ID != waiting.ID { t.Fatalf("expected queued booking promoted, got %v", promoted) } events, err := repo.ListActivityEvents(context.Background(), activityTenantID, 10) if err != nil { t.Fatalf("list activity: %v", err) } for _, event := range events { if event.Action == "booking.promoted" && event.ActorKind == "system" { if event.EntityID == nil || *event.EntityID != waiting.ID { t.Fatalf("expected entity id %s, got %v", waiting.ID, event.EntityID) } return } } t.Fatal("expected system booking.promoted event") }