mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-03 20:13:00 +00:00
first commit
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
package bookings
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bookra/apps/backend/internal/db"
|
||||
"bookra/apps/backend/internal/domain"
|
||||
)
|
||||
|
||||
func TestCreateAppointmentRejectsConflict(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
service := NewService(repo)
|
||||
|
||||
availability, err := service.Availability(context.Background(), "studio-atelier")
|
||||
if err != nil {
|
||||
t.Fatalf("availability: %v", err)
|
||||
}
|
||||
|
||||
var appointment domain.TimeSlot
|
||||
for _, slot := range availability.Slots {
|
||||
if slot.Mode == "appointment" {
|
||||
appointment = slot
|
||||
break
|
||||
}
|
||||
}
|
||||
if appointment.StartsAt == "" {
|
||||
t.Fatal("expected appointment slot")
|
||||
}
|
||||
|
||||
first, err := service.Create(context.Background(), domain.CreateBookingRequest{
|
||||
TenantSlug: "studio-atelier",
|
||||
BookingMode: "appointment",
|
||||
ServiceID: appointment.ServiceID,
|
||||
StaffID: appointment.StaffID,
|
||||
LocationID: appointment.LocationID,
|
||||
CustomerName: "First",
|
||||
CustomerEmail: "first@example.com",
|
||||
StartsAt: appointment.StartsAt,
|
||||
EndsAt: appointment.EndsAt,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("first create: %v", err)
|
||||
}
|
||||
if first.Status != "confirmed" {
|
||||
t.Fatalf("expected confirmed, got %s", first.Status)
|
||||
}
|
||||
|
||||
_, err = service.Create(context.Background(), domain.CreateBookingRequest{
|
||||
TenantSlug: "studio-atelier",
|
||||
BookingMode: "appointment",
|
||||
ServiceID: appointment.ServiceID,
|
||||
StaffID: appointment.StaffID,
|
||||
LocationID: appointment.LocationID,
|
||||
CustomerName: "Second",
|
||||
CustomerEmail: "second@example.com",
|
||||
StartsAt: appointment.StartsAt,
|
||||
EndsAt: appointment.EndsAt,
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("expected conflict error")
|
||||
}
|
||||
if err != ErrBookingConflict {
|
||||
t.Fatalf("expected ErrBookingConflict, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateClassFallsBackToWaitlistWhenCapacityReached(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
service := NewService(repo)
|
||||
|
||||
availability, err := service.Availability(context.Background(), "studio-atelier")
|
||||
if err != nil {
|
||||
t.Fatalf("availability: %v", err)
|
||||
}
|
||||
|
||||
var classSlot domain.TimeSlot
|
||||
for _, slot := range availability.Slots {
|
||||
if slot.Mode == "class" {
|
||||
classSlot = slot
|
||||
break
|
||||
}
|
||||
}
|
||||
if classSlot.ClassSessionID == nil {
|
||||
t.Fatal("expected class slot")
|
||||
}
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
response, err := service.Create(context.Background(), domain.CreateBookingRequest{
|
||||
TenantSlug: "studio-atelier",
|
||||
BookingMode: "class",
|
||||
ClassSessionID: classSlot.ClassSessionID,
|
||||
LocationID: classSlot.LocationID,
|
||||
CustomerName: "Capacity",
|
||||
CustomerEmail: "capacity@example.com",
|
||||
StartsAt: classSlot.StartsAt,
|
||||
EndsAt: classSlot.EndsAt,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create within capacity: %v", err)
|
||||
}
|
||||
if response.Status != "confirmed" {
|
||||
t.Fatalf("expected confirmed within capacity, got %s", response.Status)
|
||||
}
|
||||
}
|
||||
|
||||
response, err := service.Create(context.Background(), domain.CreateBookingRequest{
|
||||
TenantSlug: "studio-atelier",
|
||||
BookingMode: "class",
|
||||
ClassSessionID: classSlot.ClassSessionID,
|
||||
LocationID: classSlot.LocationID,
|
||||
CustomerName: "Waitlist",
|
||||
CustomerEmail: "waitlist@example.com",
|
||||
StartsAt: classSlot.StartsAt,
|
||||
EndsAt: classSlot.EndsAt,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create waitlist: %v", err)
|
||||
}
|
||||
if response.Status != "waitlisted" {
|
||||
t.Fatalf("expected waitlisted, got %s", response.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAvailabilityGeneratesUpcomingSlots(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
service := NewService(repo)
|
||||
|
||||
availability, err := service.Availability(context.Background(), "studio-atelier")
|
||||
if err != nil {
|
||||
t.Fatalf("availability: %v", err)
|
||||
}
|
||||
if len(availability.Slots) == 0 {
|
||||
t.Fatal("expected slots")
|
||||
}
|
||||
|
||||
for _, slot := range availability.Slots {
|
||||
startsAt, err := time.Parse(time.RFC3339, slot.StartsAt)
|
||||
if err != nil {
|
||||
t.Fatalf("parse startsAt: %v", err)
|
||||
}
|
||||
if startsAt.Before(time.Now().UTC().Add(90 * time.Minute)) {
|
||||
t.Fatalf("expected upcoming slot, got %s", slot.StartsAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateSchedulesReminderJobForUpcomingAppointment(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
service := NewService(repo)
|
||||
|
||||
availability, err := service.Availability(context.Background(), "studio-atelier")
|
||||
if err != nil {
|
||||
t.Fatalf("availability: %v", err)
|
||||
}
|
||||
|
||||
var appointment domain.TimeSlot
|
||||
for _, slot := range availability.Slots {
|
||||
if slot.Mode == "appointment" {
|
||||
appointment = slot
|
||||
break
|
||||
}
|
||||
}
|
||||
if appointment.StartsAt == "" {
|
||||
t.Fatal("expected appointment slot")
|
||||
}
|
||||
|
||||
_, err = service.Create(context.Background(), domain.CreateBookingRequest{
|
||||
TenantSlug: "studio-atelier",
|
||||
BookingMode: "appointment",
|
||||
ServiceID: appointment.ServiceID,
|
||||
StaffID: appointment.StaffID,
|
||||
LocationID: appointment.LocationID,
|
||||
CustomerName: "Reminder",
|
||||
CustomerEmail: "reminder@example.com",
|
||||
StartsAt: time.Now().UTC().Add(30 * time.Hour).Format(time.RFC3339),
|
||||
EndsAt: time.Now().UTC().Add(31 * time.Hour).Format(time.RFC3339),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create: %v", err)
|
||||
}
|
||||
|
||||
reminders, err := repo.ListDueReminderJobs(context.Background(), time.Now().UTC().Add(365*24*time.Hour), 10)
|
||||
if err != nil {
|
||||
t.Fatalf("list reminder jobs: %v", err)
|
||||
}
|
||||
if len(reminders) == 0 {
|
||||
t.Fatal("expected reminder job to be scheduled")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user