@@ -1672,3 +1672,333 @@ def mock_run(command, ok_message=None, error_message=None, **kwargs):
16721672
16731673 # Should handle malformed responses gracefully without raising exceptions
16741674 infrastructures ._cleanup_resources ('test-deployment' , 'test-rg' )
1675+
1676+ # ==============================
1677+ # ENHANCED COVERAGE TESTS
1678+ # ==============================
1679+
1680+ def test_appgw_apim_infrastructure_bicep_parameters (mock_utils ):
1681+ """Test APPGW-APIM-PE specific Bicep parameters."""
1682+ # Test with custom APIs (should enable ACA)
1683+ custom_apis = [
1684+ API ('test-api' , 'Test API' , '/test' , 'Test API description' )
1685+ ]
1686+
1687+ infra = infrastructures .AppGwApimPeInfrastructure (
1688+ rg_location = 'eastus' ,
1689+ index = 1 ,
1690+ apim_sku = APIM_SKU .STANDARDV2 ,
1691+ infra_apis = custom_apis
1692+ )
1693+
1694+ # Initialize components
1695+ infra ._define_policy_fragments ()
1696+ infra ._define_apis ()
1697+
1698+ bicep_params = infra ._define_bicep_parameters ()
1699+
1700+ # Check APPGW-specific parameters
1701+ assert 'apimPublicAccess' in bicep_params
1702+ assert bicep_params ['apimPublicAccess' ]['value' ] is True
1703+ assert 'useACA' in bicep_params
1704+ assert bicep_params ['useACA' ]['value' ] is True # Should be True due to custom APIs
1705+
1706+
1707+ def test_appgw_apim_internal_infrastructure_parameters (mock_utils ):
1708+ """Test APPGW-APIM (Internal) specific parameters."""
1709+ infra = infrastructures .AppGwApimInfrastructure (
1710+ rg_location = 'eastus' ,
1711+ index = 1 ,
1712+ apim_sku = APIM_SKU .DEVELOPER
1713+ )
1714+
1715+ # Verify network mode is INTERNAL_VNET
1716+ assert infra .networkMode == APIMNetworkMode .INTERNAL_VNET
1717+
1718+ # Verify SKU defaults to DEVELOPER
1719+ assert infra .apim_sku == APIM_SKU .DEVELOPER
1720+
1721+
1722+ def test_infrastructure_resource_suffix_generation (mock_utils , mock_az ):
1723+ """Test that resource suffix is properly generated and stored."""
1724+ mock_az .get_unique_suffix_for_resource_group .return_value = 'test123abc'
1725+
1726+ infra = infrastructures .Infrastructure (
1727+ infra = INFRASTRUCTURE .SIMPLE_APIM ,
1728+ index = 1 ,
1729+ rg_location = 'eastus'
1730+ )
1731+
1732+ assert infra .resource_suffix == 'test123abc'
1733+ mock_az .get_unique_suffix_for_resource_group .assert_called_once ()
1734+
1735+
1736+ def test_infrastructure_account_info_retrieval (mock_utils , mock_az ):
1737+ """Test that account info is properly retrieved and stored."""
1738+ mock_az .get_account_info .return_value = (
1739+ 'test-user' , 'user-id-123' , 'tenant-id-456' , 'subscription-id-789'
1740+ )
1741+
1742+ infra = infrastructures .Infrastructure (
1743+ infra = INFRASTRUCTURE .APIM_ACA ,
1744+ index = 1 ,
1745+ rg_location = 'westus2'
1746+ )
1747+
1748+ assert infra .current_user == 'test-user'
1749+ assert infra .current_user_id == 'user-id-123'
1750+ assert infra .tenant_id == 'tenant-id-456'
1751+ assert infra .subscription_id == 'subscription-id-789'
1752+
1753+
1754+ def test_infrastructure_policy_fragments_ordering (mock_utils ):
1755+ """Test that policy fragments are properly ordered (base + custom)."""
1756+ custom_pf = PolicyFragment ('Custom-PF' , '<policy>custom</policy>' , 'Custom policy fragment' )
1757+
1758+ infra = infrastructures .Infrastructure (
1759+ infra = INFRASTRUCTURE .SIMPLE_APIM ,
1760+ index = 1 ,
1761+ rg_location = 'eastus' ,
1762+ infra_pfs = [custom_pf ]
1763+ )
1764+
1765+ pfs = infra ._define_policy_fragments ()
1766+
1767+ # Verify base fragments come before custom
1768+ base_names = [pf .name for pf in infra .base_pfs ]
1769+ custom_names = [pf .name for pf in [custom_pf ]]
1770+
1771+ pf_names = [pf .name for pf in pfs ]
1772+
1773+ # Find indices
1774+ base_indices = [pf_names .index (name ) for name in base_names if name in pf_names ]
1775+ custom_indices = [pf_names .index (name ) for name in custom_names if name in pf_names ]
1776+
1777+ # Last base should come before first custom
1778+ if base_indices and custom_indices :
1779+ assert max (base_indices ) < min (custom_indices )
1780+
1781+
1782+ def test_infrastructure_api_hello_world_always_present (mock_utils ):
1783+ """Test that hello-world API is always present in base APIs."""
1784+ # Test without custom APIs
1785+ infra1 = infrastructures .SimpleApimInfrastructure (
1786+ rg_location = 'eastus' ,
1787+ index = 1
1788+ )
1789+ infra1 ._define_apis ()
1790+ assert any (api .name == 'hello-world' for api in infra1 .base_apis )
1791+
1792+ # Test with custom APIs
1793+ custom_api = API ('custom-api' , 'Custom API' , '/custom' , 'Custom API' )
1794+ infra2 = infrastructures .SimpleApimInfrastructure (
1795+ rg_location = 'eastus' ,
1796+ index = 1 ,
1797+ infra_apis = [custom_api ]
1798+ )
1799+ infra2 ._define_apis ()
1800+ assert any (api .name == 'hello-world' for api in infra2 .base_apis )
1801+ assert any (api .name == 'custom-api' for api in infra2 .apis )
1802+
1803+
1804+ def test_afd_apim_infrastructure_private_link_handling (mock_utils , mock_az ):
1805+ """Test AFD-APIM-PE infrastructure private link handling."""
1806+ infra = infrastructures .AfdApimAcaInfrastructure (
1807+ rg_location = 'eastus' ,
1808+ index = 1
1809+ )
1810+
1811+ # Mock private endpoint connection list with single pending connection
1812+ pending_connection = {
1813+ 'id' : '/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/privateEndpointConnections/conn1' ,
1814+ 'name' : 'conn1' ,
1815+ 'properties' : {'privateLinkServiceConnectionState' : {'status' : 'Pending' }}
1816+ }
1817+
1818+ mock_az .run .return_value = Mock (
1819+ success = True ,
1820+ json_data = [pending_connection ],
1821+ is_json = True
1822+ )
1823+
1824+ result = infra ._approve_private_link_connections ('/subscriptions/sub/resourceGroups/rg/providers/Microsoft.ApiManagement/service/test-apim' )
1825+
1826+ # Verify approval was attempted and succeeded
1827+ assert mock_az .run .call_count >= 1
1828+ assert result is True
1829+
1830+
1831+ def test_appgw_apim_pe_infrastructure_keyvault_creation (mock_utils , mock_az ):
1832+ """Test APPGW-APIM-PE infrastructure Key Vault creation."""
1833+ infra = infrastructures .AppGwApimPeInfrastructure (
1834+ rg_location = 'eastus' ,
1835+ index = 1
1836+ )
1837+
1838+ # Mock Key Vault doesn't exist
1839+ mock_az .run .return_value = Mock (success = False )
1840+
1841+ result = infra ._create_keyvault ('test-kv' )
1842+
1843+ # Should attempt to create Key Vault when it doesn't exist
1844+ assert not result # Will fail due to mocking, but should attempt creation
1845+
1846+
1847+ def test_appgw_apim_certificate_properties ():
1848+ """Test APPGW-APIM certificate configuration."""
1849+ # Test that certificate constants are properly defined
1850+ assert infrastructures .AppGwApimPeInfrastructure .CERT_NAME == 'appgw-cert'
1851+ assert infrastructures .AppGwApimPeInfrastructure .DOMAIN_NAME == 'api.apim-samples.contoso.com'
1852+
1853+ # Test AppGwApimInfrastructure also has the same constants
1854+ assert infrastructures .AppGwApimInfrastructure .CERT_NAME == 'appgw-cert'
1855+ assert infrastructures .AppGwApimInfrastructure .DOMAIN_NAME == 'api.apim-samples.contoso.com'
1856+
1857+
1858+ def test_infrastructure_concrete_class_sku_inheritance ():
1859+ """Test that concrete infrastructure classes properly inherit and default SKUs."""
1860+ simple = infrastructures .SimpleApimInfrastructure ('eastus' , 1 )
1861+ assert simple .apim_sku == APIM_SKU .BASICV2
1862+
1863+ aca = infrastructures .ApimAcaInfrastructure ('eastus' , 1 )
1864+ assert aca .apim_sku == APIM_SKU .BASICV2
1865+
1866+ afd = infrastructures .AfdApimAcaInfrastructure ('eastus' , 1 )
1867+ assert afd .apim_sku == APIM_SKU .BASICV2
1868+
1869+ appgw_pe = infrastructures .AppGwApimPeInfrastructure ('eastus' , 1 )
1870+ assert appgw_pe .apim_sku == APIM_SKU .BASICV2
1871+
1872+ appgw = infrastructures .AppGwApimInfrastructure ('eastus' , 1 )
1873+ assert appgw .apim_sku == APIM_SKU .DEVELOPER # This one defaults to DEVELOPER
1874+
1875+
1876+ def test_cleanup_single_resource_exception_handling (monkeypatch ):
1877+ """Test _cleanup_single_resource exception handling."""
1878+ def mock_run (command , ok_message = None , error_message = None ):
1879+ raise Exception ("Test exception" )
1880+
1881+ monkeypatch .setattr (infrastructures .az , 'run' , mock_run )
1882+
1883+ resource = {
1884+ 'type' : 'apim' ,
1885+ 'name' : 'test-apim' ,
1886+ 'location' : 'eastus' ,
1887+ 'rg_name' : 'test-rg'
1888+ }
1889+
1890+ success , error_msg = infrastructures ._cleanup_single_resource (resource )
1891+
1892+ assert success is False
1893+ assert "Test exception" in error_msg
1894+
1895+
1896+ def test_cleanup_resources_with_all_resource_types (monkeypatch ):
1897+ """Test cleanup with a mix of all resource types."""
1898+ run_commands = []
1899+
1900+ def mock_run (command , ok_message = None , error_message = None , ** kwargs ):
1901+ run_commands .append (command )
1902+
1903+ # Mock deployment show response
1904+ if 'deployment group show' in command :
1905+ return Output (success = True , text = '{"properties": {}}' )
1906+
1907+ # Mock lists returning one of each resource type
1908+ if 'cognitiveservices account list' in command :
1909+ return Output (success = True , text = '[{"name": "cog-1", "location": "eastus"}]' )
1910+
1911+ if 'apim list' in command :
1912+ return Output (success = True , text = '[{"name": "apim-1", "location": "eastus"}]' )
1913+
1914+ if 'keyvault list' in command :
1915+ return Output (success = True , text = '[{"name": "kv-1", "location": "eastus"}]' )
1916+
1917+ # Default successful response
1918+ return Output (success = True , text = '{}' )
1919+
1920+ monkeypatch .setattr (infrastructures .az , 'run' , mock_run )
1921+ monkeypatch .setattr (console , 'print_info' , lambda * a , ** kw : None )
1922+ monkeypatch .setattr (console , 'print_message' , lambda * a , ** kw : None )
1923+
1924+ infrastructures ._cleanup_resources ('test-deployment' , 'test-rg' )
1925+
1926+ # Verify all resource types were processed
1927+ all_commands = ' ' .join (run_commands )
1928+ assert 'cognitiveservices' in all_commands
1929+ assert 'apim' in all_commands
1930+ assert 'keyvault' in all_commands
1931+
1932+
1933+ def test_infrastructure_initialization_error_handling (mock_utils , mock_az ):
1934+ """Test infrastructure initialization with mock errors."""
1935+ # Test with resource group creation failure
1936+ mock_az .create_resource_group .side_effect = Exception ("RG creation failed" )
1937+
1938+ with pytest .raises (Exception ):
1939+ infrastructures .Infrastructure (
1940+ infra = INFRASTRUCTURE .SIMPLE_APIM ,
1941+ index = 1 ,
1942+ rg_location = 'eastus'
1943+ )
1944+
1945+
1946+ def test_policy_fragment_list_serialization (mock_utils ):
1947+ """Test that policy fragments serialize correctly for Bicep."""
1948+ custom_pf = PolicyFragment (
1949+ name = 'Test-PF' ,
1950+ policyXml = '<policy>test</policy>' ,
1951+ description = 'Test policy fragment'
1952+ )
1953+
1954+ infra = infrastructures .Infrastructure (
1955+ infra = INFRASTRUCTURE .SIMPLE_APIM ,
1956+ index = 1 ,
1957+ rg_location = 'eastus' ,
1958+ infra_pfs = [custom_pf ]
1959+ )
1960+
1961+ infra ._define_policy_fragments ()
1962+ infra ._define_apis ()
1963+ infra ._define_bicep_parameters ()
1964+
1965+ # Verify policy fragments are in Bicep parameters
1966+ assert 'policyFragments' in infra .bicep_parameters
1967+ pf_values = infra .bicep_parameters ['policyFragments' ]['value' ]
1968+
1969+ # Should include both base and custom
1970+ assert len (pf_values ) == 7 # 6 base + 1 custom
1971+
1972+
1973+ def test_api_serialization_for_bicep (mock_utils ):
1974+ """Test that APIs serialize correctly for Bicep."""
1975+ custom_api = API (
1976+ name = 'test-api' ,
1977+ displayName = 'Test API' ,
1978+ path = '/test' ,
1979+ description = 'Test API' ,
1980+ policyXml = '<policy></policy>'
1981+ )
1982+
1983+ infra = infrastructures .Infrastructure (
1984+ infra = INFRASTRUCTURE .SIMPLE_APIM ,
1985+ index = 1 ,
1986+ rg_location = 'eastus' ,
1987+ infra_apis = [custom_api ]
1988+ )
1989+
1990+ infra ._define_policy_fragments ()
1991+ infra ._define_apis ()
1992+ infra ._define_bicep_parameters ()
1993+
1994+ # Verify APIs are in Bicep parameters
1995+ assert 'apis' in infra .bicep_parameters
1996+ api_values = infra .bicep_parameters ['apis' ]['value' ]
1997+
1998+ # Should include both base (hello-world) and custom
1999+ assert len (api_values ) == 2
2000+
2001+ # Verify serialization includes required fields
2002+ api_names = [api .get ('name' ) if isinstance (api , dict ) else api ['name' ] for api in api_values ]
2003+ assert 'hello-world' in api_names
2004+ assert 'test-api' in api_names
0 commit comments