408 lines
9.3 KiB
Go
408 lines
9.3 KiB
Go
package services
|
|
|
|
import (
|
|
"database/sql"
|
|
"testing"
|
|
|
|
"authentication/db"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
)
|
|
|
|
func setupMockDB(t *testing.T) (sqlmock.Sqlmock, func()) {
|
|
mockDB, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatalf("Failed to create mock database: %v", err)
|
|
}
|
|
|
|
originalDB := db.DB
|
|
db.DB = mockDB
|
|
|
|
cleanup := func() {
|
|
mockDB.Close()
|
|
db.DB = originalDB
|
|
}
|
|
|
|
return mock, cleanup
|
|
}
|
|
|
|
func TestGetUser(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "test@example.com"
|
|
expectedID := "user123"
|
|
expectedFirstName := "John"
|
|
expectedLastName := "Doe"
|
|
expectedEmail := "test@example.com"
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "email_address"}).
|
|
AddRow(expectedID, expectedFirstName, expectedLastName, expectedEmail)
|
|
|
|
mock.ExpectQuery(`SELECT id, first_name, last_name, email_address FROM users WHERE email_address = \? AND is_deleted = 0 LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
id, firstName, lastName, emailAddress, err := GetUser(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if id != expectedID {
|
|
t.Errorf("Expected ID %s, got %s", expectedID, id)
|
|
}
|
|
|
|
if firstName == nil || *firstName != expectedFirstName {
|
|
t.Errorf("Expected first name %s, got %v", expectedFirstName, firstName)
|
|
}
|
|
|
|
if lastName == nil || *lastName != expectedLastName {
|
|
t.Errorf("Expected last name %s, got %v", expectedLastName, lastName)
|
|
}
|
|
|
|
if emailAddress != expectedEmail {
|
|
t.Errorf("Expected email %s, got %s", expectedEmail, emailAddress)
|
|
}
|
|
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Errorf("Unfulfilled expectations: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGetUserNotFound(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "nonexistent@example.com"
|
|
|
|
mock.ExpectQuery(`SELECT id, first_name, last_name, email_address FROM users WHERE email_address = \? AND is_deleted = 0 LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnError(sql.ErrNoRows)
|
|
|
|
id, firstName, lastName, emailAddress, err := GetUser(email)
|
|
|
|
if err != sql.ErrNoRows {
|
|
t.Errorf("Expected sql.ErrNoRows, got: %v", err)
|
|
}
|
|
|
|
if id != "" {
|
|
t.Errorf("Expected empty ID, got %s", id)
|
|
}
|
|
|
|
if firstName != nil {
|
|
t.Errorf("Expected nil firstName, got %v", firstName)
|
|
}
|
|
|
|
if lastName != nil {
|
|
t.Errorf("Expected nil lastName, got %v", lastName)
|
|
}
|
|
|
|
if emailAddress != "" {
|
|
t.Errorf("Expected empty email, got %s", emailAddress)
|
|
}
|
|
}
|
|
|
|
func TestGetUserNullNames(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "test@example.com"
|
|
expectedID := "user456"
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "email_address"}).
|
|
AddRow(expectedID, nil, nil, email)
|
|
|
|
mock.ExpectQuery(`SELECT id, first_name, last_name, email_address FROM users WHERE email_address = \? AND is_deleted = 0 LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
id, firstName, lastName, emailAddress, err := GetUser(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if id != expectedID {
|
|
t.Errorf("Expected ID %s, got %s", expectedID, id)
|
|
}
|
|
|
|
if firstName != nil {
|
|
t.Errorf("Expected nil firstName for NULL value, got %v", firstName)
|
|
}
|
|
|
|
if lastName != nil {
|
|
t.Errorf("Expected nil lastName for NULL value, got %v", lastName)
|
|
}
|
|
|
|
if emailAddress != email {
|
|
t.Errorf("Expected email %s, got %s", email, emailAddress)
|
|
}
|
|
}
|
|
|
|
func TestGetUserID(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "test@example.com"
|
|
expectedID := "user789"
|
|
|
|
rows := sqlmock.NewRows([]string{"id"}).
|
|
AddRow(expectedID)
|
|
|
|
// Note: The query has a typo "SELECT id, FROM" but we match it as-is
|
|
mock.ExpectQuery(`SELECT id, FROM users WHERE email_address = \? AND is_deleted = 0 LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
id, err := GetUserID(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if id != expectedID {
|
|
t.Errorf("Expected ID %s, got %s", expectedID, id)
|
|
}
|
|
}
|
|
|
|
func TestCheckEmailInDB(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "existing@example.com"
|
|
|
|
rows := sqlmock.NewRows([]string{"exists"}).
|
|
AddRow(true)
|
|
|
|
mock.ExpectQuery(`SELECT EXISTS \( SELECT 1 FROM users WHERE email_address = \? AND is_deleted = 0\)`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
exists, err := CheckEmailInDB(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if !exists {
|
|
t.Error("Expected email to exist")
|
|
}
|
|
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Errorf("Unfulfilled expectations: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCheckEmailInDBNotExists(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "nonexistent@example.com"
|
|
|
|
rows := sqlmock.NewRows([]string{"exists"}).
|
|
AddRow(false)
|
|
|
|
mock.ExpectQuery(`SELECT EXISTS \( SELECT 1 FROM users WHERE email_address = \? AND is_deleted = 0\)`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
exists, err := CheckEmailInDB(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if exists {
|
|
t.Error("Expected email to not exist")
|
|
}
|
|
}
|
|
|
|
func TestCheckEmailInDBError(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "error@example.com"
|
|
|
|
mock.ExpectQuery(`SELECT EXISTS \( SELECT 1 FROM users WHERE email_address = \? AND is_deleted = 0\)`).
|
|
WithArgs(email).
|
|
WillReturnError(sql.ErrConnDone)
|
|
|
|
exists, err := CheckEmailInDB(email)
|
|
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
|
|
if exists {
|
|
t.Error("Expected false when error occurs")
|
|
}
|
|
}
|
|
|
|
func TestGetUserIDFromEmail(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "test@example.com"
|
|
expectedID := "user999"
|
|
|
|
rows := sqlmock.NewRows([]string{"id"}).
|
|
AddRow(expectedID)
|
|
|
|
mock.ExpectQuery(`SELECT id FROM \( SELECT id, 1 AS priority FROM users WHERE email_address = \? AND is_deleted = 0 \) t ORDER BY priority ASC LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
id, err := GetUserIDFromEmail(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if id != expectedID {
|
|
t.Errorf("Expected ID %s, got %s", expectedID, id)
|
|
}
|
|
|
|
if err := mock.ExpectationsWereMet(); err != nil {
|
|
t.Errorf("Unfulfilled expectations: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGetUserIDFromEmailNotFound(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "notfound@example.com"
|
|
|
|
mock.ExpectQuery(`SELECT id FROM \( SELECT id, 1 AS priority FROM users WHERE email_address = \? AND is_deleted = 0 \) t ORDER BY priority ASC LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnError(sql.ErrNoRows)
|
|
|
|
id, err := GetUserIDFromEmail(email)
|
|
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
|
|
if id != "" {
|
|
t.Errorf("Expected empty ID on error, got %s", id)
|
|
}
|
|
}
|
|
|
|
func TestGetUserIDFromEmailDBError(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
email := "error@example.com"
|
|
|
|
mock.ExpectQuery(`SELECT id FROM \( SELECT id, 1 AS priority FROM users WHERE email_address = \? AND is_deleted = 0 \) t ORDER BY priority ASC LIMIT 1`).
|
|
WithArgs(email).
|
|
WillReturnError(sql.ErrConnDone)
|
|
|
|
id, err := GetUserIDFromEmail(email)
|
|
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
|
|
if err != sql.ErrConnDone {
|
|
t.Errorf("Expected sql.ErrConnDone, got: %v", err)
|
|
}
|
|
|
|
if id != "" {
|
|
t.Errorf("Expected empty ID on error, got %s", id)
|
|
}
|
|
}
|
|
|
|
func TestGetUserMultipleEmails(t *testing.T) {
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
testCases := []struct {
|
|
email string
|
|
userID string
|
|
hasNames bool
|
|
}{
|
|
{"user1@example.com", "id1", true},
|
|
{"user2@example.com", "id2", false},
|
|
{"user3@example.com", "id3", true},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.email, func(t *testing.T) {
|
|
var firstName, lastName interface{}
|
|
if tc.hasNames {
|
|
firstName = "First"
|
|
lastName = "Last"
|
|
} else {
|
|
firstName = nil
|
|
lastName = nil
|
|
}
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "email_address"}).
|
|
AddRow(tc.userID, firstName, lastName, tc.email)
|
|
|
|
mock.ExpectQuery(`SELECT id, first_name, last_name, email_address FROM users WHERE email_address = \? AND is_deleted = 0 LIMIT 1`).
|
|
WithArgs(tc.email).
|
|
WillReturnRows(rows)
|
|
|
|
id, fn, ln, email, err := GetUser(tc.email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if id != tc.userID {
|
|
t.Errorf("Expected ID %s, got %s", tc.userID, id)
|
|
}
|
|
|
|
if tc.hasNames {
|
|
if fn == nil || ln == nil {
|
|
t.Error("Expected names to be present")
|
|
}
|
|
} else {
|
|
if fn != nil || ln != nil {
|
|
t.Error("Expected names to be nil")
|
|
}
|
|
}
|
|
|
|
if email != tc.email {
|
|
t.Errorf("Expected email %s, got %s", tc.email, email)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCheckEmailInDBVariousEmails(t *testing.T) {
|
|
testEmails := []string{
|
|
"normal@example.com",
|
|
"with+plus@example.com",
|
|
"with.dot@example.com",
|
|
"with-dash@example.com",
|
|
}
|
|
|
|
mock, cleanup := setupMockDB(t)
|
|
defer cleanup()
|
|
|
|
for i, email := range testEmails {
|
|
exists := i%2 == 0 // Alternate between true and false
|
|
|
|
rows := sqlmock.NewRows([]string{"exists"}).
|
|
AddRow(exists)
|
|
|
|
mock.ExpectQuery(`SELECT EXISTS \( SELECT 1 FROM users WHERE email_address = \? AND is_deleted = 0\)`).
|
|
WithArgs(email).
|
|
WillReturnRows(rows)
|
|
|
|
result, err := CheckEmailInDB(email)
|
|
|
|
if err != nil {
|
|
t.Errorf("Expected no error for %s, got: %v", email, err)
|
|
}
|
|
|
|
if result != exists {
|
|
t.Errorf("Expected %v for %s, got %v", exists, email, result)
|
|
}
|
|
}
|
|
}
|