12 "github.com/stretchr/testify/require"
13 "go.mau.fi/whatsmeow/types/events"
16 func TestWhatsAppStatusFollowsTheConnection(t *testing.T) {
18 whatsappTestSession(t, dir, true)
19 clock := newTestClock()
20 fake := &WhatsAppFake{
21 connected: make(chan struct{}),
24 whatsapp, err := openWhatsApp(t.Context(), dir, clock.Now, log.New(io.Discard, "", 0), fake.newClient)
25 require.NoError(t, err)
28 require.NoError(t, whatsapp.Close())
31 ctx, cancel := context.WithCancel(t.Context())
32 done := make(chan struct{})
45 require.Equal(t, "WhatsApp is linked and not connected yet.", whatsapp.Status())
47 require.True(t, fake.Emit(&events.Connected{}))
48 require.Equal(t, "WhatsApp is linked and connected since 2026-01-01 12:00.", whatsapp.Status())
50 clock.now = clock.now.Add(20 * time.Minute)
51 require.True(t, fake.Emit(&events.Disconnected{}))
52 clock.now = clock.now.Add(time.Minute)
53 require.True(t, fake.Emit(&events.Disconnected{}))
54 require.Equal(t, "WhatsApp is linked and disconnected since 2026-01-01 12:20. The last connection started at 2026-01-01 12:00.", whatsapp.Status())
57 func TestWhatsAppStatusOfAFirstConnectionThatFailed(t *testing.T) {
59 whatsappTestSession(t, dir, true)
60 whatsapp, fake := whatsappStartTest(t, dir)
62 ctx, cancel := context.WithCancel(t.Context())
63 done := make(chan struct{})
76 require.True(t, fake.Emit(&events.Disconnected{}))
77 require.Equal(t, "WhatsApp is linked and disconnected since 2026-01-01 12:00.", whatsapp.Status())
80 func TestWhatsAppIsNotLinkedWithoutALinkedDevice(t *testing.T) {
81 testCases := []struct {
83 session func(t *testing.T, dir string)
86 name: "no session file",
87 session: func(t *testing.T, dir string) {
91 name: "a session of a pairing that did not end",
92 session: func(t *testing.T, dir string) {
93 whatsappTestSession(t, dir, false)
98 for _, tc := range testCases {
99 t.Run(tc.name, func(t *testing.T) {
102 whatsapp, _ := whatsappStartTest(t, dir)
103 require.Equal(t, "WhatsApp is not linked.", whatsapp.Status())
108 func TestWhatsAppRefusesASessionThatOthersCanRead(t *testing.T) {
110 whatsappTestSession(t, dir, true)
111 require.NoError(t, os.Chmod(filepath.Join(dir, whatsappDirName, whatsappSessionFileName), 0o644))
113 _, err := openWhatsApp(t.Context(), dir, time.Now, log.New(io.Discard, "", 0), whatsappNewClient)
114 require.EqualError(t, err, "whatsapp/session.db holds the WhatsApp session, so its mode must be 0600")
117 func TestWhatsAppCommandsAnswerOnlyTheClientThatAsked(t *testing.T) {
118 server := newModelFake(t)
119 telegram := newTelegramFake(t)
120 bot, _ := telegramStartTestBot(t, telegram)
121 socket := daemonStartTestWithBot(t, server, bot)
122 asking := terminalStartTestClient(t, socket)
123 other := terminalStartTestClient(t, socket)
124 asking.WaitFor(t, "[connected to OneChat]")
125 other.WaitFor(t, "[connected to OneChat]")
127 asking.Type("/whatsapp status")
128 asking.WaitFor(t, "WhatsApp is not linked.")
129 asking.Type(" /whatsapp unknown ")
130 asking.WaitFor(t, whatsappUsage)
132 telegram.Add(TelegramUpdate{
134 Message: telegramOwnerMessage("/whatsapp status"),
137 telegramWaitForSent(t, telegram, "WhatsApp is not linked.")
138 require.Equal(t, []string{"WhatsApp is not linked."}, telegram.Sent())
139 require.Equal(t, "[connected to OneChat]\n", other.Output())
140 require.Zero(t, server.Calls())
143 func TestWhatsAppCommandArgs(t *testing.T) {
144 testCases := []struct {
151 name: "a command with its arguments",
152 line: " /whatsapp pair +1 555 ",
157 name: "the command alone",
163 name: "a word that starts with the command",
164 line: "/whatsappstatus",
169 name: "a message that names the command",
170 line: "what does /whatsapp status do?",
176 for _, tc := range testCases {
177 t.Run(tc.name, func(t *testing.T) {
178 args, found := whatsappCommandArgs(tc.line)
179 require.Equal(t, tc.args, args)
180 require.Equal(t, tc.found, found)