"""Regression: ``IntegrationResponse.effective_capabilities`` must fall back to the cmdb provider class's ``supported_capabilities()`` when the admin-set ``capabilities`` column is blank. Prod incident 2026-06-01: the AWS integration row in prod had ``capabilities=NULL`` (admin never explicitly opted into the cloud sync capability list). The integrations list endpoint returned ``capabilities=null`` verbatim — every FE feature gate that checks ``provider.capabilities.includes('dns_records')`` then silently filtered AWS out, and the CloudDnsPage's "first capable provider" fallback picked AliCloud (海外) for unrelated zones. This test pins the fix: any cloud integration with a registered driver advertises its driver's capabilities via ``effective_capabilities`` regardless of the ``capabilities`` column state, so FE feature gates see the same set the cron scheduler sees (``resolve_sync_capabilities`` is the shared source). """ from __future__ import annotations import uuid import pytest from sqlalchemy.ext.asyncio import AsyncSession from app.integrations.models import Integration from app.integrations.service import IntegrationService @pytest.mark.asyncio async def test_effective_capabilities_falls_back_to_driver_when_null( db_session: AsyncSession, ): """``capabilities=NULL`` → ``effective_capabilities`` = driver default. The AWS prod symptom.""" integ = Integration( id=uuid.uuid4(), kind="cloud", provider="aws", name=f"pytest-aws-{uuid.uuid4().hex[:8]}", slug=f"pytest-aws-{uuid.uuid4().hex[:8]}", enabled=True, is_primary=False, # capabilities deliberately omitted — None in the JSON column ) db_session.add(integ) await db_session.commit() svc = IntegrationService(db_session) items = await svc.list(kind="cloud") item = next(i for i in items if i.id == integ.id) assert item.capabilities is None, ( "raw column should still surface NULL — admin editor needs " "to know nothing's saved yet" ) # AWS driver declares dns_records / servers / domains / iam etc. # The exact set is the driver's call; we just assert dns_records # is in there (the DNS picker depends on this). assert "dns_records" in item.effective_capabilities, ( "AWS driver supports dns_records via the Route53 surface — " "effective_capabilities must surface it so the DNS picker " "doesn't silently filter AWS out" ) @pytest.mark.asyncio async def test_effective_capabilities_honors_admin_override( db_session: AsyncSession, ): """When admin explicitly sets a subset, ``effective_capabilities`` reflects that subset (not the driver's full default).""" integ = Integration( id=uuid.uuid4(), kind="cloud", provider="aws", name=f"pytest-aws-{uuid.uuid4().hex[:8]}", slug=f"pytest-aws-{uuid.uuid4().hex[:8]}", enabled=True, is_primary=False, # Admin scoped to IAM-only — common pattern for read-only roles. capabilities=["iam"], ) db_session.add(integ) await db_session.commit() svc = IntegrationService(db_session) items = await svc.list(kind="cloud") item = next(i for i in items if i.id == integ.id) assert item.effective_capabilities == ["iam"] # Driver default INCLUDES dns_records but admin said no — must # NOT leak through. Otherwise the override is meaningless. assert "dns_records" not in item.effective_capabilities @pytest.mark.asyncio async def test_effective_capabilities_empty_for_non_cloud_kind( db_session: AsyncSession, ): """Non-cloud integrations (feishu, slack, etc.) have no cmdb provider class — ``effective_capabilities`` returns [] cleanly without raising.""" integ = Integration( id=uuid.uuid4(), kind="chat_approval", provider="feishu", name=f"pytest-feishu-{uuid.uuid4().hex[:8]}", slug=f"pytest-feishu-{uuid.uuid4().hex[:8]}", enabled=True, is_primary=False, ) db_session.add(integ) await db_session.commit() svc = IntegrationService(db_session) items = await svc.list(kind="chat_approval") item = next(i for i in items if i.id == integ.id) assert item.effective_capabilities == []