gohorsejobs/backend/internal/services/chat_service_test.go
NANDO9322 ddc2f5dd03 feat: atualiza fluxo de cadastro de candidatos com persistência completa de dados e máscara de telefone
Frontend:
- Implementar máscara de entrada de telefone para números BR ((XX) XXXXX-XXXX).
- Atualizar formulário de cadastro para enviar dados completos do perfil do candidato (endereço, formação, habilidades, etc.).
- Corrigir problemas de idioma misto na página de Detalhes da Vaga e adicionar traduções faltantes.

Backend:
- Atualizar modelo de Usuário, Entidade e DTOs para incluir campos de perfil (Data de Nascimento, Endereço, Formação, etc.).
- Atualizar UserRepository para persistir e recuperar os dados estendidos do usuário no PostgreSQL.
- Atualizar RegisterCandidateUseCase para mapear campos de entrada para a entidade Usuário.
2026-01-06 18:19:47 -03:00

214 lines
5.9 KiB
Go

package services
import (
"context"
"testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
)
func TestNewChatService(t *testing.T) {
db, _, err := sqlmock.New()
if err != nil {
t.Fatalf("Failed to create mock db: %v", err)
}
defer db.Close()
appwrite := &AppwriteService{}
service := NewChatService(db, appwrite)
if service == nil {
t.Error("Expected service, got nil")
}
if service.DB != db {
t.Error("Expected DB to be set")
}
if service.Appwrite != appwrite {
t.Error("Expected Appwrite to be set")
}
}
func TestChatService_SendMessage(t *testing.T) {
// NOTE: This test is skipped because SendMessage spawns a goroutine that
// calls Appwrite.PushMessage, which requires a real CredentialsService/DB.
// The goroutine panics with nil pointer when using mocks.
// In production, consider using an interface for AppwriteService to enable mocking.
t.Skip("Skipping due to async goroutine requiring real dependencies")
}
func TestChatService_ListMessages(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("Failed to create mock db: %v", err)
}
defer db.Close()
service := NewChatService(db, nil)
ctx := context.Background()
t.Run("returns messages list", func(t *testing.T) {
convID := "conv-123"
now := time.Now()
mock.ExpectQuery("SELECT id, conversation_id, sender_id, content, created_at").
WithArgs(convID).
WillReturnRows(sqlmock.NewRows([]string{"id", "conversation_id", "sender_id", "content", "created_at"}).
AddRow("msg-1", convID, "user-1", "Hello", now).
AddRow("msg-2", convID, "user-2", "Hi there!", now.Add(time.Minute)))
msgs, err := service.ListMessages(ctx, convID)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if len(msgs) != 2 {
t.Errorf("Expected 2 messages, got %d", len(msgs))
}
if msgs[0].Content != "Hello" {
t.Errorf("Expected first message='Hello', got '%s'", msgs[0].Content)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Unmet expectations: %v", err)
}
})
t.Run("returns empty list when no messages", func(t *testing.T) {
mock.ExpectQuery("SELECT id, conversation_id, sender_id, content, created_at").
WithArgs("empty-conv").
WillReturnRows(sqlmock.NewRows([]string{"id", "conversation_id", "sender_id", "content", "created_at"}))
msgs, err := service.ListMessages(ctx, "empty-conv")
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if len(msgs) != 0 {
t.Errorf("Expected 0 messages, got %d", len(msgs))
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Unmet expectations: %v", err)
}
})
}
func TestChatService_ListConversations(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("Failed to create mock db: %v", err)
}
defer db.Close()
service := NewChatService(db, nil)
ctx := context.Background()
t.Run("lists conversations for candidate", func(t *testing.T) {
userID := "candidate-123"
now := time.Now()
mock.ExpectQuery("SELECT c.id, c.candidate_id, c.company_id, c.job_id, c.last_message, c.last_message_at").
WithArgs(userID).
WillReturnRows(sqlmock.NewRows([]string{"id", "candidate_id", "company_id", "job_id", "last_message", "last_message_at", "participant_name"}).
AddRow("conv-1", userID, "company-1", nil, "Last msg", now, "Acme Corp"))
convs, err := service.ListConversations(ctx, userID, "", true)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if len(convs) != 1 {
t.Errorf("Expected 1 conversation, got %d", len(convs))
}
if convs[0].ParticipantName != "Acme Corp" {
t.Errorf("Expected participant='Acme Corp', got '%s'", convs[0].ParticipantName)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Unmet expectations: %v", err)
}
})
t.Run("lists conversations for company", func(t *testing.T) {
tenantID := "company-456"
now := time.Now()
mock.ExpectQuery("SELECT c.id, c.candidate_id, c.company_id, c.job_id, c.last_message, c.last_message_at").
WithArgs(tenantID).
WillReturnRows(sqlmock.NewRows([]string{"id", "candidate_id", "company_id", "job_id", "last_message", "last_message_at", "participant_name"}).
AddRow("conv-2", "cand-1", tenantID, nil, "Hello", now, "John Doe"))
convs, err := service.ListConversations(ctx, "", tenantID, false)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if len(convs) != 1 {
t.Errorf("Expected 1 conversation, got %d", len(convs))
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("Unmet expectations: %v", err)
}
})
t.Run("returns error for invalid context", func(t *testing.T) {
_, err := service.ListConversations(ctx, "", "", false)
if err == nil {
t.Error("Expected error for invalid context")
}
})
}
func TestMessage_Struct(t *testing.T) {
msg := Message{
ID: "msg-1",
ConversationID: "conv-1",
SenderID: "user-1",
Content: "Test message",
CreatedAt: time.Now(),
IsMine: true,
}
if msg.ID != "msg-1" {
t.Errorf("Expected ID='msg-1', got '%s'", msg.ID)
}
if msg.IsMine != true {
t.Error("Expected IsMine=true")
}
_ = msg.ConversationID
_ = msg.SenderID
_ = msg.Content
_ = msg.CreatedAt
}
func TestConversation_Struct(t *testing.T) {
jobID := "job-1"
lastMsg := "Last message"
lastAt := time.Now()
conv := Conversation{
ID: "conv-1",
CandidateID: "cand-1",
CompanyID: "comp-1",
JobID: &jobID,
LastMessage: &lastMsg,
LastMessageAt: &lastAt,
ParticipantName: "Test User",
ParticipantAvatar: "https://example.com/avatar.png",
UnreadCount: 5,
}
if conv.ID != "conv-1" {
t.Errorf("Expected ID='conv-1', got '%s'", conv.ID)
}
if *conv.JobID != "job-1" {
t.Errorf("Expected JobID='job-1', got '%s'", *conv.JobID)
}
if conv.UnreadCount != 5 {
t.Errorf("Expected UnreadCount=5, got %d", conv.UnreadCount)
}
_ = conv.CandidateID
_ = conv.CompanyID
_ = conv.LastMessage
_ = conv.LastMessageAt
_ = conv.ParticipantName
_ = conv.ParticipantAvatar
}