package auth import ( "context" "encoding/json" "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" domainAuth "base/internal/domain/auth" "base/internal/pkg/oauth" ) func TestAccountRepository_Create(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() t.Run("create account successfully", func(t *testing.T) { // Create user first user := &domainAuth.User{ ID: uuid.New(), FirstName: "Account", LastName: "User", Email: "account@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, Password: nil, Scope: []string{"read", "write"}, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account) assert.NoError(t, err) assert.NotEqual(t, uuid.Nil, account.ID) // Verify account was created found, err := repo.FindByID(ctx, account.ID) assert.NoError(t, err) assert.Equal(t, account.UserID, found.UserID) assert.Equal(t, account.Provider, found.Provider) assert.Equal(t, account.Scope, found.Scope) }) t.Run("create account with password", func(t *testing.T) { user := &domainAuth.User{ ID: uuid.New(), FirstName: "Password", LastName: "User", Email: "password@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) password := "hashedpassword" account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Credentials, Password: &password, Scope: []string{}, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account) assert.NoError(t, err) found, err := repo.FindByID(ctx, account.ID) assert.NoError(t, err) assert.NotNil(t, found.Password) assert.Equal(t, password, *found.Password) }) t.Run("create account with meta", func(t *testing.T) { user := &domainAuth.User{ ID: uuid.New(), FirstName: "Meta", LastName: "User", Email: "meta@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) metaJSON := json.RawMessage(`{"key": "value", "number": 123}`) account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, Meta: metaJSON, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account) assert.NoError(t, err) found, err := repo.FindByID(ctx, account.ID) assert.NoError(t, err) assert.NotNil(t, found.Meta) }) } func TestAccountRepository_FindByID(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() t.Run("find existing account by id", func(t *testing.T) { user := &domainAuth.User{ ID: uuid.New(), FirstName: "Find", LastName: "User", Email: "find@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account) require.NoError(t, err) found, err := repo.FindByID(ctx, account.ID) assert.NoError(t, err) assert.Equal(t, account.ID, found.ID) assert.Equal(t, account.UserID, found.UserID) }) t.Run("find non-existent account", func(t *testing.T) { nonExistentID := uuid.New() found, err := repo.FindByID(ctx, nonExistentID) assert.Error(t, err) assert.Nil(t, found) }) } func TestAccountRepository_FindByUserID(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() t.Run("find accounts by user id", func(t *testing.T) { user := &domainAuth.User{ ID: uuid.New(), FirstName: "Multi", LastName: "Account", Email: "multi@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) // Create multiple accounts account1 := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account1) require.NoError(t, err) account2 := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.GitHub, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account2) require.NoError(t, err) accounts, err := repo.FindByUserID(ctx, user.ID) assert.NoError(t, err) assert.Len(t, accounts, 2) }) } func TestAccountRepository_Update(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() t.Run("update account successfully", func(t *testing.T) { user := &domainAuth.User{ ID: uuid.New(), FirstName: "Update", LastName: "User", Email: "update@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, Scope: []string{"read"}, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account) require.NoError(t, err) // Update account account.Scope = []string{"read", "write", "admin"} newToken := "newtoken" account.AccessToken = &newToken err = repo.Update(ctx, account) assert.NoError(t, err) // Verify update found, err := repo.FindByID(ctx, account.ID) assert.NoError(t, err) assert.Equal(t, []string{"read", "write", "admin"}, found.Scope) assert.NotNil(t, found.AccessToken) assert.Equal(t, newToken, *found.AccessToken) }) } func TestAccountRepository_Delete(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() t.Run("delete account successfully", func(t *testing.T) { user := &domainAuth.User{ ID: uuid.New(), FirstName: "Delete", LastName: "User", Email: "delete@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = repo.Create(ctx, account) require.NoError(t, err) err = repo.Delete(ctx, account.ID) assert.NoError(t, err) // Verify deletion found, err := repo.FindByID(ctx, account.ID) assert.Error(t, err) assert.Nil(t, found) }) } func TestAccountRepository_List(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() // Create user and multiple accounts user := &domainAuth.User{ ID: uuid.New(), FirstName: "List", LastName: "User", Email: "list@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := userRepo.Create(ctx, user) require.NoError(t, err) for i := 0; i < 5; i++ { account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Provider(i % 4), // Cycle through providers CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := repo.Create(ctx, account) require.NoError(t, err) } t.Run("list accounts with limit and offset", func(t *testing.T) { accounts, err := repo.List(ctx, 3, 0) assert.NoError(t, err) assert.Len(t, accounts, 3) accounts, err = repo.List(ctx, 3, 3) assert.NoError(t, err) assert.Len(t, accounts, 2) // Remaining 2 accounts }) } func TestAccountRepository_Count(t *testing.T) { db := setupTestDB(t) repo := createTestAccountRepository(db) userRepo := createTestUserRepository(db) ctx := context.Background() t.Run("count accounts", func(t *testing.T) { initialCount, err := repo.Count(ctx) assert.NoError(t, err) assert.Equal(t, int64(0), initialCount) user := &domainAuth.User{ ID: uuid.New(), FirstName: "Count", LastName: "User", Email: "count@example.com", Status: domainAuth.UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err = userRepo.Create(ctx, user) require.NoError(t, err) // Create accounts for i := 0; i < 3; i++ { account := &domainAuth.Account{ ID: uuid.New(), UserID: user.ID, Provider: oauth.Google, CreatedAt: time.Now(), UpdatedAt: time.Now(), } err := repo.Create(ctx, account) require.NoError(t, err) } count, err := repo.Count(ctx) assert.NoError(t, err) assert.Equal(t, int64(3), count) }) }