# tests/integration/api/v1/admin/test_email_settings.py """Integration tests for admin email settings API.""" import pytest from app.modules.tenancy.models import AdminSetting # ============================================================================= # GET EMAIL STATUS TESTS # ============================================================================= @pytest.mark.integration @pytest.mark.email class TestGetAdminEmailStatus: """Test suite for GET /admin/settings/email/status endpoint.""" def test_get_status_unauthenticated(self, client): """Test getting status without auth fails.""" response = client.get("/api/v1/admin/settings/email/status") assert response.status_code == 401 def test_get_status_non_admin(self, client, auth_headers): """Test getting status as non-admin fails.""" response = client.get( "/api/v1/admin/settings/email/status", headers=auth_headers, ) assert response.status_code == 403 def test_get_status_admin(self, client, admin_headers): """Test getting status as admin succeeds.""" response = client.get( "/api/v1/admin/settings/email/status", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert "provider" in data assert "from_email" in data assert "enabled" in data assert "is_configured" in data def test_get_status_has_db_overrides_flag(self, client, admin_headers): """Test status includes has_db_overrides flag.""" response = client.get( "/api/v1/admin/settings/email/status", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert "has_db_overrides" in data # Initially should be False (no DB settings) assert data["has_db_overrides"] is False # ============================================================================= # UPDATE EMAIL SETTINGS TESTS # ============================================================================= @pytest.mark.integration @pytest.mark.email class TestUpdateAdminEmailSettings: """Test suite for PUT /admin/settings/email/settings endpoint.""" def test_update_unauthenticated(self, client): """Test updating settings without auth fails.""" response = client.put( "/api/v1/admin/settings/email/settings", json={"from_email": "test@example.com"}, ) assert response.status_code == 401 def test_update_non_admin(self, client, auth_headers): """Test updating settings as non-admin fails.""" response = client.put( "/api/v1/admin/settings/email/settings", headers=auth_headers, json={"from_email": "test@example.com"}, ) assert response.status_code == 403 def test_update_settings_admin(self, client, admin_headers, db): """Test updating settings as admin succeeds.""" response = client.put( "/api/v1/admin/settings/email/settings", headers=admin_headers, json={ "from_email": "platform@example.com", "from_name": "Test Platform", "provider": "smtp", "smtp_host": "smtp.test.com", "smtp_port": 587, }, ) assert response.status_code == 200 data = response.json() assert data["success"] is True assert "updated_keys" in data assert "from_email" in data["updated_keys"] # Verify settings were stored in DB setting = ( db.query(AdminSetting) .filter(AdminSetting.key == "email_from_address") .first() ) assert setting is not None assert setting.value == "platform@example.com" def test_update_partial_settings(self, client, admin_headers): """Test updating only some settings.""" response = client.put( "/api/v1/admin/settings/email/settings", headers=admin_headers, json={ "enabled": False, "debug": True, }, ) assert response.status_code == 200 data = response.json() assert data["success"] is True assert "enabled" in data["updated_keys"] assert "debug" in data["updated_keys"] def test_status_shows_db_overrides(self, client, admin_headers): """Test that status shows DB overrides after update.""" # First, set a DB override client.put( "/api/v1/admin/settings/email/settings", headers=admin_headers, json={"from_email": "override@example.com"}, ) # Check status response = client.get( "/api/v1/admin/settings/email/status", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert data["has_db_overrides"] is True assert data["from_email"] == "override@example.com" # ============================================================================= # RESET EMAIL SETTINGS TESTS # ============================================================================= @pytest.mark.integration @pytest.mark.email class TestResetAdminEmailSettings: """Test suite for DELETE /admin/settings/email/settings endpoint.""" def test_reset_unauthenticated(self, client): """Test resetting settings without auth fails.""" response = client.delete("/api/v1/admin/settings/email/settings") assert response.status_code == 401 def test_reset_non_admin(self, client, auth_headers): """Test resetting settings as non-admin fails.""" response = client.delete( "/api/v1/admin/settings/email/settings", headers=auth_headers, ) assert response.status_code == 403 def test_reset_settings_admin(self, client, admin_headers, db): """Test resetting settings as admin.""" # First, create some DB overrides client.put( "/api/v1/admin/settings/email/settings", headers=admin_headers, json={ "from_email": "tobereset@example.com", "provider": "sendgrid", }, ) # Verify they exist setting = ( db.query(AdminSetting) .filter(AdminSetting.key == "email_from_address") .first() ) assert setting is not None # Reset response = client.delete( "/api/v1/admin/settings/email/settings", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert data["success"] is True # Verify they're gone db.expire_all() setting = ( db.query(AdminSetting) .filter(AdminSetting.key == "email_from_address") .first() ) assert setting is None def test_status_after_reset(self, client, admin_headers): """Test status after reset shows no DB overrides.""" # Set an override client.put( "/api/v1/admin/settings/email/settings", headers=admin_headers, json={"from_email": "override@example.com"}, ) # Reset client.delete( "/api/v1/admin/settings/email/settings", headers=admin_headers, ) # Check status response = client.get( "/api/v1/admin/settings/email/status", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert data["has_db_overrides"] is False # ============================================================================= # TEST EMAIL TESTS # ============================================================================= @pytest.mark.integration @pytest.mark.email class TestSendAdminTestEmail: """Test suite for POST /admin/settings/email/test endpoint.""" def test_send_test_unauthenticated(self, client): """Test sending test email without auth fails.""" response = client.post( "/api/v1/admin/settings/email/test", json={"to_email": "test@example.com"}, ) assert response.status_code == 401 def test_send_test_non_admin(self, client, auth_headers): """Test sending test email as non-admin fails.""" response = client.post( "/api/v1/admin/settings/email/test", headers=auth_headers, json={"to_email": "test@example.com"}, ) assert response.status_code == 403 def test_send_test_invalid_email(self, client, admin_headers): """Test sending to invalid email format fails.""" response = client.post( "/api/v1/admin/settings/email/test", headers=admin_headers, json={"to_email": "not-an-email"}, ) assert response.status_code == 422 # Validation error def test_send_test_admin(self, client, admin_headers): """Test sending test email as admin.""" response = client.post( "/api/v1/admin/settings/email/test", headers=admin_headers, json={"to_email": "test@example.com"}, ) # May fail if email not configured, but should not be 401/403 assert response.status_code in (200, 500) data = response.json() assert "success" in data assert "message" in data