"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"
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()
}
// 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()
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),
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)
+}