wishli-api/tests/unit/auth_service_test.go
2025-03-23 20:05:51 +03:00

348 lines
8.2 KiB
Go

package unit
import (
"errors"
"testing"
"time"
"wish-list-api/api/presenter"
"wish-list-api/pkg/auth"
"wish-list-api/pkg/entities"
"wish-list-api/pkg/user"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var ErrUserNotFound = errors.New("user not found")
type MockUserRepository struct {
users map[string]*entities.User
email map[string]*entities.User
telegram map[int64]*entities.User
}
func NewMockUserRepository() user.Repository {
return &MockUserRepository{
users: make(map[string]*entities.User),
email: make(map[string]*entities.User),
telegram: make(map[int64]*entities.User),
}
}
func (r *MockUserRepository) CreateUser(user *entities.User) (*entities.User, error) {
if user.ID.IsZero() {
user.ID = primitive.NewObjectID()
}
user.CreatedAt = time.Now()
user.UpdatedAt = time.Now()
r.users[user.ID.Hex()] = user
r.email[user.Email] = user
if user.TelegramID != 0 {
r.telegram[user.TelegramID] = user
}
return user, nil
}
func (r *MockUserRepository) ReadUser(id string) (*entities.User, error) {
if user, ok := r.users[id]; ok {
return user, nil
}
return nil, ErrUserNotFound
}
func (r *MockUserRepository) ReadUserByEmail(email string) (*entities.User, error) {
if user, ok := r.email[email]; ok {
return user, nil
}
return nil, ErrUserNotFound
}
func (r *MockUserRepository) ReadAllUsers() (*[]presenter.User, error) {
var users []presenter.User
for _, u := range r.users {
users = append(users, presenter.User{
ID: u.ID,
Email: u.Email,
CreatedAt: u.CreatedAt,
UpdatedAt: u.UpdatedAt,
})
}
return &users, nil
}
func (r *MockUserRepository) UpdateUser(user *entities.User) (*entities.User, error) {
if _, ok := r.users[user.ID.Hex()]; !ok {
return nil, ErrUserNotFound
}
user.UpdatedAt = time.Now()
r.users[user.ID.Hex()] = user
for email, u := range r.email {
if u.ID == user.ID && email != user.Email {
delete(r.email, email)
break
}
}
r.email[user.Email] = user
if user.TelegramID != 0 {
r.telegram[user.TelegramID] = user
}
return user, nil
}
func (r *MockUserRepository) DeleteUser(id string) error {
user, ok := r.users[id]
if !ok {
return ErrUserNotFound
}
delete(r.users, id)
delete(r.email, user.Email)
if user.TelegramID != 0 {
delete(r.telegram, user.TelegramID)
}
return nil
}
func (r *MockUserRepository) ReadUserByTelegramID(telegramID int64) (*entities.User, error) {
if user, ok := r.telegram[telegramID]; ok {
return user, nil
}
return nil, ErrUserNotFound
}
func (r *MockUserRepository) UpdateUserTelegramData(user *entities.User) (*entities.User, error) {
if _, ok := r.users[user.ID.Hex()]; !ok {
return nil, ErrUserNotFound
}
existingUser := r.users[user.ID.Hex()]
existingUser.TelegramID = user.TelegramID
existingUser.TelegramUsername = user.TelegramUsername
existingUser.FirstName = user.FirstName
existingUser.LastName = user.LastName
existingUser.PhotoURL = user.PhotoURL
existingUser.UpdatedAt = time.Now()
r.users[user.ID.Hex()] = existingUser
if user.TelegramID != 0 {
for tgID, u := range r.telegram {
if u.ID == user.ID && tgID != user.TelegramID {
delete(r.telegram, tgID)
break
}
}
r.telegram[user.TelegramID] = existingUser
}
return existingUser, nil
}
func TestRegister(t *testing.T) {
mockRepo := NewMockUserRepository()
mockUserService := user.NewService(mockRepo)
serviceConfig := auth.ServiceConfig{
UserService: mockUserService,
}
service := auth.NewService(serviceConfig)
t.Run("Register_Success", func(t *testing.T) {
userData := &entities.RegisterRequest{
Email: "test@example.com",
Password: "password123",
}
user, err := service.Register(userData)
assert.NoError(t, err)
assert.NotNil(t, user)
assert.Equal(t, userData.Email, user.Email)
assert.NotEqual(t, userData.Password, user.Password)
})
t.Run("Register_DuplicateEmail", func(t *testing.T) {
userData := &entities.RegisterRequest{
Email: "test@example.com",
Password: "different_password",
}
user, err := service.Register(userData)
assert.Error(t, err)
assert.Nil(t, user)
})
}
func TestLogin(t *testing.T) {
mockRepo := NewMockUserRepository()
mockUserService := user.NewService(mockRepo)
serviceConfig := auth.ServiceConfig{
UserService: mockUserService,
}
service := auth.NewService(serviceConfig)
registerData := &entities.RegisterRequest{
Email: "login_test@example.com",
Password: "password123",
}
_, err := service.Register(registerData)
assert.NoError(t, err)
t.Run("Login_Success", func(t *testing.T) {
loginData := &entities.LoginRequest{
Email: "login_test@example.com",
Password: "password123",
}
tokens, err := service.Login(loginData)
assert.NoError(t, err)
assert.NotNil(t, tokens)
assert.NotEmpty(t, tokens.AccessToken)
assert.NotEmpty(t, tokens.RefreshToken)
})
t.Run("Login_InvalidEmail", func(t *testing.T) {
loginData := &entities.LoginRequest{
Email: "nonexistent@example.com",
Password: "password123",
}
tokens, err := service.Login(loginData)
assert.Error(t, err)
assert.Nil(t, tokens)
})
t.Run("Login_InvalidPassword", func(t *testing.T) {
loginData := &entities.LoginRequest{
Email: "login_test@example.com",
Password: "wrong_password",
}
tokens, err := service.Login(loginData)
assert.Error(t, err)
assert.Nil(t, tokens)
})
}
func TestRefreshToken(t *testing.T) {
mockRepo := NewMockUserRepository()
mockUserService := user.NewService(mockRepo)
serviceConfig := auth.ServiceConfig{
UserService: mockUserService,
}
service := auth.NewService(serviceConfig)
registerData := &entities.RegisterRequest{
Email: "refresh_test@example.com",
Password: "password123",
}
_, err := service.Register(registerData)
assert.NoError(t, err)
loginData := &entities.LoginRequest{
Email: "refresh_test@example.com",
Password: "password123",
}
tokens, err := service.Login(loginData)
assert.NoError(t, err)
t.Run("RefreshToken_Success", func(t *testing.T) {
newTokens, err := service.RefreshToken(tokens.RefreshToken)
assert.NoError(t, err)
assert.NotNil(t, newTokens)
assert.NotEmpty(t, newTokens.AccessToken)
assert.NotEmpty(t, newTokens.RefreshToken)
})
t.Run("RefreshToken_Invalid", func(t *testing.T) {
newTokens, err := service.RefreshToken("invalid_refresh_token")
assert.Error(t, err)
assert.Nil(t, newTokens)
})
}
func TestValidateToken(t *testing.T) {
mockRepo := NewMockUserRepository()
mockUserService := user.NewService(mockRepo)
serviceConfig := auth.ServiceConfig{
UserService: mockUserService,
}
service := auth.NewService(serviceConfig)
registerData := &entities.RegisterRequest{
Email: "validate_test@example.com",
Password: "password123",
}
_, err := service.Register(registerData)
assert.NoError(t, err)
loginData := &entities.LoginRequest{
Email: "validate_test@example.com",
Password: "password123",
}
tokens, err := service.Login(loginData)
assert.NoError(t, err)
t.Run("ValidateToken_Success", func(t *testing.T) {
token, err := service.ValidateToken(tokens.AccessToken)
assert.NoError(t, err)
assert.NotNil(t, token)
})
t.Run("ValidateToken_Invalid", func(t *testing.T) {
token, err := service.ValidateToken("invalid_token")
assert.Error(t, err)
assert.Nil(t, token)
})
}
func TestGetUserIDFromToken(t *testing.T) {
mockRepo := NewMockUserRepository()
mockUserService := user.NewService(mockRepo)
serviceConfig := auth.ServiceConfig{
UserService: mockUserService,
}
service := auth.NewService(serviceConfig)
registerData := &entities.RegisterRequest{
Email: "userid_test@example.com",
Password: "password123",
}
user, err := service.Register(registerData)
assert.NoError(t, err)
loginData := &entities.LoginRequest{
Email: "userid_test@example.com",
Password: "password123",
}
tokens, err := service.Login(loginData)
assert.NoError(t, err)
t.Run("GetUserIDFromToken_Success", func(t *testing.T) {
userID, err := service.GetUserIDFromToken(tokens.AccessToken)
assert.NoError(t, err)
assert.Equal(t, user.ID.Hex(), userID)
})
t.Run("GetUserIDFromToken_Invalid", func(t *testing.T) {
userID, err := service.GetUserIDFromToken("invalid_token")
assert.Error(t, err)
assert.Empty(t, userID)
})
}