package calendartest import ( calendar "amadan.net/oficina/calendar/internal/calendar" "context" "errors" "net/url" "testing" "time" ) func TestGapSeriesRefusesFreeSlotsWithoutBreakingOrdinaryDates(t *testing.T) { app, session := signedIn(t, "gap@example.test") createEvent(t, app.Handler(), session, url.Values{"title": {"Gap fixture"}, "start": {"2026-03-01T01:30"}, "end": {"2026-03-01T02:00"}, "tz": {"Europe/Dublin"}, "kind": {"meeting"}, "status": {"confirmed"}, "repeat": {"daily"}}) host := app.PersonByAddressForTest(t, "gap@example.test") st := app.StoreForTest() ctx := context.Background() ws, problems := calendar.ParseAvailability("every day 0-4") if len(problems) != 0 { t.Fatal(problems) } stored, err := st.CreateBookingPage(ctx, host.ID, calendar.BookingPageInput{Title: "Gap check", Availability: "every day 0-4", DurationMin: 30, HorizonDays: 30}, ws) if err != nil { t.Fatal(err) } page, err := st.BookingPage(ctx, host.ID, stored.ID) if err != nil { t.Fatal(err) } for _, c := range []struct { day int month time.Month incomplete bool }{{29, time.March, true}, {27, time.March, false}, {1, time.April, false}} { from := time.Date(2026, c.month, c.day, 0, 0, 0, 0, time.UTC) to := from.Add(24 * time.Hour) slots, err := st.FreeSlots(ctx, page, host, from, from, to, 0, 0) if c.incomplete { if !errors.Is(err, calendar.ErrIncompleteExpansion) || len(slots) != 0 { t.Fatalf("gap FreeSlots=%v err=%v", slots, err) } } else if err != nil || len(slots) == 0 { t.Fatalf("ordinary date %v incomplete", from) } views, err := st.EventsInRange(ctx, host.ID, from.Unix(), to.Unix()) if err != nil { t.Fatal(err) } if c.incomplete && len(views) != 0 { t.Fatalf("invalid chip: %+v", views) } if !c.incomplete && len(views) != 1 { t.Fatalf("ordinary date %v: %d views", from, len(views)) } } }