Files
workspace/apps/go-crm/internal/whatsapp/session_test.go

139 lines
3.9 KiB
Go

package whatsapp_test
import (
"context"
"fmt"
"testing"
"time"
"go-crm/internal/whatsapp"
)
// TestFakeConnector_FirstConnectReturnsQR verifies that a fresh Connect()
// emits a QR frame before the connected state.
func TestFakeConnector_FirstConnectReturnsQR(t *testing.T) {
fc := whatsapp.NewFakeConnector()
ch, err := fc.Connect(context.Background(), 1)
if err != nil {
t.Fatalf("Connect failed: %v", err)
}
select {
case frame := <-ch:
if frame.QR == "" {
t.Errorf("expected QR code in first frame, got empty QR with state=%s", frame.State)
}
if frame.State != whatsapp.StateWaitingQR {
t.Errorf("expected StateWaitingQR, got %s", frame.State)
}
case <-time.After(500 * time.Millisecond):
t.Fatal("timeout waiting for QR frame")
}
}
// TestFakeConnector_IsConnectedFalseBeforeScan verifies IsConnected returns false
// until MarkConnected is explicitly called — mirrors the IsLoggedIn() semantics.
func TestFakeConnector_IsConnectedFalseBeforeScan(t *testing.T) {
fc := whatsapp.NewFakeConnector()
connected, err := fc.IsConnected(context.Background(), 1)
if err != nil {
t.Fatalf("IsConnected error: %v", err)
}
if connected {
t.Errorf("expected not connected before any scan, got connected=true")
}
// Connect and drain QR frame — still not authenticated.
ch, _ := fc.Connect(context.Background(), 1)
<-ch // consume QR frame
connected, err = fc.IsConnected(context.Background(), 1)
if err != nil {
t.Fatalf("IsConnected error after Connect: %v", err)
}
if connected {
t.Errorf("expected not connected after QR issued but before scan, got connected=true")
}
}
// TestFakeConnector_IsConnectedTrueAfterMarkConnected verifies MarkConnected flips IsConnected.
func TestFakeConnector_IsConnectedTrueAfterMarkConnected(t *testing.T) {
fc := whatsapp.NewFakeConnector()
fc.MarkConnected(1)
connected, err := fc.IsConnected(context.Background(), 1)
if err != nil {
t.Fatalf("IsConnected error: %v", err)
}
if !connected {
t.Errorf("expected connected=true after MarkConnected, got false")
}
}
// TestFakeConnector_ConnectErrorPropagates verifies SetConnectError is returned from Connect.
func TestFakeConnector_ConnectErrorPropagates(t *testing.T) {
fc := whatsapp.NewFakeConnector()
fc.SetConnectError(fmt.Errorf("simulated failure"))
_, err := fc.Connect(context.Background(), 1)
if err == nil {
t.Fatal("expected error from Connect, got nil")
}
}
// TestFakeConnector_QueuedFramesDeliveredInOrder verifies custom QR frames via QueueQR.
func TestFakeConnector_QueuedFramesDeliveredInOrder(t *testing.T) {
fc := whatsapp.NewFakeConnector()
fc.QueueQR(1,
whatsapp.QRFrame{QR: "qr-frame-1", State: whatsapp.StateWaitingQR},
whatsapp.QRFrame{QR: "qr-frame-2", State: whatsapp.StateWaitingQR},
)
ch, err := fc.Connect(context.Background(), 1)
if err != nil {
t.Fatalf("Connect failed: %v", err)
}
first := <-ch
if first.QR != "qr-frame-1" {
t.Errorf("expected qr-frame-1, got %q", first.QR)
}
second := <-ch
if second.QR != "qr-frame-2" {
t.Errorf("expected qr-frame-2, got %q", second.QR)
}
}
// TestFakeConnector_DisconnectClearsState verifies Disconnect removes connected state.
func TestFakeConnector_DisconnectClearsState(t *testing.T) {
fc := whatsapp.NewFakeConnector()
fc.MarkConnected(1)
if err := fc.Disconnect(context.Background(), 1); err != nil {
t.Fatalf("Disconnect error: %v", err)
}
connected, _ := fc.IsConnected(context.Background(), 1)
if connected {
t.Errorf("expected connected=false after Disconnect")
}
}
// TestFakeConnector_MultipleClientsIsolated verifies separate clients don't share state.
func TestFakeConnector_MultipleClientsIsolated(t *testing.T) {
fc := whatsapp.NewFakeConnector()
fc.MarkConnected(1)
connected1, _ := fc.IsConnected(context.Background(), 1)
connected2, _ := fc.IsConnected(context.Background(), 2)
if !connected1 {
t.Errorf("client 1 should be connected")
}
if connected2 {
t.Errorf("client 2 should not be connected")
}
}