package services import ( "context" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/treytartt/honeydue-api/internal/config" "github.com/treytartt/honeydue-api/internal/dto/requests" "github.com/treytartt/honeydue-api/internal/repositories" "github.com/treytartt/honeydue-api/internal/testutil" ) func setupAuthService(t *testing.T) (*AuthService, *repositories.UserRepository) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) notifRepo := repositories.NewNotificationRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) service.SetNotificationRepository(notifRepo) return service, userRepo } // === GetCurrentUser === func TestAuthService_GetCurrentUser(t *testing.T) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123") // Create profile userRepo.GetOrCreateProfile(user.ID) resp, err := service.GetCurrentUser(context.Background(), user.ID) require.NoError(t, err) assert.Equal(t, "testuser", resp.Username) assert.Equal(t, "test@test.com", resp.Email) assert.Equal(t, "kratos", resp.AuthProvider) // All users are Kratos-managed } // === UpdateProfile === func TestAuthService_UpdateProfile(t *testing.T) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123") userRepo.GetOrCreateProfile(user.ID) newFirst := "John" newLast := "Doe" req := &requests.UpdateProfileRequest{ FirstName: &newFirst, LastName: &newLast, } resp, err := service.UpdateProfile(context.Background(), user.ID, req) require.NoError(t, err) assert.Equal(t, "John", resp.FirstName) assert.Equal(t, "Doe", resp.LastName) } func TestAuthService_UpdateProfile_DuplicateEmail(t *testing.T) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) testutil.CreateTestUser(t, db, "user1", "user1@test.com", "Password123") user2 := testutil.CreateTestUser(t, db, "user2", "user2@test.com", "Password123") userRepo.GetOrCreateProfile(user2.ID) takenEmail := "user1@test.com" req := &requests.UpdateProfileRequest{ Email: &takenEmail, } _, err := service.UpdateProfile(context.Background(), user2.ID, req) testutil.AssertAppError(t, err, http.StatusConflict, "error.email_already_taken") } func TestAuthService_UpdateProfile_SameEmail(t *testing.T) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123") userRepo.GetOrCreateProfile(user.ID) sameEmail := "test@test.com" req := &requests.UpdateProfileRequest{ Email: &sameEmail, } // Same email should not trigger duplicate error resp, err := service.UpdateProfile(context.Background(), user.ID, req) require.NoError(t, err) assert.Equal(t, "test@test.com", resp.Email) } func TestAuthService_UpdateProfile_ChangeEmail(t *testing.T) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123") userRepo.GetOrCreateProfile(user.ID) newEmail := "newemail@test.com" req := &requests.UpdateProfileRequest{ Email: &newEmail, } resp, err := service.UpdateProfile(context.Background(), user.ID, req) require.NoError(t, err) assert.Equal(t, "newemail@test.com", resp.Email) } // === DeleteAccount === func TestAuthService_DeleteAccount_WithConfirmation(t *testing.T) { service, userRepo := setupAuthService(t) user := testutil.CreateTestUser(t, (*userRepo).DB(), "testuser", "test@test.com", "") _ = user confirmation := "DELETE" _, err := service.DeleteAccount(context.Background(), user.ID, nil, &confirmation) require.NoError(t, err) } func TestAuthService_DeleteAccount_WrongConfirmation(t *testing.T) { service, userRepo := setupAuthService(t) user := testutil.CreateTestUser(t, (*userRepo).DB(), "testuser", "test@test.com", "") wrongConf := "delete" _, err := service.DeleteAccount(context.Background(), user.ID, nil, &wrongConf) testutil.AssertAppError(t, err, http.StatusBadRequest, "error.confirmation_required") } func TestAuthService_DeleteAccount_NoConfirmation(t *testing.T) { service, userRepo := setupAuthService(t) user := testutil.CreateTestUser(t, (*userRepo).DB(), "testuser", "test@test.com", "") _, err := service.DeleteAccount(context.Background(), user.ID, nil, nil) testutil.AssertAppError(t, err, http.StatusBadRequest, "error.confirmation_required") } func TestAuthService_DeleteAccount_UserNotFound(t *testing.T) { service, _ := setupAuthService(t) confirmation := "DELETE" _, err := service.DeleteAccount(context.Background(), 99999, nil, &confirmation) testutil.AssertAppError(t, err, http.StatusNotFound, "error.user_not_found") } // === SetNotificationRepository === func TestAuthService_SetNotificationRepository(t *testing.T) { db := testutil.SetupTestDB(t) userRepo := repositories.NewUserRepository(db) notifRepo := repositories.NewNotificationRepository(db) cfg := &config.Config{} service := NewAuthService(userRepo, cfg) assert.Nil(t, service.notificationRepo) service.SetNotificationRepository(notifRepo) assert.NotNil(t, service.notificationRepo) }