Files
food-ai/backend/tests/auth/service_test.go
dbastrikin 6594013b53 refactor: introduce internal/domain/ layer, rename model.go → entity.go
Move all business-logic packages from internal/ root into internal/domain/:
  auth, cuisine, diary, dish, home, ingredient, language, menu, product,
  recipe, recognition, recommendation, savedrecipe, tag, units, user

Rename model.go → entity.go in packages that hold domain entities:
  diary, dish, home, ingredient, menu, product, recipe, savedrecipe, user

Update all import paths accordingly (adapters, infra/server, cmd/server,
tests). No logic changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 22:12:07 +02:00

215 lines
6.6 KiB
Go

package auth_test
import (
"context"
"fmt"
"testing"
"time"
"github.com/food-ai/backend/internal/domain/auth"
"github.com/food-ai/backend/internal/domain/auth/mocks"
"github.com/food-ai/backend/internal/domain/user"
umocks "github.com/food-ai/backend/internal/domain/user/mocks"
)
func newTestService(verifier *mocks.MockTokenVerifier, repo *umocks.MockUserRepository) *auth.Service {
jm := auth.NewJWTManager("test-secret", 15*time.Minute, 720*time.Hour)
return auth.NewService(verifier, repo, jm)
}
func TestLogin_Success(t *testing.T) {
verifier := &mocks.MockTokenVerifier{
VerifyTokenFn: func(ctx context.Context, idToken string) (string, string, string, string, error) {
return "fb-uid", "test@example.com", "Test User", "https://avatar.url", nil
},
}
repo := &umocks.MockUserRepository{
UpsertByFirebaseUIDFn: func(ctx context.Context, uid, email, name, avatarURL string) (*user.User, error) {
return &user.User{ID: "user-1", Email: email, Name: name, Plan: "free"}, nil
},
SetRefreshTokenFn: func(ctx context.Context, id, token string, expiresAt time.Time) error {
return nil
},
}
svc := newTestService(verifier, repo)
resp, loginError := svc.Login(context.Background(), "firebase-token")
if loginError != nil {
t.Fatalf("unexpected error: %v", loginError)
}
if resp.AccessToken == "" {
t.Error("expected non-empty access token")
}
if resp.RefreshToken == "" {
t.Error("expected non-empty refresh token")
}
if resp.User.ID != "user-1" {
t.Errorf("expected user ID 'user-1', got %q", resp.User.ID)
}
}
func TestLogin_InvalidFirebaseToken(t *testing.T) {
verifier := &mocks.MockTokenVerifier{
VerifyTokenFn: func(ctx context.Context, idToken string) (string, string, string, string, error) {
return "", "", "", "", fmt.Errorf("invalid token")
},
}
repo := &umocks.MockUserRepository{}
svc := newTestService(verifier, repo)
_, loginError := svc.Login(context.Background(), "bad-token")
if loginError == nil {
t.Fatal("expected error for invalid firebase token")
}
}
func TestLogin_UpsertError(t *testing.T) {
verifier := &mocks.MockTokenVerifier{
VerifyTokenFn: func(ctx context.Context, idToken string) (string, string, string, string, error) {
return "fb-uid", "test@example.com", "Test", "", nil
},
}
repo := &umocks.MockUserRepository{
UpsertByFirebaseUIDFn: func(ctx context.Context, uid, email, name, avatarURL string) (*user.User, error) {
return nil, fmt.Errorf("db error")
},
}
svc := newTestService(verifier, repo)
_, loginError := svc.Login(context.Background(), "token")
if loginError == nil {
t.Fatal("expected error for upsert failure")
}
}
func TestLogin_SetRefreshTokenError(t *testing.T) {
verifier := &mocks.MockTokenVerifier{
VerifyTokenFn: func(ctx context.Context, idToken string) (string, string, string, string, error) {
return "fb-uid", "test@example.com", "Test", "", nil
},
}
repo := &umocks.MockUserRepository{
UpsertByFirebaseUIDFn: func(ctx context.Context, uid, email, name, avatarURL string) (*user.User, error) {
return &user.User{ID: "user-1", Plan: "free"}, nil
},
SetRefreshTokenFn: func(ctx context.Context, id, token string, expiresAt time.Time) error {
return fmt.Errorf("db error")
},
}
svc := newTestService(verifier, repo)
_, loginError := svc.Login(context.Background(), "token")
if loginError == nil {
t.Fatal("expected error for set refresh token failure")
}
}
func TestRefresh_Success(t *testing.T) {
repo := &umocks.MockUserRepository{
FindByRefreshTokenFn: func(ctx context.Context, token string) (*user.User, error) {
return &user.User{ID: "user-1", Plan: "free"}, nil
},
SetRefreshTokenFn: func(ctx context.Context, id, token string, expiresAt time.Time) error {
return nil
},
}
verifier := &mocks.MockTokenVerifier{}
svc := newTestService(verifier, repo)
resp, refreshError := svc.Refresh(context.Background(), "valid-refresh-token")
if refreshError != nil {
t.Fatalf("unexpected error: %v", refreshError)
}
if resp.AccessToken == "" {
t.Error("expected non-empty access token")
}
if resp.RefreshToken == "" {
t.Error("expected non-empty refresh token")
}
}
func TestRefresh_InvalidToken(t *testing.T) {
repo := &umocks.MockUserRepository{
FindByRefreshTokenFn: func(ctx context.Context, token string) (*user.User, error) {
return nil, fmt.Errorf("not found")
},
}
verifier := &mocks.MockTokenVerifier{}
svc := newTestService(verifier, repo)
_, refreshError := svc.Refresh(context.Background(), "bad-token")
if refreshError == nil {
t.Fatal("expected error for invalid refresh token")
}
}
func TestRefresh_SetRefreshTokenError(t *testing.T) {
repo := &umocks.MockUserRepository{
FindByRefreshTokenFn: func(ctx context.Context, token string) (*user.User, error) {
return &user.User{ID: "user-1", Plan: "free"}, nil
},
SetRefreshTokenFn: func(ctx context.Context, id, token string, expiresAt time.Time) error {
return fmt.Errorf("db error")
},
}
verifier := &mocks.MockTokenVerifier{}
svc := newTestService(verifier, repo)
_, refreshError := svc.Refresh(context.Background(), "valid-token")
if refreshError == nil {
t.Fatal("expected error")
}
}
func TestLogout_Success(t *testing.T) {
repo := &umocks.MockUserRepository{
ClearRefreshTokenFn: func(ctx context.Context, id string) error {
return nil
},
}
verifier := &mocks.MockTokenVerifier{}
svc := newTestService(verifier, repo)
logoutError := svc.Logout(context.Background(), "user-1")
if logoutError != nil {
t.Fatalf("unexpected error: %v", logoutError)
}
}
func TestLogout_Error(t *testing.T) {
repo := &umocks.MockUserRepository{
ClearRefreshTokenFn: func(ctx context.Context, id string) error {
return fmt.Errorf("db error")
},
}
verifier := &mocks.MockTokenVerifier{}
svc := newTestService(verifier, repo)
logoutError := svc.Logout(context.Background(), "user-1")
if logoutError == nil {
t.Fatal("expected error")
}
}
func TestLogin_ExpiresIn(t *testing.T) {
verifier := &mocks.MockTokenVerifier{
VerifyTokenFn: func(ctx context.Context, idToken string) (string, string, string, string, error) {
return "fb-uid", "test@example.com", "Test", "", nil
},
}
repo := &umocks.MockUserRepository{
UpsertByFirebaseUIDFn: func(ctx context.Context, uid, email, name, avatarURL string) (*user.User, error) {
return &user.User{ID: "user-1", Plan: "free"}, nil
},
SetRefreshTokenFn: func(ctx context.Context, id, token string, expiresAt time.Time) error {
return nil
},
}
svc := newTestService(verifier, repo)
resp, _ := svc.Login(context.Background(), "token")
if resp.ExpiresIn != 900 {
t.Errorf("expected expires_in 900, got %d", resp.ExpiresIn)
}
}