- Implemented methods to check the existence of OAuth accounts, roles, types, and users by their respective identifiers, enhancing the user provider's functionality. - Added error handling for these methods to ensure robust feedback in case of failures. - Updated the user provider interface to include the new existence check methods, improving overall usability and maintainability.
243 lines
7 KiB
Go
243 lines
7 KiB
Go
package user_test
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/yaoapp/kun/maps"
|
|
)
|
|
|
|
// TestExistsMethods tests all resource existence check methods
|
|
func TestExistsMethods(t *testing.T) {
|
|
prepare(t)
|
|
defer clean()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Use UUID to ensure unique identifiers across test runs
|
|
testUUID := strings.ReplaceAll(uuid.New().String(), "-", "")[:8] // 8 char UUID
|
|
|
|
testUserID := "test-user-for-exists-" + testUUID
|
|
testUsername := "testexistsuser" + testUUID
|
|
testEmail := "testexists" + testUUID + "@example.com"
|
|
|
|
t.Run("UserExists", func(t *testing.T) {
|
|
// Test non-existent user
|
|
exists, err := testProvider.UserExists(ctx, "nonexistent-user-id")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
// Create a test user
|
|
userData := maps.MapStrAny{
|
|
"user_id": testUserID,
|
|
"preferred_username": testUsername,
|
|
"email": testEmail,
|
|
"password": "password123",
|
|
"status": "active",
|
|
}
|
|
|
|
_, err = testProvider.CreateUser(ctx, userData)
|
|
assert.NoError(t, err)
|
|
|
|
// Test existing user
|
|
exists, err = testProvider.UserExists(ctx, testUserID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
|
|
t.Run("UserExistsByEmail", func(t *testing.T) {
|
|
// Test non-existent email
|
|
exists, err := testProvider.UserExistsByEmail(ctx, "nonexistent@example.com")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
// Test existing email (using unique email from test setup)
|
|
exists, err = testProvider.UserExistsByEmail(ctx, testEmail)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
|
|
t.Run("UserExistsByPreferredUsername", func(t *testing.T) {
|
|
// Test non-existent username
|
|
exists, err := testProvider.UserExistsByPreferredUsername(ctx, "nonexistentuser")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
// Test existing username (using unique username from test setup)
|
|
exists, err = testProvider.UserExistsByPreferredUsername(ctx, testUsername)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
|
|
// Define unique IDs for roles and types
|
|
testRoleID := "test-role-for-exists-" + testUUID
|
|
testTypeID := "test-type-for-exists-" + testUUID
|
|
|
|
t.Run("RoleExists", func(t *testing.T) {
|
|
// Test non-existent role
|
|
exists, err := testProvider.RoleExists(ctx, "nonexistent-role")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
// Create a test role
|
|
roleData := maps.MapStrAny{
|
|
"role_id": testRoleID,
|
|
"name": "Test Exists Role " + testUUID,
|
|
"description": "Role for testing exists method",
|
|
"is_active": true,
|
|
}
|
|
|
|
_, err = testProvider.CreateRole(ctx, roleData)
|
|
assert.NoError(t, err)
|
|
|
|
// Test existing role
|
|
exists, err = testProvider.RoleExists(ctx, testRoleID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
|
|
t.Run("TypeExists", func(t *testing.T) {
|
|
// Test non-existent type
|
|
exists, err := testProvider.TypeExists(ctx, "nonexistent-type")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
// Create a test type
|
|
typeData := maps.MapStrAny{
|
|
"type_id": testTypeID,
|
|
"name": "Test Exists Type " + testUUID,
|
|
"description": "Type for testing exists method",
|
|
"is_active": true,
|
|
}
|
|
|
|
_, err = testProvider.CreateType(ctx, typeData)
|
|
assert.NoError(t, err)
|
|
|
|
// Test existing type
|
|
exists, err = testProvider.TypeExists(ctx, testTypeID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
|
|
t.Run("OAuthAccountExists", func(t *testing.T) {
|
|
// Test non-existent OAuth account
|
|
exists, err := testProvider.OAuthAccountExists(ctx, "nonexistent-provider", "nonexistent-subject")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
// Create a test OAuth account (using unique identifiers)
|
|
testOAuthProvider := "test-provider-" + testUUID
|
|
testSubject := "test-subject-for-exists-" + testUUID
|
|
oauthData := maps.MapStrAny{
|
|
"provider": testOAuthProvider,
|
|
"sub": testSubject,
|
|
"name": "Test OAuth User " + testUUID,
|
|
"email": "testoauth" + testUUID + "@example.com",
|
|
"is_active": true,
|
|
}
|
|
|
|
_, err = testProvider.CreateOAuthAccount(ctx, testUserID, oauthData)
|
|
assert.NoError(t, err)
|
|
|
|
// Test existing OAuth account
|
|
exists, err = testProvider.OAuthAccountExists(ctx, testOAuthProvider, testSubject)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
|
|
t.Run("UserHasRole", func(t *testing.T) {
|
|
// Test user without role
|
|
hasRole, err := testProvider.UserHasRole(ctx, testUserID)
|
|
assert.NoError(t, err)
|
|
assert.False(t, hasRole)
|
|
|
|
// Assign role to user
|
|
err = testProvider.SetUserRole(ctx, testUserID, testRoleID)
|
|
assert.NoError(t, err)
|
|
|
|
// Test user with role
|
|
hasRole, err = testProvider.UserHasRole(ctx, testUserID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, hasRole)
|
|
|
|
// Test non-existent user
|
|
_, err = testProvider.UserHasRole(ctx, "nonexistent-user")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "user not found")
|
|
})
|
|
|
|
t.Run("UserHasType", func(t *testing.T) {
|
|
// Test user without type
|
|
hasType, err := testProvider.UserHasType(ctx, testUserID)
|
|
assert.NoError(t, err)
|
|
assert.False(t, hasType)
|
|
|
|
// Assign type to user
|
|
err = testProvider.SetUserType(ctx, testUserID, testTypeID)
|
|
assert.NoError(t, err)
|
|
|
|
// Test user with type
|
|
hasType, err = testProvider.UserHasType(ctx, testUserID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, hasType)
|
|
|
|
// Test non-existent user
|
|
_, err = testProvider.UserHasType(ctx, "nonexistent-user")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "user not found")
|
|
})
|
|
}
|
|
|
|
// TestExistsPerformance tests the performance benefit of Exists methods vs full Get methods
|
|
func TestExistsPerformance(t *testing.T) {
|
|
prepare(t)
|
|
defer clean()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Use UUID to ensure unique identifiers
|
|
perfUUID := strings.ReplaceAll(uuid.New().String(), "-", "")[:8] // 8 char UUID
|
|
perfUserID := "perf-test-user-" + perfUUID
|
|
perfUsername := "perfuser" + perfUUID
|
|
perfEmail := "perf" + perfUUID + "@example.com"
|
|
|
|
// Create a test user for performance comparison
|
|
userData := maps.MapStrAny{
|
|
"user_id": perfUserID,
|
|
"preferred_username": perfUsername,
|
|
"email": perfEmail,
|
|
"password": "password123",
|
|
"status": "active",
|
|
}
|
|
|
|
_, err := testProvider.CreateUser(ctx, userData)
|
|
assert.NoError(t, err)
|
|
|
|
t.Run("UserExists_vs_GetUser", func(t *testing.T) {
|
|
// Both should work, but UserExists should be more efficient
|
|
// (we can't easily measure performance in unit tests, but we verify functionality)
|
|
|
|
// Test UserExists
|
|
exists, err := testProvider.UserExists(ctx, perfUserID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, exists)
|
|
|
|
// Test GetUser (more expensive)
|
|
user, err := testProvider.GetUser(ctx, perfUserID)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, user)
|
|
assert.Equal(t, perfUserID, user["user_id"])
|
|
|
|
// Both methods should give consistent results for existence
|
|
exists, err = testProvider.UserExists(ctx, "nonexistent-user")
|
|
assert.NoError(t, err)
|
|
assert.False(t, exists)
|
|
|
|
_, err = testProvider.GetUser(ctx, "nonexistent-user")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "user not found")
|
|
})
|
|
}
|