]> git.giacomolli.uk - onechat/blobdiff - whatsapp_fake_helper_test.go
Link WhatsApp with a pairing code
[onechat] / whatsapp_fake_helper_test.go
index f7e6cad948f88fe2c46967f3ffce18852c3311da..1a7130c9b21099832180d9fc996c5576eaff9fde 100644 (file)
@@ -10,6 +10,7 @@ import (
        "testing"
 
        "github.com/stretchr/testify/require"
+       "go.mau.fi/whatsmeow"
        waAdv "go.mau.fi/whatsmeow/proto/waAdv"
        "go.mau.fi/whatsmeow/store"
        "go.mau.fi/whatsmeow/store/sqlstore"
@@ -17,29 +18,93 @@ import (
        waLog "go.mau.fi/whatsmeow/util/log"
 )
 
-// whatsappTestNumber is the phone number of the own account in the tests. It
-// is a number for fiction.
-const whatsappTestNumber = "15550001111"
+const (
+       // whatsappTestNumber is the phone number of the own account in the
+       // tests. It is a number for fiction.
+       whatsappTestNumber = "15550001111"
+
+       // whatsappTestLID is the LID of the own account in the tests.
+       whatsappTestLID = "987654321012345"
+
+       // whatsappTestCode is the pairing code of the fake.
+       whatsappTestCode = "ABCD-EFGH"
+)
 
 // 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.
 type WhatsAppFake struct {
-       mutex     sync.Mutex
-       handle    func(event any) bool
-       connected chan struct{}
+       connects chan struct{}
+       pairings chan chan whatsmeow.QRChannelItem
+
+       mutex      sync.Mutex
+       handle     func(event any) bool
+       connectErr error
+       logoutErr  error
+       phones     []string
+       logouts    int
 }
 
 // ConnectContext tells the test that the daemon connected.
 func (f *WhatsAppFake) ConnectContext(ctx context.Context) error {
-       close(f.connected)
+       f.connects <- struct{}{}
 
-       return nil
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       return f.connectErr
 }
 
 // Disconnect does nothing.
 func (f *WhatsAppFake) Disconnect() {
 }
 
+// GetQRChannel gives a new channel of pairing items to the test.
+func (f *WhatsAppFake) GetQRChannel(ctx context.Context) (<-chan whatsmeow.QRChannelItem, error) {
+       items := make(chan whatsmeow.QRChannelItem, 8)
+       f.pairings <- items
+
+       return items, nil
+}
+
+// PairPhone keeps phone and returns whatsappTestCode.
+func (f *WhatsAppFake) PairPhone(ctx context.Context, phone string, showPushNotification bool, clientType whatsmeow.PairClientType, clientDisplayName string) (string, error) {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       f.phones = append(f.phones, phone)
+
+       return whatsappTestCode, nil
+}
+
+// Logout counts the logouts and returns logoutErr.
+func (f *WhatsAppFake) Logout(ctx context.Context) error {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       f.logouts++
+
+       return f.logoutErr
+}
+
+// Phones returns the phone numbers of the pairings.
+func (f *WhatsAppFake) Phones() []string {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       return append([]string{}, f.phones...)
+}
+
+// Logouts returns the number of logouts.
+func (f *WhatsAppFake) Logouts() int {
+       f.mutex.Lock()
+       defer f.mutex.Unlock()
+
+       return f.logouts
+}
+
 // Emit gives event to the handler of the daemon and returns its answer.
 func (f *WhatsAppFake) Emit(event any) bool {
        f.mutex.Lock()
@@ -60,27 +125,30 @@ func (f *WhatsAppFake) newClient(device *store.Device, handle func(event any) bo
 }
 
 // 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.
-func whatsappStartTest(t *testing.T, dir string) (*WhatsApp, *WhatsAppFake) {
+// client and the test clock, and closes it at the end of the test. The daemon
+// log goes to the returned buffer.
+func whatsappStartTest(t *testing.T, dir string, clock *TestClock) (*WhatsApp, *WhatsAppFake, *SyncBuffer) {
        t.Helper()
 
        fake := &WhatsAppFake{
-               connected: make(chan struct{}),
+               connects: make(chan struct{}, 16),
+               pairings: make(chan chan whatsmeow.QRChannelItem, 16),
        }
 
-       whatsapp, err := openWhatsApp(t.Context(), dir, newTestClock().Now, log.New(io.Discard, "", 0), fake.newClient)
+       logs := &SyncBuffer{}
+       whatsapp, err := openWhatsApp(t.Context(), dir, clock.Now, log.New(logs, "", 0), fake.newClient)
        require.NoError(t, err)
 
        t.Cleanup(func() {
                require.NoError(t, whatsapp.Close())
        })
 
-       return whatsapp, fake
+       return whatsapp, fake, logs
 }
 
 // whatsappTestSession writes a session database with mode 0600 to the data
 // directory dir. When linked is true, it holds a device linked to
-// whatsappTestNumber, and else a device with no link.
+// whatsappTestNumber and whatsappTestLID, and else no device.
 func whatsappTestSession(t *testing.T, dir string, linked bool) {
        t.Helper()
 
@@ -98,6 +166,8 @@ func whatsappTestSession(t *testing.T, dir string, linked bool) {
                device := container.NewDevice()
                jid := types.NewADJID(whatsappTestNumber, 0, 1)
                device.ID = &jid
+               device.LID = types.NewADJID(whatsappTestLID, 0, 1)
+               device.LID.Server = types.HiddenUserServer
                device.Account = &waAdv.ADVSignedDeviceIdentity{
                        Details:             []byte{},
                        AccountSignature:    make([]byte, 64),
@@ -109,3 +179,9 @@ func whatsappTestSession(t *testing.T, dir string, linked bool) {
 
        require.NoError(t, container.Close())
 }
+
+// whatsappDiscardLog is a logger for a WhatsApp whose log a test does not
+// read.
+func whatsappDiscardLog() *log.Logger {
+       return log.New(io.Discard, "", 0)
+}