From 72755a8b61ae139b1ae87f45cab993cc0fdfb10f Mon Sep 17 00:00:00 2001 From: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com> Date: Sun, 11 Oct 2026 09:38:06 -0400 Subject: [PATCH 1/2] Assert Home tonight dinner exact id and photo URL (Maestro 9d81c325) (#196) Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com> --- internal/home/home_test.go | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/internal/home/home_test.go b/internal/home/home_test.go index a158d2b..0d131a4 100644 --- a/internal/home/home_test.go +++ b/internal/home/home_test.go @@ -222,16 +222,44 @@ func TestTonightSwitchesAtLocalMidnight(t *testing.T) { func TestTonightDinner(t *testing.T) { t.Parallel() e := newEnv(t) - e.planWeek(t) + ctx := t.Context() + planID := e.planWeek(t) + planned := func(date string) string { + t.Helper() + var id string + if err := e.st.Reader.QueryRowContext(ctx, `SELECT dinner_id FROM plan_days WHERE plan_id = ? AND date = ?`, planID, date).Scan(&id); err != nil { + t.Fatal(err) + } + return id + } h := e.at(t, "2026-10-13 18:00") - if h.Tonight == nil || h.Tonight.ID == "" || h.Tonight.Origin != "regular" || h.Tonight.Photo != nil || + if h.Tonight == nil || h.Tonight.ID != planned("2026-10-13") || h.Tonight.Origin != "regular" || h.Tonight.Photo != nil || h.Tonight.MinutesTotal == nil || *h.Tonight.MinutesTotal != 30 { - t.Errorf("tonight = %+v, want Tuesday's 30-minute Regular with no photo", h.Tonight) + t.Errorf("tonight = %+v, want Tuesday's 30-minute Regular %s with no photo", h.Tonight, planned("2026-10-13")) } h = e.at(t, "2026-10-14 18:00") - if h.Tonight == nil || h.Tonight.Origin != "side_quest" || h.Tonight.MinutesTotal != nil { - t.Errorf("tonight = %+v, want Wednesday's Side quest of unknown minutes", h.Tonight) + if h.Tonight == nil || h.Tonight.ID != planned("2026-10-14") || h.Tonight.Origin != "side_quest" || h.Tonight.MinutesTotal != nil { + t.Errorf("tonight = %+v, want Wednesday's Side quest %s of unknown minutes", h.Tonight, planned("2026-10-14")) + } + + // Thursday's dinner has a photo: Home serves its list-sized copy. + now := store.Now().String() + photo, err := db.New(e.st.Writer).CreatePhoto(ctx, db.CreatePhotoParams{ + ID: store.NewID(), SourceUrl: "https://example.com/thursday.jpg", LocalPath: "photos/thursday.jpg", + Width: 800, Height: 600, Sha256: "thursday", FetchedAt: now, CreatedAt: now, UpdatedAt: now, + }) + if err != nil { + t.Fatal(err) + } + thursday := planned("2026-10-15") + if _, err := e.st.Writer.ExecContext(ctx, `UPDATE dinners SET photo_id = ? WHERE id = ?`, photo.ID, thursday); err != nil { + t.Fatal(err) + } + h = e.at(t, "2026-10-15 18:00") + wantPhoto := "/media/photos/" + photo.ID + "-400.jpg" + if h.Tonight == nil || h.Tonight.ID != thursday || h.Tonight.Photo == nil || *h.Tonight.Photo != wantPhoto { + t.Errorf("tonight = %+v, want Thursday's dinner %s with photo %s", h.Tonight, thursday, wantPhoto) } } From d1823496462f8da8c075d204663d444a56527832 Mon Sep 17 00:00:00 2001 From: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com> Date: Sun, 11 Oct 2026 09:38:12 -0400 Subject: [PATCH 2/2] Plan draft schedule tests: assert the plan_ready title and channel (Maestro ece60217) (#195) Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com> --- cmd/server/main.go | 2 +- internal/home/home_test.go | 2 +- internal/plan/draft.go | 2 +- internal/plan/plan.go | 15 +++-- internal/plan/plan_test.go | 2 +- internal/scheduler/plan_draft_test.go | 86 +++++++++++++++++++++++---- internal/scheduler/scheduler.go | 5 ++ internal/server/ideaactions_test.go | 2 +- internal/server/plans_test.go | 3 +- internal/server/server_test.go | 5 +- internal/suggest/suggest_test.go | 2 +- 11 files changed, 99 insertions(+), 27 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 0ca16d6..7470dd2 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -158,7 +158,7 @@ func run(cfg config.Config, logger *slog.Logger) error { return err } - planSvc, err := plan.NewService(db, weekDrafter(ai, guard), runner, googleSvc, notifier, sched.Wake, cfg.PublicURL, logger) + planSvc, err := plan.NewService(db, weekDrafter(ai, guard), runner, googleSvc, notifier, sched.Wake, cfg.PublicURL, sched.Now, logger) if err != nil { return err } diff --git a/internal/home/home_test.go b/internal/home/home_test.go index 0d131a4..078070a 100644 --- a/internal/home/home_test.go +++ b/internal/home/home_test.go @@ -94,7 +94,7 @@ func newEnv(t *testing.T) *env { draft := func(context.Context, string, skills.WeekRequest) (skills.Week, error) { return skills.Week{}, errors.New("no model in this test") } - plans, err := plan.NewService(st, draft, runner, googleSvc, notifier, func() {}, pub, logger) + plans, err := plan.NewService(st, draft, runner, googleSvc, notifier, func() {}, pub, time.Now, logger) if err != nil { t.Fatal(err) } diff --git a/internal/plan/draft.go b/internal/plan/draft.go index 6bb1271..74428ad 100644 --- a/internal/plan/draft.go +++ b/internal/plan/draft.go @@ -96,7 +96,7 @@ func (s *Service) revision(ctx context.Context, weekStart store.LocalDate) (int6 // the household context, the pool, last week's dinners and the dinner // time. func (s *Service) request(ctx context.Context, weekStart store.LocalDate) (skills.WeekRequest, error) { - hctx, err := harness.BuildContext(ctx, s.st, time.Now(), ContextBudget) + hctx, err := harness.BuildContext(ctx, s.st, s.now(), ContextBudget) if err != nil { return skills.WeekRequest{}, fmt.Errorf("plan: %w", err) } diff --git a/internal/plan/plan.go b/internal/plan/plan.go index 7e66458..95f7084 100644 --- a/internal/plan/plan.go +++ b/internal/plan/plan.go @@ -149,16 +149,19 @@ type Service struct { // publicURL is MEALQUEST_PUBLIC_URL, under which a pushed event links // to its dinner. publicURL *url.URL + // now is the clock today is read from: the scheduler's. + now func() time.Time } // NewService returns a service over st that drafts with draft, pushes to // cal with links under publicURL, tells the household through notifier, // which must be over st, calls wake (the scheduler's Wake) after every -// committed change to a plan's days, and registers the KindDraftWeek job on -// runner, which must not have started yet. The kind is service-only: +// committed change to a plan's days, reads today from now (the scheduler's +// Now) and registers the KindDraftWeek job on runner, which must not have +// started yet. The kind is service-only: // StartDraft and StartScheduledDraft, which keep one draft in flight per // week, are the only way to enqueue it. -func NewService(st *store.Store, draft Drafter, runner *jobs.Runner, cal Calendar, notifier *notify.Service, wake func(), publicURL *url.URL, logger *slog.Logger) (*Service, error) { +func NewService(st *store.Store, draft Drafter, runner *jobs.Runner, cal Calendar, notifier *notify.Service, wake func(), publicURL *url.URL, now func() time.Time, logger *slog.Logger) (*Service, error) { switch { case st == nil: return nil, errors.New("plan: nil store") @@ -174,10 +177,12 @@ func NewService(st *store.Store, draft Drafter, runner *jobs.Runner, cal Calenda return nil, errors.New("plan: nil wake") case publicURL == nil: return nil, errors.New("plan: nil public URL") + case now == nil: + return nil, errors.New("plan: nil clock") case logger == nil: return nil, errors.New("plan: nil logger") } - s := &Service{st: st, draft: draft, cal: cal, notifier: notifier, wake: wake, logger: logger, publicURL: publicURL} + s := &Service{st: st, draft: draft, cal: cal, notifier: notifier, wake: wake, logger: logger, publicURL: publicURL, now: now} kind, err := jobs.Register(runner, KindDraftWeek, s.runDraft, Reasons...) if err != nil { return nil, err @@ -501,7 +506,7 @@ func (s *Service) Tonight(ctx context.Context) (week, today store.LocalDate, err if err != nil { return store.LocalDate{}, store.LocalDate{}, fmt.Errorf("plan: household settings: %w", err) } - today = household.Today(time.Now(), zone) + today = household.Today(s.now(), zone) week = household.WeekStart(today) _, err = q.GetWeekPlan(ctx, week.String()) if errors.Is(err, sql.ErrNoRows) { diff --git a/internal/plan/plan_test.go b/internal/plan/plan_test.go index 4b1f557..da23842 100644 --- a/internal/plan/plan_test.go +++ b/internal/plan/plan_test.go @@ -146,7 +146,7 @@ func newEnv(t *testing.T) *env { if err != nil { t.Fatal(err) } - e.svc, err = plan.NewService(st, drafter, e.runner, e.gcal, notifytest.New(t, st), func() {}, publicURL, logger) + e.svc, err = plan.NewService(st, drafter, e.runner, e.gcal, notifytest.New(t, st), func() {}, publicURL, time.Now, logger) if err != nil { t.Fatal(err) } diff --git a/internal/scheduler/plan_draft_test.go b/internal/scheduler/plan_draft_test.go index 8696487..9dd9304 100644 --- a/internal/scheduler/plan_draft_test.go +++ b/internal/scheduler/plan_draft_test.go @@ -7,6 +7,7 @@ import ( "fmt" "log/slog" "net/url" + "slices" "strings" "sync" "testing" @@ -85,7 +86,21 @@ func (c noCalendar) PushEvents(context.Context, []gcal.Event, func() error) erro // pass the fake clock's waits do not expect. func (e *env) plans(ids map[string]string) *planEnv { e.t.Helper() - return e.newPlans(ids, func() {}) + return e.newPlans(ids, func() {}, time.Now) +} + +// scheduledPlans is plans whose today is read from the clock of the +// scheduler start last started, as in the server, so a draft's plan_ready +// title follows the fake clock. It drafts only once a scheduler started. +func (e *env) scheduledPlans(ids map[string]string) *planEnv { + e.t.Helper() + return e.newPlans(ids, func() {}, func() time.Time { + s := e.sched.Load() + if s == nil { + panic("plan service read the clock before a scheduler started") + } + return s.Now() + }) } // wakingPlans is plans whose changes wake the scheduler, as in the server. @@ -93,11 +108,12 @@ func (e *env) plans(ids map[string]string) *planEnv { // the wake's pass with changed. func (e *env) wakingPlans(ids map[string]string) *planEnv { e.t.Helper() - return e.newPlans(ids, e.wake) + return e.newPlans(ids, e.wake, time.Now) } -// newPlans is plans whose service calls wake after a plan change. -func (e *env) newPlans(ids map[string]string, wake func()) *planEnv { +// newPlans is plans whose service calls wake after a plan change and reads +// today from now. +func (e *env) newPlans(ids map[string]string, wake func(), now func() time.Time) *planEnv { e.t.Helper() p := &planEnv{e: e, model: &llm.Fake{}, ids: ids, logs: &syncBuffer{}} guard, err := harness.NewGuard(harness.DefaultMaxCalls) @@ -118,7 +134,7 @@ func (e *env) newPlans(ids map[string]string, wake func()) *planEnv { if err != nil { e.t.Fatal(err) } - p.svc, err = plan.NewService(e.st, drafter, runner, noCalendar{e.t}, notifytest.New(e.t, e.st), wake, publicURL, logger) + p.svc, err = plan.NewService(e.st, drafter, runner, noCalendar{e.t}, notifytest.New(e.t, e.st), wake, publicURL, now, logger) if err != nil { e.t.Fatal(err) } @@ -235,6 +251,41 @@ func (e *env) planReady() []string { return keys } +// readyRow is a stored plan_ready notification as these tests check it. +type readyRow struct { + Key string + Channel notify.Channel + Title string +} + +// planReadyRows returns every plan_ready notification stored, oldest +// first, each week's Google Chat row before its push row. +func (e *env) planReadyRows() []readyRow { + e.t.Helper() + var out []readyRow + for _, r := range notifytest.Rows(e.t, e.st, notify.PlanReady) { + out = append(out, readyRow{Key: r.Key, Channel: r.Channel, Title: r.Payload.Title}) + } + return out +} + +// nextWeekReady is the plan_ready rows of a draft of the week starting +// week, drafted the week before: one to Google Chat and one to push. +func nextWeekReady(week string) []readyRow { + const title = "Next week's plan is ready" + key := string(notify.PlanReady) + ":" + week + return []readyRow{{key, notify.ChannelChat, title}, {key, notify.ChannelPush, title}} +} + +// wantReady fails unless the plan_ready rows are got. +func wantReady(t *testing.T, what string, got []readyRow, want ...[]readyRow) { + t.Helper() + all := slices.Concat(want...) + if !slices.Equal(got, all) { + t.Fatalf("%s: plan_ready rows = %+v, want %+v", what, got, all) + } +} + var ( succeeded = draftJob{Status: string(jobs.StatusSucceeded)} aiFailed = draftJob{Status: string(jobs.StatusFailed), Error: plan.ReasonAIFailed} @@ -257,7 +308,7 @@ func mustLocalDate(s string) store.LocalDate { // by its Monday once. func TestPlanDraftDraftsNextWeek(t *testing.T) { e := newEnv(t) - p := e.plans(e.pool()) + p := e.scheduledPlans(e.pool()) p.reply(w43) p.reply(w44) @@ -271,6 +322,7 @@ func TestPlanDraftDraftsNextWeek(t *testing.T) { wantDrafts(t, "at Friday 09:00", e.drafts(), succeeded) wantKeys(t, "plans at Friday 09:00", e.weekPlans(), []string{"2026-10-19"}) wantKeys(t, "plan_ready of W43", e.planReady(), []string{"plan_ready:2026-10-19"}) + wantReady(t, "plan_ready rows of W43", e.planReadyRows(), nextWeekReady("2026-10-19")) got, err := p.svc.Get(context.Background(), w43) if err != nil { t.Fatal(err) @@ -283,6 +335,7 @@ func TestPlanDraftDraftsNextWeek(t *testing.T) { wantDrafts(t, "W44", e.drafts(), succeeded, succeeded) wantKeys(t, "plans", e.weekPlans(), []string{"2026-10-19", "2026-10-26"}) wantKeys(t, "plan_ready of W43 and W44", e.planReady(), []string{"plan_ready:2026-10-19", "plan_ready:2026-10-26"}) + wantReady(t, "plan_ready rows of W43 and W44", e.planReadyRows(), nextWeekReady("2026-10-19"), nextWeekReady("2026-10-26")) wantKeys(t, "schedule_runs", e.claimed(scheduler.PlanDraft), []string{"2026-W42", "2026-W43", "2026-W44"}) } @@ -291,23 +344,25 @@ func TestPlanDraftDraftsNextWeek(t *testing.T) { // notifies no one and says so. func TestPlanDraftLeavesAnExistingPlan(t *testing.T) { e := newEnv(t) - p := e.plans(e.pool()) + p := e.scheduledPlans(e.pool()) p.reply(w43) p.reply(w43) // a second draft would succeed too + r := e.start(at(2026, 10, 16, 8, 0), p.svc.DraftSchedule()) if _, err := p.svc.StartDraft(context.Background(), w43, false); err != nil { t.Fatal(err) } wantDrafts(t, "manual draft", e.drafts(), succeeded) wantKeys(t, "plan_ready of the manual draft", e.planReady(), []string{"plan_ready:2026-10-19"}) + wantReady(t, "plan_ready rows of the manual draft", e.planReadyRows(), nextWeekReady("2026-10-19")) before, err := p.svc.Get(context.Background(), w43) if err != nil { t.Fatal(err) } - r := e.start(at(2026, 10, 16, 8, 0), p.svc.DraftSchedule()) r.runUntil(at(2026, 10, 16, 9, 0)) wantDrafts(t, "with a plan", e.drafts(), succeeded) wantKeys(t, "plan_ready with a plan", e.planReady(), []string{"plan_ready:2026-10-19"}) + wantReady(t, "plan_ready rows with a plan", e.planReadyRows(), nextWeekReady("2026-10-19")) wantKeys(t, "schedule_runs", e.claimed(scheduler.PlanDraft), []string{"2026-W42", "2026-W43"}) after, err := p.svc.Get(context.Background(), w43) if err != nil { @@ -327,23 +382,25 @@ func TestPlanDraftLeavesAnExistingPlan(t *testing.T) { func TestPlanDraftNoDuplicateAfterRestart(t *testing.T) { e := newEnv(t) ids := e.pool() - p := e.plans(ids) + p := e.scheduledPlans(ids) p.reply(w43) r := e.start(at(2026, 10, 16, 8, 0), p.svc.DraftSchedule()) r.runUntil(at(2026, 10, 16, 9, 0)) wantDrafts(t, "first process", e.drafts(), succeeded) + wantReady(t, "plan_ready rows of the first process", e.planReadyRows(), nextWeekReady("2026-10-19")) r.stop() p.stop() // The restarted process has a new job runner, plan service and // scheduler; it would answer a second draft if one were started. - p2 := e.plans(ids) + p2 := e.scheduledPlans(ids) p2.reply(w43) r2 := e.start(at(2026, 10, 16, 10, 0), p2.svc.DraftSchedule()) r2.runUntil(at(2026, 10, 23, 8, 59)) wantDrafts(t, "after restart", e.drafts(), succeeded) wantKeys(t, "plans after restart", e.weekPlans(), []string{"2026-10-19"}) wantKeys(t, "plan_ready after restart", e.planReady(), []string{"plan_ready:2026-10-19"}) + wantReady(t, "plan_ready rows after restart", e.planReadyRows(), nextWeekReady("2026-10-19")) wantKeys(t, "schedule_runs", e.claimed(scheduler.PlanDraft), []string{"2026-W42", "2026-W43"}) } @@ -354,7 +411,7 @@ func TestPlanDraftNoDuplicateAfterRestart(t *testing.T) { func TestPlanDraftAIFailureEmitsNothing(t *testing.T) { e := newEnv(t) ids := e.pool() - p := e.plans(ids) + p := e.scheduledPlans(ids) p.model.QueueGenerate(llm.GenerateResult{Err: errors.New("provider down")}) r := e.start(at(2026, 10, 16, 8, 0), p.svc.DraftSchedule()) @@ -362,6 +419,7 @@ func TestPlanDraftAIFailureEmitsNothing(t *testing.T) { wantDrafts(t, "after the AI failed", e.drafts(), aiFailed) wantKeys(t, "plans after the AI failed", e.weekPlans(), nil) wantKeys(t, "plan_ready after the AI failed", e.planReady(), nil) + wantReady(t, "plan_ready rows after the AI failed", e.planReadyRows()) wantKeys(t, "schedule_runs", e.claimed(scheduler.PlanDraft), []string{"2026-W42", "2026-W43"}) var status, msg string @@ -377,11 +435,12 @@ func TestPlanDraftAIFailureEmitsNothing(t *testing.T) { r.stop() p.stop() - p2 := e.plans(ids) + p2 := e.scheduledPlans(ids) p2.reply(w43) e.start(at(2026, 10, 16, 10, 0), p2.svc.DraftSchedule()) wantDrafts(t, "after restart", e.drafts(), aiFailed) wantKeys(t, "plan_ready after restart", e.planReady(), nil) + wantReady(t, "plan_ready rows after restart", e.planReadyRows()) } // TestPlanDraftFollowsSettingsWithoutRestart: a plan_draft_dow and @@ -390,7 +449,7 @@ func TestPlanDraftAIFailureEmitsNothing(t *testing.T) { // week. func TestPlanDraftFollowsSettingsWithoutRestart(t *testing.T) { e := newEnv(t) - p := e.plans(e.pool()) + p := e.scheduledPlans(e.pool()) p.reply(w43) r := e.start(at(2026, 10, 12, 12, 0), p.svc.DraftSchedule()) // Monday @@ -401,6 +460,7 @@ func TestPlanDraftFollowsSettingsWithoutRestart(t *testing.T) { r.runUntil(at(2026, 10, 14, 18, 30)) wantDrafts(t, "at Wednesday 18:30", e.drafts(), succeeded) wantKeys(t, "plan_ready", e.planReady(), []string{"plan_ready:2026-10-19"}) + wantReady(t, "plan_ready rows", e.planReadyRows(), nextWeekReady("2026-10-19")) // Friday 09:00, the old fire time, drafts nothing more. r.runUntil(at(2026, 10, 16, 9, 0)) diff --git a/internal/scheduler/scheduler.go b/internal/scheduler/scheduler.go index a37eaf5..d66e8fd 100644 --- a/internal/scheduler/scheduler.go +++ b/internal/scheduler/scheduler.go @@ -378,6 +378,11 @@ func (s *Scheduler) Wake() { s.signal() } +// Now is the time on the scheduler's clock, by which its schedules fire. +func (s *Scheduler) Now() time.Time { + return s.now() +} + // signal leaves one token in wake for the loop. func (s *Scheduler) signal() { select { diff --git a/internal/server/ideaactions_test.go b/internal/server/ideaactions_test.go index 5bc40bc..746c715 100644 --- a/internal/server/ideaactions_test.go +++ b/internal/server/ideaactions_test.go @@ -73,7 +73,7 @@ func newIdeaActionsRouter(t *testing.T, model, normalize *llm.Fake, search *reci t.Error("draft_week ran: an idea action must never draft a plan") return skills.Week{}, context.Canceled } - planSvc, err := plan.NewService(st, draft, runner, newTestGoogle(t), notifytest.New(t, st), func() {}, &url.URL{Scheme: "https", Host: "mealquest.example"}, logger) + planSvc, err := plan.NewService(st, draft, runner, newTestGoogle(t), notifytest.New(t, st), func() {}, &url.URL{Scheme: "https", Host: "mealquest.example"}, time.Now, logger) if err != nil { t.Fatal(err) } diff --git a/internal/server/plans_test.go b/internal/server/plans_test.go index 5da305e..9b62108 100644 --- a/internal/server/plans_test.go +++ b/internal/server/plans_test.go @@ -14,6 +14,7 @@ import ( "sync" "testing" "testing/fstest" + "time" "code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/ai/harness" "code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/ai/skills" @@ -93,7 +94,7 @@ func newPlansRouterTitled(t *testing.T, title shopping.Titler) plansEnv { t.Fatal(err) } notifier := notifytest.New(t, st) - svc, err := plan.NewService(st, fail, runner, googleSvc, notifier, func() {}, pub, logger) + svc, err := plan.NewService(st, fail, runner, googleSvc, notifier, func() {}, pub, time.Now, logger) if err != nil { t.Fatal(err) } diff --git a/internal/server/server_test.go b/internal/server/server_test.go index 402b925..c46ff0f 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -15,6 +15,7 @@ import ( "strings" "testing" "testing/fstest" + "time" "github.com/go-chi/chi/v5" "golang.org/x/oauth2" @@ -240,7 +241,7 @@ func newTestPlan(t *testing.T) *plan.Service { fail := func(context.Context, string, skills.WeekRequest) (skills.Week, error) { return skills.Week{}, errors.New("no model in this test") } - svc, err := plan.NewService(st, fail, runner, newTestGoogle(t), notifytest.New(t, st), func() {}, &url.URL{Scheme: "https", Host: "mealquest.example"}, logger) + svc, err := plan.NewService(st, fail, runner, newTestGoogle(t), notifytest.New(t, st), func() {}, &url.URL{Scheme: "https", Host: "mealquest.example"}, time.Now, logger) if err != nil { t.Fatal(err) } @@ -303,7 +304,7 @@ func newTestHomeOn(t *testing.T, st *store.Store) *home.Service { if err != nil { t.Fatal(err) } - planSvc, err := plan.NewService(st, draft, runner, googleSvc, notifier, func() {}, pub, logger) + planSvc, err := plan.NewService(st, draft, runner, googleSvc, notifier, func() {}, pub, time.Now, logger) if err != nil { t.Fatal(err) } diff --git a/internal/suggest/suggest_test.go b/internal/suggest/suggest_test.go index 6c0052c..fc0f79d 100644 --- a/internal/suggest/suggest_test.go +++ b/internal/suggest/suggest_test.go @@ -1157,7 +1157,7 @@ func TestLaterBatchNeverResuggestsRenamedDrop(t *testing.T) { fail := func(context.Context, string, skills.WeekRequest) (skills.Week, error) { return skills.Week{}, errors.New("no draft in this test") } - planSvc, err := plan.NewService(e.st, fail, e.runner, noCalendar{}, notifytest.New(t, e.st), func() {}, &url.URL{Scheme: "https", Host: "meals.example.com"}, logger) + planSvc, err := plan.NewService(e.st, fail, e.runner, noCalendar{}, notifytest.New(t, e.st), func() {}, &url.URL{Scheme: "https", Host: "meals.example.com"}, time.Now, logger) if err != nil { t.Fatal(err) }