mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 15:51:15 +00:00
activity_events records booking lifecycle transitions with the actor behind each change — staff (dashboard), customer (self-service), or system (auto-promotion). The notification dropdown leads with the real feed instead of derived recent-booking guesses. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
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")
|
|
}
|