package main import ( "context" "testing" "time" "github.com/kami/maven/internal/router" ) // systemHandler — a handler with nothing but a fixed clock, which is all // replySystem needs. func systemHandler(now time.Time) *reactiveHandler { return &reactiveHandler{now: func() time.Time { return now }} } // TestReplySystemDateOffset — "какое число завтра" must answer tomorrow's // date, not today's (Vikunja #388). func TestReplySystemDateOffset(t *testing.T) { // Thursday, 30 July 2026. now := time.Date(2026, 7, 30, 14, 5, 0, 0, time.UTC) h := systemHandler(now) cases := []struct{ utterance, want string }{ {"какое сегодня число", "сегодня четверг, 30 июля 2026 года"}, {"какое число", "сегодня четверг, 30 июля 2026 года"}, {"какое число завтра", "завтра пятница, 31 июля 2026 года"}, {"какое число послезавтра", "послезавтра суббота, 1 августа 2026 года"}, {"какое было число вчера", "вчера среда, 29 июля 2026 года"}, } for _, c := range cases { got := h.replySystem(context.Background(), router.Decision{Utterance: c.utterance}) if got != c.want { t.Errorf("replySystem(%q) = %q, want %q", c.utterance, got, c.want) } } } // A day she cannot work out must not come back as today's date — that is the // same silent wrong answer #388 was about, one step further out. func TestReplySystemUnknownDayIsHonest(t *testing.T) { now := time.Date(2026, 7, 30, 14, 5, 0, 0, time.UTC) h := systemHandler(now) for _, u := range []string{ "какое число в пятницу", "какое число через неделю", "какое число в понедельник", } { got := h.replySystem(context.Background(), router.Decision{Utterance: u}) if got != onlyNearDaysReply { t.Errorf("replySystem(%q) = %q, want the honest reply", u, got) } } // The days she does know must not be caught by the same guard. if got := h.replySystem(context.Background(), router.Decision{Utterance: "какое число завтра"}); got == onlyNearDaysReply { t.Error("завтра was treated as an unknown day") } } // TestReplySystemClockCity — the clock arm must not answer local time for a // question about another city (Vikunja #388). She keeps one clock, so every // named place gets the honest "local time only" answer. func TestReplySystemClockCity(t *testing.T) { now := time.Date(2026, 7, 30, 12, 0, 0, 0, time.UTC) h := systemHandler(now) cases := []struct{ utterance, want string }{ {"который час", "сейчас 12 часов ровно"}, {"который час в киеве", onlyLocalTimeReply}, {"сколько времени в москве", onlyLocalTimeReply}, {"который час в лондоне", onlyLocalTimeReply}, {"который час в бишкеке", onlyLocalTimeReply}, } for _, c := range cases { got := h.replySystem(context.Background(), router.Decision{Utterance: c.utterance}) if got != c.want { t.Errorf("replySystem(%q) = %q, want %q", c.utterance, got, c.want) } } }