From c2fbc014f778fea453601709c452a972bafd5df0 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Tue, 22 Sep 2026 19:58:01 +0200 Subject: [PATCH] test: make reschedule reminder test weekday-agnostic The test rescheduled a booking with a blind +48h shift. With Mon-Fri availability rules the target lands on a weekend roughly a third of the time (booking ~72h out + 48h), so it flaked by day of week. It now picks a real availability slot >25h out, mirroring the manage-page picker and keeping the -24h reminder tier deterministic. Authored By: TDvorak Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../backend/internal/bookings/service_test.go | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/apps/backend/internal/bookings/service_test.go b/apps/backend/internal/bookings/service_test.go index 7a68eee..c3d1833 100644 --- a/apps/backend/internal/bookings/service_test.go +++ b/apps/backend/internal/bookings/service_test.go @@ -607,8 +607,40 @@ func TestRescheduleRearmsReminder(t *testing.T) { resp := bookAppointmentSlot(t, repo, service) booking, _ := repo.GetBookingByID(ctx, resp.BookingID) - newStartsAt := booking.StartsAt.Add(48 * time.Hour) - newEndsAt := booking.EndsAt.Add(48 * time.Hour) + // Reschedule into a real availability slot on a later day, mirroring the + // manage-page slot picker — a blind +48h shift can land on a weekend or + // blocked day and fail validation for the wrong reason. + var newStartsAt, newEndsAt time.Time + horizon := time.Now().UTC().Add(25 * time.Hour) + for offset := 1; offset <= 14 && newStartsAt.IsZero(); offset++ { + date := time.Now().UTC().AddDate(0, 0, offset).Format("2006-01-02") + availability, err := service.Availability(ctx, "studio-atelier", AvailabilityFilter{Date: date}) + if err != nil { + t.Fatalf("availability for %s: %v", date, err) + } + for _, slot := range availability.Slots { + if slot.Mode != "appointment" { + continue + } + starts, err := time.Parse(time.RFC3339, slot.StartsAt) + if err != nil { + t.Fatalf("parse slot start: %v", err) + } + ends, err := time.Parse(time.RFC3339, slot.EndsAt) + if err != nil { + t.Fatalf("parse slot end: %v", err) + } + // Stay above the 25h tier so the reminder re-arms at -24h. + if starts.Equal(booking.StartsAt) || !starts.After(horizon) { + continue + } + newStartsAt, newEndsAt = starts, ends + break + } + } + if newStartsAt.IsZero() { + t.Fatal("no alternative appointment slot found within 14 days") + } manageURL, _ := url.Parse(resp.ManageURL) token := manageURL.Query().Get("token") if err := customerService.RescheduleBooking(ctx, resp.Reference, domain.RescheduleBookingRequest{