]> git.giacomolli.uk - onechat/blobdiff - whatsapp_fake_helper_test.go
Convert WhatsApp events with pure functions
[onechat] / whatsapp_fake_helper_test.go
index 7cb61b3495e0cb65c6e7763adc7852744dd0ce53..c9bc8357efc79e527fb8ffe7f746f57b5aec1c77 100644 (file)
@@ -2,10 +2,12 @@ package main
 
 import (
        "context"
 
 import (
        "context"
+       "fmt"
        "io"
        "log"
        "os"
        "path/filepath"
        "io"
        "log"
        "os"
        "path/filepath"
+       "slices"
        "sync"
        "testing"
        "time"
        "sync"
        "testing"
        "time"
@@ -52,6 +54,9 @@ var (
                Name: "Ana Souza",
        }
 
                Name: "Ana Souza",
        }
 
+       // whatsappTestSendTime is the time of the sends of the fake.
+       whatsappTestSendTime = time.Date(2026, 1, 1, 12, 5, 0, 0, time.UTC)
+
        // whatsappTestGroup is the chat of whatsappTestFamily.
        whatsappTestGroup = WhatsAppChat{
                ID:    whatsappTestFamily.String(),
        // whatsappTestGroup is the chat of whatsappTestFamily.
        whatsappTestGroup = WhatsAppChat{
                ID:    whatsappTestFamily.String(),
@@ -62,25 +67,33 @@ var (
 
 // WhatsAppFake is a fake WhatsApp client. It keeps the event handler that the
 // daemon gives it, and Emit gives events to the handler, as the library does.
 
 // WhatsAppFake is a fake WhatsApp client. It keeps the event handler that the
 // daemon gives it, and Emit gives events to the handler, as the library does.
-// Each connection sends to connects, and each pairing sends its channel to
-// pairings, so that the test gives the items of the pairing. A connection fails
-// with connectErr, and a logout with logoutErr. groups are the groups of the
-// account.
+// Each connection keeps its context and sends to connects, and each pairing
+// sends its channel to pairings, so that the test gives the items of the
+// pairing. A connection fails with connectErr, a logout with logoutErr, and a
+// send with sendErr. groups are the groups of the account. A send that does not
+// fail gets the time whatsappTestSendTime.
 type WhatsAppFake struct {
        connects chan struct{}
        pairings chan chan whatsmeow.QRChannelItem
 
 type WhatsAppFake struct {
        connects chan struct{}
        pairings chan chan whatsmeow.QRChannelItem
 
-       mutex      sync.Mutex
-       handle     func(event any) bool
-       connectErr error
-       logoutErr  error
-       groups     []*types.GroupInfo
-       phones     []string
-       logouts    int
+       mutex       sync.Mutex
+       handle      func(event any) bool
+       connectErr  error
+       logoutErr   error
+       groups      []*types.GroupInfo
+       sendErr     error
+       phones      []string
+       logouts     int
+       sent        []WhatsAppFakeSend
+       connections []context.Context
 }
 
 }
 
-// ConnectContext tells the test that the daemon connected.
+// ConnectContext keeps ctx and tells the test that the daemon connected.
 func (f *WhatsAppFake) ConnectContext(ctx context.Context) error {
 func (f *WhatsAppFake) ConnectContext(ctx context.Context) error {
+       f.mutex.Lock()
+       f.connections = append(f.connections, ctx)
+       f.mutex.Unlock()
+
        f.connects <- struct{}{}
 
        f.mutex.Lock()
        f.connects <- struct{}{}
 
        f.mutex.Lock()
@@ -89,6 +102,14 @@ func (f *WhatsAppFake) ConnectContext(ctx context.Context) error {
        return f.connectErr
 }
 
        return f.connectErr
 }
 
+// Connections returns the contexts of the connections, in order.
+func (f *WhatsAppFake) Connections() []context.Context {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       return slices.Clone(f.connections)
+}
+
 // Disconnect does nothing.
 func (f *WhatsAppFake) Disconnect() {
 }
 // Disconnect does nothing.
 func (f *WhatsAppFake) Disconnect() {
 }
@@ -129,6 +150,42 @@ func (f *WhatsAppFake) GetJoinedGroups(ctx context.Context) ([]*types.GroupInfo,
        return f.groups, nil
 }
 
        return f.groups, nil
 }
 
+// GenerateMessageID returns a new message ID.
+func (f *WhatsAppFake) GenerateMessageID() types.MessageID {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       return fmt.Sprintf("MSG%d", len(f.sent)+1)
+}
+
+// SendMessage keeps the send and returns sendErr.
+func (f *WhatsAppFake) SendMessage(ctx context.Context, to types.JID, message *waE2E.Message, extra ...whatsmeow.SendRequestExtra) (whatsmeow.SendResponse, error) {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       f.sent = append(f.sent, WhatsAppFakeSend{
+               to:   to.String(),
+               text: message.GetConversation(),
+               id:   extra[0].ID,
+       })
+
+       if f.sendErr != nil {
+               return whatsmeow.SendResponse{}, f.sendErr
+       }
+
+       return whatsmeow.SendResponse{
+               Timestamp: whatsappTestSendTime,
+       }, nil
+}
+
+// Sent returns the sends.
+func (f *WhatsAppFake) Sent() []WhatsAppFakeSend {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       return slices.Clone(f.sent)
+}
+
 // Phones returns the phone numbers of the pairings.
 func (f *WhatsAppFake) Phones() []string {
        f.mutex.Lock()
 // Phones returns the phone numbers of the pairings.
 func (f *WhatsAppFake) Phones() []string {
        f.mutex.Lock()
@@ -164,6 +221,14 @@ func (f *WhatsAppFake) newClient(device *store.Device, handle func(event any) bo
        return f
 }
 
        return f
 }
 
+// WhatsAppFakeSend is one send of the fake: the chat, the text, and the message
+// ID.
+type WhatsAppFakeSend struct {
+       to   string
+       text string
+       id   string
+}
+
 // whatsappStartTest opens the WhatsApp of the data directory dir with a fake
 // client and the test clock, and closes it at the end of the test. The daemon
 // log goes to the returned buffer.
 // whatsappStartTest opens the WhatsApp of the data directory dir with a fake
 // client and the test clock, and closes it at the end of the test. The daemon
 // log goes to the returned buffer.