mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 07:41:16 +00:00
refactor(db): replace sqlc with handwritten pgx repos
- Finish Paddle-to-Stripe billing migration; drop paddle/stripe libs - Renumber migrations; add 00012 memberships+manage_token, 00013 location_type_capacity - Add tests: admin, auth, bookings customer service - Remove graphify-out artifacts and stale env files Authored By: TDvorak <[email protected]> Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
2039669e2c
commit
f2f7439050
93 files changed
+6987
-69060
No files matched your search
@@ -0,0 +1,113 @@
|
||||
package bookings
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bookra/apps/backend/internal/db"
|
||||
"bookra/apps/backend/internal/domain"
|
||||
)
|
||||
|
||||
func newBookingFixture(t *testing.T, repo *db.MemoryRepository) db.BookingRecord {
|
||||
t.Helper()
|
||||
created, err := repo.CreateBooking(context.Background(), db.CreateBookingParams{
|
||||
TenantID: "5d6b3551-0a3e-4b86-bdf0-e9df20a47148",
|
||||
CustomerName: "Test Customer",
|
||||
CustomerEmail: "[email protected]",
|
||||
StartsAt: time.Now().Add(24 * time.Hour),
|
||||
EndsAt: time.Now().Add(25 * time.Hour),
|
||||
Status: "confirmed",
|
||||
Reference: "BOK-TEST-1",
|
||||
ManageToken: "secret-manage-token",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create booking: %v", err)
|
||||
}
|
||||
booking, err := repo.GetBookingByReference(context.Background(), created.Reference)
|
||||
if err != nil {
|
||||
t.Fatalf("get booking: %v", err)
|
||||
}
|
||||
return booking
|
||||
}
|
||||
|
||||
func TestGetBookingRequiresManageToken(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
booking := newBookingFixture(t, repo)
|
||||
svc := NewCustomerService(repo, nil, "http://localhost:3000")
|
||||
|
||||
if _, err := svc.GetBookingByReference(context.Background(), booking.Reference, ""); err != ErrUnauthorized {
|
||||
t.Fatalf("expected ErrUnauthorized for missing token, got %v", err)
|
||||
}
|
||||
if _, err := svc.GetBookingByReference(context.Background(), booking.Reference, "wrong"); err != ErrUnauthorized {
|
||||
t.Fatalf("expected ErrUnauthorized for wrong token, got %v", err)
|
||||
}
|
||||
view, err := svc.GetBookingByReference(context.Background(), booking.Reference, "secret-manage-token")
|
||||
if err != nil {
|
||||
t.Fatalf("expected authorized view, got %v", err)
|
||||
}
|
||||
if view.Reference != booking.Reference {
|
||||
t.Fatalf("expected reference %s, got %s", booking.Reference, view.Reference)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRescheduleRequiresManageToken(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
booking := newBookingFixture(t, repo)
|
||||
svc := NewCustomerService(repo, nil, "http://localhost:3000")
|
||||
|
||||
req := domain.RescheduleBookingRequest{
|
||||
NewStartsAt: time.Now().Add(48 * time.Hour).Format(time.RFC3339),
|
||||
NewEndsAt: time.Now().Add(49 * time.Hour).Format(time.RFC3339),
|
||||
}
|
||||
if err := svc.RescheduleBooking(context.Background(), booking.Reference, req, ""); err != ErrUnauthorized {
|
||||
t.Fatalf("expected ErrUnauthorized, got %v", err)
|
||||
}
|
||||
if err := svc.RescheduleBooking(context.Background(), booking.Reference, req, "wrong"); err != ErrUnauthorized {
|
||||
t.Fatalf("expected ErrUnauthorized, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelRequiresManageToken(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, ""); err != ErrUnauthorized {
|
||||
t.Fatalf("expected ErrUnauthorized, got %v", err)
|
||||
}
|
||||
if err := svc.CancelBooking(context.Background(), booking.Reference, "wrong"); err != ErrUnauthorized {
|
||||
t.Fatalf("expected ErrUnauthorized, got %v", err)
|
||||
}
|
||||
if err := svc.CancelBooking(context.Background(), booking.Reference, "secret-manage-token"); err != nil {
|
||||
t.Fatalf("expected successful cancel, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRescheduleRejectsConflictingSlot(t *testing.T) {
|
||||
repo := db.NewMemoryRepository()
|
||||
svc := NewCustomerService(repo, nil, "http://localhost:3000")
|
||||
base := time.Now().Add(48 * time.Hour)
|
||||
|
||||
// Existing booking in the same tenant occupying the target slot.
|
||||
_, err := repo.CreateBooking(context.Background(), db.CreateBookingParams{
|
||||
TenantID: "5d6b3551-0a3e-4b86-bdf0-e9df20a47148",
|
||||
StartsAt: base,
|
||||
EndsAt: base.Add(time.Hour),
|
||||
Status: "confirmed",
|
||||
Reference: "BOK-OCCUPIED",
|
||||
ManageToken: "token-a",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create occupying booking: %v", err)
|
||||
}
|
||||
|
||||
booking := newBookingFixture(t, repo)
|
||||
err = svc.RescheduleBooking(context.Background(), booking.Reference, domain.RescheduleBookingRequest{
|
||||
NewStartsAt: base.Add(30 * time.Minute).Format(time.RFC3339), // overlaps BOK-OCCUPIED
|
||||
NewEndsAt: base.Add(90 * time.Minute).Format(time.RFC3339),
|
||||
}, "secret-manage-token")
|
||||
if err != ErrBookingConflict {
|
||||
t.Fatalf("expected ErrBookingConflict, got %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user