""" Integration tests for domain verification service. Tests the complete domain verification flow with mocked external services. """ import pytest from unittest.mock import Mock class TestDomainVerificationIntegration: """Integration tests for DomainVerificationService.""" def test_complete_verification_flow(self, verification_service, mock_email_service): """Test complete DNS + email verification flow.""" # Start verification result = verification_service.start_verification( domain="example.com", me_url="https://example.com/" ) assert result["success"] is True assert "email" in result assert result["verification_method"] == "email" # Email should have been sent assert len(mock_email_service.messages_sent) == 1 sent = mock_email_service.messages_sent[0] assert sent["email"] == "test@example.com" assert sent["domain"] == "example.com" assert len(sent["code"]) == 6 def test_dns_failure_blocks_verification(self, verification_service_dns_failure): """Test that DNS verification failure stops the process.""" result = verification_service_dns_failure.start_verification( domain="example.com", me_url="https://example.com/" ) assert result["success"] is False assert result["error"] == "dns_verification_failed" def test_email_discovery_failure(self, mock_dns_service, mock_email_service, mock_html_fetcher, test_code_storage): """Test verification fails when no email is discovered.""" from gondulf.services.domain_verification import DomainVerificationService from gondulf.services.relme_parser import RelMeParser # HTML fetcher returns page without email mock_html_fetcher.fetch = Mock(return_value="No email here") service = DomainVerificationService( dns_service=mock_dns_service, email_service=mock_email_service, code_storage=test_code_storage, html_fetcher=mock_html_fetcher, relme_parser=RelMeParser() ) result = service.start_verification( domain="example.com", me_url="https://example.com/" ) assert result["success"] is False assert result["error"] == "email_discovery_failed" def test_code_verification_success(self, verification_service, test_code_storage): """Test successful code verification.""" # Start verification to generate code verification_service.start_verification( domain="example.com", me_url="https://example.com/" ) # Get the stored code stored_code = test_code_storage.get("email_verify:example.com") assert stored_code is not None # Verify the code result = verification_service.verify_email_code( domain="example.com", code=stored_code ) assert result["success"] is True assert result["email"] == "test@example.com" def test_code_verification_invalid_code(self, verification_service, test_code_storage): """Test code verification fails with wrong code.""" # Start verification verification_service.start_verification( domain="example.com", me_url="https://example.com/" ) # Try to verify with wrong code result = verification_service.verify_email_code( domain="example.com", code="000000" ) assert result["success"] is False assert result["error"] == "invalid_code" def test_code_single_use(self, verification_service, test_code_storage): """Test verification code can only be used once.""" # Start verification verification_service.start_verification( domain="example.com", me_url="https://example.com/" ) # Get the stored code stored_code = test_code_storage.get("email_verify:example.com") # First verification should succeed result1 = verification_service.verify_email_code( domain="example.com", code=stored_code ) assert result1["success"] is True # Second verification should fail result2 = verification_service.verify_email_code( domain="example.com", code=stored_code ) assert result2["success"] is False class TestAuthorizationCodeGeneration: """Integration tests for authorization code generation.""" def test_create_authorization_code(self, verification_service): """Test authorization code creation stores metadata.""" code = verification_service.create_authorization_code( client_id="https://app.example.com", redirect_uri="https://app.example.com/callback", state="test123", code_challenge="abc123", code_challenge_method="S256", scope="", me="https://user.example.com" ) assert code is not None assert len(code) > 20 # Should be a substantial code def test_authorization_code_unique(self, verification_service): """Test each authorization code is unique.""" codes = set() for _ in range(100): code = verification_service.create_authorization_code( client_id="https://app.example.com", redirect_uri="https://app.example.com/callback", state="test123", code_challenge="abc123", code_challenge_method="S256", scope="", me="https://user.example.com" ) codes.add(code) # All 100 codes should be unique assert len(codes) == 100 def test_authorization_code_stored_with_metadata(self, verification_service, test_code_storage): """Test authorization code metadata is stored correctly.""" code = verification_service.create_authorization_code( client_id="https://app.example.com", redirect_uri="https://app.example.com/callback", state="test123", code_challenge="abc123", code_challenge_method="S256", scope="profile", me="https://user.example.com" ) # Retrieve stored metadata metadata = test_code_storage.get(f"authz:{code}") assert metadata is not None assert metadata["client_id"] == "https://app.example.com" assert metadata["redirect_uri"] == "https://app.example.com/callback" assert metadata["state"] == "test123" assert metadata["code_challenge"] == "abc123" assert metadata["code_challenge_method"] == "S256" assert metadata["scope"] == "profile" assert metadata["me"] == "https://user.example.com" assert metadata["used"] is False