package main import ( "context" "testing" "time" "github.com/kami/maven/internal/ipc" ) // quietFakeAPI records the WriteFact the toggle performs. type quietFakeAPI struct { ipc.UnimplementedCoreAPI got ipc.WriteFactReq call int } func (a *quietFakeAPI) WriteFact(_ context.Context, req ipc.WriteFactReq) (int64, error) { a.got, a.call = req, a.call+1 return 1, nil } // quietVerdict — what a phrase should do to the setting. type quietVerdict int const ( quietNone quietVerdict = iota quietOn quietOff ) func TestResolveQuietToggle(t *testing.T) { cases := []struct { text string want quietVerdict }{ // ON vocabulary. {"quiet on", quietOn}, {"quiet mode", quietOn}, {"тихий режим", quietOn}, {"тихий", quietOn}, {"не шуми", quietOn}, {"не беспокоить", quietOn}, {"тихо", quietOn}, // ON, inflected / embedded in a sentence. {"включи тихий режим", quietOn}, {"побудь в тихом режиме", quietOn}, {"Тихий Режим!", quietOn}, {"тихая", quietOn}, // OFF vocabulary — all seven, incl. the three that used to say ON. {"quiet off", quietOff}, {"quiet end", quietOff}, {"громкий режим", quietOff}, {"шумный режим", quietOff}, {"отмени тихий", quietOff}, {"выключи тихий", quietOff}, {"не тихо", quietOff}, // OFF wins over the ON words it contains. {"выключи тихий режим", quietOff}, {"отмени тихий режим пожалуйста", quietOff}, {"верни громкий режим", quietOff}, // False positives: "тихо"/"тихий" as ordinary Russian. {"очень тихий сегодня день", quietNone}, {"в комнате тихо", quietNone}, {"тихонько напомни", quietNone}, {"потихоньку", quietNone}, {"тихонько", quietNone}, {"он говорил тихим голосом весь вечер", quietNone}, // Unrelated. {"напомни завтра позвонить маме", quietNone}, {"какая погода", quietNone}, {"", quietNone}, } for _, tc := range cases { t.Run(tc.text, func(t *testing.T) { api := &quietFakeAPI{} h := &reactiveHandler{api: api, now: func() time.Time { return time.Unix(0, 0).UTC() }} reply, handled := h.resolveQuietToggle(context.Background(), tc.text) if tc.want == quietNone { if handled || reply != "" { t.Fatalf("%q: got (%q, %v), want no match", tc.text, reply, handled) } if api.call != 0 { t.Fatalf("%q: wrote a fact on a non-match", tc.text) } return } if !handled { t.Fatalf("%q: not handled, want %v", tc.text, tc.want) } wantReply, wantVal := "тихий режим выключен.", "false" if tc.want == quietOn { wantReply, wantVal = "тихий режим включён. буду реже напоминать.", "true" } if reply != wantReply { t.Errorf("%q: reply = %q, want %q", tc.text, reply, wantReply) } if api.call != 1 { t.Fatalf("%q: WriteFact called %d times, want 1", tc.text, api.call) } if api.got.Kind != "config" || api.got.Key != "quiet_hours" || api.got.Source != "tap:voice" || api.got.Confidence != 1.0 { t.Errorf("%q: request shape = %+v", tc.text, api.got) } if api.got.Value != wantVal { t.Errorf("%q: value = %q, want %q", tc.text, api.got.Value, wantVal) } }) } }