package handlers import ( "net/http" "net/http/httptest" "os" "strings" "testing" "time" "go-crm/internal/db" "go-crm/internal/whatsapp" "golang.org/x/crypto/bcrypt" ) func TestDashboardHidesConnectLinkWhenDBConnected(t *testing.T) { tmpfile, err := os.CreateTemp("", "test_*.db") if err != nil { t.Fatal(err) } defer os.Remove(tmpfile.Name()) tmpfile.Close() testDB, err := db.Init(tmpfile.Name()) if err != nil { t.Fatalf("failed to init db: %v", err) } defer testDB.Close() // FakeConnector NOT marked connected — only DB column is set. DB = testDB WAConnector = whatsapp.NewFakeConnector() hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost) _, err = testDB.Exec( "INSERT INTO accounts (email, name, password, created_at) VALUES (?, ?, ?, ?)", "test@example.com", "Test Account", string(hashedPassword), time.Now().Unix(), ) if err != nil { t.Fatalf("failed to create account: %v", err) } var accountID int64 err = testDB.QueryRow("SELECT account_id FROM accounts WHERE email = ?", "test@example.com").Scan(&accountID) if err != nil { t.Fatalf("failed to get account id: %v", err) } var clientID int64 testDB.QueryRow( "INSERT INTO clients (account_id, name, phone, whatsapp_connected, created_at) VALUES (?, ?, ?, ?, ?) RETURNING client_id", accountID, "DB Connected Client", "+5521987654321", 1, time.Now().Unix(), ).Scan(&clientID) sessionID := "test-session-db-connected" expires := time.Now().Add(time.Hour).Unix() _, err = testDB.Exec( "INSERT INTO sessions (session_id, account_id, expires) VALUES (?, ?, ?)", sessionID, accountID, expires, ) if err != nil { t.Fatalf("failed to create session: %v", err) } req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(&http.Cookie{Name: "session", Value: sessionID}) w := httptest.NewRecorder() Dashboard(w, req) if w.Code != http.StatusOK { t.Fatalf("expected status 200, got %d", w.Code) } body := w.Body.String() if !strings.Contains(body, "connected") { t.Error("expected dashboard to show 'connected' status from DB column") } if strings.Contains(body, "/leads/connect") { t.Error("expected dashboard to NOT show Connect link when DB column indicates connected") } } func TestDashboardShowsConnectLinkWhenDisconnected(t *testing.T) { tmpfile, err := os.CreateTemp("", "test_*.db") if err != nil { t.Fatal(err) } defer os.Remove(tmpfile.Name()) tmpfile.Close() testDB, err := db.Init(tmpfile.Name()) if err != nil { t.Fatalf("failed to init db: %v", err) } defer testDB.Close() DB = testDB WAConnector = whatsapp.NewFakeConnector() hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost) _, err = testDB.Exec( "INSERT INTO accounts (email, name, password, created_at) VALUES (?, ?, ?, ?)", "test@example.com", "Test Account", string(hashedPassword), time.Now().Unix(), ) if err != nil { t.Fatalf("failed to create account: %v", err) } var accountID int64 err = testDB.QueryRow("SELECT account_id FROM accounts WHERE email = ?", "test@example.com").Scan(&accountID) if err != nil { t.Fatalf("failed to get account id: %v", err) } sessionID := "test-session-dashboard" expires := time.Now().Add(time.Hour).Unix() _, err = testDB.Exec( "INSERT INTO sessions (session_id, account_id, expires) VALUES (?, ?, ?)", sessionID, accountID, expires, ) if err != nil { t.Fatalf("failed to create session: %v", err) } req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(&http.Cookie{Name: "session", Value: sessionID}) w := httptest.NewRecorder() Dashboard(w, req) if w.Code != http.StatusOK { t.Fatalf("expected status 200, got %d", w.Code) } body := w.Body.String() if !strings.Contains(body, "disconnected") { t.Error("expected dashboard to show 'disconnected' status") } if !strings.Contains(body, "/clients") { t.Error("expected dashboard to show link to create client when no client exists") } } func TestDashboardShowsConnectedStatus(t *testing.T) { tmpfile, err := os.CreateTemp("", "test_*.db") if err != nil { t.Fatal(err) } defer os.Remove(tmpfile.Name()) tmpfile.Close() testDB, err := db.Init(tmpfile.Name()) if err != nil { t.Fatalf("failed to init db: %v", err) } defer testDB.Close() fakeWA := whatsapp.NewFakeConnector() fakeWA.MarkConnected(1) DB = testDB WAConnector = fakeWA hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost) _, err = testDB.Exec( "INSERT INTO accounts (email, name, password, created_at) VALUES (?, ?, ?, ?)", "test@example.com", "Test Account", string(hashedPassword), time.Now().Unix(), ) if err != nil { t.Fatalf("failed to create account: %v", err) } var accountID int64 err = testDB.QueryRow("SELECT account_id FROM accounts WHERE email = ?", "test@example.com").Scan(&accountID) if err != nil { t.Fatalf("failed to get account id: %v", err) } _, err = testDB.Exec( "INSERT INTO clients (account_id, name, phone, created_at) VALUES (?, ?, ?, ?)", accountID, "Test Client", "+5521987654321", time.Now().Unix(), ) if err != nil { t.Fatalf("failed to create client: %v", err) } sessionID := "test-session-connected" expires := time.Now().Add(time.Hour).Unix() _, err = testDB.Exec( "INSERT INTO sessions (session_id, account_id, expires) VALUES (?, ?, ?)", sessionID, accountID, expires, ) if err != nil { t.Fatalf("failed to create session: %v", err) } req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(&http.Cookie{Name: "session", Value: sessionID}) w := httptest.NewRecorder() Dashboard(w, req) if w.Code != http.StatusOK { t.Fatalf("expected status 200, got %d", w.Code) } body := w.Body.String() if !strings.Contains(body, "connected") { t.Error("expected dashboard to show 'connected' status") } if strings.Contains(body, "/leads/connect") { t.Error("expected dashboard to NOT show Connect link when WhatsApp is connected") } } func TestDashboardShowsConnectLinkWithClientID(t *testing.T) { tmpfile, err := os.CreateTemp("", "test_*.db") if err != nil { t.Fatal(err) } defer os.Remove(tmpfile.Name()) tmpfile.Close() testDB, err := db.Init(tmpfile.Name()) if err != nil { t.Fatalf("failed to init db: %v", err) } defer testDB.Close() DB = testDB WAConnector = whatsapp.NewFakeConnector() hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost) _, err = testDB.Exec( "INSERT INTO accounts (email, name, password, created_at) VALUES (?, ?, ?, ?)", "test@example.com", "Test Account", string(hashedPassword), time.Now().Unix(), ) if err != nil { t.Fatalf("failed to create account: %v", err) } var accountID int64 err = testDB.QueryRow("SELECT account_id FROM accounts WHERE email = ?", "test@example.com").Scan(&accountID) if err != nil { t.Fatalf("failed to get account id: %v", err) } var clientID int64 testDB.QueryRow( "INSERT INTO clients (account_id, name, phone, created_at) VALUES (?, ?, ?, ?) RETURNING client_id", accountID, "Test Client", "+5521987654321", time.Now().Unix(), ).Scan(&clientID) sessionID := "test-session-disconnected-client" expires := time.Now().Add(time.Hour).Unix() _, err = testDB.Exec( "INSERT INTO sessions (session_id, account_id, expires) VALUES (?, ?, ?)", sessionID, accountID, expires, ) if err != nil { t.Fatalf("failed to create session: %v", err) } req := httptest.NewRequest(http.MethodGet, "/", nil) req.AddCookie(&http.Cookie{Name: "session", Value: sessionID}) w := httptest.NewRecorder() Dashboard(w, req) if w.Code != http.StatusOK { t.Fatalf("expected status 200, got %d", w.Code) } body := w.Body.String() if !strings.Contains(body, "disconnected") { t.Error("expected dashboard to show 'disconnected' status") } if !strings.Contains(body, "/leads/connect?client_id=") { t.Error("expected dashboard to show Connect link with client_id when client exists") } }