X-Git-Url: http://git.giacomolli.uk/onechat/blobdiff_plain/0018014ab36f3de61a4b8a5515009dab803d6c38..56d959f2d573eef1be5c04d0bf1659fa30d36e7c:/whatsapp_test.go diff --git a/whatsapp_test.go b/whatsapp_test.go index e0018e5..38a7b8d 100644 --- a/whatsapp_test.go +++ b/whatsapp_test.go @@ -2,6 +2,7 @@ package main import ( "errors" + "net/http" "os" "path/filepath" "strings" @@ -10,6 +11,8 @@ import ( "github.com/stretchr/testify/require" "go.mau.fi/whatsmeow" + "go.mau.fi/whatsmeow/proto/waE2E" + "go.mau.fi/whatsmeow/proto/waWeb" "go.mau.fi/whatsmeow/types" "go.mau.fi/whatsmeow/types/events" ) @@ -467,3 +470,203 @@ func whatsappTestLogTexts(t *testing.T, memory *Memory) []string { return texts } + +func TestWhatsAppPrivateBatchStartsATurnWithAnEmptyReply(t *testing.T) { + whatsapp, fake := whatsappStartTestLinked(t) + require.NoError(t, whatsapp.device.Contacts.PutContactName(t.Context(), whatsappTestAna, "Ana", "Ana Souza")) + + server := newModelFake(t) + server.reply = func(w http.ResponseWriter, call ModelFakeCall) { + modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("")}, 100, 0, 5)) + } + + telegram := newTelegramFake(t) + bot, _ := telegramStartTestBot(t, telegram) + socket, memory := daemonStartTestWithWhatsApp(t, server, bot, whatsapp) + client := terminalStartTestClient(t, socket) + client.WaitFor(t, "[connected to OneChat]") + <-fake.connects + + at := time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC) + require.True(t, fake.Emit(whatsappTestMessage(whatsappTestAna, whatsappTestAna, "m1", "Are you at home?", at))) + require.True(t, fake.Emit(whatsappTestMessage(whatsappTestAna, whatsappTestOwn, "m2", "Yes", at))) + + text := "[WhatsApp] Ana Souza, private chat 15550002222@s.whatsapp.net, Thursday 2026-01-01\n12:00 Ana Souza: Are you at home?\n12:00 You: Yes\n" + whatsappBatchEmptyReply + client.WaitFor(t, text+"\n[working]\n[done]\n") + require.Equal(t, 1, server.Calls()) + require.Contains(t, string(server.Call(0).raw), "Are you at home?") + require.Equal(t, []string{text}, whatsappTestLogTexts(t, memory)) + require.Empty(t, telegram.Sent()) + require.Eventually(t, func() bool { + return len(whatsapp.batches.Closed()) == 0 + }, 10*time.Second, time.Millisecond) +} + +func TestWhatsAppGroupTurns(t *testing.T) { + testCases := []struct { + name string + message func(event *events.Message) + line string + turn bool + }{ + { + name: "plain", + message: func(event *events.Message) { + }, + line: "12:00 Bruno Lima: Who brings the cake?", + }, + { + name: "mention", + message: func(event *events.Message) { + event.Message = &waE2E.Message{ + ExtendedTextMessage: &waE2E.ExtendedTextMessage{ + Text: new("@" + whatsappTestLID + " can you bring the cake? Call " + whatsappTestNumber + "."), + ContextInfo: &waE2E.ContextInfo{ + MentionedJID: []string{whatsappTestLID + "@lid"}, + }, + }, + } + }, + line: "12:00 Bruno Lima (mentions you): @you can you bring the cake? Call OWN.", + turn: true, + }, + { + name: "reply", + message: func(event *events.Message) { + event.Message = &waE2E.Message{ + ExtendedTextMessage: &waE2E.ExtendedTextMessage{ + Text: new("Who brings the cake?"), + ContextInfo: &waE2E.ContextInfo{ + Participant: new(whatsappTestOwn.String()), + }, + }, + } + }, + line: "12:00 Bruno Lima (replies to you): Who brings the cake?", + turn: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + whatsapp, fake := whatsappStartTestLinked(t) + fake.groups = []*types.GroupInfo{ + { + JID: whatsappTestFamily, + GroupName: types.GroupName{ + Name: "Family", + }, + }, + } + + server := newModelFake(t) + socket, memory := daemonStartTestWithWhatsApp(t, server, nil, whatsapp) + client := terminalStartTestClient(t, socket) + client.WaitFor(t, "[connected to OneChat]") + <-fake.connects + + event := whatsappTestMessage(whatsappTestFamily, whatsappTestBruno, "m1", "Who brings the cake?", time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC)) + event.Info.PushName = "Bruno Lima" + tc.message(event) + require.True(t, fake.Emit(event)) + + text := "[WhatsApp] Family, group 120363000000000001@g.us, Thursday 2026-01-01\n" + tc.line + if tc.turn { + text += "\n" + whatsappBatchEmptyReply + client.WaitFor(t, "[done]") + require.Equal(t, 1, server.Calls()) + } else { + client.WaitFor(t, text) + time.Sleep(100 * time.Millisecond) + require.Zero(t, server.Calls()) + } + + require.Equal(t, text, whatsappTestLogTexts(t, memory)[0]) + }) + } +} + +func TestWhatsAppTakesOnlyText(t *testing.T) { + at := time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC) + testCases := []struct { + name string + change func(event *events.Message) + }{ + { + name: "an edit", + change: func(event *events.Message) { + event.IsEdit = true + }, + }, + { + name: "old history", + change: func(event *events.Message) { + event.SourceWebMsg = &waWeb.WebMessageInfo{} + }, + }, + { + name: "a view-once message", + change: func(event *events.Message) { + event.IsViewOnce = true + }, + }, + { + name: "a disappearing message", + change: func(event *events.Message) { + event.IsEphemeral = true + }, + }, + { + name: "the chat of the user with itself", + change: func(event *events.Message) { + event.Info.Chat = whatsappTestOwn + }, + }, + { + name: "a status broadcast", + change: func(event *events.Message) { + event.Info.Chat = types.StatusBroadcastJID + }, + }, + { + name: "a photo with a caption", + change: func(event *events.Message) { + event.Message = &waE2E.Message{ + ImageMessage: &waE2E.ImageMessage{ + Caption: new("look"), + }, + } + }, + }, + { + name: "a text of spaces", + change: func(event *events.Message) { + event.Message.Conversation = new(" ") + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + whatsapp, _ := whatsappStartTestLinked(t) + event := whatsappTestMessage(whatsappTestAna, whatsappTestAna, "m1", "hi", at) + tc.change(event) + require.True(t, whatsapp.handle(event)) + require.NoError(t, whatsapp.batches.CloseAll()) + require.Empty(t, whatsapp.batches.Closed()) + }) + } +} + +// whatsappStartTestLinked opens a WhatsApp with a linked device in a temporary +// directory, with a quiet time of 50 ms for its batches. +func whatsappStartTestLinked(t *testing.T) (*WhatsApp, *WhatsAppFake) { + t.Helper() + + dir := t.TempDir() + whatsappTestSession(t, dir, true) + whatsapp, fake, _ := whatsappStartTest(t, dir, newTestClock()) + whatsapp.batches.quiet = 50 * time.Millisecond + + return whatsapp, fake +}