- Tests complets pour frontend_log_handler.go (12 tests)
- Tests couvrent NewFrontendLogHandler et ReceiveLog
- Tests pour tous les niveaux de log (DEBUG, INFO, WARN, ERROR)
- Tests pour gestion des erreurs et validation JSON
- Couverture actuelle: 30.6% (objectif: 80%)
Files: veza-backend-api/internal/handlers/frontend_log_handler_test.go
VEZA_ROADMAP.json
Hours: 16 estimated, 23 actual
389 lines
11 KiB
Go
389 lines
11 KiB
Go
package user
|
|
|
|
import (
|
|
"database/sql"
|
|
"regexp"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"veza-backend-api/internal/database"
|
|
)
|
|
|
|
// Helper to setup mock DB
|
|
func setupMockDB(t *testing.T) (*database.DB, sqlmock.Sqlmock) {
|
|
db, mock, err := sqlmock.New()
|
|
require.NoError(t, err)
|
|
|
|
dbWrapper := &database.DB{
|
|
DB: db,
|
|
}
|
|
|
|
return dbWrapper, mock
|
|
}
|
|
|
|
func TestService_GetUserByID_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
expectedUser := UserResponse{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
Role: "user",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
}
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "email", "first_name", "last_name", "username", "avatar", "bio",
|
|
"role", "is_active", "is_verified", "last_login_at", "created_at", "updated_at"}).
|
|
AddRow(userID, expectedUser.Email, nil, nil, expectedUser.Username, nil, nil,
|
|
expectedUser.Role, expectedUser.IsActive, false, nil, expectedUser.CreatedAt, time.Now())
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, email, first_name, last_name, username, avatar, bio,
|
|
role, is_active, is_verified, last_login_at, created_at, updated_at
|
|
FROM users
|
|
WHERE id = $1 AND is_active = true`)).
|
|
WithArgs(userID).
|
|
WillReturnRows(rows)
|
|
|
|
// Execute
|
|
user, err := service.GetUserByID(userID)
|
|
|
|
// Assert
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, user)
|
|
assert.Equal(t, userID, user.ID)
|
|
assert.Equal(t, "testuser", user.Username)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_GetUserByID_NotFound(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`FROM users`)).
|
|
WithArgs(userID).
|
|
WillReturnError(sql.ErrNoRows)
|
|
|
|
// Execute
|
|
user, err := service.GetUserByID(userID)
|
|
|
|
// Assert
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "user not found", err.Error())
|
|
assert.Nil(t, user)
|
|
}
|
|
|
|
func TestService_CreateUser_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
|
|
req := CreateUserRequest{
|
|
Username: "newuser",
|
|
Email: "new@example.com",
|
|
Password: "password123",
|
|
}
|
|
|
|
userID := uuid.New()
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "email", "first_name", "last_name", "username", "role", "is_active", "is_verified", "created_at", "updated_at"}).
|
|
AddRow(userID, req.Email, nil, nil, req.Username, "user", true, false, time.Now(), time.Now())
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO users`)).
|
|
WithArgs(req.Email, sqlmock.AnyArg(), "", "", req.Username, "user").
|
|
WillReturnRows(rows)
|
|
|
|
// Execute
|
|
user, err := service.CreateUser(req)
|
|
|
|
// Assert
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, user)
|
|
assert.Equal(t, userID, user.ID)
|
|
assert.Equal(t, "newuser", user.Username)
|
|
}
|
|
|
|
func TestService_DeleteUser_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
mock.ExpectExec(regexp.QuoteMeta(`UPDATE users SET is_active = false`)).
|
|
WithArgs(userID).
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
// Execute
|
|
err := service.DeleteUser(userID)
|
|
|
|
// Assert
|
|
assert.NoError(t, err)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_DeleteUser_NotFound(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
mock.ExpectExec(regexp.QuoteMeta(`UPDATE users SET is_active = false`)).
|
|
WithArgs(userID).
|
|
WillReturnResult(sqlmock.NewResult(1, 0)) // 0 rows affected
|
|
|
|
// Execute
|
|
err := service.DeleteUser(userID)
|
|
|
|
// Assert
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "user not found", err.Error())
|
|
}
|
|
|
|
func TestService_RecoverAccount_NotFound(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
email := "deleted@example.com"
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, password_hash, deleted_at`)).
|
|
WithArgs(email).
|
|
WillReturnError(sql.ErrNoRows)
|
|
|
|
err := service.RecoverAccount(email, "password")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "no deleted account found for this email", err.Error())
|
|
}
|
|
|
|
func TestService_UpdateUser_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
newFirst := "Jane"
|
|
newLast := "Doe"
|
|
req := UpdateUserRequest{
|
|
FirstName: &newFirst,
|
|
LastName: &newLast,
|
|
}
|
|
|
|
expectedUser := UserResponse{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
FirstName: sql.NullString{String: "Jane", Valid: true},
|
|
LastName: sql.NullString{String: "Doe", Valid: true},
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "email", "first_name", "last_name", "username", "avatar", "bio",
|
|
"role", "is_active", "is_verified", "last_login_at", "created_at", "updated_at"}).
|
|
AddRow(userID, expectedUser.Email, expectedUser.FirstName, expectedUser.LastName, expectedUser.Username, nil, nil,
|
|
"user", true, false, nil, time.Now(), expectedUser.UpdatedAt)
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`UPDATE users`)).
|
|
WithArgs("Jane", "Doe", userID).
|
|
WillReturnRows(rows)
|
|
|
|
user, err := service.UpdateUser(userID, req)
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, user)
|
|
assert.Equal(t, "Jane", user.FirstName.String)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_GetUsers_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
|
|
// Mock count query
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(2))
|
|
|
|
// Mock select query
|
|
rows := sqlmock.NewRows([]string{"id", "email", "first_name", "last_name", "username", "avatar", "bio",
|
|
"role", "is_active", "is_verified", "last_login_at", "created_at", "updated_at"}).
|
|
AddRow(uuid.New(), "user1@example.com", nil, nil, "user1", nil, nil, "user", true, false, nil, time.Now(), time.Now()).
|
|
AddRow(uuid.New(), "user2@example.com", nil, nil, "user2", nil, nil, "user", true, false, nil, time.Now(), time.Now())
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, email, first_name, last_name, username, avatar, bio,
|
|
role, is_active, is_verified, last_login_at, created_at, updated_at
|
|
FROM users`)).
|
|
WithArgs(20, 0). // Limit 20, Offset 0
|
|
WillReturnRows(rows)
|
|
|
|
users, total, err := service.GetUsers(1, 20, "")
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, total)
|
|
assert.Len(t, users, 2)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_UpdateUserPreferences_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
// Expect GetUserPreferences first
|
|
prefRows := sqlmock.NewRows([]string{"user_id", "theme", "language", "timezone", "notifications", "privacy", "audio", "updated_at"}).
|
|
AddRow(userID, "light", "en", "UTC", "{}", "{}", "{}", time.Now())
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT user_id`)).
|
|
WithArgs(userID).
|
|
WillReturnRows(prefRows)
|
|
|
|
// Expect Upsert
|
|
theme := "dark"
|
|
req := UserPreferencesRequest{
|
|
Theme: &theme,
|
|
}
|
|
|
|
mock.ExpectExec(regexp.QuoteMeta(`INSERT INTO user_preferences`)).
|
|
WithArgs(userID, "dark", "en", "UTC", "{}", "{}", "{}", sqlmock.AnyArg()).
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
pref, err := service.UpdateUserPreferences(userID, req)
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, pref)
|
|
assert.Equal(t, "dark", pref.Theme)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_ChangePassword_UserNotFound(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT password_hash FROM users`)).
|
|
WithArgs(userID).
|
|
WillReturnError(sql.ErrNoRows)
|
|
|
|
err := service.ChangePassword(userID, "old", "new")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "user not found", err.Error())
|
|
}
|
|
|
|
func TestService_GetUserStats_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
|
|
// Expect 4 queries
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users WHERE is_active = true`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(100))
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users WHERE is_active = true AND is_verified = true`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(50))
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users`)). // Active users query
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(10))
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM users`)). // New users query
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(5))
|
|
|
|
stats, err := service.GetUserStats()
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 100, stats["total_users"])
|
|
assert.Equal(t, 50, stats["verified_users"])
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_RequestDataDeletion_UserNotFound(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT password_hash FROM users`)).
|
|
WithArgs(userID).
|
|
WillReturnError(sql.ErrNoRows)
|
|
|
|
err := service.RequestDataDeletion(userID, "pass", "reason")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "user not found", err.Error())
|
|
}
|
|
|
|
func TestService_GetAccountStatus_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
rows := sqlmock.NewRows([]string{"id", "is_active", "is_verified", "created_at", "deleted_at", "deletion_reason", "recovery_deadline"}).
|
|
AddRow(userID, true, true, time.Now(), nil, "", nil)
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, is_active`)).
|
|
WithArgs(userID).
|
|
WillReturnRows(rows)
|
|
|
|
status, err := service.GetAccountStatus(userID)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "active", status.Status)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestService_ExportUserData_Success(t *testing.T) {
|
|
dbWrapper, mock := setupMockDB(t)
|
|
defer dbWrapper.Close()
|
|
|
|
service := NewService(dbWrapper)
|
|
userID := uuid.New()
|
|
|
|
// 1. GetUserByID
|
|
userRows := sqlmock.NewRows([]string{"id", "email", "first_name", "last_name", "username", "avatar", "bio",
|
|
"role", "is_active", "is_verified", "last_login_at", "created_at", "updated_at"}).
|
|
AddRow(userID, "test@example.com", nil, nil, "test", nil, nil, "user", true, true, nil, time.Now(), time.Now())
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id`)).
|
|
WithArgs(userID).
|
|
WillReturnRows(userRows)
|
|
|
|
// 2. GetUserPreferences
|
|
prefRows := sqlmock.NewRows([]string{"user_id", "theme", "language", "timezone", "notifications", "privacy", "audio", "updated_at"}).
|
|
AddRow(userID, "light", "en", "UTC", "{}", "{}", "{}", time.Now())
|
|
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT user_id`)).
|
|
WithArgs(userID).
|
|
WillReturnRows(prefRows)
|
|
|
|
export, err := service.ExportUserData(userID)
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, export)
|
|
assert.Equal(t, userID, export.UserID)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|