274 lines
9.2 KiB
Python
274 lines
9.2 KiB
Python
"""Tests for user OAuth repository."""
|
|
# ruff: noqa: ARG002
|
|
|
|
from collections.abc import AsyncGenerator
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from sqlalchemy.exc import IntegrityError
|
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
|
|
from app.models.user import User
|
|
from app.models.user_oauth import UserOauth
|
|
from app.repositories.user_oauth import UserOauthRepository
|
|
|
|
|
|
class TestUserOauthRepository:
|
|
"""Test user OAuth repository operations."""
|
|
|
|
@pytest_asyncio.fixture
|
|
async def user_oauth_repository(
|
|
self,
|
|
test_session: AsyncSession,
|
|
) -> AsyncGenerator[UserOauthRepository, None]:
|
|
"""Create a user OAuth repository instance."""
|
|
yield UserOauthRepository(test_session)
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_user_id(
|
|
self,
|
|
test_user: User,
|
|
) -> int:
|
|
"""Get test user ID to avoid lazy loading issues."""
|
|
assert test_user.id is not None
|
|
return test_user.id
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_oauth(
|
|
self,
|
|
test_session: AsyncSession,
|
|
test_user_id: int,
|
|
) -> AsyncGenerator[UserOauth, None]:
|
|
"""Create a test OAuth record."""
|
|
oauth_data = {
|
|
"user_id": test_user_id,
|
|
"provider": "google",
|
|
"provider_user_id": "google_123456",
|
|
"email": "test@gmail.com",
|
|
"name": "Test User Google",
|
|
"picture": None,
|
|
}
|
|
oauth = UserOauth(**oauth_data)
|
|
test_session.add(oauth)
|
|
await test_session.commit()
|
|
await test_session.refresh(oauth)
|
|
yield oauth
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_by_provider_user_id_existing(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_oauth: UserOauth,
|
|
) -> None:
|
|
"""Test getting OAuth by provider user ID when it exists."""
|
|
oauth = await user_oauth_repository.get_by_provider_user_id(
|
|
"google", "google_123456",
|
|
)
|
|
|
|
assert oauth is not None
|
|
assert oauth.id == test_oauth.id
|
|
assert oauth.provider == "google"
|
|
assert oauth.provider_user_id == "google_123456"
|
|
assert oauth.user_id == test_oauth.user_id
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_by_provider_user_id_nonexistent(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
) -> None:
|
|
"""Test getting OAuth by provider user ID when it doesn't exist."""
|
|
oauth = await user_oauth_repository.get_by_provider_user_id(
|
|
"google", "nonexistent_id",
|
|
)
|
|
|
|
assert oauth is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_by_user_id_and_provider_existing(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_oauth: UserOauth,
|
|
test_user_id: int,
|
|
) -> None:
|
|
"""Test getting OAuth by user ID and provider when it exists."""
|
|
oauth = await user_oauth_repository.get_by_user_id_and_provider(
|
|
test_user_id, "google",
|
|
)
|
|
|
|
assert oauth is not None
|
|
assert oauth.id == test_oauth.id
|
|
assert oauth.provider == "google"
|
|
assert oauth.user_id == test_user_id
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_by_user_id_and_provider_nonexistent(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_user_id: int,
|
|
) -> None:
|
|
"""Test getting OAuth by user ID and provider when it doesn't exist."""
|
|
oauth = await user_oauth_repository.get_by_user_id_and_provider(
|
|
test_user_id, "github",
|
|
)
|
|
|
|
assert oauth is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_oauth(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_user_id: int,
|
|
) -> None:
|
|
"""Test creating a new OAuth record."""
|
|
oauth_data = {
|
|
"user_id": test_user_id,
|
|
"provider": "github",
|
|
"provider_user_id": "github_789",
|
|
"email": "test@github.com",
|
|
"name": "Test User GitHub",
|
|
"picture": None,
|
|
}
|
|
|
|
oauth = await user_oauth_repository.create(oauth_data)
|
|
|
|
assert oauth.id is not None
|
|
assert oauth.user_id == test_user_id
|
|
assert oauth.provider == "github"
|
|
assert oauth.provider_user_id == "github_789"
|
|
assert oauth.email == "test@github.com"
|
|
assert oauth.name == "Test User GitHub"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_oauth(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_oauth: UserOauth,
|
|
) -> None:
|
|
"""Test updating an OAuth record."""
|
|
update_data = {
|
|
"email": "updated@gmail.com",
|
|
"name": "Updated User Name",
|
|
"picture": "https://example.com/photo.jpg",
|
|
}
|
|
|
|
updated_oauth = await user_oauth_repository.update(test_oauth, update_data)
|
|
|
|
assert updated_oauth.id == test_oauth.id
|
|
assert updated_oauth.email == "updated@gmail.com"
|
|
assert updated_oauth.name == "Updated User Name"
|
|
assert updated_oauth.picture == "https://example.com/photo.jpg"
|
|
assert updated_oauth.provider == test_oauth.provider # Unchanged
|
|
assert (
|
|
updated_oauth.provider_user_id == test_oauth.provider_user_id
|
|
) # Unchanged
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_oauth(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_session: AsyncSession,
|
|
test_user_id: int,
|
|
) -> None:
|
|
"""Test deleting an OAuth record."""
|
|
# Create an OAuth record to delete
|
|
oauth_data = {
|
|
"user_id": test_user_id,
|
|
"provider": "twitter",
|
|
"provider_user_id": "twitter_456",
|
|
"email": "test@twitter.com",
|
|
"name": "Test User Twitter",
|
|
"picture": None,
|
|
}
|
|
oauth = await user_oauth_repository.create(oauth_data)
|
|
_ = oauth.id # Store ID but don't use it
|
|
|
|
# Delete the OAuth record
|
|
await user_oauth_repository.delete(oauth)
|
|
|
|
# Verify it's deleted by trying to find it
|
|
deleted_oauth = await user_oauth_repository.get_by_provider_user_id(
|
|
"twitter", "twitter_456",
|
|
)
|
|
assert deleted_oauth is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_duplicate_provider_user_id(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_oauth: UserOauth,
|
|
test_user_id: int,
|
|
) -> None:
|
|
"""Test creating OAuth with duplicate provider user ID should fail."""
|
|
# Try to create another OAuth with the same provider and provider_user_id
|
|
duplicate_oauth_data = {
|
|
"user_id": test_user_id,
|
|
"provider": "google",
|
|
"provider_user_id": "google_123456", # Same as test_oauth
|
|
"email": "another@gmail.com",
|
|
"name": "Another User",
|
|
"picture": None,
|
|
}
|
|
|
|
# This should fail due to unique constraint
|
|
with pytest.raises(IntegrityError, match="UNIQUE constraint failed"):
|
|
await user_oauth_repository.create(duplicate_oauth_data)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_multiple_providers_same_user(
|
|
self,
|
|
user_oauth_repository: UserOauthRepository,
|
|
test_user_id: int,
|
|
) -> None:
|
|
"""Test that a user can have multiple OAuth providers."""
|
|
# Create Google OAuth
|
|
google_oauth_data = {
|
|
"user_id": test_user_id,
|
|
"provider": "google",
|
|
"provider_user_id": "google_user_1",
|
|
"email": "user@gmail.com",
|
|
"name": "Test User Google",
|
|
"picture": None,
|
|
}
|
|
_ = await user_oauth_repository.create(google_oauth_data)
|
|
|
|
# Create GitHub OAuth for the same user
|
|
github_oauth_data = {
|
|
"user_id": test_user_id,
|
|
"provider": "github",
|
|
"provider_user_id": "github_user_1",
|
|
"email": "user@github.com",
|
|
"name": "Test User GitHub",
|
|
"picture": None,
|
|
}
|
|
_ = await user_oauth_repository.create(github_oauth_data)
|
|
|
|
# Verify both exist by querying back from database
|
|
found_google = await user_oauth_repository.get_by_user_id_and_provider(
|
|
test_user_id, "google",
|
|
)
|
|
found_github = await user_oauth_repository.get_by_user_id_and_provider(
|
|
test_user_id, "github",
|
|
)
|
|
|
|
assert found_google is not None
|
|
assert found_github is not None
|
|
assert found_google.provider == "google"
|
|
assert found_github.provider == "github"
|
|
assert found_google.user_id == test_user_id
|
|
assert found_github.user_id == test_user_id
|
|
assert found_google.provider_user_id == "google_user_1"
|
|
assert found_github.provider_user_id == "github_user_1"
|
|
|
|
# Verify we can also find them by provider_user_id
|
|
found_google_by_provider = await user_oauth_repository.get_by_provider_user_id(
|
|
"google", "google_user_1",
|
|
)
|
|
found_github_by_provider = await user_oauth_repository.get_by_provider_user_id(
|
|
"github", "github_user_1",
|
|
)
|
|
|
|
assert found_google_by_provider is not None
|
|
assert found_github_by_provider is not None
|
|
assert found_google_by_provider.user_id == test_user_id
|
|
assert found_github_by_provider.user_id == test_user_id
|