# tests/integration/api/v1/admin/test_merchant_domains.py """Integration tests for admin merchant domain management endpoints. Tests the /api/v1/admin/merchants/{id}/domains/* and /api/v1/admin/merchants/domains/merchant/* endpoints. """ import uuid from datetime import UTC, datetime import pytest from app.modules.tenancy.models.merchant_domain import MerchantDomain @pytest.mark.integration @pytest.mark.api @pytest.mark.admin class TestAdminMerchantDomainsAPI: """Test admin merchant domain management endpoints.""" def test_create_merchant_domain(self, client, admin_headers, test_merchant): """Test POST create merchant domain returns 201-equivalent (200 with data).""" unique_id = str(uuid.uuid4())[:8] response = client.post( f"/api/v1/admin/merchants/{test_merchant.id}/domains", headers=admin_headers, json={ "domain": f"newmerch{unique_id}.example.com", "is_primary": True, }, ) assert response.status_code == 200 data = response.json() assert data["domain"] == f"newmerch{unique_id}.example.com" assert data["merchant_id"] == test_merchant.id assert data["is_primary"] is True assert data["is_verified"] is False assert data["is_active"] is False assert data["verification_token"] is not None def test_create_duplicate_domain( self, client, admin_headers, test_merchant, db ): """Test POST create duplicate domain returns 409 conflict.""" unique_id = str(uuid.uuid4())[:8] domain_name = f"dup{unique_id}.example.com" # Create existing domain existing = MerchantDomain( merchant_id=test_merchant.id, domain=domain_name, verification_token=f"dup_{unique_id}", ) db.add(existing) db.commit() response = client.post( f"/api/v1/admin/merchants/{test_merchant.id}/domains", headers=admin_headers, json={"domain": domain_name, "is_primary": True}, ) assert response.status_code == 409 data = response.json() assert data["error_code"] == "MERCHANT_DOMAIN_ALREADY_EXISTS" def test_create_domain_invalid_format( self, client, admin_headers, test_merchant ): """Test POST create domain with invalid format returns 422.""" response = client.post( f"/api/v1/admin/merchants/{test_merchant.id}/domains", headers=admin_headers, json={"domain": "notadomain", "is_primary": True}, ) assert response.status_code == 422 def test_create_domain_merchant_not_found(self, client, admin_headers): """Test POST create domain for non-existent merchant returns 404.""" response = client.post( "/api/v1/admin/merchants/99999/domains", headers=admin_headers, json={"domain": "test.example.com", "is_primary": True}, ) assert response.status_code == 404 def test_list_merchant_domains( self, client, admin_headers, test_merchant, db ): """Test GET list merchant domains returns 200.""" unique_id = str(uuid.uuid4())[:8] domain = MerchantDomain( merchant_id=test_merchant.id, domain=f"list{unique_id}.example.com", verification_token=f"list_{unique_id}", ) db.add(domain) db.commit() response = client.get( f"/api/v1/admin/merchants/{test_merchant.id}/domains", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert data["total"] >= 1 domain_names = [d["domain"] for d in data["domains"]] assert f"list{unique_id}.example.com" in domain_names def test_get_domain_detail(self, client, admin_headers, test_merchant, db): """Test GET domain detail returns 200.""" unique_id = str(uuid.uuid4())[:8] domain = MerchantDomain( merchant_id=test_merchant.id, domain=f"detail{unique_id}.example.com", verification_token=f"det_{unique_id}", ) db.add(domain) db.commit() db.refresh(domain) response = client.get( f"/api/v1/admin/merchants/domains/merchant/{domain.id}", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert data["id"] == domain.id assert data["domain"] == f"detail{unique_id}.example.com" def test_update_domain(self, client, admin_headers, test_merchant, db): """Test PUT update domain returns 200.""" unique_id = str(uuid.uuid4())[:8] domain = MerchantDomain( merchant_id=test_merchant.id, domain=f"update{unique_id}.example.com", is_verified=True, verified_at=datetime.now(UTC), is_active=False, is_primary=False, verification_token=f"upd_{unique_id}", ) db.add(domain) db.commit() db.refresh(domain) response = client.put( f"/api/v1/admin/merchants/domains/merchant/{domain.id}", headers=admin_headers, json={"is_active": True, "is_primary": True}, ) assert response.status_code == 200 data = response.json() assert data["is_active"] is True assert data["is_primary"] is True def test_update_activate_unverified_domain( self, client, admin_headers, test_merchant, db ): """Test PUT activate unverified domain returns 400.""" unique_id = str(uuid.uuid4())[:8] domain = MerchantDomain( merchant_id=test_merchant.id, domain=f"unver{unique_id}.example.com", is_verified=False, is_active=False, verification_token=f"unv_{unique_id}", ) db.add(domain) db.commit() db.refresh(domain) response = client.put( f"/api/v1/admin/merchants/domains/merchant/{domain.id}", headers=admin_headers, json={"is_active": True}, ) assert response.status_code == 400 data = response.json() assert data["error_code"] == "DOMAIN_NOT_VERIFIED" def test_delete_domain(self, client, admin_headers, test_merchant, db): """Test DELETE domain returns 200.""" unique_id = str(uuid.uuid4())[:8] domain = MerchantDomain( merchant_id=test_merchant.id, domain=f"del{unique_id}.example.com", verification_token=f"del_{unique_id}", ) db.add(domain) db.commit() db.refresh(domain) response = client.delete( f"/api/v1/admin/merchants/domains/merchant/{domain.id}", headers=admin_headers, ) assert response.status_code == 200 data = response.json() assert "deleted" in data["message"].lower() assert data["merchant_id"] == test_merchant.id def test_non_admin_access(self, client, auth_headers, test_merchant): """Test non-admin access returns 403.""" response = client.get( f"/api/v1/admin/merchants/{test_merchant.id}/domains", headers=auth_headers, ) assert response.status_code == 403