"""Integration tests for GraphQL mutation resolvers.""" import pytest from sqlalchemy import select from src.models.member import Member from src.resolvers.member import MemberNotFoundError, Mutation from src.schemas.member import CreateMemberInput, UpdateMemberInput from src.validation import ValidationError class TestCreateMemberMutation: """Tests for createMember mutation.""" async def test_create_member_with_minimal_data(self, async_session, patched_session_maker): """Test creating a member with only firstName.""" mutation = Mutation() input_data = CreateMemberInput(first_name="Bob") result = await mutation.create_member(input=input_data) assert result.id is not None assert result.first_name == "Bob" assert result.last_name is None assert result.email is None assert result.phone is None # Verify in database db_result = await async_session.execute( select(Member).where(Member.id == result.id) ) db_member = db_result.scalar_one() assert db_member.first_name == "Bob" async def test_create_member_with_complete_data(self, patched_session_maker): """Test creating a member with all fields populated.""" mutation = Mutation() input_data = CreateMemberInput( first_name="Alice", last_name="Johnson", street="456 Oak Ave", apartment_number="2A", zip="54321", city="Portland", country="USA", email="alice@example.com", phone="+14155559999", ) result = await mutation.create_member(input=input_data) assert result.first_name == "Alice" assert result.last_name == "Johnson" assert result.street == "456 Oak Ave" assert result.apartment_number == "2A" assert result.zip == "54321" assert result.city == "Portland" assert result.country == "USA" assert result.email == "alice@example.com" assert result.phone == "+14155559999" async def test_create_member_with_invalid_email(self, patched_session_maker): """Test creating a member with invalid email raises ValidationError.""" mutation = Mutation() input_data = CreateMemberInput( first_name="Charlie", email="not-an-email" ) with pytest.raises(ValidationError, match="Invalid email format"): await mutation.create_member(input=input_data) async def test_create_member_with_invalid_phone(self, patched_session_maker): """Test creating a member with invalid phone raises ValidationError.""" mutation = Mutation() input_data = CreateMemberInput( first_name="David", phone="abc123" # Invalid characters ) with pytest.raises(ValidationError, match="Invalid phone format"): await mutation.create_member(input=input_data) async def test_create_member_with_empty_first_name(self, patched_session_maker): """Test creating a member with empty firstName raises ValidationError.""" mutation = Mutation() input_data = CreateMemberInput(first_name="") with pytest.raises(ValidationError, match="firstName is required for individual members"): await mutation.create_member(input=input_data) class TestUpdateMemberMutation: """Tests for updateMember mutation.""" async def test_update_member_successfully(self, async_session, patched_session_maker): """Test updating a member's fields successfully.""" # Create a member member = Member(first_name="Eve", email="old@example.com") async_session.add(member) await async_session.commit() await async_session.refresh(member) original_created_at = member.created_at # Update the member mutation = Mutation() input_data = UpdateMemberInput( id=member.id, email="new@example.com", phone="+14155551111" ) result = await mutation.update_member(input=input_data) assert result.id == member.id assert result.first_name == "Eve" # Unchanged assert result.email == "new@example.com" # Updated assert result.phone == "+14155551111" # Updated # Verify updated_at is set (can't reliably test it changed due to timing) assert result.updated_at is not None assert result.created_at == original_created_at async def test_update_member_with_nonexistent_id(self, patched_session_maker): """Test updating a non-existent member raises MemberNotFoundError.""" mutation = Mutation() input_data = UpdateMemberInput(id=999, email="test@example.com") with pytest.raises(MemberNotFoundError, match="Member with ID 999 not found"): await mutation.update_member(input=input_data) async def test_update_member_partial_data(self, async_session, patched_session_maker): """Test updating only some fields leaves others unchanged.""" # Create a member with complete data member = Member( first_name="Frank", last_name="Miller", email="frank@example.com", phone="+14155552222" ) async_session.add(member) await async_session.commit() await async_session.refresh(member) # Update only email mutation = Mutation() input_data = UpdateMemberInput(id=member.id, email="updated@example.com") result = await mutation.update_member(input=input_data) assert result.first_name == "Frank" # Unchanged assert result.last_name == "Miller" # Unchanged assert result.email == "updated@example.com" # Updated assert result.phone == "+14155552222" # Unchanged async def test_update_member_with_invalid_email(self, async_session, patched_session_maker): """Test updating with invalid email raises ValidationError.""" # Create a member member = Member(first_name="Grace") async_session.add(member) await async_session.commit() await async_session.refresh(member) # Try to update with invalid email mutation = Mutation() input_data = UpdateMemberInput(id=member.id, email="invalid-email") with pytest.raises(ValidationError, match="Invalid email format"): await mutation.update_member(input=input_data) class TestDeleteMemberMutation: """Tests for deleteMember mutation.""" async def test_delete_member_successfully(self, async_session, patched_session_maker): """Test deleting a member successfully.""" # Create a member member = Member(first_name="Henry") async_session.add(member) await async_session.commit() await async_session.refresh(member) member_id = member.id # Delete the member mutation = Mutation() result = await mutation.delete_member(id=member_id) assert result is True # Verify member is gone db_result = await async_session.execute( select(Member).where(Member.id == member_id) ) db_member = db_result.scalar_one_or_none() assert db_member is None async def test_delete_member_with_nonexistent_id(self, patched_session_maker): """Test deleting a non-existent member raises MemberNotFoundError.""" mutation = Mutation() with pytest.raises(MemberNotFoundError, match="Member with ID 999 not found"): await mutation.delete_member(id=999)