package services_test import ( "context" "regexp" "testing" "time" "github.com/DATA-DOG/go-sqlmock" "github.com/rede5/gohorsejobs/backend/internal/services" "github.com/stretchr/testify/assert" ) func TestTicketService_CRUD(t *testing.T) { db, mock, err := sqlmock.New() assert.NoError(t, err) defer db.Close() service := services.NewTicketService(db) ctx := context.Background() // 1. Create Ticket mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO tickets`)). WithArgs("user-id", "Help", "high"). WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "subject", "status", "priority", "created_at", "updated_at"}). AddRow("ticket-id", "user-id", "Help", "open", "high", time.Now(), time.Now())) ticket, err := service.CreateTicket(ctx, "user-id", "Help", "high") assert.NoError(t, err) assert.Equal(t, "ticket-id", ticket.ID) // 2. List Tickets mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, user_id, subject, status, priority, created_at, updated_at FROM tickets`)). WithArgs("user-id"). WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "subject", "status", "priority", "created_at", "updated_at"}). AddRow("ticket-id", "user-id", "Help", "open", "high", time.Now(), time.Now())) tickets, err := service.ListTickets(ctx, "user-id") assert.NoError(t, err) assert.Equal(t, 1, len(tickets)) // 3. Add Message mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM tickets`)). WithArgs("ticket-id", "user-id"). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO ticket_messages`)). WithArgs("ticket-id", "user-id", "reply"). WillReturnRows(sqlmock.NewRows([]string{"id", "ticket_id", "user_id", "message", "created_at"}). AddRow("msg-id", "ticket-id", "user-id", "reply", time.Now())) mock.ExpectExec(regexp.QuoteMeta(`UPDATE tickets SET updated_at`)). WithArgs("ticket-id"). WillReturnResult(sqlmock.NewResult(1, 1)) msg, err := service.AddMessage(ctx, "ticket-id", "user-id", "reply", false) assert.NoError(t, err) assert.NotNil(t, msg) // 4. Close Ticket mock.ExpectQuery(regexp.QuoteMeta(`SELECT user_id FROM tickets WHERE id = $1`)). WithArgs("ticket-id"). WillReturnRows(sqlmock.NewRows([]string{"user_id"}).AddRow("user-id")) mock.ExpectQuery(regexp.QuoteMeta(`UPDATE tickets SET updated_at = NOW(), status = $1 WHERE id = $2`)). WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "subject", "status", "priority", "created_at", "updated_at"}). AddRow("ticket-id", "user-id", "Help", "closed", "high", time.Now(), time.Now())) _, err = service.CloseTicket(ctx, "ticket-id", "user-id", false) assert.NoError(t, err) } func TestTicketService_Extended(t *testing.T) { db, mock, err := sqlmock.New() assert.NoError(t, err) defer db.Close() service := services.NewTicketService(db) ctx := context.Background() // 1. GetTicket (With messages) mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, user_id, subject, status, priority, created_at, updated_at FROM tickets WHERE id = $1 AND user_id = $2`)). WithArgs("ticket-id", "user-id"). WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "subject", "status", "priority", "created_at", "updated_at"}). AddRow("ticket-id", "user-id", "Subject", "open", "high", time.Now(), time.Now())) mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, ticket_id, user_id, message, created_at FROM ticket_messages WHERE ticket_id = $1 ORDER BY created_at ASC`)). WithArgs("ticket-id"). WillReturnRows(sqlmock.NewRows([]string{"id", "ticket_id", "user_id", "message", "created_at"}). AddRow("msg-1", "ticket-id", "user-id", "msg body", time.Now())) tTicket, tMsgs, err := service.GetTicket(ctx, "ticket-id", "user-id", false) assert.NoError(t, err) assert.Equal(t, "ticket-id", tTicket.ID) assert.Len(t, tMsgs, 1) // 2. DeleteTicket mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM ticket_messages WHERE ticket_id = $1`)). WithArgs("ticket-id"). WillReturnResult(sqlmock.NewResult(0, 1)) mock.ExpectExec(regexp.QuoteMeta(`DELETE FROM tickets WHERE id = $1`)). WithArgs("ticket-id"). WillReturnResult(sqlmock.NewResult(0, 1)) err = service.DeleteTicket(ctx, "ticket-id") assert.NoError(t, err) // 3. ListAllTickets mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, user_id, subject, status, priority, created_at, updated_at FROM tickets ORDER BY updated_at DESC`)). WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "subject", "status", "priority", "created_at", "updated_at"}). AddRow("ticket-1", "u1", "s1", "open", "low", time.Now(), time.Now()). AddRow("ticket-2", "u2", "s2", "closed", "high", time.Now(), time.Now())) allTickets, err := service.ListAllTickets(ctx, "") assert.NoError(t, err) assert.Len(t, allTickets, 2) }