)
func TestOwnerTalksToTheAgentThroughTelegram(t *testing.T) {
- server := newFakeResponses(t)
- server.reply = func(w http.ResponseWriter, call fakeCall) {
- writeEvents(w, completedEvent([]any{messageItem("Hello from the agent.")}, 100, 0, 5))
+ server := newModelFake(t)
+ server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
+ modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("Hello from the agent.")}, 100, 0, 5))
}
telegram := newTelegramFake(t)
bot, _ := telegramStartTestBot(t, telegram)
- socket := startTestDaemonWithBot(t, server, bot)
- terminal := startTestClient(t, socket)
+ socket := daemonStartTestWithBot(t, server, bot)
+ terminal := terminalStartTestClient(t, socket)
terminal.WaitFor(t, "[connected to OneChat]")
telegram.Add(TelegramUpdate{
func TestBotIgnoresEveryoneButTheOwner(t *testing.T) {
telegram := newTelegramFake(t)
bot, logs := telegramStartTestBot(t, telegram)
- socket := startTestDaemonWithBot(t, newFakeResponses(t), bot)
- terminal := startTestClient(t, socket)
+ socket := daemonStartTestWithBot(t, newModelFake(t), bot)
+ terminal := terminalStartTestClient(t, socket)
terminal.WaitFor(t, "[connected to OneChat]")
group := telegramOwnerMessage("secret in a group")
func TestBotAnswersThatOnlyTextIsSupported(t *testing.T) {
telegram := newTelegramFake(t)
bot, _ := telegramStartTestBot(t, telegram)
- startTestDaemonWithBot(t, newFakeResponses(t), bot)
+ daemonStartTestWithBot(t, newModelFake(t), bot)
telegram.Add(TelegramUpdate{
UpdateID: 1,
}
func TestStopFromTelegramInterruptsTheTurn(t *testing.T) {
- server := newFakeResponses(t)
+ server := newModelFake(t)
arrived := make(chan struct{})
release := make(chan struct{})
t.Cleanup(func() {
close(release)
})
- server.reply = func(w http.ResponseWriter, call fakeCall) {
+ server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
close(arrived)
<-release
}
telegram := newTelegramFake(t)
bot, _ := telegramStartTestBot(t, telegram)
- startTestDaemonWithBot(t, server, bot)
+ daemonStartTestWithBot(t, server, bot)
telegram.Add(TelegramUpdate{
UpdateID: 1,
}
func TestBotStartsAtTheStoredOffset(t *testing.T) {
- server := newFakeResponses(t)
- server.reply = func(w http.ResponseWriter, call fakeCall) {
- writeEvents(w, completedEvent([]any{messageItem("ok")}, 100, 0, 5))
+ server := newModelFake(t)
+ server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
+ modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("ok")}, 100, 0, 5))
}
telegram := newTelegramFake(t)
Message: telegramOwnerMessage("new after the restart"),
})
- socket := startTestDaemonWithBot(t, server, bot)
- terminal := startTestClient(t, socket)
+ socket := daemonStartTestWithBot(t, server, bot)
+ terminal := terminalStartTestClient(t, socket)
terminal.WaitFor(t, "[connected to OneChat]")
telegramWaitForSent(t, telegram, "ok")
}
func TestBotTriesAgainAfterFailures(t *testing.T) {
- server := newFakeResponses(t)
- server.reply = func(w http.ResponseWriter, call fakeCall) {
- writeEvents(w, completedEvent([]any{messageItem("ok")}, 100, 0, 5))
+ server := newModelFake(t)
+ server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
+ modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("ok")}, 100, 0, 5))
}
telegram := newTelegramFake(t)
}
bot, logs := telegramStartTestBot(t, telegram)
- startTestDaemonWithBot(t, server, bot)
+ daemonStartTestWithBot(t, server, bot)
telegram.Add(TelegramUpdate{
UpdateID: 1,
func TestRepliesGoAsRichMessages(t *testing.T) {
reply := "**Done.** The table:\n\n| Name | Size |\n|:-----|-----:|\n| `a.go` | 10 |\n\n- one\n- two\n\n```go\nx := 1\n```"
- server := newFakeResponses(t)
- server.reply = func(w http.ResponseWriter, call fakeCall) {
- writeEvents(w, completedEvent([]any{messageItem(reply)}, 100, 0, 5))
+ server := newModelFake(t)
+ server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
+ modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem(reply)}, 100, 0, 5))
}
telegram := newTelegramFake(t)
bot, _ := telegramStartTestBot(t, telegram)
- socket := startTestDaemonWithBot(t, server, bot)
- terminal := startTestClient(t, socket)
+ socket := daemonStartTestWithBot(t, server, bot)
+ terminal := terminalStartTestClient(t, socket)
terminal.WaitFor(t, "[connected to OneChat]")
terminal.Type("make **it** so")
require.Equal(t, []string{paragraphs, table}, telegram.Sent())
}
+func TestReplyTagsGoAsText(t *testing.T) {
+ testCases := []struct {
+ name string
+ status int
+ sent []string
+ }{
+ {
+ name: "rich message escapes the tag outside code",
+ sent: []string{"a \\<details> tag and `<b>`"},
+ },
+ {
+ name: "entity fallback shows the tag as written",
+ status: http.StatusBadRequest,
+ sent: []string{"a <details> tag and <b>"},
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ telegram := newTelegramFake(t)
+ telegram.fail = func(call TelegramFakeCall) (int, string) {
+ if call.method != "sendRichMessage" {
+ return 0, ""
+ }
+
+ return tc.status, "Bad Request"
+ }
+
+ bot, _ := telegramStartTestBot(t, telegram)
+ bot.post(t.Context(), Event{
+ Kind: "reply",
+ Text: "a <details> tag and `<b>`",
+ })
+
+ require.Equal(t, tc.sent, telegram.Sent())
+ })
+ }
+}
+
+func TestLongReplySplitCountsTheEscapedTags(t *testing.T) {
+ paragraph := "A <b> tag.\n\n"
+ count := telegramRichBytes / len(paragraph)
+ reply := strings.Repeat(paragraph, count)
+ require.LessOrEqual(t, len(reply), telegramRichBytes)
+
+ telegram := newTelegramFake(t)
+ bot, _ := telegramStartTestBot(t, telegram)
+ bot.post(t.Context(), Event{
+ Kind: "reply",
+ Text: reply,
+ })
+
+ sent := telegram.Sent()
+ require.Len(t, sent, 2)
+ require.Equal(t, telegramEscapeTags(reply), strings.Join(sent, ""))
+
+ for _, markdown := range sent {
+ require.LessOrEqual(t, len(markdown), telegramRichBytes)
+ }
+}
+
func TestRefusedEntitiesGoAgainAsPlainText(t *testing.T) {
telegram := newTelegramFake(t)
telegram.fail = func(call TelegramFakeCall) (int, string) {
telegram.Close()
bot, logs := telegramStartTestBot(t, telegram)
- startTestDaemonWithBot(t, newFakeResponses(t), bot)
+ daemonStartTestWithBot(t, newModelFake(t), bot)
require.Eventually(t, func() bool {
return strings.Count(logs.String(), "no valid answer") >= 2
// telegramStartTestBot returns a bot of telegramTestOwner on server, with its
// offset file in a temporary directory and short waits, and the buffer of its
// log.
-func telegramStartTestBot(t *testing.T, server *TelegramFake) (*TelegramBot, *syncBuffer) {
+func telegramStartTestBot(t *testing.T, server *TelegramFake) (*TelegramBot, *SyncBuffer) {
t.Helper()
- logs := &syncBuffer{}
+ logs := &SyncBuffer{}
bot := newTelegramBot(newTelegramAPI(server.URL, telegramTestToken), telegramTestOwner, filepath.Join(t.TempDir(), telegramOffsetFileName), log.New(logs, "", 0))
bot.minWait = time.Millisecond
bot.maxWait = 10 * time.Millisecond