Files
Maven/internal/router/calendar_test.go
kami bddf52d1ee router: refuse a plan question about a day that is not today
IsDayPlanQuery only rejected the сегодня family, so "какие планы на
понедельник?" carried no other-day token, did carry "планы", and the
plan claimed it ahead of the calendar listing and recited today under
today's date. Weekday names, week, weekend and month join the refusal
list. This is a refusal and not a feature: it stands until the plan can
build a day other than the clock's own.

isRestOfDayQuery also lived in cmd/mavend and matched by substring while
IsDayPlanQuery tokenized, so the two predicates deciding one utterance
could disagree, and "проверь nextcloud" read as a request for the rest
of the day. It moves to the router and tokenizes.
Found in review of #58.
2026-08-01 14:07:43 +04:00

119 lines
3.7 KiB
Go

package router
import (
"testing"
"time"
)
func TestCalendarEventFormatter(t *testing.T) {
f := CalendarEventFormatter{}
date := time.Date(2026, 7, 6, 0, 0, 0, 0, time.UTC)
// Empty
if got := f.Format(nil, date); got != "на 06.07.2026 ничего нет." {
t.Errorf("empty: got %q", got)
}
// One event
if got := f.Format([]string{"Standup @ 10:00-10:30"}, date); got != "на 06.07.2026: Standup @ 10:00-10:30" {
t.Errorf("one: got %q", got)
}
// Multiple events
if got := f.Format([]string{"Standup @ 10:00-10:30", "Lunch @ 12:00-13:00"}, date); got != "на 06.07.2026: Standup @ 10:00-10:30; Lunch @ 12:00-13:00" {
t.Errorf("multiple: got %q", got)
}
}
func TestCalendarEventFormatterHedgesUncertainEntries(t *testing.T) {
f := CalendarEventFormatter{}
date := time.Date(2026, 7, 6, 0, 0, 0, 0, time.UTC)
// An event relayed off a phone notification is not a calendar read, and she
// says so instead of reciting a guess as fact.
got := f.FormatEntries([]CalendarEntry{
{Text: "Standup @ 10:00-10:30"},
{Text: "Планёрка @ 14:00-14:30", Uncertain: true},
}, date)
want := "на 06.07.2026: Standup @ 10:00-10:30; похоже, Планёрка @ 14:00-14:30"
if got != want {
t.Errorf("got %q\nwant %q", got, want)
}
// Format is FormatEntries with everything certain.
if got := f.FormatEntries(nil, date); got != "на 06.07.2026 ничего нет." {
t.Errorf("empty: got %q", got)
}
}
func TestIsDayPlanQuery(t *testing.T) {
yes := []string{
"какие планы на сегодня?",
"что у меня по плану",
"расскажи план",
"мой распорядок на сегодня",
"расписание?",
"что дальше?",
"what's next",
"what is my plan today",
}
for _, s := range yes {
if !IsDayPlanQuery(s) {
t.Errorf("IsDayPlanQuery(%q) = false, want true", s)
}
}
no := []string{
// The calendar listing owns these.
"что у меня сегодня?",
"какие планы на завтра?",
"план на послезавтра",
"что было вчера",
// "планёрка" is a meeting, not a request for the plan.
"когда планёрка?",
"запиши планёрку на 14:00",
"какая погода?",
"",
}
for _, s := range no {
if IsDayPlanQuery(s) {
t.Errorf("IsDayPlanQuery(%q) = true, want false", s)
}
}
}
// The plan is built for the clock's own day. A weekday, a week or a weekend
// carries no сегодня-family token, so the plan used to claim the utterance and
// recite today under today's date. Refusing is the right answer until the plan
// can build a day that is not the clock's own.
func TestIsDayPlanQueryRefusesOtherSpans(t *testing.T) {
for _, s := range []string{
"какие планы на понедельник?",
"планы на пятницу",
"какие планы на неделю?",
"планы на выходные",
"какие планы на месяц?",
"what are my plans for friday?",
"my plan for the week",
} {
if IsDayPlanQuery(s) {
t.Errorf("IsDayPlanQuery(%q) = true, want false", s)
}
}
}
// The rest-of-day test tokenizes like IsDayPlanQuery does. The substring form
// it replaced fired on any word containing "next" or "дальше".
func TestIsRestOfDayQuery(t *testing.T) {
for _, s := range []string{"что дальше?", "и что потом, дальше?", "what's next", "NEXT"} {
if !IsRestOfDayQuery(s) {
t.Errorf("IsRestOfDayQuery(%q) = false, want true", s)
}
}
for _, s := range []string{"какие планы на сегодня?", "проверь nextcloud", "дальшесъезд", ""} {
if IsRestOfDayQuery(s) {
t.Errorf("IsRestOfDayQuery(%q) = true, want false", s)
}
}
}