From c7a3274dc4afa7449a111d7525c4626260778e9f Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 13:42:29 +0100 Subject: [PATCH 01/22] Added space workaround --- utilities/pipelines/staticValidation/module.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 28f9f8e005..52b57b1526 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -824,7 +824,7 @@ Describe 'Deployment template tests' -Tag 'Template' { $ApiVersionArray | Should -Not -Contain $false } - It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources`' -TestCases $deploymentFolderTestCases { + It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { param( [string] $moduleFolderName, From 52a020f853d1816223e24f1fe71f09a0d71e3009 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 14:21:57 +0100 Subject: [PATCH 02/22] Update to latest --- utilities/pipelines/staticValidation/module.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 52b57b1526..50f1a5b094 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -3,7 +3,7 @@ param ( [Parameter(Mandatory = $false)] [array] $moduleFolderPaths = ((Get-ChildItem $repoRootPath -Recurse -Directory -Force).FullName | Where-Object { - (Get-ChildItem $_ -File -Depth 0 -Include @('deploy.json', 'deploy.bicep') -Force).Count -gt 0 + (Get-ChildItem $_ -File -Depth 0 -Include @('deploy.json', 'deploy.bicep') -Force).Count -gt 0 }), [Parameter(Mandatory = $false)] From d3e9f08dfcdbd2f9a939bbbabe246e25e72e20f7 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:08:39 +0100 Subject: [PATCH 03/22] Update to latest --- utilities/pipelines/staticValidation/module.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 50f1a5b094..0c0759253e 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -1154,7 +1154,7 @@ Describe 'Deployment template tests' -Tag 'Template' { } } -Describe 'API version tests' -Tag ApiCheck { +Describe 'API version tests' -Tag 'ApiCheck' { $testCases = @() $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' From 76012735336059e38bc07269e69ec776ee9a406a Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:12:29 +0100 Subject: [PATCH 04/22] Disabled tests --- .../staticValidation/module.tests.ps1 | 1308 ++++++++--------- 1 file changed, 654 insertions(+), 654 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 0c0759253e..f80a8c96d8 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -672,657 +672,657 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } -Describe 'Deployment template tests' -Tag 'Template' { - - Context 'General template' { - - $deploymentFolderTestCases = [System.Collections.ArrayList] @() - foreach ($moduleFolderPath in $moduleFolderPaths) { - - # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key - $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') - if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { - if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' - $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($bicepTemplateCompilationFailedException -f $templateFilePath) - } - } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } else { - throw ($templateNotFoundException -f $moduleFolderPath) - } - $convertedTemplates[$moduleFolderPathKey] = @{ - templateFilePath = $templateFilePath - templateContent = $templateContent - } - } else { - $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent - $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath - } - - # Parameter file test cases - $testFileTestCases = @() - $templateFile_Parameters = $templateContent.parameters - $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object - $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object - - if (Test-Path (Join-Path $moduleFolderPath '.test')) { - - # Can be removed after full migration to bicep test files - $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } - - foreach ($moduleTestFilePath in $moduleTestFilePaths) { - if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { - - $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable - - # Skipping any file that is not actually a ARM-JSON parameter file - $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' - if (-not $isParameterFile) { - continue - } - - $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object - } else { - $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable - $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test - } - $testFileTestCases += @{ - testFile_Path = $moduleTestFilePath - testFile_Name = Split-Path $moduleTestFilePath -Leaf - testFile_AllParameterNames = $deploymentTestFile_AllParameterNames - templateFile_AllParameterNames = $TemplateFile_AllParameterNames - templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames - tokenConfiguration = $tokenConfiguration - } - } - } - - # Test file setup - $deploymentFolderTestCases += @{ - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - templateContent = $templateContent - templateFilePath = $templateFilePath - testFileTestCases = $testFileTestCases - } - } - - It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $templateContent | Should -Not -Be $null - } - - It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { - # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! - # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - - $Schemaverion = $templateContent.'$schema' - $SchemaArray = @() - if ($Schemaverion -eq $RGdeployment) { - $SchemaOutput = $true - } elseIf ($Schemaverion -eq $Subscriptiondeployment) { - $SchemaOutput = $true - } elseIf ($Schemaverion -eq $MGdeployment) { - $SchemaOutput = $true - } elseIf ($Schemaverion -eq $Tenantdeployment) { - $SchemaOutput = $true - } else { - $SchemaOutput = $false - } - $SchemaArray += $SchemaOutput - $SchemaArray | Should -Not -Contain $false - } - - It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $Schemaverion = $templateContent.'$schema' - ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true - } - - It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { - #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $ApiVersion = $templateContent.resources.apiVersion - $ApiVersionArray = @() - foreach ($API in $ApiVersion) { - if ($API.Substring(0, 2) -eq '20') { - $ApiVersionOutput = $true - } elseIf ($API.substring(1, 10) -eq 'parameters') { - # An API version should not be referenced as a parameter - $ApiVersionOutput = $false - } elseIf ($API.substring(1, 10) -eq 'variables') { - # An API version should not be referenced as a variable - $ApiVersionOutput = $false - } else { - $ApiVersionOutput = $false - } - $ApiVersionArray += $ApiVersionOutput - } - $ApiVersionArray | Should -Not -Contain $false - } - - It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $templateContent.Keys | Should -Contain '$schema' - $templateContent.Keys | Should -Contain 'contentVersion' - $templateContent.Keys | Should -Contain 'resources' - } - - It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - if ($lock = $templateContent.parameters.lock) { - $lock.Keys | Should -Contain 'defaultValue' - $lock.defaultValue | Should -Be '' - } - } - - It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - - if (-not $templateContent.parameters) { - Set-ItResult -Skipped -Because 'the module template has no parameters.' - return - } - - $CamelCasingFlag = @() - $Parameter = $templateContent.parameters.Keys - foreach ($Param in $Parameter) { - if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { - $CamelCasingFlag += $false - } else { - $CamelCasingFlag += $true - } - } - $CamelCasingFlag | Should -Not -Contain $false - } - - It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - - if (-not $templateContent.variables) { - Set-ItResult -Skipped -Because 'the module template has no variables.' - return - } - - $CamelCasingFlag = @() - $Variable = $templateContent.variables.Keys - - foreach ($Variab in $Variable) { - if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { - $CamelCasingFlag += $false - } else { - $CamelCasingFlag += $true - } - } - $CamelCasingFlag | Should -Not -Contain $false - } - - It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $CamelCasingFlag = @() - $Outputs = $templateContent.outputs.Keys - - foreach ($Output in $Outputs) { - if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { - $CamelCasingFlag += $false - } else { - $CamelCasingFlag += $true - } - } - $CamelCasingFlag | Should -Not -Contain $false - } - - It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $enableDefaultTelemetryFlag = @() - $Schemaverion = $templateContent.'$schema' - if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { - if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { - $enableDefaultTelemetryFlag += $true - } else { - $enableDefaultTelemetryFlag += $false - } - } - $enableDefaultTelemetryFlag | Should -Not -Contain $false - } - - It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $LocationFlag = $true - $Schemaverion = $templateContent.'$schema' - if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { - $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue - $Locationparamoutput = $templateContent.parameters.Keys - if ($Locationparamoutput -contains 'Location') { - if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { - $LocationFlag = $true - } else { - - $LocationFlag = $false - } - $LocationFlag | Should -Contain $true - } - } - } - - It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [string] $templateFilePath - ) - - $outputs = $templateContent.outputs - - $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] - $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } - - if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { - # If the main resource has a location property, an output should be returned too - $outputs.keys | Should -Contain 'location' - - # It should further reference the location property of the primary resource and not e.g. the location input parameter - $outputs.location.value | Should -Match $primaryResourceType - } - } - - It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [string] $templateFilePath - ) - - $outputs = $templateContent.outputs.Keys - $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath - - if ($deploymentScope -eq 'resourceGroup') { - $outputs | Should -Contain 'resourceGroupName' - } - } - - It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - $templateFilePath - ) - - # check if module contains a 'primary' resource we could draw a name from - $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' - if ($templateContent.resources.type -notcontains $moduleResourceType) { - Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' - return - } - - # Otherwise test for standard outputs - $outputs = $templateContent.outputs.Keys - $outputs | Should -Contain 'name' - } - - It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - $templateFilePath - ) - - # check if module contains a 'primary' resource we could draw a name from - $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' - if ($templateContent.resources.type -notcontains $moduleResourceType) { - Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' - return - } - - # Otherwise test for standard outputs - $outputs = $templateContent.outputs.Keys - $outputs | Should -Contain 'resourceId' - } - - It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - - if (-not $templateContent.parameters) { - Set-ItResult -Skipped -Because 'the module template has no parameters.' - return - } - - $incorrectParameters = @() - $templateParameters = $templateContent.parameters.Keys - foreach ($parameter in $templateParameters) { - $data = ($templateContent.parameters.$parameter.metadata).description - if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { - $incorrectParameters += $parameter - } - } - $incorrectParameters | Should -BeNullOrEmpty - } - - It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - - if (-not $templateContent.parameters) { - Set-ItResult -Skipped -Because 'the module template has no parameters.' - return - } - - $incorrectParameters = @() - $templateParameters = $templateContent.parameters.Keys - foreach ($parameter in $templateParameters) { - $data = ($templateContent.parameters.$parameter.metadata).description - switch -regex ($data) { - '^Conditional. .*' { - if ($data -notmatch '.*\. Required if .*') { - $incorrectParameters += $parameter - } - } - } - } - $incorrectParameters | Should -BeNullOrEmpty - } - - It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { - - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - - if (-not $templateContent.outputs) { - Set-ItResult -Skipped -Because 'the module template has no outputs.' - return - } - - $incorrectOutputs = @() - $templateOutputs = $templateContent.outputs.Keys - foreach ($output in $templateOutputs) { - $data = ($templateContent.outputs.$output.metadata).description - if ($data -notmatch '(?s)^[A-Z].+\.$') { - $incorrectOutputs += $output - } - } - $incorrectOutputs | Should -BeNullOrEmpty - } - - # PARAMETER Tests - It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { - param ( - [hashtable[]] $testFileTestCases - ) - - foreach ($parameterFileTestCase in $testFileTestCases) { - $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames - $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames - - $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } - $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) - } - } - - It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { - param ( - [hashtable[]] $testFileTestCases - ) - - foreach ($parameterFileTestCase in $testFileTestCases) { - $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames - $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames - - $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } - $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) - } - } - - It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { - param ( - [hashtable[]] $testFileTestCases, - [hashtable] $templateContent - ) - - foreach ($parameterFileTestCase in $testFileTestCases) { - $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames - $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames - $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } - - $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } - $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) - } - } - } -} - -Describe 'API version tests' -Tag 'ApiCheck' { - - $testCases = @() - $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' - - if (-not (Test-Path $apiSpecsFilePath)) { - Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" - return - } - - $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json - foreach ($moduleFolderPath in $moduleFolderPaths) { - - $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - - # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key - $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') - if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { - if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' - $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($bicepTemplateCompilationFailedException -f $templateFilePath) - } - } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } else { - throw ($templateNotFoundException -f $moduleFolderPath) - } - $convertedTemplates[$moduleFolderPathKey] = @{ - templateFilePath = $templateFilePath - templateContent = $templateContent - } - } else { - $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent - $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath - } - - $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { - $_.type -notin @('Microsoft.Resources/deployments') -and $_ - } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type - - foreach ($resource in $nestedResources) { - - switch ($resource.type) { - { $PSItem -like '*diagnosticsettings*' } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'diagnosticsettings' - ProviderNamespace = 'Microsoft.insights' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - { $PSItem -like '*locks' } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'locks' - ProviderNamespace = 'Microsoft.Authorization' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - { $PSItem -like '*roleAssignments' } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'roleassignments' - ProviderNamespace = 'Microsoft.Authorization' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'privateEndpoints' - ProviderNamespace = 'Microsoft.Network' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - Default { - $ProviderNamespace, $rest = $resource.Type.Split('/') - $testCases += @{ - moduleName = $moduleFolderName - resourceType = $rest -join '/' - ProviderNamespace = $ProviderNamespace - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - } - } - } - - It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { - - param( - [string] $moduleName, - [string] $ResourceType, - [string] $TargetApi, - [string] $ProviderNamespace, - [PSCustomObject] $AvailableApiVersions, - [bool] $AllowPreviewVersionsInAPITests - ) - - if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { - Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." - Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." - return - } - if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { - Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." - Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." - return - } - - $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType - - if (-not $resourceTypeApiVersions) { - Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) - continue - } - - $approvedApiVersions = @() - if ($AllowPreviewVersionsInAPITests) { - # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview - $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 - $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 - } else { - # We allow the latest 3 non-preview preview - $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 - } - - $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending - $approvedApiVersions | Should -Contain $TargetApi - - # Provide a warning if an API version is second to next to expire. - if ($approvedApiVersions -contains $TargetApi) { - $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) - - # Example - # Available versions: - # - # 2017-08-01-beta - # 2017-08-01 < $TargetApi (Index = 1) - # 2017-07-14 - # 2016-05-16 - - if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { - $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] - Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) - } - } - } -} +# Describe 'Deployment template tests' -Tag 'Template' { + +# Context 'General template' { + +# $deploymentFolderTestCases = [System.Collections.ArrayList] @() +# foreach ($moduleFolderPath in $moduleFolderPaths) { + +# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key +# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') +# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { +# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' +# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + +# if (-not $templateContent) { +# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) +# } +# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' +# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + +# if (-not $templateContent) { +# throw ($jsonTemplateLoadFailedException -f $templateFilePath) +# } +# } else { +# throw ($templateNotFoundException -f $moduleFolderPath) +# } +# $convertedTemplates[$moduleFolderPathKey] = @{ +# templateFilePath = $templateFilePath +# templateContent = $templateContent +# } +# } else { +# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent +# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath +# } + +# # Parameter file test cases +# $testFileTestCases = @() +# $templateFile_Parameters = $templateContent.parameters +# $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object +# $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object + +# if (Test-Path (Join-Path $moduleFolderPath '.test')) { + +# # Can be removed after full migration to bicep test files +# $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + +# foreach ($moduleTestFilePath in $moduleTestFilePaths) { +# if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { + +# $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable + +# # Skipping any file that is not actually a ARM-JSON parameter file +# $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' +# if (-not $isParameterFile) { +# continue +# } + +# $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object +# } else { +# $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable +# $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test +# } +# $testFileTestCases += @{ +# testFile_Path = $moduleTestFilePath +# testFile_Name = Split-Path $moduleTestFilePath -Leaf +# testFile_AllParameterNames = $deploymentTestFile_AllParameterNames +# templateFile_AllParameterNames = $TemplateFile_AllParameterNames +# templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames +# tokenConfiguration = $tokenConfiguration +# } +# } +# } + +# # Test file setup +# $deploymentFolderTestCases += @{ +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# templateContent = $templateContent +# templateFilePath = $templateFilePath +# testFileTestCases = $testFileTestCases +# } +# } + +# It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $templateContent | Should -Not -Be $null +# } + +# It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { +# # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! +# # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) + +# $Schemaverion = $templateContent.'$schema' +# $SchemaArray = @() +# if ($Schemaverion -eq $RGdeployment) { +# $SchemaOutput = $true +# } elseIf ($Schemaverion -eq $Subscriptiondeployment) { +# $SchemaOutput = $true +# } elseIf ($Schemaverion -eq $MGdeployment) { +# $SchemaOutput = $true +# } elseIf ($Schemaverion -eq $Tenantdeployment) { +# $SchemaOutput = $true +# } else { +# $SchemaOutput = $false +# } +# $SchemaArray += $SchemaOutput +# $SchemaArray | Should -Not -Contain $false +# } + +# It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $Schemaverion = $templateContent.'$schema' +# ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true +# } + +# It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { +# #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $ApiVersion = $templateContent.resources.apiVersion +# $ApiVersionArray = @() +# foreach ($API in $ApiVersion) { +# if ($API.Substring(0, 2) -eq '20') { +# $ApiVersionOutput = $true +# } elseIf ($API.substring(1, 10) -eq 'parameters') { +# # An API version should not be referenced as a parameter +# $ApiVersionOutput = $false +# } elseIf ($API.substring(1, 10) -eq 'variables') { +# # An API version should not be referenced as a variable +# $ApiVersionOutput = $false +# } else { +# $ApiVersionOutput = $false +# } +# $ApiVersionArray += $ApiVersionOutput +# } +# $ApiVersionArray | Should -Not -Contain $false +# } + +# It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $templateContent.Keys | Should -Contain '$schema' +# $templateContent.Keys | Should -Contain 'contentVersion' +# $templateContent.Keys | Should -Contain 'resources' +# } + +# It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# if ($lock = $templateContent.parameters.lock) { +# $lock.Keys | Should -Contain 'defaultValue' +# $lock.defaultValue | Should -Be '' +# } +# } + +# It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) + +# if (-not $templateContent.parameters) { +# Set-ItResult -Skipped -Because 'the module template has no parameters.' +# return +# } + +# $CamelCasingFlag = @() +# $Parameter = $templateContent.parameters.Keys +# foreach ($Param in $Parameter) { +# if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { +# $CamelCasingFlag += $false +# } else { +# $CamelCasingFlag += $true +# } +# } +# $CamelCasingFlag | Should -Not -Contain $false +# } + +# It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) + +# if (-not $templateContent.variables) { +# Set-ItResult -Skipped -Because 'the module template has no variables.' +# return +# } + +# $CamelCasingFlag = @() +# $Variable = $templateContent.variables.Keys + +# foreach ($Variab in $Variable) { +# if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { +# $CamelCasingFlag += $false +# } else { +# $CamelCasingFlag += $true +# } +# } +# $CamelCasingFlag | Should -Not -Contain $false +# } + +# It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $CamelCasingFlag = @() +# $Outputs = $templateContent.outputs.Keys + +# foreach ($Output in $Outputs) { +# if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { +# $CamelCasingFlag += $false +# } else { +# $CamelCasingFlag += $true +# } +# } +# $CamelCasingFlag | Should -Not -Contain $false +# } + +# It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $enableDefaultTelemetryFlag = @() +# $Schemaverion = $templateContent.'$schema' +# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { +# if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { +# $enableDefaultTelemetryFlag += $true +# } else { +# $enableDefaultTelemetryFlag += $false +# } +# } +# $enableDefaultTelemetryFlag | Should -Not -Contain $false +# } + +# It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $LocationFlag = $true +# $Schemaverion = $templateContent.'$schema' +# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { +# $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue +# $Locationparamoutput = $templateContent.parameters.Keys +# if ($Locationparamoutput -contains 'Location') { +# if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { +# $LocationFlag = $true +# } else { + +# $LocationFlag = $false +# } +# $LocationFlag | Should -Contain $true +# } +# } +# } + +# It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [string] $templateFilePath +# ) + +# $outputs = $templateContent.outputs + +# $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] +# $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } + +# if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { +# # If the main resource has a location property, an output should be returned too +# $outputs.keys | Should -Contain 'location' + +# # It should further reference the location property of the primary resource and not e.g. the location input parameter +# $outputs.location.value | Should -Match $primaryResourceType +# } +# } + +# It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [string] $templateFilePath +# ) + +# $outputs = $templateContent.outputs.Keys +# $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath + +# if ($deploymentScope -eq 'resourceGroup') { +# $outputs | Should -Contain 'resourceGroupName' +# } +# } + +# It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# $templateFilePath +# ) + +# # check if module contains a 'primary' resource we could draw a name from +# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' +# if ($templateContent.resources.type -notcontains $moduleResourceType) { +# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' +# return +# } + +# # Otherwise test for standard outputs +# $outputs = $templateContent.outputs.Keys +# $outputs | Should -Contain 'name' +# } + +# It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# $templateFilePath +# ) + +# # check if module contains a 'primary' resource we could draw a name from +# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' +# if ($templateContent.resources.type -notcontains $moduleResourceType) { +# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' +# return +# } + +# # Otherwise test for standard outputs +# $outputs = $templateContent.outputs.Keys +# $outputs | Should -Contain 'resourceId' +# } + +# It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) + +# if (-not $templateContent.parameters) { +# Set-ItResult -Skipped -Because 'the module template has no parameters.' +# return +# } + +# $incorrectParameters = @() +# $templateParameters = $templateContent.parameters.Keys +# foreach ($parameter in $templateParameters) { +# $data = ($templateContent.parameters.$parameter.metadata).description +# if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { +# $incorrectParameters += $parameter +# } +# } +# $incorrectParameters | Should -BeNullOrEmpty +# } + +# It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) + +# if (-not $templateContent.parameters) { +# Set-ItResult -Skipped -Because 'the module template has no parameters.' +# return +# } + +# $incorrectParameters = @() +# $templateParameters = $templateContent.parameters.Keys +# foreach ($parameter in $templateParameters) { +# $data = ($templateContent.parameters.$parameter.metadata).description +# switch -regex ($data) { +# '^Conditional. .*' { +# if ($data -notmatch '.*\. Required if .*') { +# $incorrectParameters += $parameter +# } +# } +# } +# } +# $incorrectParameters | Should -BeNullOrEmpty +# } + +# It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { + +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) + +# if (-not $templateContent.outputs) { +# Set-ItResult -Skipped -Because 'the module template has no outputs.' +# return +# } + +# $incorrectOutputs = @() +# $templateOutputs = $templateContent.outputs.Keys +# foreach ($output in $templateOutputs) { +# $data = ($templateContent.outputs.$output.metadata).description +# if ($data -notmatch '(?s)^[A-Z].+\.$') { +# $incorrectOutputs += $output +# } +# } +# $incorrectOutputs | Should -BeNullOrEmpty +# } + +# # PARAMETER Tests +# It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { +# param ( +# [hashtable[]] $testFileTestCases +# ) + +# foreach ($parameterFileTestCase in $testFileTestCases) { +# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames +# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames + +# $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } +# $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) +# } +# } + +# It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { +# param ( +# [hashtable[]] $testFileTestCases +# ) + +# foreach ($parameterFileTestCase in $testFileTestCases) { +# $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames +# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames + +# $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } +# $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) +# } +# } + +# It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { +# param ( +# [hashtable[]] $testFileTestCases, +# [hashtable] $templateContent +# ) + +# foreach ($parameterFileTestCase in $testFileTestCases) { +# $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames +# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames +# $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } + +# $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } +# $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) +# } +# } +# } +# } + +# Describe 'API version tests' -Tag 'ApiCheck' { + +# $testCases = @() +# $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' + +# if (-not (Test-Path $apiSpecsFilePath)) { +# Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" +# return +# } + +# $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json +# foreach ($moduleFolderPath in $moduleFolderPaths) { + +# $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + +# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key +# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') +# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { +# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' +# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + +# if (-not $templateContent) { +# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) +# } +# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' +# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + +# if (-not $templateContent) { +# throw ($jsonTemplateLoadFailedException -f $templateFilePath) +# } +# } else { +# throw ($templateNotFoundException -f $moduleFolderPath) +# } +# $convertedTemplates[$moduleFolderPathKey] = @{ +# templateFilePath = $templateFilePath +# templateContent = $templateContent +# } +# } else { +# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent +# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath +# } + +# $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { +# $_.type -notin @('Microsoft.Resources/deployments') -and $_ +# } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type + +# foreach ($resource in $nestedResources) { + +# switch ($resource.type) { +# { $PSItem -like '*diagnosticsettings*' } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'diagnosticsettings' +# ProviderNamespace = 'Microsoft.insights' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# { $PSItem -like '*locks' } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'locks' +# ProviderNamespace = 'Microsoft.Authorization' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# { $PSItem -like '*roleAssignments' } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'roleassignments' +# ProviderNamespace = 'Microsoft.Authorization' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'privateEndpoints' +# ProviderNamespace = 'Microsoft.Network' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# Default { +# $ProviderNamespace, $rest = $resource.Type.Split('/') +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = $rest -join '/' +# ProviderNamespace = $ProviderNamespace +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# } +# } +# } + +# It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { + +# param( +# [string] $moduleName, +# [string] $ResourceType, +# [string] $TargetApi, +# [string] $ProviderNamespace, +# [PSCustomObject] $AvailableApiVersions, +# [bool] $AllowPreviewVersionsInAPITests +# ) + +# if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { +# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." +# Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." +# return +# } +# if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { +# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." +# Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." +# return +# } + +# $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType + +# if (-not $resourceTypeApiVersions) { +# Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) +# continue +# } + +# $approvedApiVersions = @() +# if ($AllowPreviewVersionsInAPITests) { +# # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview +# $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 +# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 +# } else { +# # We allow the latest 3 non-preview preview +# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 +# } + +# $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending +# $approvedApiVersions | Should -Contain $TargetApi + +# # Provide a warning if an API version is second to next to expire. +# if ($approvedApiVersions -contains $TargetApi) { +# $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) + +# # Example +# # Available versions: +# # +# # 2017-08-01-beta +# # 2017-08-01 < $TargetApi (Index = 1) +# # 2017-07-14 +# # 2016-05-16 + +# if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { +# $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] +# Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) +# } +# } +# } +# } From 2a0fd10cd3ed7f8cc194d3a7f24bb7b90f369eff Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:16:26 +0100 Subject: [PATCH 05/22] Disabled tests --- .../staticValidation/module.tests.ps1 | 1906 ++++++++--------- 1 file changed, 953 insertions(+), 953 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index f80a8c96d8..bd410210fa 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -158,1171 +158,1171 @@ Describe 'File/folder tests' -Tag 'Modules' { } } } -Describe 'Readme tests' -Tag 'Readme' { +# Describe 'Readme tests' -Tag 'Readme' { - Context 'Readme content tests' { +# Context 'Readme content tests' { - $readmeFolderTestCases = [System.Collections.ArrayList] @() - foreach ($moduleFolderPath in $moduleFolderPaths) { +# $readmeFolderTestCases = [System.Collections.ArrayList] @() +# foreach ($moduleFolderPath in $moduleFolderPaths) { - # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key - $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') - if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { - if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' - $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable +# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key +# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') +# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { +# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' +# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - if (-not $templateContent) { - throw ($bicepTemplateCompilationFailedException -f $templateFilePath) - } - } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable +# if (-not $templateContent) { +# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) +# } +# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' +# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } else { - throw ($templateNotFoundException -f $moduleFolderPath) - } - $convertedTemplates[$moduleFolderPathKey] = @{ - templateFilePath = $templateFilePath - templateContent = $templateContent - } - } else { - $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent - $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath - } +# if (-not $templateContent) { +# throw ($jsonTemplateLoadFailedException -f $templateFilePath) +# } +# } else { +# throw ($templateNotFoundException -f $moduleFolderPath) +# } +# $convertedTemplates[$moduleFolderPathKey] = @{ +# templateFilePath = $templateFilePath +# templateContent = $templateContent +# } +# } else { +# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent +# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath +# } - $resourceTypeIdentifier = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - - $readmeFolderTestCases += @{ - moduleFolderName = $resourceTypeIdentifier - moduleFolderPath = $moduleFolderPath - templateContent = $templateContent - templateFilePath = $templateFilePath - readMeFilePath = Join-Path -Path $moduleFolderPath 'readme.md' - readMeContent = Get-Content (Join-Path -Path $moduleFolderPath 'readme.md') - isTopLevelModule = $resourceTypeIdentifier.Split('/').Count -eq 2 # / - resourceTypeIdentifier = $resourceTypeIdentifier - templateReferences = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] - } - } +# $resourceTypeIdentifier = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + +# $readmeFolderTestCases += @{ +# moduleFolderName = $resourceTypeIdentifier +# moduleFolderPath = $moduleFolderPath +# templateContent = $templateContent +# templateFilePath = $templateFilePath +# readMeFilePath = Join-Path -Path $moduleFolderPath 'readme.md' +# readMeContent = Get-Content (Join-Path -Path $moduleFolderPath 'readme.md') +# isTopLevelModule = $resourceTypeIdentifier.Split('/').Count -eq 2 # / +# resourceTypeIdentifier = $resourceTypeIdentifier +# templateReferences = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] +# } +# } - It '[] `Readme.md` file should not be empty' -TestCases $readmeFolderTestCases { +# It '[] `Readme.md` file should not be empty' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [object[]] $readMeContent - ) - $readMeContent | Should -Not -Be $null - } +# param( +# [string] $moduleFolderName, +# [object[]] $readMeContent +# ) +# $readMeContent | Should -Not -Be $null +# } - It '[] `Readme.md` file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples' -TestCases $readmeFolderTestCases { +# It '[] `Readme.md` file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [object[]] $readMeContent, - [boolean] $isTopLevelModule - ) +# param( +# [string] $moduleFolderName, +# [object[]] $readMeContent, +# [boolean] $isTopLevelModule +# ) - $expectedHeadersInOrder = @('Navigation', 'Resource types', 'Parameters', 'Outputs', 'Cross-referenced modules') +# $expectedHeadersInOrder = @('Navigation', 'Resource types', 'Parameters', 'Outputs', 'Cross-referenced modules') - if ($isTopLevelModule) { - # Only top-level modules have parameter files and hence deployment examples - $expectedHeadersInOrder += 'Deployment examples' - } +# if ($isTopLevelModule) { +# # Only top-level modules have parameter files and hence deployment examples +# $expectedHeadersInOrder += 'Deployment examples' +# } - $actualHeadersInOrder = $readMeContent | Where-Object { $_ -like '#*' } | ForEach-Object { ($_ -replace '#', '').TrimStart() } +# $actualHeadersInOrder = $readMeContent | Where-Object { $_ -like '#*' } | ForEach-Object { ($_ -replace '#', '').TrimStart() } - $filteredActuals = $actualHeadersInOrder | Where-Object { $expectedHeadersInOrder -contains $_ } +# $filteredActuals = $actualHeadersInOrder | Where-Object { $expectedHeadersInOrder -contains $_ } - $missingHeaders = $expectedHeadersInOrder | Where-Object { $actualHeadersInOrder -notcontains $_ } - $missingHeaders.Count | Should -Be 0 -Because ('the list of missing headers [{0}] should be empty' -f ($missingHeaders -join ',')) +# $missingHeaders = $expectedHeadersInOrder | Where-Object { $actualHeadersInOrder -notcontains $_ } +# $missingHeaders.Count | Should -Be 0 -Because ('the list of missing headers [{0}] should be empty' -f ($missingHeaders -join ',')) - $filteredActuals | Should -Be $expectedHeadersInOrder -Because 'the headers should exist in the expected order' - } +# $filteredActuals | Should -Be $expectedHeadersInOrder -Because 'the headers should exist in the expected order' +# } - It '[] Resources section should contain all resources from the template file' -TestCases $readmeFolderTestCases { +# It '[] Resources section should contain all resources from the template file' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent +# ) - # Get ReadMe data - $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' +# # Get ReadMe data +# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' - $ReadMeResourcesList = [System.Collections.ArrayList]@() - for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { - $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() - } +# $ReadMeResourcesList = [System.Collections.ArrayList]@() +# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { +# $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() +# } - # Get template data - $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { - $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique +# # Get template data +# $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { +# $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique - # Compare - $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ("list of template resources missing from the ReadMe's list [{0}] should be empty" -f ($differentiatingItems -join ',')) - } +# # Compare +# $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ("list of template resources missing from the ReadMe's list [{0}] should be empty" -f ($differentiatingItems -join ',')) +# } - It '[] Resources section should not contain more resources than the template file' -TestCases $readmeFolderTestCases { +# It '[] Resources section should not contain more resources than the template file' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent +# ) - # Get ReadMe data - $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' +# # Get ReadMe data +# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' - $ReadMeResourcesList = [System.Collections.ArrayList]@() - for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { - $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() - } +# $ReadMeResourcesList = [System.Collections.ArrayList]@() +# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { +# $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() +# } - # Get template data - $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { - $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique +# # Get template data +# $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { +# $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique - # Compare - $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ("list of resources in the ReadMe's list [{0}] not in the template file should be empty" -f ($differentiatingItems -join ',')) - } +# # Compare +# $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ("list of resources in the ReadMe's list [{0}] not in the template file should be empty" -f ($differentiatingItems -join ',')) +# } - It '[] Parameters section should contain a table for each existing parameter category in the following order: Required, Conditional, Optional, Generated' -TestCases $readmeFolderTestCases { +# It '[] Parameters section should contain a table for each existing parameter category in the following order: Required, Conditional, Optional, Generated' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent +# ) - $expectColumnsInOrder = @('Required', 'Conditional', 'Optional', 'Generated') +# $expectColumnsInOrder = @('Required', 'Conditional', 'Optional', 'Generated') - ## Get all descriptions - $descriptions = $templateContent.parameters.Values.metadata.description +# ## Get all descriptions +# $descriptions = $templateContent.parameters.Values.metadata.description - ## Get the module parameter categories - $expectedParamCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique # Get categories in template - $expectedParamCategoriesInOrder = $expectColumnsInOrder | Where-Object { $_ -in $expectedParamCategories } # add required ones in order - $expectedParamCategoriesInOrder += $expectedParamCategories | Where-Object { $_ -notin $expectColumnsInOrder } # add non-required ones after +# ## Get the module parameter categories +# $expectedParamCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique # Get categories in template +# $expectedParamCategoriesInOrder = $expectColumnsInOrder | Where-Object { $_ -in $expectedParamCategories } # add required ones in order +# $expectedParamCategoriesInOrder += $expectedParamCategories | Where-Object { $_ -notin $expectColumnsInOrder } # add non-required ones after - $actualParamCategories = $readMeContent | Select-String -Pattern '^\*\*(.+) parameters\*\*$' -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } # get actual in readme +# $actualParamCategories = $readMeContent | Select-String -Pattern '^\*\*(.+) parameters\*\*$' -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } # get actual in readme - $actualParamCategories | Should -Be $expectedParamCategoriesInOrder - } +# $actualParamCategories | Should -Be $expectedParamCategoriesInOrder +# } - It '[] Parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows.' -TestCases $readmeFolderTestCases { +# It '[] Parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows.' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent +# ) - ## Get all descriptions - $descriptions = $templateContent.parameters.Values.metadata.description +# ## Get all descriptions +# $descriptions = $templateContent.parameters.Values.metadata.description - ## Get the module parameter categories - $paramCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique +# ## Get the module parameter categories +# $paramCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique - foreach ($paramCategory in $paramCategories) { +# foreach ($paramCategory in $paramCategories) { - # Filter to relevant items - [array] $categoryParameters = $templateContent.parameters.Values | Where-Object { $_.metadata.description -like "$paramCategory. *" } | Sort-Object -Property 'Name' -Culture 'en-US' +# # Filter to relevant items +# [array] $categoryParameters = $templateContent.parameters.Values | Where-Object { $_.metadata.description -like "$paramCategory. *" } | Sort-Object -Property 'Name' -Culture 'en-US' - # Check properties for later reference - $shouldHaveDefault = $categoryParameters.defaultValue.count -gt 0 - $shouldHaveAllowed = $categoryParameters.allowedValues.count -gt 0 +# # Check properties for later reference +# $shouldHaveDefault = $categoryParameters.defaultValue.count -gt 0 +# $shouldHaveAllowed = $categoryParameters.allowedValues.count -gt 0 - $expectedColumnsInOrder = @('Parameter Name', 'Type') - if ($shouldHaveDefault) { $expectedColumnsInOrder += @('Default Value') } - if ($shouldHaveAllowed) { $expectedColumnsInOrder += @('Allowed Values') } - $expectedColumnsInOrder += @('Description') +# $expectedColumnsInOrder = @('Parameter Name', 'Type') +# if ($shouldHaveDefault) { $expectedColumnsInOrder += @('Default Value') } +# if ($shouldHaveAllowed) { $expectedColumnsInOrder += @('Allowed Values') } +# $expectedColumnsInOrder += @('Description') - $readMeCategoryIndex = $readMeContent | Select-String -Pattern "^\*\*$paramCategory parameters\*\*$" | ForEach-Object { $_.LineNumber } +# $readMeCategoryIndex = $readMeContent | Select-String -Pattern "^\*\*$paramCategory parameters\*\*$" | ForEach-Object { $_.LineNumber } - $tableStartIndex = $readMeCategoryIndex - while ($readMeContent[$tableStartIndex] -notlike '*|*' -and -not ($tableStartIndex -ge $readMeContent.count)) { - $tableStartIndex++ - } +# $tableStartIndex = $readMeCategoryIndex +# while ($readMeContent[$tableStartIndex] -notlike '*|*' -and -not ($tableStartIndex -ge $readMeContent.count)) { +# $tableStartIndex++ +# } - $readmeCategoryColumns = ($readMeContent[$tableStartIndex] -split '\|') | ForEach-Object { $_.Trim() } | Where-Object { -not [String]::IsNullOrEmpty($_) } - $readmeCategoryColumns | Should -Be $expectedColumnsInOrder - } - } +# $readmeCategoryColumns = ($readMeContent[$tableStartIndex] -split '\|') | ForEach-Object { $_.Trim() } | Where-Object { -not [String]::IsNullOrEmpty($_) } +# $readmeCategoryColumns | Should -Be $expectedColumnsInOrder +# } +# } - It '[] Parameters section should contain all parameters from the template file' -TestCases $readmeFolderTestCases { +# It '[] Parameters section should contain all parameters from the template file' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent +# ) - # Get Template data - $parameters = $templateContent.parameters.Keys +# # Get Template data +# $parameters = $templateContent.parameters.Keys - # Get ReadMe data - ## Get section start index - $sectionStartIndex = Get-MarkdownSectionStartIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Parameters' +# # Get ReadMe data +# ## Get section start index +# $sectionStartIndex = Get-MarkdownSectionStartIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Parameters' - if ($sectionStartIndex -ge $readMeContent.count) { - throw 'Parameters section is missing in the Readme. Please add and re-run the tests.' - } +# if ($sectionStartIndex -ge $readMeContent.count) { +# throw 'Parameters section is missing in the Readme. Please add and re-run the tests.' +# } - $parametersSectionEndIndex = Get-MarkdownSectionEndIndex -ReadMeContent $readMeContent -SectionStartIndex $sectionStartIndex +# $parametersSectionEndIndex = Get-MarkdownSectionEndIndex -ReadMeContent $readMeContent -SectionStartIndex $sectionStartIndex - ## Iterate over all parameter tables - $parametersList = [System.Collections.ArrayList]@() - $sectionIndex = $sectionStartIndex - while ($sectionIndex -lt $parametersSectionEndIndex) { - ### Get table start index - $parametersTableStartIndex = $sectionIndex - while ($readMeContent[$parametersTableStartIndex] -notlike '*|*' -and -not ($parametersTableStartIndex -ge $readMeContent.count)) { - $parametersTableStartIndex++ - } - Write-Verbose ("[loop] Start row of the parameter table: $parametersTableStartIndex") +# ## Iterate over all parameter tables +# $parametersList = [System.Collections.ArrayList]@() +# $sectionIndex = $sectionStartIndex +# while ($sectionIndex -lt $parametersSectionEndIndex) { +# ### Get table start index +# $parametersTableStartIndex = $sectionIndex +# while ($readMeContent[$parametersTableStartIndex] -notlike '*|*' -and -not ($parametersTableStartIndex -ge $readMeContent.count)) { +# $parametersTableStartIndex++ +# } +# Write-Verbose ("[loop] Start row of the parameter table: $parametersTableStartIndex") - ### Get table end index - $parametersTableEndIndex = $parametersTableStartIndex + 2 # Header row + table separator row - while ($readMeContent[$parametersTableEndIndex] -like '*|*' -and -not ($parametersTableEndIndex -ge $readMeContent.count)) { - $parametersTableEndIndex++ - } - Write-Verbose ("[loop] End row of the parameter table: $parametersTableEndIndex") +# ### Get table end index +# $parametersTableEndIndex = $parametersTableStartIndex + 2 # Header row + table separator row +# while ($readMeContent[$parametersTableEndIndex] -like '*|*' -and -not ($parametersTableEndIndex -ge $readMeContent.count)) { +# $parametersTableEndIndex++ +# } +# Write-Verbose ("[loop] End row of the parameter table: $parametersTableEndIndex") - for ($tableIndex = $parametersTableStartIndex + 2; $tableIndex -lt $parametersTableEndIndex; $tableIndex++) { - $parametersList += $readMeContent[$tableIndex].Split('|')[1].Replace('`', '').Trim() - } - $sectionIndex = $parametersTableEndIndex + 1 - } +# for ($tableIndex = $parametersTableStartIndex + 2; $tableIndex -lt $parametersTableEndIndex; $tableIndex++) { +# $parametersList += $readMeContent[$tableIndex].Split('|')[1].Replace('`', '').Trim() +# } +# $sectionIndex = $parametersTableEndIndex + 1 +# } - # Test - $differentiatingItems = $parameters | Where-Object { $parametersList -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of template parameters missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - } +# # Test +# $differentiatingItems = $parameters | Where-Object { $parametersList -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of template parameters missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# } - It '[] Outputs section should contain a table with these column names in order: Output Name, Type' -TestCases $readmeFolderTestCases { +# It '[] Outputs section should contain a table with these column names in order: Output Name, Type' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - $readMeContent - ) +# param( +# [string] $moduleFolderName, +# $readMeContent +# ) - $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' +# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' - $outputsTableHeader = $readMeContent[$tableStartIndex].Split('|').Trim() | Where-Object { -not [String]::IsNullOrEmpty($_) } +# $outputsTableHeader = $readMeContent[$tableStartIndex].Split('|').Trim() | Where-Object { -not [String]::IsNullOrEmpty($_) } - # Test - $expectedOutputsTableOrder = @('Output Name', 'Type') - $differentiatingItems = $expectedOutputsTableOrder | Where-Object { $outputsTableHeader -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of "Outputs" table columns missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - } +# # Test +# $expectedOutputsTableOrder = @('Output Name', 'Type') +# $differentiatingItems = $expectedOutputsTableOrder | Where-Object { $outputsTableHeader -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of "Outputs" table columns missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# } - It '[] Output section should contain all outputs defined in the template file' -TestCases $readmeFolderTestCases { +# It '[] Output section should contain all outputs defined in the template file' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent +# ) - # Get ReadMe data - $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' +# # Get ReadMe data +# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' - $ReadMeOutputsList = [System.Collections.ArrayList]@() - for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { - $ReadMeOutputsList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() - } +# $ReadMeOutputsList = [System.Collections.ArrayList]@() +# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { +# $ReadMeOutputsList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() +# } - # Template data - $expectedOutputs = $templateContent.outputs.Keys +# # Template data +# $expectedOutputs = $templateContent.outputs.Keys - # Test - $differentiatingItems = $expectedOutputs | Where-Object { $ReadMeOutputsList -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of template outputs missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# # Test +# $differentiatingItems = $expectedOutputs | Where-Object { $ReadMeOutputsList -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of template outputs missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - $differentiatingItems = $ReadMeOutputsList | Where-Object { $expectedOutputs -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of excess template outputs defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - } +# $differentiatingItems = $ReadMeOutputsList | Where-Object { $expectedOutputs -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of excess template outputs defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# } - It '[] Dependencies section should contain all cross-references defined in the template file' -TestCases $readmeFolderTestCases { +# It '[] Dependencies section should contain all cross-references defined in the template file' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [object[]] $readMeContent, - [string] $resourceTypeIdentifier - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [object[]] $readMeContent, +# [string] $resourceTypeIdentifier +# ) - # Get ReadMe data - $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*## Cross-referenced modules' +# # Get ReadMe data +# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*## Cross-referenced modules' - $ReadMeDependenciesList = @{ - localPathReferences = @() - remoteReferences = @() - } - for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { - $type = $readMeContent[$index].Split('|')[2].Trim() +# $ReadMeDependenciesList = @{ +# localPathReferences = @() +# remoteReferences = @() +# } +# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { +# $type = $readMeContent[$index].Split('|')[2].Trim() - switch ($type) { - 'Local reference' { - $ReadMeDependenciesList.localPathReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() - } - 'Remote reference' { - $ReadMeDependenciesList.remoteReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() - } - Default { - throw "Unkown type reference [$type]. Only [Local reference] & [Remote reference] are known. Please update ReadMe or test script." - } - } - } +# switch ($type) { +# 'Local reference' { +# $ReadMeDependenciesList.localPathReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() +# } +# 'Remote reference' { +# $ReadMeDependenciesList.remoteReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() +# } +# Default { +# throw "Unkown type reference [$type]. Only [Local reference] & [Remote reference] are known. Please update ReadMe or test script." +# } +# } +# } - # Template data - $expectedDependencies = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] +# # Template data +# $expectedDependencies = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] - # Test - if ($expectedDependencies.localPathReferences) { - $differentiatingItems = @() + $expectedDependencies.localPathReferences | Where-Object { $ReadMeDependenciesList.localPathReferences -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of local template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# # Test +# if ($expectedDependencies.localPathReferences) { +# $differentiatingItems = @() + $expectedDependencies.localPathReferences | Where-Object { $ReadMeDependenciesList.localPathReferences -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of local template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - $differentiatingItems = @() + $ReadMeDependenciesList.localPathReferences | Where-Object { $expectedDependencies.localPathReferences -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of excess local template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - } +# $differentiatingItems = @() + $ReadMeDependenciesList.localPathReferences | Where-Object { $expectedDependencies.localPathReferences -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of excess local template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# } - if ($expectedDependencies.remoteReferences) { - $differentiatingItems = @() + $expectedDependencies.remoteReferences | Where-Object { $ReadMeDependenciesList.remoteReferences -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of remote template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# if ($expectedDependencies.remoteReferences) { +# $differentiatingItems = @() + $expectedDependencies.remoteReferences | Where-Object { $ReadMeDependenciesList.remoteReferences -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of remote template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - $differentiatingItems = @() + $ReadMeDependenciesList.remoteReferences | Where-Object { $expectedDependencies.remoteReferences -notcontains $_ } - $differentiatingItems.Count | Should -Be 0 -Because ('list of excess remote template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) - } - } +# $differentiatingItems = @() + $ReadMeDependenciesList.remoteReferences | Where-Object { $expectedDependencies.remoteReferences -notcontains $_ } +# $differentiatingItems.Count | Should -Be 0 -Because ('list of excess remote template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) +# } +# } - It '[] `Set-ModuleReadMe` script should not apply any updates' -TestCases $readmeFolderTestCases { +# It '[] `Set-ModuleReadMe` script should not apply any updates' -TestCases $readmeFolderTestCases { - param( - [string] $moduleFolderName, - [string] $templateFilePath, - [hashtable] $templateContent, - [string] $readMeFilePath - ) +# param( +# [string] $moduleFolderName, +# [string] $templateFilePath, +# [hashtable] $templateContent, +# [string] $readMeFilePath +# ) - # Get current hash - $fileHashBefore = (Get-FileHash $readMeFilePath).Hash +# # Get current hash +# $fileHashBefore = (Get-FileHash $readMeFilePath).Hash - # Load function - . (Join-Path $repoRootPath 'utilities' 'tools' 'Set-ModuleReadMe.ps1') +# # Load function +# . (Join-Path $repoRootPath 'utilities' 'tools' 'Set-ModuleReadMe.ps1') - # Apply update with already compiled template content - Set-ModuleReadMe -TemplateFilePath $templateFilePath -TemplateFileContent $templateContent +# # Apply update with already compiled template content +# Set-ModuleReadMe -TemplateFilePath $templateFilePath -TemplateFileContent $templateContent - # Get hash after 'update' - $fileHashAfter = (Get-FileHash $readMeFilePath).Hash +# # Get hash after 'update' +# $fileHashAfter = (Get-FileHash $readMeFilePath).Hash - # Compare - $filesAreTheSame = $fileHashBefore -eq $fileHashAfter - if (-not $filesAreTheSame) { - $diffReponse = git diff $readMeFilePath - Write-Warning ($diffReponse | Out-String) -Verbose +# # Compare +# $filesAreTheSame = $fileHashBefore -eq $fileHashAfter +# if (-not $filesAreTheSame) { +# $diffReponse = git diff $readMeFilePath +# Write-Warning ($diffReponse | Out-String) -Verbose - # Reset readme file to original state - git checkout HEAD -- $readMeFilePath - } - $filesAreTheSame | Should -Be $true -Because 'The file hashes before and after applying the Set-ModuleReadMe function should be identical' - } - } -} +# # Reset readme file to original state +# git checkout HEAD -- $readMeFilePath +# } +# $filesAreTheSame | Should -Be $true -Because 'The file hashes before and after applying the Set-ModuleReadMe function should be identical' +# } +# } +# } -Describe 'Test file tests' -Tag 'TestTemplate' { +# Describe 'Test file tests' -Tag 'TestTemplate' { - Context 'General test file' { +# Context 'General test file' { - $deploymentTestFileTestCases = @() +# $deploymentTestFileTestCases = @() - foreach ($moduleFolderPath in $moduleFolderPaths) { - if (Test-Path (Join-Path $moduleFolderPath '.test')) { - $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } - foreach ($testFilePath in $testFilePaths) { - $testFileContent = Get-Content $testFilePath - - if ((Split-Path $testFilePath -Extension) -eq '.json') { - # Skip any classic parameter files - $contentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 - $isParameterFile = $contentHashtable.'$schema' -like '*deploymentParameters*' - if ($isParameterFile) { - continue - } - } +# foreach ($moduleFolderPath in $moduleFolderPaths) { +# if (Test-Path (Join-Path $moduleFolderPath '.test')) { +# $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } +# foreach ($testFilePath in $testFilePaths) { +# $testFileContent = Get-Content $testFilePath + +# if ((Split-Path $testFilePath -Extension) -eq '.json') { +# # Skip any classic parameter files +# $contentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 +# $isParameterFile = $contentHashtable.'$schema' -like '*deploymentParameters*' +# if ($isParameterFile) { +# continue +# } +# } - $deploymentTestFileTestCases += @{ - testFilePath = $testFilePath - testFileContent = $testFileContent - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - } - } - } - } +# $deploymentTestFileTestCases += @{ +# testFilePath = $testFilePath +# testFileContent = $testFileContent +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# } +# } +# } +# } - It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*deploy.bicep' = {`]" -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { +# It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*deploy.bicep' = {`]" -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { - param( - [object[]] $testFileContent - ) +# param( +# [object[]] $testFileContent +# ) - $testIndex = ($testFileContent | Select-String ("^module testDeployment '..\/.*deploy.bicep' = {$") | ForEach-Object { $_.LineNumber - 1 })[0] +# $testIndex = ($testFileContent | Select-String ("^module testDeployment '..\/.*deploy.bicep' = {$") | ForEach-Object { $_.LineNumber - 1 })[0] - $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' - } +# $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' +# } - It '[] Bicep test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { +# It '[] Bicep test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { - param( - [object[]] $testFileContent - ) +# param( +# [object[]] $testFileContent +# ) - $expectedNameFormat = ($testFileContent | Out-String) -match '\s*name:.+-test-.+\s*' +# $expectedNameFormat = ($testFileContent | Out-String) -match '\s*name:.+-test-.+\s*' - $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' - } +# $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' +# } - It '[] Bicep test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { +# It '[] Bicep test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { - param( - [object[]] $testFileContent - ) +# param( +# [object[]] $testFileContent +# ) - $hasExpectedParam = ($testFileContent | Out-String) -match '\s*param\s+serviceShort\s+string\s*' +# $hasExpectedParam = ($testFileContent | Out-String) -match '\s*param\s+serviceShort\s+string\s*' - $hasExpectedParam | Should -Be $true - } +# $hasExpectedParam | Should -Be $true +# } - It '[] JSON test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { +# It '[] JSON test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { - param( - [object[]] $testFileContent - ) +# param( +# [object[]] $testFileContent +# ) - # Handle case of deployment test file (instead of ARM-JSON parameter file) - $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 +# # Handle case of deployment test file (instead of ARM-JSON parameter file) +# $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 - # Uses deployment test file (instead of parameter file). Need to extract parameters. - $testResource = $rawContentHashtable.resources | Where-Object { $_.name -like '*-test-*' } +# # Uses deployment test file (instead of parameter file). Need to extract parameters. +# $testResource = $rawContentHashtable.resources | Where-Object { $_.name -like '*-test-*' } - $testResource | Should -Not -BeNullOrEmpty -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' - } +# $testResource | Should -Not -BeNullOrEmpty -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' +# } - It '[] JSON test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { +# It '[] JSON test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { - param( - [object[]] $testFileContent - ) +# param( +# [object[]] $testFileContent +# ) - $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 -AsHashtable - $rawContentHashtable.parameters.keys | Should -Contain 'serviceShort' - } - } +# $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 -AsHashtable +# $rawContentHashtable.parameters.keys | Should -Contain 'serviceShort' +# } +# } - Context 'Token usage' { +# Context 'Token usage' { - # Parameter file test cases - $parameterFileTokenTestCases = @() +# # Parameter file test cases +# $parameterFileTokenTestCases = @() - foreach ($moduleFolderPath in $moduleFolderPaths) { - if (Test-Path (Join-Path $moduleFolderPath '.test')) { - $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } - foreach ($testFilePath in $testFilePaths) { - foreach ($token in $enforcedTokenList.Keys) { - $parameterFileTokenTestCases += @{ - testFilePath = $testFilePath - parameterFileName = Split-Path $testFilePath -Leaf - tokenSettings = $Settings.parameterFileTokens - tokenName = $token - tokenValue = $enforcedTokenList[$token] - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - } - } - } - } - } +# foreach ($moduleFolderPath in $moduleFolderPaths) { +# if (Test-Path (Join-Path $moduleFolderPath '.test')) { +# $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } +# foreach ($testFilePath in $testFilePaths) { +# foreach ($token in $enforcedTokenList.Keys) { +# $parameterFileTokenTestCases += @{ +# testFilePath = $testFilePath +# parameterFileName = Split-Path $testFilePath -Leaf +# tokenSettings = $Settings.parameterFileTokens +# tokenName = $token +# tokenValue = $enforcedTokenList[$token] +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# } +# } +# } +# } +# } - It '[] [Tokens] Test file [] should not contain the plain value for token [] guid' -TestCases $parameterFileTokenTestCases { - param ( - [string] $testFilePath, - [string] $parameterFileName, - [hashtable] $tokenSettings, - [string] $tokenName, - [string] $tokenValue, - [string] $moduleFolderName - ) - $ParameterFileTokenName = -join ($tokenSettings.tokenPrefix, $tokenName, $tokenSettings.tokenSuffix) - $ParameterFileContent = Get-Content -Path $testFilePath +# It '[] [Tokens] Test file [] should not contain the plain value for token [] guid' -TestCases $parameterFileTokenTestCases { +# param ( +# [string] $testFilePath, +# [string] $parameterFileName, +# [hashtable] $tokenSettings, +# [string] $tokenName, +# [string] $tokenValue, +# [string] $moduleFolderName +# ) +# $ParameterFileTokenName = -join ($tokenSettings.tokenPrefix, $tokenName, $tokenSettings.tokenSuffix) +# $ParameterFileContent = Get-Content -Path $testFilePath - $incorrectReferencesFound = $ParameterFileContent | Select-String -Pattern $tokenValue -AllMatches - if ($incorrectReferencesFound.Matches) { - $incorrectReferencesFound.Matches.Count | Should -Be 0 -Because ('Test file should not contain the value [{0}], instead it should reference the token value [{1}]. Please check the {2} lines: [{3}]' -f $tokenName, $ParameterFileTokenName, $incorrectReferencesFound.Matches.Count, ($incorrectReferencesFound.Line.Trim() -join ",`n")) - } - } - } -} +# $incorrectReferencesFound = $ParameterFileContent | Select-String -Pattern $tokenValue -AllMatches +# if ($incorrectReferencesFound.Matches) { +# $incorrectReferencesFound.Matches.Count | Should -Be 0 -Because ('Test file should not contain the value [{0}], instead it should reference the token value [{1}]. Please check the {2} lines: [{3}]' -f $tokenName, $ParameterFileTokenName, $incorrectReferencesFound.Matches.Count, ($incorrectReferencesFound.Line.Trim() -join ",`n")) +# } +# } +# } +# } -# Describe 'Deployment template tests' -Tag 'Template' { +Describe 'Deployment template tests' -Tag 'Template' { -# Context 'General template' { + Context 'General template' { -# $deploymentFolderTestCases = [System.Collections.ArrayList] @() -# foreach ($moduleFolderPath in $moduleFolderPaths) { + $deploymentFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { -# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key -# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') -# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { -# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' -# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key + $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') + if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' + $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) -# } -# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' -# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + if (-not $templateContent) { + throw ($bicepTemplateCompilationFailedException -f $templateFilePath) + } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($jsonTemplateLoadFailedException -f $templateFilePath) -# } -# } else { -# throw ($templateNotFoundException -f $moduleFolderPath) -# } -# $convertedTemplates[$moduleFolderPathKey] = @{ -# templateFilePath = $templateFilePath -# templateContent = $templateContent -# } -# } else { -# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent -# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath -# } + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } + } else { + throw ($templateNotFoundException -f $moduleFolderPath) + } + $convertedTemplates[$moduleFolderPathKey] = @{ + templateFilePath = $templateFilePath + templateContent = $templateContent + } + } else { + $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath + } -# # Parameter file test cases -# $testFileTestCases = @() -# $templateFile_Parameters = $templateContent.parameters -# $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object -# $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object + # Parameter file test cases + $testFileTestCases = @() + $templateFile_Parameters = $templateContent.parameters + $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object + $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object -# if (Test-Path (Join-Path $moduleFolderPath '.test')) { + if (Test-Path (Join-Path $moduleFolderPath '.test')) { -# # Can be removed after full migration to bicep test files -# $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + # Can be removed after full migration to bicep test files + $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } -# foreach ($moduleTestFilePath in $moduleTestFilePaths) { -# if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { + foreach ($moduleTestFilePath in $moduleTestFilePaths) { + if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { -# $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable + $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable -# # Skipping any file that is not actually a ARM-JSON parameter file -# $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' -# if (-not $isParameterFile) { -# continue -# } + # Skipping any file that is not actually a ARM-JSON parameter file + $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' + if (-not $isParameterFile) { + continue + } -# $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object -# } else { -# $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable -# $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test -# } -# $testFileTestCases += @{ -# testFile_Path = $moduleTestFilePath -# testFile_Name = Split-Path $moduleTestFilePath -Leaf -# testFile_AllParameterNames = $deploymentTestFile_AllParameterNames -# templateFile_AllParameterNames = $TemplateFile_AllParameterNames -# templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames -# tokenConfiguration = $tokenConfiguration -# } -# } -# } + $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object + } else { + $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable + $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test + } + $testFileTestCases += @{ + testFile_Path = $moduleTestFilePath + testFile_Name = Split-Path $moduleTestFilePath -Leaf + testFile_AllParameterNames = $deploymentTestFile_AllParameterNames + templateFile_AllParameterNames = $TemplateFile_AllParameterNames + templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames + tokenConfiguration = $tokenConfiguration + } + } + } -# # Test file setup -# $deploymentFolderTestCases += @{ -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# templateContent = $templateContent -# templateFilePath = $templateFilePath -# testFileTestCases = $testFileTestCases -# } -# } + # Test file setup + $deploymentFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + templateContent = $templateContent + templateFilePath = $templateFilePath + testFileTestCases = $testFileTestCases + } + } -# It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { + It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $templateContent | Should -Not -Be $null -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $templateContent | Should -Not -Be $null + } -# It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { -# # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! -# # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { + # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! + # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# $Schemaverion = $templateContent.'$schema' -# $SchemaArray = @() -# if ($Schemaverion -eq $RGdeployment) { -# $SchemaOutput = $true -# } elseIf ($Schemaverion -eq $Subscriptiondeployment) { -# $SchemaOutput = $true -# } elseIf ($Schemaverion -eq $MGdeployment) { -# $SchemaOutput = $true -# } elseIf ($Schemaverion -eq $Tenantdeployment) { -# $SchemaOutput = $true -# } else { -# $SchemaOutput = $false -# } -# $SchemaArray += $SchemaOutput -# $SchemaArray | Should -Not -Contain $false -# } + $Schemaverion = $templateContent.'$schema' + $SchemaArray = @() + if ($Schemaverion -eq $RGdeployment) { + $SchemaOutput = $true + } elseIf ($Schemaverion -eq $Subscriptiondeployment) { + $SchemaOutput = $true + } elseIf ($Schemaverion -eq $MGdeployment) { + $SchemaOutput = $true + } elseIf ($Schemaverion -eq $Tenantdeployment) { + $SchemaOutput = $true + } else { + $SchemaOutput = $false + } + $SchemaArray += $SchemaOutput + $SchemaArray | Should -Not -Contain $false + } -# It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { + It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $Schemaverion = $templateContent.'$schema' -# ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $Schemaverion = $templateContent.'$schema' + ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true + } -# It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { -# #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $ApiVersion = $templateContent.resources.apiVersion -# $ApiVersionArray = @() -# foreach ($API in $ApiVersion) { -# if ($API.Substring(0, 2) -eq '20') { -# $ApiVersionOutput = $true -# } elseIf ($API.substring(1, 10) -eq 'parameters') { -# # An API version should not be referenced as a parameter -# $ApiVersionOutput = $false -# } elseIf ($API.substring(1, 10) -eq 'variables') { -# # An API version should not be referenced as a variable -# $ApiVersionOutput = $false -# } else { -# $ApiVersionOutput = $false -# } -# $ApiVersionArray += $ApiVersionOutput -# } -# $ApiVersionArray | Should -Not -Contain $false -# } + It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { + #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $ApiVersion = $templateContent.resources.apiVersion + $ApiVersionArray = @() + foreach ($API in $ApiVersion) { + if ($API.Substring(0, 2) -eq '20') { + $ApiVersionOutput = $true + } elseIf ($API.substring(1, 10) -eq 'parameters') { + # An API version should not be referenced as a parameter + $ApiVersionOutput = $false + } elseIf ($API.substring(1, 10) -eq 'variables') { + # An API version should not be referenced as a variable + $ApiVersionOutput = $false + } else { + $ApiVersionOutput = $false + } + $ApiVersionArray += $ApiVersionOutput + } + $ApiVersionArray | Should -Not -Contain $false + } -# It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { + It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $templateContent.Keys | Should -Contain '$schema' -# $templateContent.Keys | Should -Contain 'contentVersion' -# $templateContent.Keys | Should -Contain 'resources' -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $templateContent.Keys | Should -Contain '$schema' + $templateContent.Keys | Should -Contain 'contentVersion' + $templateContent.Keys | Should -Contain 'resources' + } -# It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { + It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# if ($lock = $templateContent.parameters.lock) { -# $lock.Keys | Should -Contain 'defaultValue' -# $lock.defaultValue | Should -Be '' -# } -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + if ($lock = $templateContent.parameters.lock) { + $lock.Keys | Should -Contain 'defaultValue' + $lock.defaultValue | Should -Be '' + } + } -# It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.parameters) { -# Set-ItResult -Skipped -Because 'the module template has no parameters.' -# return -# } + if (-not $templateContent.parameters) { + Set-ItResult -Skipped -Because 'the module template has no parameters.' + return + } -# $CamelCasingFlag = @() -# $Parameter = $templateContent.parameters.Keys -# foreach ($Param in $Parameter) { -# if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { -# $CamelCasingFlag += $false -# } else { -# $CamelCasingFlag += $true -# } -# } -# $CamelCasingFlag | Should -Not -Contain $false -# } + $CamelCasingFlag = @() + $Parameter = $templateContent.parameters.Keys + foreach ($Param in $Parameter) { + if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } -# It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.variables) { -# Set-ItResult -Skipped -Because 'the module template has no variables.' -# return -# } + if (-not $templateContent.variables) { + Set-ItResult -Skipped -Because 'the module template has no variables.' + return + } -# $CamelCasingFlag = @() -# $Variable = $templateContent.variables.Keys + $CamelCasingFlag = @() + $Variable = $templateContent.variables.Keys -# foreach ($Variab in $Variable) { -# if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { -# $CamelCasingFlag += $false -# } else { -# $CamelCasingFlag += $true -# } -# } -# $CamelCasingFlag | Should -Not -Contain $false -# } + foreach ($Variab in $Variable) { + if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } -# It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $CamelCasingFlag = @() -# $Outputs = $templateContent.outputs.Keys + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $CamelCasingFlag = @() + $Outputs = $templateContent.outputs.Keys -# foreach ($Output in $Outputs) { -# if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { -# $CamelCasingFlag += $false -# } else { -# $CamelCasingFlag += $true -# } -# } -# $CamelCasingFlag | Should -Not -Contain $false -# } + foreach ($Output in $Outputs) { + if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } -# It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { + It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $enableDefaultTelemetryFlag = @() -# $Schemaverion = $templateContent.'$schema' -# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { -# if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { -# $enableDefaultTelemetryFlag += $true -# } else { -# $enableDefaultTelemetryFlag += $false -# } -# } -# $enableDefaultTelemetryFlag | Should -Not -Contain $false -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $enableDefaultTelemetryFlag = @() + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { + $enableDefaultTelemetryFlag += $true + } else { + $enableDefaultTelemetryFlag += $false + } + } + $enableDefaultTelemetryFlag | Should -Not -Contain $false + } -# It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { + It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $LocationFlag = $true -# $Schemaverion = $templateContent.'$schema' -# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { -# $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue -# $Locationparamoutput = $templateContent.parameters.Keys -# if ($Locationparamoutput -contains 'Location') { -# if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { -# $LocationFlag = $true -# } else { - -# $LocationFlag = $false -# } -# $LocationFlag | Should -Contain $true -# } -# } -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $LocationFlag = $true + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue + $Locationparamoutput = $templateContent.parameters.Keys + if ($Locationparamoutput -contains 'Location') { + if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { + $LocationFlag = $true + } else { + + $LocationFlag = $false + } + $LocationFlag | Should -Contain $true + } + } + } -# It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { + It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [string] $templateFilePath -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [string] $templateFilePath + ) -# $outputs = $templateContent.outputs + $outputs = $templateContent.outputs -# $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] -# $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } + $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] + $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } -# if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { -# # If the main resource has a location property, an output should be returned too -# $outputs.keys | Should -Contain 'location' + if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { + # If the main resource has a location property, an output should be returned too + $outputs.keys | Should -Contain 'location' -# # It should further reference the location property of the primary resource and not e.g. the location input parameter -# $outputs.location.value | Should -Match $primaryResourceType -# } -# } + # It should further reference the location property of the primary resource and not e.g. the location input parameter + $outputs.location.value | Should -Match $primaryResourceType + } + } -# It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { + It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [string] $templateFilePath -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [string] $templateFilePath + ) -# $outputs = $templateContent.outputs.Keys -# $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath + $outputs = $templateContent.outputs.Keys + $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath -# if ($deploymentScope -eq 'resourceGroup') { -# $outputs | Should -Contain 'resourceGroupName' -# } -# } + if ($deploymentScope -eq 'resourceGroup') { + $outputs | Should -Contain 'resourceGroupName' + } + } -# It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { + It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# $templateFilePath -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + $templateFilePath + ) -# # check if module contains a 'primary' resource we could draw a name from -# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' -# if ($templateContent.resources.type -notcontains $moduleResourceType) { -# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' -# return -# } + # check if module contains a 'primary' resource we could draw a name from + $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' + if ($templateContent.resources.type -notcontains $moduleResourceType) { + Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' + return + } -# # Otherwise test for standard outputs -# $outputs = $templateContent.outputs.Keys -# $outputs | Should -Contain 'name' -# } + # Otherwise test for standard outputs + $outputs = $templateContent.outputs.Keys + $outputs | Should -Contain 'name' + } -# It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { + It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# $templateFilePath -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + $templateFilePath + ) -# # check if module contains a 'primary' resource we could draw a name from -# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' -# if ($templateContent.resources.type -notcontains $moduleResourceType) { -# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' -# return -# } + # check if module contains a 'primary' resource we could draw a name from + $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' + if ($templateContent.resources.type -notcontains $moduleResourceType) { + Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' + return + } -# # Otherwise test for standard outputs -# $outputs = $templateContent.outputs.Keys -# $outputs | Should -Contain 'resourceId' -# } + # Otherwise test for standard outputs + $outputs = $templateContent.outputs.Keys + $outputs | Should -Contain 'resourceId' + } -# It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { + It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.parameters) { -# Set-ItResult -Skipped -Because 'the module template has no parameters.' -# return -# } + if (-not $templateContent.parameters) { + Set-ItResult -Skipped -Because 'the module template has no parameters.' + return + } -# $incorrectParameters = @() -# $templateParameters = $templateContent.parameters.Keys -# foreach ($parameter in $templateParameters) { -# $data = ($templateContent.parameters.$parameter.metadata).description -# if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { -# $incorrectParameters += $parameter -# } -# } -# $incorrectParameters | Should -BeNullOrEmpty -# } + $incorrectParameters = @() + $templateParameters = $templateContent.parameters.Keys + foreach ($parameter in $templateParameters) { + $data = ($templateContent.parameters.$parameter.metadata).description + if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { + $incorrectParameters += $parameter + } + } + $incorrectParameters | Should -BeNullOrEmpty + } -# It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { + It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.parameters) { -# Set-ItResult -Skipped -Because 'the module template has no parameters.' -# return -# } + if (-not $templateContent.parameters) { + Set-ItResult -Skipped -Because 'the module template has no parameters.' + return + } -# $incorrectParameters = @() -# $templateParameters = $templateContent.parameters.Keys -# foreach ($parameter in $templateParameters) { -# $data = ($templateContent.parameters.$parameter.metadata).description -# switch -regex ($data) { -# '^Conditional. .*' { -# if ($data -notmatch '.*\. Required if .*') { -# $incorrectParameters += $parameter -# } -# } -# } -# } -# $incorrectParameters | Should -BeNullOrEmpty -# } + $incorrectParameters = @() + $templateParameters = $templateContent.parameters.Keys + foreach ($parameter in $templateParameters) { + $data = ($templateContent.parameters.$parameter.metadata).description + switch -regex ($data) { + '^Conditional. .*' { + if ($data -notmatch '.*\. Required if .*') { + $incorrectParameters += $parameter + } + } + } + } + $incorrectParameters | Should -BeNullOrEmpty + } -# It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { + It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.outputs) { -# Set-ItResult -Skipped -Because 'the module template has no outputs.' -# return -# } + if (-not $templateContent.outputs) { + Set-ItResult -Skipped -Because 'the module template has no outputs.' + return + } -# $incorrectOutputs = @() -# $templateOutputs = $templateContent.outputs.Keys -# foreach ($output in $templateOutputs) { -# $data = ($templateContent.outputs.$output.metadata).description -# if ($data -notmatch '(?s)^[A-Z].+\.$') { -# $incorrectOutputs += $output -# } -# } -# $incorrectOutputs | Should -BeNullOrEmpty -# } + $incorrectOutputs = @() + $templateOutputs = $templateContent.outputs.Keys + foreach ($output in $templateOutputs) { + $data = ($templateContent.outputs.$output.metadata).description + if ($data -notmatch '(?s)^[A-Z].+\.$') { + $incorrectOutputs += $output + } + } + $incorrectOutputs | Should -BeNullOrEmpty + } -# # PARAMETER Tests -# It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { -# param ( -# [hashtable[]] $testFileTestCases -# ) + # PARAMETER Tests + It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $testFileTestCases + ) -# foreach ($parameterFileTestCase in $testFileTestCases) { -# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames -# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames + foreach ($parameterFileTestCase in $testFileTestCases) { + $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames + $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames -# $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } -# $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) -# } -# } + $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } + $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) + } + } -# It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { -# param ( -# [hashtable[]] $testFileTestCases -# ) + It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $testFileTestCases + ) -# foreach ($parameterFileTestCase in $testFileTestCases) { -# $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames -# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames + foreach ($parameterFileTestCase in $testFileTestCases) { + $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames + $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames -# $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } -# $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) -# } -# } + $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } + $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) + } + } -# It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { -# param ( -# [hashtable[]] $testFileTestCases, -# [hashtable] $templateContent -# ) + It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $testFileTestCases, + [hashtable] $templateContent + ) -# foreach ($parameterFileTestCase in $testFileTestCases) { -# $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames -# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames -# $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } + foreach ($parameterFileTestCase in $testFileTestCases) { + $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames + $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames + $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } -# $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } -# $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) -# } -# } -# } -# } + $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } + $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) + } + } + } +} -# Describe 'API version tests' -Tag 'ApiCheck' { +Describe 'API version tests' -Tag 'ApiCheck' { -# $testCases = @() -# $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' + $testCases = @() + $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' -# if (-not (Test-Path $apiSpecsFilePath)) { -# Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" -# return -# } + if (-not (Test-Path $apiSpecsFilePath)) { + Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" + return + } -# $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json -# foreach ($moduleFolderPath in $moduleFolderPaths) { + $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json + foreach ($moduleFolderPath in $moduleFolderPaths) { -# $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key -# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') -# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { -# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' -# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key + $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') + if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' + $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) -# } -# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' -# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + if (-not $templateContent) { + throw ($bicepTemplateCompilationFailedException -f $templateFilePath) + } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($jsonTemplateLoadFailedException -f $templateFilePath) -# } -# } else { -# throw ($templateNotFoundException -f $moduleFolderPath) -# } -# $convertedTemplates[$moduleFolderPathKey] = @{ -# templateFilePath = $templateFilePath -# templateContent = $templateContent -# } -# } else { -# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent -# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath -# } + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } + } else { + throw ($templateNotFoundException -f $moduleFolderPath) + } + $convertedTemplates[$moduleFolderPathKey] = @{ + templateFilePath = $templateFilePath + templateContent = $templateContent + } + } else { + $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath + } -# $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { -# $_.type -notin @('Microsoft.Resources/deployments') -and $_ -# } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type - -# foreach ($resource in $nestedResources) { - -# switch ($resource.type) { -# { $PSItem -like '*diagnosticsettings*' } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'diagnosticsettings' -# ProviderNamespace = 'Microsoft.insights' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# { $PSItem -like '*locks' } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'locks' -# ProviderNamespace = 'Microsoft.Authorization' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# { $PSItem -like '*roleAssignments' } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'roleassignments' -# ProviderNamespace = 'Microsoft.Authorization' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'privateEndpoints' -# ProviderNamespace = 'Microsoft.Network' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# Default { -# $ProviderNamespace, $rest = $resource.Type.Split('/') -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = $rest -join '/' -# ProviderNamespace = $ProviderNamespace -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# } -# } -# } + $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ + } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type + + foreach ($resource in $nestedResources) { + + switch ($resource.type) { + { $PSItem -like '*diagnosticsettings*' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'diagnosticsettings' + ProviderNamespace = 'Microsoft.insights' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + { $PSItem -like '*locks' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'locks' + ProviderNamespace = 'Microsoft.Authorization' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + { $PSItem -like '*roleAssignments' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'roleassignments' + ProviderNamespace = 'Microsoft.Authorization' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'privateEndpoints' + ProviderNamespace = 'Microsoft.Network' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + Default { + $ProviderNamespace, $rest = $resource.Type.Split('/') + $testCases += @{ + moduleName = $moduleFolderName + resourceType = $rest -join '/' + ProviderNamespace = $ProviderNamespace + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + } + } + } -# It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { - -# param( -# [string] $moduleName, -# [string] $ResourceType, -# [string] $TargetApi, -# [string] $ProviderNamespace, -# [PSCustomObject] $AvailableApiVersions, -# [bool] $AllowPreviewVersionsInAPITests -# ) - -# if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { -# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." -# Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." -# return -# } -# if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { -# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." -# Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." -# return -# } + It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { + + param( + [string] $moduleName, + [string] $ResourceType, + [string] $TargetApi, + [string] $ProviderNamespace, + [PSCustomObject] $AvailableApiVersions, + [bool] $AllowPreviewVersionsInAPITests + ) + + if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { + Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." + Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." + return + } + if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { + Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." + Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." + return + } -# $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType + $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType -# if (-not $resourceTypeApiVersions) { -# Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) -# continue -# } + if (-not $resourceTypeApiVersions) { + Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) + continue + } -# $approvedApiVersions = @() -# if ($AllowPreviewVersionsInAPITests) { -# # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview -# $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 -# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 -# } else { -# # We allow the latest 3 non-preview preview -# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 -# } + $approvedApiVersions = @() + if ($AllowPreviewVersionsInAPITests) { + # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview + $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 + $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 + } else { + # We allow the latest 3 non-preview preview + $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 + } -# $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending -# $approvedApiVersions | Should -Contain $TargetApi + $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending + $approvedApiVersions | Should -Contain $TargetApi -# # Provide a warning if an API version is second to next to expire. -# if ($approvedApiVersions -contains $TargetApi) { -# $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) + # Provide a warning if an API version is second to next to expire. + if ($approvedApiVersions -contains $TargetApi) { + $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) -# # Example -# # Available versions: -# # -# # 2017-08-01-beta -# # 2017-08-01 < $TargetApi (Index = 1) -# # 2017-07-14 -# # 2016-05-16 + # Example + # Available versions: + # + # 2017-08-01-beta + # 2017-08-01 < $TargetApi (Index = 1) + # 2017-07-14 + # 2016-05-16 -# if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { -# $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] -# Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) -# } -# } -# } -# } + if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { + $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] + Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) + } + } + } +} From cb8530864d887a42efb2f88037ca0d6c9a3a04ff Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:23:54 +0100 Subject: [PATCH 06/22] Update to latest --- .../staticValidation/module.tests.ps1 | 1894 ++++++++--------- 1 file changed, 947 insertions(+), 947 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index bd410210fa..d0488dfd52 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -37,508 +37,508 @@ $script:templateNotFoundException = 'No template file found in folder [{0}]' # - # Import any helper function used in this test script Import-Module (Join-Path $PSScriptRoot 'helper' 'helper.psm1') -Force -Describe 'File/folder tests' -Tag 'Modules' { +# Describe 'File/folder tests' -Tag 'Modules' { - Context 'General module folder tests' { +# Context 'General module folder tests' { - $moduleFolderTestCases = [System.Collections.ArrayList] @() - foreach ($moduleFolderPath in $moduleFolderPaths) { - $moduleFolderTestCases += @{ - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - moduleFolderPath = $moduleFolderPath - isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / - } - } - - if (Test-Path (Join-Path $repoRootPath '.github')) { - It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - - param( - [string] $moduleFolderName, - [string] $moduleFolderPath - ) - - $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' - $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() - $workflowPath = Join-Path $workflowsFolderName $workflowFileName - Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." - } - } - - if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { - It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { +# $moduleFolderTestCases = [System.Collections.ArrayList] @() +# foreach ($moduleFolderPath in $moduleFolderPaths) { +# $moduleFolderTestCases += @{ +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# moduleFolderPath = $moduleFolderPath +# isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / +# } +# } - param( - [string] $moduleFolderName, - [string] $moduleFolderPath - ) +# if (Test-Path (Join-Path $repoRootPath '.github')) { +# It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' - $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() - $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName - Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." - } - } +# param( +# [string] $moduleFolderName, +# [string] $moduleFolderPath +# ) - It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { +# $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' +# $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() +# $workflowPath = Join-Path $workflowsFolderName $workflowFileName +# Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." +# } +# } - param( [string] $moduleFolderPath ) +# if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { +# It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) - $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) - ($hasARM -or $hasBicep) | Should -Be $true - } +# param( +# [string] $moduleFolderName, +# [string] $moduleFolderPath +# ) - It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { +# $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' +# $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() +# $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName +# Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." +# } +# } - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true - } +# It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { - It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { +# param( [string] $moduleFolderPath ) - param( [string] $moduleFolderPath ) - Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true - } +# $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) +# $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) +# ($hasARM -or $hasBicep) | Should -Be $true +# } - It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { +# It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true - } - } +# param( [string] $moduleFolderPath ) +# (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true +# } - Context '.test folder' { +# It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - $folderTestCases = [System.Collections.ArrayList]@() - foreach ($moduleFolderPath in $moduleFolderPaths) { - if (Test-Path (Join-Path $moduleFolderPath '.test')) { - $folderTestCases += @{ - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - moduleFolderPath = $moduleFolderPath - } - } - } +# param( [string] $moduleFolderPath ) +# Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true +# } - It '[] Folder should contain one or more test files' -TestCases $folderTestCases { +# It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - param( - [string] $moduleFolderName, - [string] $moduleFolderPath - ) +# param( [string] $moduleFolderPath ) +# (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true +# } +# } - $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } - $moduleTestFilePaths.Count | Should -BeGreaterThan 0 - } +# Context '.test folder' { - $testFolderFilesTestCases = [System.Collections.ArrayList] @() - foreach ($moduleFolderPath in $moduleFolderPaths) { - $testFolderPath = Join-Path $moduleFolderPath '.test' - if (Test-Path $testFolderPath) { - foreach ($testFilePath in (Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ })) { - $testFolderFilesTestCases += @{ - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - testFilePath = $testFilePath - } - } - } - } +# $folderTestCases = [System.Collections.ArrayList]@() +# foreach ($moduleFolderPath in $moduleFolderPaths) { +# if (Test-Path (Join-Path $moduleFolderPath '.test')) { +# $folderTestCases += @{ +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# moduleFolderPath = $moduleFolderPath +# } +# } +# } - It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { +# It '[] Folder should contain one or more test files' -TestCases $folderTestCases { - param( - [string] $moduleFolderName, - [string] $testFilePath - ) - if ((Split-Path $testFilePath -Extension) -eq '.json') { - { (Get-Content $testFilePath) | ConvertFrom-Json } | Should -Not -Throw - } else { - Set-ItResult -Skipped -Because 'the module has no JSON test files.' - } - } - } -} -# Describe 'Readme tests' -Tag 'Readme' { +# param( +# [string] $moduleFolderName, +# [string] $moduleFolderPath +# ) -# Context 'Readme content tests' { +# $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } +# $moduleTestFilePaths.Count | Should -BeGreaterThan 0 +# } -# $readmeFolderTestCases = [System.Collections.ArrayList] @() +# $testFolderFilesTestCases = [System.Collections.ArrayList] @() # foreach ($moduleFolderPath in $moduleFolderPaths) { - -# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key -# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') -# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { -# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' -# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - -# if (-not $templateContent) { -# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) -# } -# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' -# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - -# if (-not $templateContent) { -# throw ($jsonTemplateLoadFailedException -f $templateFilePath) +# $testFolderPath = Join-Path $moduleFolderPath '.test' +# if (Test-Path $testFolderPath) { +# foreach ($testFilePath in (Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ })) { +# $testFolderFilesTestCases += @{ +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# testFilePath = $testFilePath # } -# } else { -# throw ($templateNotFoundException -f $moduleFolderPath) -# } -# $convertedTemplates[$moduleFolderPathKey] = @{ -# templateFilePath = $templateFilePath -# templateContent = $templateContent # } -# } else { -# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent -# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath -# } - -# $resourceTypeIdentifier = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - -# $readmeFolderTestCases += @{ -# moduleFolderName = $resourceTypeIdentifier -# moduleFolderPath = $moduleFolderPath -# templateContent = $templateContent -# templateFilePath = $templateFilePath -# readMeFilePath = Join-Path -Path $moduleFolderPath 'readme.md' -# readMeContent = Get-Content (Join-Path -Path $moduleFolderPath 'readme.md') -# isTopLevelModule = $resourceTypeIdentifier.Split('/').Count -eq 2 # / -# resourceTypeIdentifier = $resourceTypeIdentifier -# templateReferences = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] # } # } -# It '[] `Readme.md` file should not be empty' -TestCases $readmeFolderTestCases { +# It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { # param( # [string] $moduleFolderName, -# [object[]] $readMeContent +# [string] $testFilePath # ) -# $readMeContent | Should -Not -Be $null +# if ((Split-Path $testFilePath -Extension) -eq '.json') { +# { (Get-Content $testFilePath) | ConvertFrom-Json } | Should -Not -Throw +# } else { +# Set-ItResult -Skipped -Because 'the module has no JSON test files.' +# } # } +# } +# } +Describe 'Readme tests' -Tag 'Readme' { -# It '[] `Readme.md` file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples' -TestCases $readmeFolderTestCases { - -# param( -# [string] $moduleFolderName, -# [object[]] $readMeContent, -# [boolean] $isTopLevelModule -# ) + Context 'Readme content tests' { -# $expectedHeadersInOrder = @('Navigation', 'Resource types', 'Parameters', 'Outputs', 'Cross-referenced modules') + $readmeFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { -# if ($isTopLevelModule) { -# # Only top-level modules have parameter files and hence deployment examples -# $expectedHeadersInOrder += 'Deployment examples' -# } + # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key + $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') + if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' + $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable -# $actualHeadersInOrder = $readMeContent | Where-Object { $_ -like '#*' } | ForEach-Object { ($_ -replace '#', '').TrimStart() } + if (-not $templateContent) { + throw ($bicepTemplateCompilationFailedException -f $templateFilePath) + } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable -# $filteredActuals = $actualHeadersInOrder | Where-Object { $expectedHeadersInOrder -contains $_ } + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } + } else { + throw ($templateNotFoundException -f $moduleFolderPath) + } + $convertedTemplates[$moduleFolderPathKey] = @{ + templateFilePath = $templateFilePath + templateContent = $templateContent + } + } else { + $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath + } -# $missingHeaders = $expectedHeadersInOrder | Where-Object { $actualHeadersInOrder -notcontains $_ } -# $missingHeaders.Count | Should -Be 0 -Because ('the list of missing headers [{0}] should be empty' -f ($missingHeaders -join ',')) + $resourceTypeIdentifier = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + + $readmeFolderTestCases += @{ + moduleFolderName = $resourceTypeIdentifier + moduleFolderPath = $moduleFolderPath + templateContent = $templateContent + templateFilePath = $templateFilePath + readMeFilePath = Join-Path -Path $moduleFolderPath 'readme.md' + readMeContent = Get-Content (Join-Path -Path $moduleFolderPath 'readme.md') + isTopLevelModule = $resourceTypeIdentifier.Split('/').Count -eq 2 # / + resourceTypeIdentifier = $resourceTypeIdentifier + templateReferences = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] + } + } -# $filteredActuals | Should -Be $expectedHeadersInOrder -Because 'the headers should exist in the expected order' -# } + It '[] `Readme.md` file should not be empty' -TestCases $readmeFolderTestCases { -# It '[] Resources section should contain all resources from the template file' -TestCases $readmeFolderTestCases { + param( + [string] $moduleFolderName, + [object[]] $readMeContent + ) + $readMeContent | Should -Not -Be $null + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent -# ) + It '[] `Readme.md` file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples' -TestCases $readmeFolderTestCases { -# # Get ReadMe data -# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' + param( + [string] $moduleFolderName, + [object[]] $readMeContent, + [boolean] $isTopLevelModule + ) -# $ReadMeResourcesList = [System.Collections.ArrayList]@() -# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { -# $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() -# } + $expectedHeadersInOrder = @('Navigation', 'Resource types', 'Parameters', 'Outputs', 'Cross-referenced modules') -# # Get template data -# $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { -# $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique + if ($isTopLevelModule) { + # Only top-level modules have parameter files and hence deployment examples + $expectedHeadersInOrder += 'Deployment examples' + } -# # Compare -# $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ("list of template resources missing from the ReadMe's list [{0}] should be empty" -f ($differentiatingItems -join ',')) -# } + $actualHeadersInOrder = $readMeContent | Where-Object { $_ -like '#*' } | ForEach-Object { ($_ -replace '#', '').TrimStart() } -# It '[] Resources section should not contain more resources than the template file' -TestCases $readmeFolderTestCases { + $filteredActuals = $actualHeadersInOrder | Where-Object { $expectedHeadersInOrder -contains $_ } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent -# ) + $missingHeaders = $expectedHeadersInOrder | Where-Object { $actualHeadersInOrder -notcontains $_ } + $missingHeaders.Count | Should -Be 0 -Because ('the list of missing headers [{0}] should be empty' -f ($missingHeaders -join ',')) -# # Get ReadMe data -# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' + $filteredActuals | Should -Be $expectedHeadersInOrder -Because 'the headers should exist in the expected order' + } -# $ReadMeResourcesList = [System.Collections.ArrayList]@() -# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { -# $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() -# } + It '[] Resources section should contain all resources from the template file' -TestCases $readmeFolderTestCases { -# # Get template data -# $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { -# $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent + ) -# # Compare -# $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ("list of resources in the ReadMe's list [{0}] not in the template file should be empty" -f ($differentiatingItems -join ',')) -# } + # Get ReadMe data + $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' -# It '[] Parameters section should contain a table for each existing parameter category in the following order: Required, Conditional, Optional, Generated' -TestCases $readmeFolderTestCases { + $ReadMeResourcesList = [System.Collections.ArrayList]@() + for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { + $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent -# ) + # Get template data + $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique -# $expectColumnsInOrder = @('Required', 'Conditional', 'Optional', 'Generated') + # Compare + $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ("list of template resources missing from the ReadMe's list [{0}] should be empty" -f ($differentiatingItems -join ',')) + } -# ## Get all descriptions -# $descriptions = $templateContent.parameters.Values.metadata.description + It '[] Resources section should not contain more resources than the template file' -TestCases $readmeFolderTestCases { -# ## Get the module parameter categories -# $expectedParamCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique # Get categories in template -# $expectedParamCategoriesInOrder = $expectColumnsInOrder | Where-Object { $_ -in $expectedParamCategories } # add required ones in order -# $expectedParamCategoriesInOrder += $expectedParamCategories | Where-Object { $_ -notin $expectColumnsInOrder } # add non-required ones after + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent + ) -# $actualParamCategories = $readMeContent | Select-String -Pattern '^\*\*(.+) parameters\*\*$' -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } # get actual in readme + # Get ReadMe data + $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Resource Types' -# $actualParamCategories | Should -Be $expectedParamCategoriesInOrder -# } + $ReadMeResourcesList = [System.Collections.ArrayList]@() + for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { + $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } -# It '[] Parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows.' -TestCases $readmeFolderTestCases { + # Get template data + $templateResources = (Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent -# ) + # Compare + $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ("list of resources in the ReadMe's list [{0}] not in the template file should be empty" -f ($differentiatingItems -join ',')) + } -# ## Get all descriptions -# $descriptions = $templateContent.parameters.Values.metadata.description + It '[] Parameters section should contain a table for each existing parameter category in the following order: Required, Conditional, Optional, Generated' -TestCases $readmeFolderTestCases { -# ## Get the module parameter categories -# $paramCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent + ) -# foreach ($paramCategory in $paramCategories) { + $expectColumnsInOrder = @('Required', 'Conditional', 'Optional', 'Generated') -# # Filter to relevant items -# [array] $categoryParameters = $templateContent.parameters.Values | Where-Object { $_.metadata.description -like "$paramCategory. *" } | Sort-Object -Property 'Name' -Culture 'en-US' + ## Get all descriptions + $descriptions = $templateContent.parameters.Values.metadata.description -# # Check properties for later reference -# $shouldHaveDefault = $categoryParameters.defaultValue.count -gt 0 -# $shouldHaveAllowed = $categoryParameters.allowedValues.count -gt 0 + ## Get the module parameter categories + $expectedParamCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique # Get categories in template + $expectedParamCategoriesInOrder = $expectColumnsInOrder | Where-Object { $_ -in $expectedParamCategories } # add required ones in order + $expectedParamCategoriesInOrder += $expectedParamCategories | Where-Object { $_ -notin $expectColumnsInOrder } # add non-required ones after -# $expectedColumnsInOrder = @('Parameter Name', 'Type') -# if ($shouldHaveDefault) { $expectedColumnsInOrder += @('Default Value') } -# if ($shouldHaveAllowed) { $expectedColumnsInOrder += @('Allowed Values') } -# $expectedColumnsInOrder += @('Description') + $actualParamCategories = $readMeContent | Select-String -Pattern '^\*\*(.+) parameters\*\*$' -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } # get actual in readme -# $readMeCategoryIndex = $readMeContent | Select-String -Pattern "^\*\*$paramCategory parameters\*\*$" | ForEach-Object { $_.LineNumber } + $actualParamCategories | Should -Be $expectedParamCategoriesInOrder + } -# $tableStartIndex = $readMeCategoryIndex -# while ($readMeContent[$tableStartIndex] -notlike '*|*' -and -not ($tableStartIndex -ge $readMeContent.count)) { -# $tableStartIndex++ -# } + It '[] Parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows.' -TestCases $readmeFolderTestCases { -# $readmeCategoryColumns = ($readMeContent[$tableStartIndex] -split '\|') | ForEach-Object { $_.Trim() } | Where-Object { -not [String]::IsNullOrEmpty($_) } -# $readmeCategoryColumns | Should -Be $expectedColumnsInOrder -# } -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent + ) -# It '[] Parameters section should contain all parameters from the template file' -TestCases $readmeFolderTestCases { + ## Get all descriptions + $descriptions = $templateContent.parameters.Values.metadata.description -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent -# ) + ## Get the module parameter categories + $paramCategories = $descriptions | ForEach-Object { $_.Split('.')[0] } | Select-Object -Unique -# # Get Template data -# $parameters = $templateContent.parameters.Keys + foreach ($paramCategory in $paramCategories) { -# # Get ReadMe data -# ## Get section start index -# $sectionStartIndex = Get-MarkdownSectionStartIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Parameters' + # Filter to relevant items + [array] $categoryParameters = $templateContent.parameters.Values | Where-Object { $_.metadata.description -like "$paramCategory. *" } | Sort-Object -Property 'Name' -Culture 'en-US' -# if ($sectionStartIndex -ge $readMeContent.count) { -# throw 'Parameters section is missing in the Readme. Please add and re-run the tests.' -# } + # Check properties for later reference + $shouldHaveDefault = $categoryParameters.defaultValue.count -gt 0 + $shouldHaveAllowed = $categoryParameters.allowedValues.count -gt 0 -# $parametersSectionEndIndex = Get-MarkdownSectionEndIndex -ReadMeContent $readMeContent -SectionStartIndex $sectionStartIndex + $expectedColumnsInOrder = @('Parameter Name', 'Type') + if ($shouldHaveDefault) { $expectedColumnsInOrder += @('Default Value') } + if ($shouldHaveAllowed) { $expectedColumnsInOrder += @('Allowed Values') } + $expectedColumnsInOrder += @('Description') -# ## Iterate over all parameter tables -# $parametersList = [System.Collections.ArrayList]@() -# $sectionIndex = $sectionStartIndex -# while ($sectionIndex -lt $parametersSectionEndIndex) { -# ### Get table start index -# $parametersTableStartIndex = $sectionIndex -# while ($readMeContent[$parametersTableStartIndex] -notlike '*|*' -and -not ($parametersTableStartIndex -ge $readMeContent.count)) { -# $parametersTableStartIndex++ -# } -# Write-Verbose ("[loop] Start row of the parameter table: $parametersTableStartIndex") + $readMeCategoryIndex = $readMeContent | Select-String -Pattern "^\*\*$paramCategory parameters\*\*$" | ForEach-Object { $_.LineNumber } -# ### Get table end index -# $parametersTableEndIndex = $parametersTableStartIndex + 2 # Header row + table separator row -# while ($readMeContent[$parametersTableEndIndex] -like '*|*' -and -not ($parametersTableEndIndex -ge $readMeContent.count)) { -# $parametersTableEndIndex++ -# } -# Write-Verbose ("[loop] End row of the parameter table: $parametersTableEndIndex") + $tableStartIndex = $readMeCategoryIndex + while ($readMeContent[$tableStartIndex] -notlike '*|*' -and -not ($tableStartIndex -ge $readMeContent.count)) { + $tableStartIndex++ + } -# for ($tableIndex = $parametersTableStartIndex + 2; $tableIndex -lt $parametersTableEndIndex; $tableIndex++) { -# $parametersList += $readMeContent[$tableIndex].Split('|')[1].Replace('`', '').Trim() -# } -# $sectionIndex = $parametersTableEndIndex + 1 -# } + $readmeCategoryColumns = ($readMeContent[$tableStartIndex] -split '\|') | ForEach-Object { $_.Trim() } | Where-Object { -not [String]::IsNullOrEmpty($_) } + $readmeCategoryColumns | Should -Be $expectedColumnsInOrder + } + } -# # Test -# $differentiatingItems = $parameters | Where-Object { $parametersList -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of template parameters missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# } + It '[] Parameters section should contain all parameters from the template file' -TestCases $readmeFolderTestCases { -# It '[] Outputs section should contain a table with these column names in order: Output Name, Type' -TestCases $readmeFolderTestCases { + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent + ) -# param( -# [string] $moduleFolderName, -# $readMeContent -# ) + # Get Template data + $parameters = $templateContent.parameters.Keys -# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' + # Get ReadMe data + ## Get section start index + $sectionStartIndex = Get-MarkdownSectionStartIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Parameters' -# $outputsTableHeader = $readMeContent[$tableStartIndex].Split('|').Trim() | Where-Object { -not [String]::IsNullOrEmpty($_) } + if ($sectionStartIndex -ge $readMeContent.count) { + throw 'Parameters section is missing in the Readme. Please add and re-run the tests.' + } -# # Test -# $expectedOutputsTableOrder = @('Output Name', 'Type') -# $differentiatingItems = $expectedOutputsTableOrder | Where-Object { $outputsTableHeader -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of "Outputs" table columns missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# } + $parametersSectionEndIndex = Get-MarkdownSectionEndIndex -ReadMeContent $readMeContent -SectionStartIndex $sectionStartIndex -# It '[] Output section should contain all outputs defined in the template file' -TestCases $readmeFolderTestCases { + ## Iterate over all parameter tables + $parametersList = [System.Collections.ArrayList]@() + $sectionIndex = $sectionStartIndex + while ($sectionIndex -lt $parametersSectionEndIndex) { + ### Get table start index + $parametersTableStartIndex = $sectionIndex + while ($readMeContent[$parametersTableStartIndex] -notlike '*|*' -and -not ($parametersTableStartIndex -ge $readMeContent.count)) { + $parametersTableStartIndex++ + } + Write-Verbose ("[loop] Start row of the parameter table: $parametersTableStartIndex") -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent -# ) + ### Get table end index + $parametersTableEndIndex = $parametersTableStartIndex + 2 # Header row + table separator row + while ($readMeContent[$parametersTableEndIndex] -like '*|*' -and -not ($parametersTableEndIndex -ge $readMeContent.count)) { + $parametersTableEndIndex++ + } + Write-Verbose ("[loop] End row of the parameter table: $parametersTableEndIndex") -# # Get ReadMe data -# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' + for ($tableIndex = $parametersTableStartIndex + 2; $tableIndex -lt $parametersTableEndIndex; $tableIndex++) { + $parametersList += $readMeContent[$tableIndex].Split('|')[1].Replace('`', '').Trim() + } + $sectionIndex = $parametersTableEndIndex + 1 + } -# $ReadMeOutputsList = [System.Collections.ArrayList]@() -# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { -# $ReadMeOutputsList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() -# } + # Test + $differentiatingItems = $parameters | Where-Object { $parametersList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of template parameters missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } -# # Template data -# $expectedOutputs = $templateContent.outputs.Keys + It '[] Outputs section should contain a table with these column names in order: Output Name, Type' -TestCases $readmeFolderTestCases { -# # Test -# $differentiatingItems = $expectedOutputs | Where-Object { $ReadMeOutputsList -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of template outputs missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + param( + [string] $moduleFolderName, + $readMeContent + ) -# $differentiatingItems = $ReadMeOutputsList | Where-Object { $expectedOutputs -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of excess template outputs defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# } + $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' -# It '[] Dependencies section should contain all cross-references defined in the template file' -TestCases $readmeFolderTestCases { + $outputsTableHeader = $readMeContent[$tableStartIndex].Split('|').Trim() | Where-Object { -not [String]::IsNullOrEmpty($_) } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [object[]] $readMeContent, -# [string] $resourceTypeIdentifier -# ) + # Test + $expectedOutputsTableOrder = @('Output Name', 'Type') + $differentiatingItems = $expectedOutputsTableOrder | Where-Object { $outputsTableHeader -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of "Outputs" table columns missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } -# # Get ReadMe data -# $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*## Cross-referenced modules' + It '[] Output section should contain all outputs defined in the template file' -TestCases $readmeFolderTestCases { -# $ReadMeDependenciesList = @{ -# localPathReferences = @() -# remoteReferences = @() -# } -# for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { -# $type = $readMeContent[$index].Split('|')[2].Trim() + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent + ) -# switch ($type) { -# 'Local reference' { -# $ReadMeDependenciesList.localPathReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() -# } -# 'Remote reference' { -# $ReadMeDependenciesList.remoteReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() -# } -# Default { -# throw "Unkown type reference [$type]. Only [Local reference] & [Remote reference] are known. Please update ReadMe or test script." -# } -# } -# } + # Get ReadMe data + $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*# Outputs' -# # Template data -# $expectedDependencies = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] + $ReadMeOutputsList = [System.Collections.ArrayList]@() + for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { + $ReadMeOutputsList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } -# # Test -# if ($expectedDependencies.localPathReferences) { -# $differentiatingItems = @() + $expectedDependencies.localPathReferences | Where-Object { $ReadMeDependenciesList.localPathReferences -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of local template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + # Template data + $expectedOutputs = $templateContent.outputs.Keys + # Test + $differentiatingItems = $expectedOutputs | Where-Object { $ReadMeOutputsList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of template outputs missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# $differentiatingItems = @() + $ReadMeDependenciesList.localPathReferences | Where-Object { $expectedDependencies.localPathReferences -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of excess local template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# } + $differentiatingItems = $ReadMeOutputsList | Where-Object { $expectedOutputs -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of excess template outputs defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } -# if ($expectedDependencies.remoteReferences) { -# $differentiatingItems = @() + $expectedDependencies.remoteReferences | Where-Object { $ReadMeDependenciesList.remoteReferences -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of remote template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + It '[] Dependencies section should contain all cross-references defined in the template file' -TestCases $readmeFolderTestCases { + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [object[]] $readMeContent, + [string] $resourceTypeIdentifier + ) -# $differentiatingItems = @() + $ReadMeDependenciesList.remoteReferences | Where-Object { $expectedDependencies.remoteReferences -notcontains $_ } -# $differentiatingItems.Count | Should -Be 0 -Because ('list of excess remote template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# } -# } + # Get ReadMe data + $tableStartIndex, $tableEndIndex = Get-TableStartAndEndIndex -ReadMeContent $readMeContent -MarkdownSectionIdentifier '*## Cross-referenced modules' -# It '[] `Set-ModuleReadMe` script should not apply any updates' -TestCases $readmeFolderTestCases { + $ReadMeDependenciesList = @{ + localPathReferences = @() + remoteReferences = @() + } + for ($index = $tableStartIndex + 2; $index -lt $tableEndIndex; $index++) { + $type = $readMeContent[$index].Split('|')[2].Trim() -# param( -# [string] $moduleFolderName, -# [string] $templateFilePath, -# [hashtable] $templateContent, -# [string] $readMeFilePath -# ) + switch ($type) { + 'Local reference' { + $ReadMeDependenciesList.localPathReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } + 'Remote reference' { + $ReadMeDependenciesList.remoteReferences += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } + Default { + throw "Unkown type reference [$type]. Only [Local reference] & [Remote reference] are known. Please update ReadMe or test script." + } + } + } -# # Get current hash -# $fileHashBefore = (Get-FileHash $readMeFilePath).Hash + # Template data + $expectedDependencies = (Get-CrossReferencedModuleList)[$resourceTypeIdentifier] -# # Load function -# . (Join-Path $repoRootPath 'utilities' 'tools' 'Set-ModuleReadMe.ps1') + # Test + if ($expectedDependencies.localPathReferences) { + $differentiatingItems = @() + $expectedDependencies.localPathReferences | Where-Object { $ReadMeDependenciesList.localPathReferences -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of local template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# # Apply update with already compiled template content -# Set-ModuleReadMe -TemplateFilePath $templateFilePath -TemplateFileContent $templateContent -# # Get hash after 'update' -# $fileHashAfter = (Get-FileHash $readMeFilePath).Hash + $differentiatingItems = @() + $ReadMeDependenciesList.localPathReferences | Where-Object { $expectedDependencies.localPathReferences -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of excess local template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } -# # Compare -# $filesAreTheSame = $fileHashBefore -eq $fileHashAfter -# if (-not $filesAreTheSame) { -# $diffReponse = git diff $readMeFilePath -# Write-Warning ($diffReponse | Out-String) -Verbose + if ($expectedDependencies.remoteReferences) { + $differentiatingItems = @() + $expectedDependencies.remoteReferences | Where-Object { $ReadMeDependenciesList.remoteReferences -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of remote template dependencies missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) -# # Reset readme file to original state -# git checkout HEAD -- $readMeFilePath -# } -# $filesAreTheSame | Should -Be $true -Because 'The file hashes before and after applying the Set-ModuleReadMe function should be identical' -# } -# } -# } + + $differentiatingItems = @() + $ReadMeDependenciesList.remoteReferences | Where-Object { $expectedDependencies.remoteReferences -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of excess remote template references defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } + } + + It '[] `Set-ModuleReadMe` script should not apply any updates' -TestCases $readmeFolderTestCases { + + param( + [string] $moduleFolderName, + [string] $templateFilePath, + [hashtable] $templateContent, + [string] $readMeFilePath + ) + + # Get current hash + $fileHashBefore = (Get-FileHash $readMeFilePath).Hash + + # Load function + . (Join-Path $repoRootPath 'utilities' 'tools' 'Set-ModuleReadMe.ps1') + + # Apply update with already compiled template content + Set-ModuleReadMe -TemplateFilePath $templateFilePath -TemplateFileContent $templateContent + + # Get hash after 'update' + $fileHashAfter = (Get-FileHash $readMeFilePath).Hash + + # Compare + $filesAreTheSame = $fileHashBefore -eq $fileHashAfter + if (-not $filesAreTheSame) { + $diffReponse = git diff $readMeFilePath + Write-Warning ($diffReponse | Out-String) -Verbose + + # Reset readme file to original state + git checkout HEAD -- $readMeFilePath + } + $filesAreTheSame | Should -Be $true -Because 'The file hashes before and after applying the Set-ModuleReadMe function should be identical' + } + } +} # Describe 'Test file tests' -Tag 'TestTemplate' { @@ -672,657 +672,657 @@ Describe 'File/folder tests' -Tag 'Modules' { # } # } -Describe 'Deployment template tests' -Tag 'Template' { +# Describe 'Deployment template tests' -Tag 'Template' { - Context 'General template' { +# Context 'General template' { - $deploymentFolderTestCases = [System.Collections.ArrayList] @() - foreach ($moduleFolderPath in $moduleFolderPaths) { +# $deploymentFolderTestCases = [System.Collections.ArrayList] @() +# foreach ($moduleFolderPath in $moduleFolderPaths) { - # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key - $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') - if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { - if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' - $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable +# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key +# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') +# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { +# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' +# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - if (-not $templateContent) { - throw ($bicepTemplateCompilationFailedException -f $templateFilePath) - } - } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable +# if (-not $templateContent) { +# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) +# } +# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' +# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } else { - throw ($templateNotFoundException -f $moduleFolderPath) - } - $convertedTemplates[$moduleFolderPathKey] = @{ - templateFilePath = $templateFilePath - templateContent = $templateContent - } - } else { - $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent - $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath - } +# if (-not $templateContent) { +# throw ($jsonTemplateLoadFailedException -f $templateFilePath) +# } +# } else { +# throw ($templateNotFoundException -f $moduleFolderPath) +# } +# $convertedTemplates[$moduleFolderPathKey] = @{ +# templateFilePath = $templateFilePath +# templateContent = $templateContent +# } +# } else { +# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent +# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath +# } - # Parameter file test cases - $testFileTestCases = @() - $templateFile_Parameters = $templateContent.parameters - $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object - $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object +# # Parameter file test cases +# $testFileTestCases = @() +# $templateFile_Parameters = $templateContent.parameters +# $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object +# $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object - if (Test-Path (Join-Path $moduleFolderPath '.test')) { +# if (Test-Path (Join-Path $moduleFolderPath '.test')) { - # Can be removed after full migration to bicep test files - $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } +# # Can be removed after full migration to bicep test files +# $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } - foreach ($moduleTestFilePath in $moduleTestFilePaths) { - if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { +# foreach ($moduleTestFilePath in $moduleTestFilePaths) { +# if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { - $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable +# $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable - # Skipping any file that is not actually a ARM-JSON parameter file - $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' - if (-not $isParameterFile) { - continue - } +# # Skipping any file that is not actually a ARM-JSON parameter file +# $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' +# if (-not $isParameterFile) { +# continue +# } - $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object - } else { - $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable - $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test - } - $testFileTestCases += @{ - testFile_Path = $moduleTestFilePath - testFile_Name = Split-Path $moduleTestFilePath -Leaf - testFile_AllParameterNames = $deploymentTestFile_AllParameterNames - templateFile_AllParameterNames = $TemplateFile_AllParameterNames - templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames - tokenConfiguration = $tokenConfiguration - } - } - } +# $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object +# } else { +# $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable +# $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test +# } +# $testFileTestCases += @{ +# testFile_Path = $moduleTestFilePath +# testFile_Name = Split-Path $moduleTestFilePath -Leaf +# testFile_AllParameterNames = $deploymentTestFile_AllParameterNames +# templateFile_AllParameterNames = $TemplateFile_AllParameterNames +# templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames +# tokenConfiguration = $tokenConfiguration +# } +# } +# } - # Test file setup - $deploymentFolderTestCases += @{ - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - templateContent = $templateContent - templateFilePath = $templateFilePath - testFileTestCases = $testFileTestCases - } - } +# # Test file setup +# $deploymentFolderTestCases += @{ +# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# templateContent = $templateContent +# templateFilePath = $templateFilePath +# testFileTestCases = $testFileTestCases +# } +# } - It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { +# It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $templateContent | Should -Not -Be $null - } +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $templateContent | Should -Not -Be $null +# } - It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { - # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! - # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) +# It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { +# # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! +# # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) - $Schemaverion = $templateContent.'$schema' - $SchemaArray = @() - if ($Schemaverion -eq $RGdeployment) { - $SchemaOutput = $true - } elseIf ($Schemaverion -eq $Subscriptiondeployment) { - $SchemaOutput = $true - } elseIf ($Schemaverion -eq $MGdeployment) { - $SchemaOutput = $true - } elseIf ($Schemaverion -eq $Tenantdeployment) { - $SchemaOutput = $true - } else { - $SchemaOutput = $false - } - $SchemaArray += $SchemaOutput - $SchemaArray | Should -Not -Contain $false - } +# $Schemaverion = $templateContent.'$schema' +# $SchemaArray = @() +# if ($Schemaverion -eq $RGdeployment) { +# $SchemaOutput = $true +# } elseIf ($Schemaverion -eq $Subscriptiondeployment) { +# $SchemaOutput = $true +# } elseIf ($Schemaverion -eq $MGdeployment) { +# $SchemaOutput = $true +# } elseIf ($Schemaverion -eq $Tenantdeployment) { +# $SchemaOutput = $true +# } else { +# $SchemaOutput = $false +# } +# $SchemaArray += $SchemaOutput +# $SchemaArray | Should -Not -Contain $false +# } - It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { +# It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $Schemaverion = $templateContent.'$schema' - ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true - } +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $Schemaverion = $templateContent.'$schema' +# ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true +# } - It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { - #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $ApiVersion = $templateContent.resources.apiVersion - $ApiVersionArray = @() - foreach ($API in $ApiVersion) { - if ($API.Substring(0, 2) -eq '20') { - $ApiVersionOutput = $true - } elseIf ($API.substring(1, 10) -eq 'parameters') { - # An API version should not be referenced as a parameter - $ApiVersionOutput = $false - } elseIf ($API.substring(1, 10) -eq 'variables') { - # An API version should not be referenced as a variable - $ApiVersionOutput = $false - } else { - $ApiVersionOutput = $false - } - $ApiVersionArray += $ApiVersionOutput - } - $ApiVersionArray | Should -Not -Contain $false - } +# It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { +# #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $ApiVersion = $templateContent.resources.apiVersion +# $ApiVersionArray = @() +# foreach ($API in $ApiVersion) { +# if ($API.Substring(0, 2) -eq '20') { +# $ApiVersionOutput = $true +# } elseIf ($API.substring(1, 10) -eq 'parameters') { +# # An API version should not be referenced as a parameter +# $ApiVersionOutput = $false +# } elseIf ($API.substring(1, 10) -eq 'variables') { +# # An API version should not be referenced as a variable +# $ApiVersionOutput = $false +# } else { +# $ApiVersionOutput = $false +# } +# $ApiVersionArray += $ApiVersionOutput +# } +# $ApiVersionArray | Should -Not -Contain $false +# } - It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { +# It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $templateContent.Keys | Should -Contain '$schema' - $templateContent.Keys | Should -Contain 'contentVersion' - $templateContent.Keys | Should -Contain 'resources' - } +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $templateContent.Keys | Should -Contain '$schema' +# $templateContent.Keys | Should -Contain 'contentVersion' +# $templateContent.Keys | Should -Contain 'resources' +# } - It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { +# It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - if ($lock = $templateContent.parameters.lock) { - $lock.Keys | Should -Contain 'defaultValue' - $lock.defaultValue | Should -Be '' - } - } +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# if ($lock = $templateContent.parameters.lock) { +# $lock.Keys | Should -Contain 'defaultValue' +# $lock.defaultValue | Should -Be '' +# } +# } - It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { +# It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) - if (-not $templateContent.parameters) { - Set-ItResult -Skipped -Because 'the module template has no parameters.' - return - } +# if (-not $templateContent.parameters) { +# Set-ItResult -Skipped -Because 'the module template has no parameters.' +# return +# } - $CamelCasingFlag = @() - $Parameter = $templateContent.parameters.Keys - foreach ($Param in $Parameter) { - if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { - $CamelCasingFlag += $false - } else { - $CamelCasingFlag += $true - } - } - $CamelCasingFlag | Should -Not -Contain $false - } +# $CamelCasingFlag = @() +# $Parameter = $templateContent.parameters.Keys +# foreach ($Param in $Parameter) { +# if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { +# $CamelCasingFlag += $false +# } else { +# $CamelCasingFlag += $true +# } +# } +# $CamelCasingFlag | Should -Not -Contain $false +# } - It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { +# It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) - if (-not $templateContent.variables) { - Set-ItResult -Skipped -Because 'the module template has no variables.' - return - } +# if (-not $templateContent.variables) { +# Set-ItResult -Skipped -Because 'the module template has no variables.' +# return +# } - $CamelCasingFlag = @() - $Variable = $templateContent.variables.Keys +# $CamelCasingFlag = @() +# $Variable = $templateContent.variables.Keys - foreach ($Variab in $Variable) { - if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { - $CamelCasingFlag += $false - } else { - $CamelCasingFlag += $true - } - } - $CamelCasingFlag | Should -Not -Contain $false - } +# foreach ($Variab in $Variable) { +# if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { +# $CamelCasingFlag += $false +# } else { +# $CamelCasingFlag += $true +# } +# } +# $CamelCasingFlag | Should -Not -Contain $false +# } - It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { +# It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $CamelCasingFlag = @() - $Outputs = $templateContent.outputs.Keys +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $CamelCasingFlag = @() +# $Outputs = $templateContent.outputs.Keys - foreach ($Output in $Outputs) { - if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { - $CamelCasingFlag += $false - } else { - $CamelCasingFlag += $true - } - } - $CamelCasingFlag | Should -Not -Contain $false - } +# foreach ($Output in $Outputs) { +# if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { +# $CamelCasingFlag += $false +# } else { +# $CamelCasingFlag += $true +# } +# } +# $CamelCasingFlag | Should -Not -Contain $false +# } - It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { +# It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $enableDefaultTelemetryFlag = @() - $Schemaverion = $templateContent.'$schema' - if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { - if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { - $enableDefaultTelemetryFlag += $true - } else { - $enableDefaultTelemetryFlag += $false - } - } - $enableDefaultTelemetryFlag | Should -Not -Contain $false - } +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $enableDefaultTelemetryFlag = @() +# $Schemaverion = $templateContent.'$schema' +# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { +# if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { +# $enableDefaultTelemetryFlag += $true +# } else { +# $enableDefaultTelemetryFlag += $false +# } +# } +# $enableDefaultTelemetryFlag | Should -Not -Contain $false +# } - It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { +# It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) - $LocationFlag = $true - $Schemaverion = $templateContent.'$schema' - if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { - $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue - $Locationparamoutput = $templateContent.parameters.Keys - if ($Locationparamoutput -contains 'Location') { - if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { - $LocationFlag = $true - } else { - - $LocationFlag = $false - } - $LocationFlag | Should -Contain $true - } - } - } +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) +# $LocationFlag = $true +# $Schemaverion = $templateContent.'$schema' +# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { +# $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue +# $Locationparamoutput = $templateContent.parameters.Keys +# if ($Locationparamoutput -contains 'Location') { +# if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { +# $LocationFlag = $true +# } else { + +# $LocationFlag = $false +# } +# $LocationFlag | Should -Contain $true +# } +# } +# } - It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { +# It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [string] $templateFilePath - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [string] $templateFilePath +# ) - $outputs = $templateContent.outputs +# $outputs = $templateContent.outputs - $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] - $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } +# $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] +# $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } - if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { - # If the main resource has a location property, an output should be returned too - $outputs.keys | Should -Contain 'location' +# if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { +# # If the main resource has a location property, an output should be returned too +# $outputs.keys | Should -Contain 'location' - # It should further reference the location property of the primary resource and not e.g. the location input parameter - $outputs.location.value | Should -Match $primaryResourceType - } - } +# # It should further reference the location property of the primary resource and not e.g. the location input parameter +# $outputs.location.value | Should -Match $primaryResourceType +# } +# } - It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { +# It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - [string] $templateFilePath - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# [string] $templateFilePath +# ) - $outputs = $templateContent.outputs.Keys - $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath +# $outputs = $templateContent.outputs.Keys +# $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath - if ($deploymentScope -eq 'resourceGroup') { - $outputs | Should -Contain 'resourceGroupName' - } - } +# if ($deploymentScope -eq 'resourceGroup') { +# $outputs | Should -Contain 'resourceGroupName' +# } +# } - It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { +# It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - $templateFilePath - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# $templateFilePath +# ) - # check if module contains a 'primary' resource we could draw a name from - $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' - if ($templateContent.resources.type -notcontains $moduleResourceType) { - Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' - return - } +# # check if module contains a 'primary' resource we could draw a name from +# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' +# if ($templateContent.resources.type -notcontains $moduleResourceType) { +# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' +# return +# } - # Otherwise test for standard outputs - $outputs = $templateContent.outputs.Keys - $outputs | Should -Contain 'name' - } +# # Otherwise test for standard outputs +# $outputs = $templateContent.outputs.Keys +# $outputs | Should -Contain 'name' +# } - It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { +# It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent, - $templateFilePath - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent, +# $templateFilePath +# ) - # check if module contains a 'primary' resource we could draw a name from - $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' - if ($templateContent.resources.type -notcontains $moduleResourceType) { - Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' - return - } +# # check if module contains a 'primary' resource we could draw a name from +# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' +# if ($templateContent.resources.type -notcontains $moduleResourceType) { +# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' +# return +# } - # Otherwise test for standard outputs - $outputs = $templateContent.outputs.Keys - $outputs | Should -Contain 'resourceId' - } +# # Otherwise test for standard outputs +# $outputs = $templateContent.outputs.Keys +# $outputs | Should -Contain 'resourceId' +# } - It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { +# It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) - if (-not $templateContent.parameters) { - Set-ItResult -Skipped -Because 'the module template has no parameters.' - return - } +# if (-not $templateContent.parameters) { +# Set-ItResult -Skipped -Because 'the module template has no parameters.' +# return +# } - $incorrectParameters = @() - $templateParameters = $templateContent.parameters.Keys - foreach ($parameter in $templateParameters) { - $data = ($templateContent.parameters.$parameter.metadata).description - if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { - $incorrectParameters += $parameter - } - } - $incorrectParameters | Should -BeNullOrEmpty - } +# $incorrectParameters = @() +# $templateParameters = $templateContent.parameters.Keys +# foreach ($parameter in $templateParameters) { +# $data = ($templateContent.parameters.$parameter.metadata).description +# if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { +# $incorrectParameters += $parameter +# } +# } +# $incorrectParameters | Should -BeNullOrEmpty +# } - It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { +# It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) - if (-not $templateContent.parameters) { - Set-ItResult -Skipped -Because 'the module template has no parameters.' - return - } +# if (-not $templateContent.parameters) { +# Set-ItResult -Skipped -Because 'the module template has no parameters.' +# return +# } - $incorrectParameters = @() - $templateParameters = $templateContent.parameters.Keys - foreach ($parameter in $templateParameters) { - $data = ($templateContent.parameters.$parameter.metadata).description - switch -regex ($data) { - '^Conditional. .*' { - if ($data -notmatch '.*\. Required if .*') { - $incorrectParameters += $parameter - } - } - } - } - $incorrectParameters | Should -BeNullOrEmpty - } +# $incorrectParameters = @() +# $templateParameters = $templateContent.parameters.Keys +# foreach ($parameter in $templateParameters) { +# $data = ($templateContent.parameters.$parameter.metadata).description +# switch -regex ($data) { +# '^Conditional. .*' { +# if ($data -notmatch '.*\. Required if .*') { +# $incorrectParameters += $parameter +# } +# } +# } +# } +# $incorrectParameters | Should -BeNullOrEmpty +# } - It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { +# It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { - param( - [string] $moduleFolderName, - [hashtable] $templateContent - ) +# param( +# [string] $moduleFolderName, +# [hashtable] $templateContent +# ) - if (-not $templateContent.outputs) { - Set-ItResult -Skipped -Because 'the module template has no outputs.' - return - } +# if (-not $templateContent.outputs) { +# Set-ItResult -Skipped -Because 'the module template has no outputs.' +# return +# } - $incorrectOutputs = @() - $templateOutputs = $templateContent.outputs.Keys - foreach ($output in $templateOutputs) { - $data = ($templateContent.outputs.$output.metadata).description - if ($data -notmatch '(?s)^[A-Z].+\.$') { - $incorrectOutputs += $output - } - } - $incorrectOutputs | Should -BeNullOrEmpty - } +# $incorrectOutputs = @() +# $templateOutputs = $templateContent.outputs.Keys +# foreach ($output in $templateOutputs) { +# $data = ($templateContent.outputs.$output.metadata).description +# if ($data -notmatch '(?s)^[A-Z].+\.$') { +# $incorrectOutputs += $output +# } +# } +# $incorrectOutputs | Should -BeNullOrEmpty +# } - # PARAMETER Tests - It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { - param ( - [hashtable[]] $testFileTestCases - ) +# # PARAMETER Tests +# It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { +# param ( +# [hashtable[]] $testFileTestCases +# ) - foreach ($parameterFileTestCase in $testFileTestCases) { - $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames - $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames +# foreach ($parameterFileTestCase in $testFileTestCases) { +# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames +# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames - $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } - $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) - } - } +# $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } +# $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) +# } +# } - It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { - param ( - [hashtable[]] $testFileTestCases - ) +# It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { +# param ( +# [hashtable[]] $testFileTestCases +# ) - foreach ($parameterFileTestCase in $testFileTestCases) { - $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames - $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames +# foreach ($parameterFileTestCase in $testFileTestCases) { +# $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames +# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames - $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } - $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) - } - } +# $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } +# $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) +# } +# } - It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { - param ( - [hashtable[]] $testFileTestCases, - [hashtable] $templateContent - ) +# It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { +# param ( +# [hashtable[]] $testFileTestCases, +# [hashtable] $templateContent +# ) - foreach ($parameterFileTestCase in $testFileTestCases) { - $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames - $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames - $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } +# foreach ($parameterFileTestCase in $testFileTestCases) { +# $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames +# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames +# $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } - $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } - $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) - } - } - } -} +# $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } +# $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) +# } +# } +# } +# } -Describe 'API version tests' -Tag 'ApiCheck' { +# Describe 'API version tests' -Tag 'ApiCheck' { - $testCases = @() - $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' +# $testCases = @() +# $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' - if (-not (Test-Path $apiSpecsFilePath)) { - Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" - return - } +# if (-not (Test-Path $apiSpecsFilePath)) { +# Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" +# return +# } - $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json - foreach ($moduleFolderPath in $moduleFolderPaths) { +# $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json +# foreach ($moduleFolderPath in $moduleFolderPaths) { - $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] +# $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key - $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') - if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { - if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' - $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable +# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key +# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') +# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { +# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' +# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - if (-not $templateContent) { - throw ($bicepTemplateCompilationFailedException -f $templateFilePath) - } - } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable +# if (-not $templateContent) { +# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) +# } +# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { +# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' +# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } else { - throw ($templateNotFoundException -f $moduleFolderPath) - } - $convertedTemplates[$moduleFolderPathKey] = @{ - templateFilePath = $templateFilePath - templateContent = $templateContent - } - } else { - $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent - $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath - } +# if (-not $templateContent) { +# throw ($jsonTemplateLoadFailedException -f $templateFilePath) +# } +# } else { +# throw ($templateNotFoundException -f $moduleFolderPath) +# } +# $convertedTemplates[$moduleFolderPathKey] = @{ +# templateFilePath = $templateFilePath +# templateContent = $templateContent +# } +# } else { +# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent +# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath +# } - $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { - $_.type -notin @('Microsoft.Resources/deployments') -and $_ - } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type - - foreach ($resource in $nestedResources) { - - switch ($resource.type) { - { $PSItem -like '*diagnosticsettings*' } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'diagnosticsettings' - ProviderNamespace = 'Microsoft.insights' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - { $PSItem -like '*locks' } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'locks' - ProviderNamespace = 'Microsoft.Authorization' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - { $PSItem -like '*roleAssignments' } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'roleassignments' - ProviderNamespace = 'Microsoft.Authorization' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { - $testCases += @{ - moduleName = $moduleFolderName - resourceType = 'privateEndpoints' - ProviderNamespace = 'Microsoft.Network' - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - Default { - $ProviderNamespace, $rest = $resource.Type.Split('/') - $testCases += @{ - moduleName = $moduleFolderName - resourceType = $rest -join '/' - ProviderNamespace = $ProviderNamespace - TargetApi = $resource.ApiVersion - AvailableApiVersions = $ApiVersions - AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests - } - break - } - } - } - } +# $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { +# $_.type -notin @('Microsoft.Resources/deployments') -and $_ +# } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type + +# foreach ($resource in $nestedResources) { + +# switch ($resource.type) { +# { $PSItem -like '*diagnosticsettings*' } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'diagnosticsettings' +# ProviderNamespace = 'Microsoft.insights' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# { $PSItem -like '*locks' } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'locks' +# ProviderNamespace = 'Microsoft.Authorization' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# { $PSItem -like '*roleAssignments' } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'roleassignments' +# ProviderNamespace = 'Microsoft.Authorization' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = 'privateEndpoints' +# ProviderNamespace = 'Microsoft.Network' +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# Default { +# $ProviderNamespace, $rest = $resource.Type.Split('/') +# $testCases += @{ +# moduleName = $moduleFolderName +# resourceType = $rest -join '/' +# ProviderNamespace = $ProviderNamespace +# TargetApi = $resource.ApiVersion +# AvailableApiVersions = $ApiVersions +# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests +# } +# break +# } +# } +# } +# } - It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { - - param( - [string] $moduleName, - [string] $ResourceType, - [string] $TargetApi, - [string] $ProviderNamespace, - [PSCustomObject] $AvailableApiVersions, - [bool] $AllowPreviewVersionsInAPITests - ) - - if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { - Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." - Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." - return - } - if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { - Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." - Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." - return - } +# It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { + +# param( +# [string] $moduleName, +# [string] $ResourceType, +# [string] $TargetApi, +# [string] $ProviderNamespace, +# [PSCustomObject] $AvailableApiVersions, +# [bool] $AllowPreviewVersionsInAPITests +# ) + +# if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { +# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." +# Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." +# return +# } +# if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { +# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." +# Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." +# return +# } - $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType +# $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType - if (-not $resourceTypeApiVersions) { - Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) - continue - } +# if (-not $resourceTypeApiVersions) { +# Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) +# continue +# } - $approvedApiVersions = @() - if ($AllowPreviewVersionsInAPITests) { - # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview - $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 - $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 - } else { - # We allow the latest 3 non-preview preview - $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 - } +# $approvedApiVersions = @() +# if ($AllowPreviewVersionsInAPITests) { +# # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview +# $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 +# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 +# } else { +# # We allow the latest 3 non-preview preview +# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 +# } - $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending - $approvedApiVersions | Should -Contain $TargetApi +# $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending +# $approvedApiVersions | Should -Contain $TargetApi - # Provide a warning if an API version is second to next to expire. - if ($approvedApiVersions -contains $TargetApi) { - $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) +# # Provide a warning if an API version is second to next to expire. +# if ($approvedApiVersions -contains $TargetApi) { +# $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) - # Example - # Available versions: - # - # 2017-08-01-beta - # 2017-08-01 < $TargetApi (Index = 1) - # 2017-07-14 - # 2016-05-16 +# # Example +# # Available versions: +# # +# # 2017-08-01-beta +# # 2017-08-01 < $TargetApi (Index = 1) +# # 2017-07-14 +# # 2016-05-16 - if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { - $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] - Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) - } - } - } -} +# if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { +# $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] +# Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) +# } +# } +# } +# } From c651d390b0564ca0bf6bb5a5f3f3cb5d0473b512 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:29:50 +0100 Subject: [PATCH 07/22] Update to latest --- .../staticValidation/module.tests.ps1 | 204 +++++++++--------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index d0488dfd52..1228fd689b 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -540,137 +540,137 @@ Describe 'Readme tests' -Tag 'Readme' { } } -# Describe 'Test file tests' -Tag 'TestTemplate' { +Describe 'Test file tests' -Tag 'TestTemplate' { -# Context 'General test file' { + Context 'General test file' { -# $deploymentTestFileTestCases = @() + $deploymentTestFileTestCases = @() -# foreach ($moduleFolderPath in $moduleFolderPaths) { -# if (Test-Path (Join-Path $moduleFolderPath '.test')) { -# $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } -# foreach ($testFilePath in $testFilePaths) { -# $testFileContent = Get-Content $testFilePath - -# if ((Split-Path $testFilePath -Extension) -eq '.json') { -# # Skip any classic parameter files -# $contentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 -# $isParameterFile = $contentHashtable.'$schema' -like '*deploymentParameters*' -# if ($isParameterFile) { -# continue -# } -# } + foreach ($moduleFolderPath in $moduleFolderPaths) { + if (Test-Path (Join-Path $moduleFolderPath '.test')) { + $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + foreach ($testFilePath in $testFilePaths) { + $testFileContent = Get-Content $testFilePath + + if ((Split-Path $testFilePath -Extension) -eq '.json') { + # Skip any classic parameter files + $contentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 + $isParameterFile = $contentHashtable.'$schema' -like '*deploymentParameters*' + if ($isParameterFile) { + continue + } + } -# $deploymentTestFileTestCases += @{ -# testFilePath = $testFilePath -# testFileContent = $testFileContent -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# } -# } -# } -# } + $deploymentTestFileTestCases += @{ + testFilePath = $testFilePath + testFileContent = $testFileContent + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + } + } + } + } -# It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*deploy.bicep' = {`]" -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { + It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*deploy.bicep' = {`]" -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { -# param( -# [object[]] $testFileContent -# ) + param( + [object[]] $testFileContent + ) -# $testIndex = ($testFileContent | Select-String ("^module testDeployment '..\/.*deploy.bicep' = {$") | ForEach-Object { $_.LineNumber - 1 })[0] + $testIndex = ($testFileContent | Select-String ("^module testDeployment '..\/.*deploy.bicep' = {$") | ForEach-Object { $_.LineNumber - 1 })[0] -# $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' -# } + $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' + } -# It '[] Bicep test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { + It '[] Bicep test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { -# param( -# [object[]] $testFileContent -# ) + param( + [object[]] $testFileContent + ) -# $expectedNameFormat = ($testFileContent | Out-String) -match '\s*name:.+-test-.+\s*' + $expectedNameFormat = ($testFileContent | Out-String) -match '\s*name:.+-test-.+\s*' -# $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' -# } + $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' + } -# It '[] Bicep test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { + It '[] Bicep test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { -# param( -# [object[]] $testFileContent -# ) + param( + [object[]] $testFileContent + ) -# $hasExpectedParam = ($testFileContent | Out-String) -match '\s*param\s+serviceShort\s+string\s*' + $hasExpectedParam = ($testFileContent | Out-String) -match '\s*param\s+serviceShort\s+string\s*' -# $hasExpectedParam | Should -Be $true -# } + $hasExpectedParam | Should -Be $true + } -# It '[] JSON test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { + It '[] JSON test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { -# param( -# [object[]] $testFileContent -# ) + param( + [object[]] $testFileContent + ) -# # Handle case of deployment test file (instead of ARM-JSON parameter file) -# $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 + # Handle case of deployment test file (instead of ARM-JSON parameter file) + $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 -# # Uses deployment test file (instead of parameter file). Need to extract parameters. -# $testResource = $rawContentHashtable.resources | Where-Object { $_.name -like '*-test-*' } + # Uses deployment test file (instead of parameter file). Need to extract parameters. + $testResource = $rawContentHashtable.resources | Where-Object { $_.name -like '*-test-*' } -# $testResource | Should -Not -BeNullOrEmpty -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' -# } + $testResource | Should -Not -BeNullOrEmpty -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' + } -# It '[] JSON test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { + It '[] JSON test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { -# param( -# [object[]] $testFileContent -# ) + param( + [object[]] $testFileContent + ) -# $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 -AsHashtable -# $rawContentHashtable.parameters.keys | Should -Contain 'serviceShort' -# } -# } + $rawContentHashtable = $testFileContent | ConvertFrom-Json -Depth 99 -AsHashtable + $rawContentHashtable.parameters.keys | Should -Contain 'serviceShort' + } + } -# Context 'Token usage' { + Context 'Token usage' { -# # Parameter file test cases -# $parameterFileTokenTestCases = @() + # Parameter file test cases + $parameterFileTokenTestCases = @() -# foreach ($moduleFolderPath in $moduleFolderPaths) { -# if (Test-Path (Join-Path $moduleFolderPath '.test')) { -# $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } -# foreach ($testFilePath in $testFilePaths) { -# foreach ($token in $enforcedTokenList.Keys) { -# $parameterFileTokenTestCases += @{ -# testFilePath = $testFilePath -# parameterFileName = Split-Path $testFilePath -Leaf -# tokenSettings = $Settings.parameterFileTokens -# tokenName = $token -# tokenValue = $enforcedTokenList[$token] -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# } -# } -# } -# } -# } + foreach ($moduleFolderPath in $moduleFolderPaths) { + if (Test-Path (Join-Path $moduleFolderPath '.test')) { + $testFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + foreach ($testFilePath in $testFilePaths) { + foreach ($token in $enforcedTokenList.Keys) { + $parameterFileTokenTestCases += @{ + testFilePath = $testFilePath + parameterFileName = Split-Path $testFilePath -Leaf + tokenSettings = $Settings.parameterFileTokens + tokenName = $token + tokenValue = $enforcedTokenList[$token] + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + } + } + } + } + } -# It '[] [Tokens] Test file [] should not contain the plain value for token [] guid' -TestCases $parameterFileTokenTestCases { -# param ( -# [string] $testFilePath, -# [string] $parameterFileName, -# [hashtable] $tokenSettings, -# [string] $tokenName, -# [string] $tokenValue, -# [string] $moduleFolderName -# ) -# $ParameterFileTokenName = -join ($tokenSettings.tokenPrefix, $tokenName, $tokenSettings.tokenSuffix) -# $ParameterFileContent = Get-Content -Path $testFilePath + It '[] [Tokens] Test file [] should not contain the plain value for token [] guid' -TestCases $parameterFileTokenTestCases { + param ( + [string] $testFilePath, + [string] $parameterFileName, + [hashtable] $tokenSettings, + [string] $tokenName, + [string] $tokenValue, + [string] $moduleFolderName + ) + $ParameterFileTokenName = -join ($tokenSettings.tokenPrefix, $tokenName, $tokenSettings.tokenSuffix) + $ParameterFileContent = Get-Content -Path $testFilePath -# $incorrectReferencesFound = $ParameterFileContent | Select-String -Pattern $tokenValue -AllMatches -# if ($incorrectReferencesFound.Matches) { -# $incorrectReferencesFound.Matches.Count | Should -Be 0 -Because ('Test file should not contain the value [{0}], instead it should reference the token value [{1}]. Please check the {2} lines: [{3}]' -f $tokenName, $ParameterFileTokenName, $incorrectReferencesFound.Matches.Count, ($incorrectReferencesFound.Line.Trim() -join ",`n")) -# } -# } -# } -# } + $incorrectReferencesFound = $ParameterFileContent | Select-String -Pattern $tokenValue -AllMatches + if ($incorrectReferencesFound.Matches) { + $incorrectReferencesFound.Matches.Count | Should -Be 0 -Because ('Test file should not contain the value [{0}], instead it should reference the token value [{1}]. Please check the {2} lines: [{3}]' -f $tokenName, $ParameterFileTokenName, $incorrectReferencesFound.Matches.Count, ($incorrectReferencesFound.Line.Trim() -join ",`n")) + } + } + } +} # Describe 'Deployment template tests' -Tag 'Template' { From 287f67a993ad99eadd64f7939099c82f0de06624 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:34:26 +0100 Subject: [PATCH 08/22] Update to latest --- .../staticValidation/module.tests.ps1 | 312 +++++++++--------- 1 file changed, 156 insertions(+), 156 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 1228fd689b..fca5a9ade8 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -1154,175 +1154,175 @@ Describe 'Test file tests' -Tag 'TestTemplate' { # } # } -# Describe 'API version tests' -Tag 'ApiCheck' { +Describe 'API version tests' -Tag 'ApiCheck' { -# $testCases = @() -# $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' + $testCases = @() + $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' -# if (-not (Test-Path $apiSpecsFilePath)) { -# Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" -# return -# } + if (-not (Test-Path $apiSpecsFilePath)) { + Write-Verbose "Skipping API tests as no API version are available in path [$apiSpecsFilePath]" + return + } -# $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json -# foreach ($moduleFolderPath in $moduleFolderPaths) { + $ApiVersions = Get-Content -Path $apiSpecsFilePath -Raw | ConvertFrom-Json + foreach ($moduleFolderPath in $moduleFolderPaths) { -# $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key -# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') -# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { -# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' -# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key + $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') + if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' + $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) -# } -# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' -# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + if (-not $templateContent) { + throw ($bicepTemplateCompilationFailedException -f $templateFilePath) + } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($jsonTemplateLoadFailedException -f $templateFilePath) -# } -# } else { -# throw ($templateNotFoundException -f $moduleFolderPath) -# } -# $convertedTemplates[$moduleFolderPathKey] = @{ -# templateFilePath = $templateFilePath -# templateContent = $templateContent -# } -# } else { -# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent -# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath -# } + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } + } else { + throw ($templateNotFoundException -f $moduleFolderPath) + } + $convertedTemplates[$moduleFolderPathKey] = @{ + templateFilePath = $templateFilePath + templateContent = $templateContent + } + } else { + $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath + } -# $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { -# $_.type -notin @('Microsoft.Resources/deployments') -and $_ -# } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type - -# foreach ($resource in $nestedResources) { - -# switch ($resource.type) { -# { $PSItem -like '*diagnosticsettings*' } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'diagnosticsettings' -# ProviderNamespace = 'Microsoft.insights' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# { $PSItem -like '*locks' } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'locks' -# ProviderNamespace = 'Microsoft.Authorization' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# { $PSItem -like '*roleAssignments' } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'roleassignments' -# ProviderNamespace = 'Microsoft.Authorization' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = 'privateEndpoints' -# ProviderNamespace = 'Microsoft.Network' -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# Default { -# $ProviderNamespace, $rest = $resource.Type.Split('/') -# $testCases += @{ -# moduleName = $moduleFolderName -# resourceType = $rest -join '/' -# ProviderNamespace = $ProviderNamespace -# TargetApi = $resource.ApiVersion -# AvailableApiVersions = $ApiVersions -# AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests -# } -# break -# } -# } -# } -# } + $nestedResources = Get-NestedResourceList -TemplateFileContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ + } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type + + foreach ($resource in $nestedResources) { + + switch ($resource.type) { + { $PSItem -like '*diagnosticsettings*' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'diagnosticsettings' + ProviderNamespace = 'Microsoft.insights' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + { $PSItem -like '*locks' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'locks' + ProviderNamespace = 'Microsoft.Authorization' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + { $PSItem -like '*roleAssignments' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'roleassignments' + ProviderNamespace = 'Microsoft.Authorization' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + { $PSItem -like '*privateEndpoints' -and ($PSItem -notlike '*managedPrivateEndpoints') } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'privateEndpoints' + ProviderNamespace = 'Microsoft.Network' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + Default { + $ProviderNamespace, $rest = $resource.Type.Split('/') + $testCases += @{ + moduleName = $moduleFolderName + resourceType = $rest -join '/' + ProviderNamespace = $ProviderNamespace + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + AllowPreviewVersionsInAPITests = $AllowPreviewVersionsInAPITests + } + break + } + } + } + } -# It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { - -# param( -# [string] $moduleName, -# [string] $ResourceType, -# [string] $TargetApi, -# [string] $ProviderNamespace, -# [PSCustomObject] $AvailableApiVersions, -# [bool] $AllowPreviewVersionsInAPITests -# ) - -# if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { -# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." -# Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." -# return -# } -# if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { -# Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." -# Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." -# return -# } + It 'In [] used resource type [] should use one of the recent API version(s). Currently using []' -TestCases $TestCases { + + param( + [string] $moduleName, + [string] $ResourceType, + [string] $TargetApi, + [string] $ProviderNamespace, + [PSCustomObject] $AvailableApiVersions, + [bool] $AllowPreviewVersionsInAPITests + ) + + if (-not (($AvailableApiVersions | Get-Member -Type NoteProperty).Name -contains $ProviderNamespace)) { + Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing in your Azure API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." + Set-ItResult -Skipped -Because "The Azure API version file is missing the Provider Namespace [$ProviderNamespace]." + return + } + if (-not (($AvailableApiVersions.$ProviderNamespace | Get-Member -Type NoteProperty).Name -contains $ResourceType)) { + Write-Warning "[API Test] The Provider Namespace [$ProviderNamespace] is missing the Resource Type [$ResourceType] in your API versions file. Please consider updating it and if it is still missing to open an issue in the 'AzureAPICrawler' PowerShell module's GitHub repository." + Set-ItResult -Skipped -Because "The Azure API version file is missing the Resource Type [$ResourceType] for Provider Namespace [$ProviderNamespace]." + return + } -# $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType + $resourceTypeApiVersions = $AvailableApiVersions.$ProviderNamespace.$ResourceType -# if (-not $resourceTypeApiVersions) { -# Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) -# continue -# } + if (-not $resourceTypeApiVersions) { + Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) + continue + } -# $approvedApiVersions = @() -# if ($AllowPreviewVersionsInAPITests) { -# # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview -# $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 -# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 -# } else { -# # We allow the latest 3 non-preview preview -# $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 -# } + $approvedApiVersions = @() + if ($AllowPreviewVersionsInAPITests) { + # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview + $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 + $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 + } else { + # We allow the latest 3 non-preview preview + $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 3 + } -# $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending -# $approvedApiVersions | Should -Contain $TargetApi + $approvedApiVersions = $approvedApiVersions | Sort-Object -Unique -Descending + $approvedApiVersions | Should -Contain $TargetApi -# # Provide a warning if an API version is second to next to expire. -# if ($approvedApiVersions -contains $TargetApi) { -# $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) + # Provide a warning if an API version is second to next to expire. + if ($approvedApiVersions -contains $TargetApi) { + $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) -# # Example -# # Available versions: -# # -# # 2017-08-01-beta -# # 2017-08-01 < $TargetApi (Index = 1) -# # 2017-07-14 -# # 2016-05-16 + # Example + # Available versions: + # + # 2017-08-01-beta + # 2017-08-01 < $TargetApi (Index = 1) + # 2017-07-14 + # 2016-05-16 -# if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { -# $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] -# Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) -# } -# } -# } -# } + if ($indexOfVersion -gt ($approvedApiVersions.Count - 2)) { + $newerAPIVersions = $approvedApiVersions[0..($indexOfVersion - 1)] + Write-Warning ("The used API version [$TargetApi] for Resource Type [$ProviderNamespace/$ResourceType] will soon expire. Please consider updating it. Consider using one of the newer API versions [{0}]" -f ($newerAPIVersions -join ', ')) + } + } + } +} From a7b2eee61a8bc27383cd603f98ca19c37d8d9800 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:38:03 +0100 Subject: [PATCH 09/22] Update to latest --- .../staticValidation/module.tests.ps1 | 806 +++++++++--------- 1 file changed, 403 insertions(+), 403 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index fca5a9ade8..b4a5c3a026 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -672,487 +672,487 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } -# Describe 'Deployment template tests' -Tag 'Template' { +Describe 'Deployment template tests' -Tag 'Template' { -# Context 'General template' { + Context 'General template' { -# $deploymentFolderTestCases = [System.Collections.ArrayList] @() -# foreach ($moduleFolderPath in $moduleFolderPaths) { + $deploymentFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { -# # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key -# $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') -# if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { -# if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' -# $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key + $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Trim('/').Replace('/', '-') + if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.bicep' + $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($bicepTemplateCompilationFailedException -f $templateFilePath) -# } -# } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { -# $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' -# $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + if (-not $templateContent) { + throw ($bicepTemplateCompilationFailedException -f $templateFilePath) + } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'deploy.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable -# if (-not $templateContent) { -# throw ($jsonTemplateLoadFailedException -f $templateFilePath) -# } -# } else { -# throw ($templateNotFoundException -f $moduleFolderPath) -# } -# $convertedTemplates[$moduleFolderPathKey] = @{ -# templateFilePath = $templateFilePath -# templateContent = $templateContent -# } -# } else { -# $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent -# $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath -# } + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } + } else { + throw ($templateNotFoundException -f $moduleFolderPath) + } + $convertedTemplates[$moduleFolderPathKey] = @{ + templateFilePath = $templateFilePath + templateContent = $templateContent + } + } else { + $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath + } -# # Parameter file test cases -# $testFileTestCases = @() -# $templateFile_Parameters = $templateContent.parameters -# $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object -# $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object + # Parameter file test cases + $testFileTestCases = @() + $templateFile_Parameters = $templateContent.parameters + $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object + $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object -# if (Test-Path (Join-Path $moduleFolderPath '.test')) { + if (Test-Path (Join-Path $moduleFolderPath '.test')) { -# # Can be removed after full migration to bicep test files -# $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + # Can be removed after full migration to bicep test files + $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } -# foreach ($moduleTestFilePath in $moduleTestFilePaths) { -# if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { + foreach ($moduleTestFilePath in $moduleTestFilePaths) { + if ((Split-Path $moduleTestFilePath -Extension) -eq '.json') { -# $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable + $rawContentHashtable = (Get-Content $moduleTestFilePath) | ConvertFrom-Json -AsHashtable -# # Skipping any file that is not actually a ARM-JSON parameter file -# $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' -# if (-not $isParameterFile) { -# continue -# } + # Skipping any file that is not actually a ARM-JSON parameter file + $isParameterFile = $rawContentHashtable.'$schema' -like '*deploymentParameters*' + if (-not $isParameterFile) { + continue + } -# $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object -# } else { -# $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable -# $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test -# } -# $testFileTestCases += @{ -# testFile_Path = $moduleTestFilePath -# testFile_Name = Split-Path $moduleTestFilePath -Leaf -# testFile_AllParameterNames = $deploymentTestFile_AllParameterNames -# templateFile_AllParameterNames = $TemplateFile_AllParameterNames -# templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames -# tokenConfiguration = $tokenConfiguration -# } -# } -# } + $deploymentTestFile_AllParameterNames = $rawContentHashtable.parameters.Keys | Sort-Object + } else { + $deploymentFileContent = bicep build $moduleTestFilePath --stdout | ConvertFrom-Json -AsHashtable + $deploymentTestFile_AllParameterNames = $deploymentFileContent.resources[-1].properties.parameters.Keys | Sort-Object # The last resource should be the test + } + $testFileTestCases += @{ + testFile_Path = $moduleTestFilePath + testFile_Name = Split-Path $moduleTestFilePath -Leaf + testFile_AllParameterNames = $deploymentTestFile_AllParameterNames + templateFile_AllParameterNames = $TemplateFile_AllParameterNames + templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames + tokenConfiguration = $tokenConfiguration + } + } + } -# # Test file setup -# $deploymentFolderTestCases += @{ -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# templateContent = $templateContent -# templateFilePath = $templateFilePath -# testFileTestCases = $testFileTestCases -# } -# } + # Test file setup + $deploymentFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + templateContent = $templateContent + templateFilePath = $templateFilePath + testFileTestCases = $testFileTestCases + } + } -# It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { + It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $templateContent | Should -Not -Be $null -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $templateContent | Should -Not -Be $null + } -# It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { -# # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! -# # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { + # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! + # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# $Schemaverion = $templateContent.'$schema' -# $SchemaArray = @() -# if ($Schemaverion -eq $RGdeployment) { -# $SchemaOutput = $true -# } elseIf ($Schemaverion -eq $Subscriptiondeployment) { -# $SchemaOutput = $true -# } elseIf ($Schemaverion -eq $MGdeployment) { -# $SchemaOutput = $true -# } elseIf ($Schemaverion -eq $Tenantdeployment) { -# $SchemaOutput = $true -# } else { -# $SchemaOutput = $false -# } -# $SchemaArray += $SchemaOutput -# $SchemaArray | Should -Not -Contain $false -# } + $Schemaverion = $templateContent.'$schema' + $SchemaArray = @() + if ($Schemaverion -eq $RGdeployment) { + $SchemaOutput = $true + } elseIf ($Schemaverion -eq $Subscriptiondeployment) { + $SchemaOutput = $true + } elseIf ($Schemaverion -eq $MGdeployment) { + $SchemaOutput = $true + } elseIf ($Schemaverion -eq $Tenantdeployment) { + $SchemaOutput = $true + } else { + $SchemaOutput = $false + } + $SchemaArray += $SchemaOutput + $SchemaArray | Should -Not -Contain $false + } -# It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { + It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $Schemaverion = $templateContent.'$schema' -# ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $Schemaverion = $templateContent.'$schema' + ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true + } -# It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { -# #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $ApiVersion = $templateContent.resources.apiVersion -# $ApiVersionArray = @() -# foreach ($API in $ApiVersion) { -# if ($API.Substring(0, 2) -eq '20') { -# $ApiVersionOutput = $true -# } elseIf ($API.substring(1, 10) -eq 'parameters') { -# # An API version should not be referenced as a parameter -# $ApiVersionOutput = $false -# } elseIf ($API.substring(1, 10) -eq 'variables') { -# # An API version should not be referenced as a variable -# $ApiVersionOutput = $false -# } else { -# $ApiVersionOutput = $false -# } -# $ApiVersionArray += $ApiVersionOutput -# } -# $ApiVersionArray | Should -Not -Contain $false -# } + It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { + #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $ApiVersion = $templateContent.resources.apiVersion + $ApiVersionArray = @() + foreach ($API in $ApiVersion) { + if ($API.Substring(0, 2) -eq '20') { + $ApiVersionOutput = $true + } elseIf ($API.substring(1, 10) -eq 'parameters') { + # An API version should not be referenced as a parameter + $ApiVersionOutput = $false + } elseIf ($API.substring(1, 10) -eq 'variables') { + # An API version should not be referenced as a variable + $ApiVersionOutput = $false + } else { + $ApiVersionOutput = $false + } + $ApiVersionArray += $ApiVersionOutput + } + $ApiVersionArray | Should -Not -Contain $false + } -# It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { + It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources` ' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $templateContent.Keys | Should -Contain '$schema' -# $templateContent.Keys | Should -Contain 'contentVersion' -# $templateContent.Keys | Should -Contain 'resources' -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $templateContent.Keys | Should -Contain '$schema' + $templateContent.Keys | Should -Contain 'contentVersion' + $templateContent.Keys | Should -Contain 'resources' + } -# It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { + It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# if ($lock = $templateContent.parameters.lock) { -# $lock.Keys | Should -Contain 'defaultValue' -# $lock.defaultValue | Should -Be '' -# } -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + if ($lock = $templateContent.parameters.lock) { + $lock.Keys | Should -Contain 'defaultValue' + $lock.defaultValue | Should -Be '' + } + } -# It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.parameters) { -# Set-ItResult -Skipped -Because 'the module template has no parameters.' -# return -# } + if (-not $templateContent.parameters) { + Set-ItResult -Skipped -Because 'the module template has no parameters.' + return + } -# $CamelCasingFlag = @() -# $Parameter = $templateContent.parameters.Keys -# foreach ($Param in $Parameter) { -# if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { -# $CamelCasingFlag += $false -# } else { -# $CamelCasingFlag += $true -# } -# } -# $CamelCasingFlag | Should -Not -Contain $false -# } + $CamelCasingFlag = @() + $Parameter = $templateContent.parameters.Keys + foreach ($Param in $Parameter) { + if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } -# It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# if (-not $templateContent.variables) { -# Set-ItResult -Skipped -Because 'the module template has no variables.' -# return -# } + if (-not $templateContent.variables) { + Set-ItResult -Skipped -Because 'the module template has no variables.' + return + } -# $CamelCasingFlag = @() -# $Variable = $templateContent.variables.Keys + $CamelCasingFlag = @() + $Variable = $templateContent.variables.Keys -# foreach ($Variab in $Variable) { -# if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { -# $CamelCasingFlag += $false -# } else { -# $CamelCasingFlag += $true -# } -# } -# $CamelCasingFlag | Should -Not -Contain $false -# } + foreach ($Variab in $Variable) { + if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } -# It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $CamelCasingFlag = @() -# $Outputs = $templateContent.outputs.Keys - -# foreach ($Output in $Outputs) { -# if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { -# $CamelCasingFlag += $false -# } else { -# $CamelCasingFlag += $true -# } -# } -# $CamelCasingFlag | Should -Not -Contain $false -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $CamelCasingFlag = @() + $Outputs = $templateContent.outputs.Keys -# It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { + foreach ($Output in $Outputs) { + if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $enableDefaultTelemetryFlag = @() -# $Schemaverion = $templateContent.'$schema' -# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { -# if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { -# $enableDefaultTelemetryFlag += $true -# } else { -# $enableDefaultTelemetryFlag += $false -# } -# } -# $enableDefaultTelemetryFlag | Should -Not -Contain $false -# } + It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { -# It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $enableDefaultTelemetryFlag = @() + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[parameters('enableDefaultTelemetry')]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[parameters('enableDefaultTelemetry')]*")) { + $enableDefaultTelemetryFlag += $true + } else { + $enableDefaultTelemetryFlag += $false + } + } + $enableDefaultTelemetryFlag | Should -Not -Contain $false + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) -# $LocationFlag = $true -# $Schemaverion = $templateContent.'$schema' -# if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { -# $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue -# $Locationparamoutput = $templateContent.parameters.Keys -# if ($Locationparamoutput -contains 'Location') { -# if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { -# $LocationFlag = $true -# } else { - -# $LocationFlag = $false -# } -# $LocationFlag | Should -Contain $true -# } -# } -# } + It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { -# It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) + $LocationFlag = $true + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue + $Locationparamoutput = $templateContent.parameters.Keys + if ($Locationparamoutput -contains 'Location') { + if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { + $LocationFlag = $true + } else { + + $LocationFlag = $false + } + $LocationFlag | Should -Contain $true + } + } + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [string] $templateFilePath -# ) + It '[] Location output should be returned for resources that use it' -TestCases $deploymentFolderTestCases { -# $outputs = $templateContent.outputs + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [string] $templateFilePath + ) -# $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] -# $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } + $outputs = $templateContent.outputs -# if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { -# # If the main resource has a location property, an output should be returned too -# $outputs.keys | Should -Contain 'location' + $primaryResourceType = (Split-Path $TemplateFilePath -Parent).Replace('\', '/').split('/modules/')[1] + $primaryResourceTypeResource = $templateContent.resources | Where-Object { $_.type -eq $primaryResourceType } -# # It should further reference the location property of the primary resource and not e.g. the location input parameter -# $outputs.location.value | Should -Match $primaryResourceType -# } -# } + if ($primaryResourceTypeResource.keys -contains 'location' -and $primaryResourceTypeResource.location -ne 'global') { + # If the main resource has a location property, an output should be returned too + $outputs.keys | Should -Contain 'location' -# It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { + # It should further reference the location property of the primary resource and not e.g. the location input parameter + $outputs.location.value | Should -Match $primaryResourceType + } + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# [string] $templateFilePath -# ) + It '[] Resource Group output should exist for resources that are deployed into a resource group scope' -TestCases $deploymentFolderTestCases { -# $outputs = $templateContent.outputs.Keys -# $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + [string] $templateFilePath + ) -# if ($deploymentScope -eq 'resourceGroup') { -# $outputs | Should -Contain 'resourceGroupName' -# } -# } + $outputs = $templateContent.outputs.Keys + $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath -# It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { + if ($deploymentScope -eq 'resourceGroup') { + $outputs | Should -Contain 'resourceGroupName' + } + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# $templateFilePath -# ) + It '[] Resource name output should exist' -TestCases $deploymentFolderTestCases { -# # check if module contains a 'primary' resource we could draw a name from -# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' -# if ($templateContent.resources.type -notcontains $moduleResourceType) { -# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' -# return -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + $templateFilePath + ) -# # Otherwise test for standard outputs -# $outputs = $templateContent.outputs.Keys -# $outputs | Should -Contain 'name' -# } + # check if module contains a 'primary' resource we could draw a name from + $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' + if ($templateContent.resources.type -notcontains $moduleResourceType) { + Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a name from.' + return + } -# It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { + # Otherwise test for standard outputs + $outputs = $templateContent.outputs.Keys + $outputs | Should -Contain 'name' + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent, -# $templateFilePath -# ) + It '[] Resource ID output should exist' -TestCases $deploymentFolderTestCases { -# # check if module contains a 'primary' resource we could draw a name from -# $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' -# if ($templateContent.resources.type -notcontains $moduleResourceType) { -# Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' -# return -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent, + $templateFilePath + ) -# # Otherwise test for standard outputs -# $outputs = $templateContent.outputs.Keys -# $outputs | Should -Contain 'resourceId' -# } + # check if module contains a 'primary' resource we could draw a name from + $moduleResourceType = (Split-Path (($templateFilePath -replace '\\', '/') -split '/modules/')[1] -Parent) -replace '\\', '/' + if ($templateContent.resources.type -notcontains $moduleResourceType) { + Set-ItResult -Skipped -Because 'the module template has no primary resource to fetch a resource ID from.' + return + } -# It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { + # Otherwise test for standard outputs + $outputs = $templateContent.outputs.Keys + $outputs | Should -Contain 'resourceId' + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { -# if (-not $templateContent.parameters) { -# Set-ItResult -Skipped -Because 'the module template has no parameters.' -# return -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# $incorrectParameters = @() -# $templateParameters = $templateContent.parameters.Keys -# foreach ($parameter in $templateParameters) { -# $data = ($templateContent.parameters.$parameter.metadata).description -# if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { -# $incorrectParameters += $parameter -# } -# } -# $incorrectParameters | Should -BeNullOrEmpty -# } + if (-not $templateContent.parameters) { + Set-ItResult -Skipped -Because 'the module template has no parameters.' + return + } -# It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { + $incorrectParameters = @() + $templateParameters = $templateContent.parameters.Keys + foreach ($parameter in $templateParameters) { + $data = ($templateContent.parameters.$parameter.metadata).description + if ($data -notmatch '(?s)^[A-Z][a-zA-Z]+\. .+\.$') { + $incorrectParameters += $parameter + } + } + $incorrectParameters | Should -BeNullOrEmpty + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + It "[] Conditional parameters' description should contain 'Required if' followed by the condition making the parameter required." -TestCases $deploymentFolderTestCases { -# if (-not $templateContent.parameters) { -# Set-ItResult -Skipped -Because 'the module template has no parameters.' -# return -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# $incorrectParameters = @() -# $templateParameters = $templateContent.parameters.Keys -# foreach ($parameter in $templateParameters) { -# $data = ($templateContent.parameters.$parameter.metadata).description -# switch -regex ($data) { -# '^Conditional. .*' { -# if ($data -notmatch '.*\. Required if .*') { -# $incorrectParameters += $parameter -# } -# } -# } -# } -# $incorrectParameters | Should -BeNullOrEmpty -# } + if (-not $templateContent.parameters) { + Set-ItResult -Skipped -Because 'the module template has no parameters.' + return + } -# It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { + $incorrectParameters = @() + $templateParameters = $templateContent.parameters.Keys + foreach ($parameter in $templateParameters) { + $data = ($templateContent.parameters.$parameter.metadata).description + switch -regex ($data) { + '^Conditional. .*' { + if ($data -notmatch '.*\. Required if .*') { + $incorrectParameters += $parameter + } + } + } + } + $incorrectParameters | Should -BeNullOrEmpty + } -# param( -# [string] $moduleFolderName, -# [hashtable] $templateContent -# ) + It "[] outputs' description should start with a capital letter and contain text ending with a dot." -TestCases $deploymentFolderTestCases { -# if (-not $templateContent.outputs) { -# Set-ItResult -Skipped -Because 'the module template has no outputs.' -# return -# } + param( + [string] $moduleFolderName, + [hashtable] $templateContent + ) -# $incorrectOutputs = @() -# $templateOutputs = $templateContent.outputs.Keys -# foreach ($output in $templateOutputs) { -# $data = ($templateContent.outputs.$output.metadata).description -# if ($data -notmatch '(?s)^[A-Z].+\.$') { -# $incorrectOutputs += $output -# } -# } -# $incorrectOutputs | Should -BeNullOrEmpty -# } + if (-not $templateContent.outputs) { + Set-ItResult -Skipped -Because 'the module template has no outputs.' + return + } -# # PARAMETER Tests -# It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { -# param ( -# [hashtable[]] $testFileTestCases -# ) + $incorrectOutputs = @() + $templateOutputs = $templateContent.outputs.Keys + foreach ($output in $templateOutputs) { + $data = ($templateContent.outputs.$output.metadata).description + if ($data -notmatch '(?s)^[A-Z].+\.$') { + $incorrectOutputs += $output + } + } + $incorrectOutputs | Should -BeNullOrEmpty + } -# foreach ($parameterFileTestCase in $testFileTestCases) { -# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames -# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames + # PARAMETER Tests + It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $testFileTestCases + ) -# $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } -# $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) -# } -# } + foreach ($parameterFileTestCase in $testFileTestCases) { + $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames + $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames -# It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { -# param ( -# [hashtable[]] $testFileTestCases -# ) + $nonExistentParameters = $testFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } + $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) + } + } -# foreach ($parameterFileTestCase in $testFileTestCases) { -# $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames -# $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames + It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $testFileTestCases + ) -# $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } -# $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) -# } -# } + foreach ($parameterFileTestCase in $testFileTestCases) { + $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames + $testFile_AllParameterNames = $parameterFileTestCase.testFile_AllParameterNames -# It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { -# param ( -# [hashtable[]] $testFileTestCases, -# [hashtable] $templateContent -# ) + $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $testFile_AllParameterNames -notcontains $_ } + $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) + } + } + + It '[] All non-required parameters in template file should not have description that start with "Required."' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $testFileTestCases, + [hashtable] $templateContent + ) -# foreach ($parameterFileTestCase in $testFileTestCases) { -# $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames -# $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames -# $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } + foreach ($parameterFileTestCase in $testFileTestCases) { + $templateFile_RequiredParametersNames = $parameterFileTestCase.templateFile_RequiredParametersNames + $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames + $nonRequiredParameterNames = $templateFile_AllParameterNames | Where-Object { $_ -notin $templateFile_RequiredParametersNames } -# $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } -# $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) -# } -# } -# } -# } + $incorrectParameters = $nonRequiredParameterNames | Where-Object { ($templateContent.parameters[$_].defaultValue) -and ($templateContent.parameters[$_].metadata.description -like 'Required. *') } + $incorrectParameters.Count | Should -Be 0 -Because ('all non-required parameters in the template file should not have a description that starts with "Required.". Found incorrect items: [{0}]' -f ($incorrectParameters -join ', ')) + } + } + } +} Describe 'API version tests' -Tag 'ApiCheck' { From d6a4881d55f35cc63e1a3a34deefeb9796e512b2 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:41:19 +0100 Subject: [PATCH 10/22] Update to latest --- .../staticValidation/module.tests.ps1 | 242 +++++++++--------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index b4a5c3a026..ced409120a 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -37,127 +37,127 @@ $script:templateNotFoundException = 'No template file found in folder [{0}]' # - # Import any helper function used in this test script Import-Module (Join-Path $PSScriptRoot 'helper' 'helper.psm1') -Force -# Describe 'File/folder tests' -Tag 'Modules' { - -# Context 'General module folder tests' { - -# $moduleFolderTestCases = [System.Collections.ArrayList] @() -# foreach ($moduleFolderPath in $moduleFolderPaths) { -# $moduleFolderTestCases += @{ -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# moduleFolderPath = $moduleFolderPath -# isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / -# } -# } - -# if (Test-Path (Join-Path $repoRootPath '.github')) { -# It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - -# param( -# [string] $moduleFolderName, -# [string] $moduleFolderPath -# ) - -# $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' -# $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() -# $workflowPath = Join-Path $workflowsFolderName $workflowFileName -# Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." -# } -# } - -# if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { -# It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - -# param( -# [string] $moduleFolderName, -# [string] $moduleFolderPath -# ) - -# $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' -# $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() -# $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName -# Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." -# } -# } - -# It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { - -# param( [string] $moduleFolderPath ) - -# $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) -# $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) -# ($hasARM -or $hasBicep) | Should -Be $true -# } - -# It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - -# param( [string] $moduleFolderPath ) -# (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true -# } - -# It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - -# param( [string] $moduleFolderPath ) -# Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true -# } - -# It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - -# param( [string] $moduleFolderPath ) -# (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true -# } -# } - -# Context '.test folder' { - -# $folderTestCases = [System.Collections.ArrayList]@() -# foreach ($moduleFolderPath in $moduleFolderPaths) { -# if (Test-Path (Join-Path $moduleFolderPath '.test')) { -# $folderTestCases += @{ -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# moduleFolderPath = $moduleFolderPath -# } -# } -# } - -# It '[] Folder should contain one or more test files' -TestCases $folderTestCases { - -# param( -# [string] $moduleFolderName, -# [string] $moduleFolderPath -# ) - -# $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } -# $moduleTestFilePaths.Count | Should -BeGreaterThan 0 -# } - -# $testFolderFilesTestCases = [System.Collections.ArrayList] @() -# foreach ($moduleFolderPath in $moduleFolderPaths) { -# $testFolderPath = Join-Path $moduleFolderPath '.test' -# if (Test-Path $testFolderPath) { -# foreach ($testFilePath in (Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ })) { -# $testFolderFilesTestCases += @{ -# moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] -# testFilePath = $testFilePath -# } -# } -# } -# } - -# It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { - -# param( -# [string] $moduleFolderName, -# [string] $testFilePath -# ) -# if ((Split-Path $testFilePath -Extension) -eq '.json') { -# { (Get-Content $testFilePath) | ConvertFrom-Json } | Should -Not -Throw -# } else { -# Set-ItResult -Skipped -Because 'the module has no JSON test files.' -# } -# } -# } -# } +Describe 'File/folder tests' -Tag 'Modules' { + + Context 'General module folder tests' { + + $moduleFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + $moduleFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + moduleFolderPath = $moduleFolderPath + isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / + } + } + + if (Test-Path (Join-Path $repoRootPath '.github')) { + It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + + param( + [string] $moduleFolderName, + [string] $moduleFolderPath + ) + + $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' + $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() + $workflowPath = Join-Path $workflowsFolderName $workflowFileName + Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." + } + } + + if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { + It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + + param( + [string] $moduleFolderName, + [string] $moduleFolderPath + ) + + $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' + $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() + $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName + Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." + } + } + + It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { + + param( [string] $moduleFolderPath ) + + $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) + $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) + ($hasARM -or $hasBicep) | Should -Be $true + } + + It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true + } + + It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + + param( [string] $moduleFolderPath ) + Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true + } + + It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + } + } + + # Context '.test folder' { + + # $folderTestCases = [System.Collections.ArrayList]@() + # foreach ($moduleFolderPath in $moduleFolderPaths) { + # if (Test-Path (Join-Path $moduleFolderPath '.test')) { + # $folderTestCases += @{ + # moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + # moduleFolderPath = $moduleFolderPath + # } + # } + # } + + # It '[] Folder should contain one or more test files' -TestCases $folderTestCases { + + # param( + # [string] $moduleFolderName, + # [string] $moduleFolderPath + # ) + + # $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + # $moduleTestFilePaths.Count | Should -BeGreaterThan 0 + # } + + # $testFolderFilesTestCases = [System.Collections.ArrayList] @() + # foreach ($moduleFolderPath in $moduleFolderPaths) { + # $testFolderPath = Join-Path $moduleFolderPath '.test' + # if (Test-Path $testFolderPath) { + # foreach ($testFilePath in (Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ })) { + # $testFolderFilesTestCases += @{ + # moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + # testFilePath = $testFilePath + # } + # } + # } + # } + + # It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { + + # param( + # [string] $moduleFolderName, + # [string] $testFilePath + # ) + # if ((Split-Path $testFilePath -Extension) -eq '.json') { + # { (Get-Content $testFilePath) | ConvertFrom-Json } | Should -Not -Throw + # } else { + # Set-ItResult -Skipped -Because 'the module has no JSON test files.' + # } + # } + # } +} Describe 'Readme tests' -Tag 'Readme' { Context 'Readme content tests' { From 5fc8b07562a323f86ca27191b842e6aaa8f7ac60 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:44:49 +0100 Subject: [PATCH 11/22] Update to latest --- .../staticValidation/module.tests.ps1 | 188 +++++++++--------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index ced409120a..082c7cf102 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -39,124 +39,124 @@ Import-Module (Join-Path $PSScriptRoot 'helper' 'helper.psm1') -Force Describe 'File/folder tests' -Tag 'Modules' { - Context 'General module folder tests' { + # Context 'General module folder tests' { - $moduleFolderTestCases = [System.Collections.ArrayList] @() - foreach ($moduleFolderPath in $moduleFolderPaths) { - $moduleFolderTestCases += @{ - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - moduleFolderPath = $moduleFolderPath - isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / - } - } + # $moduleFolderTestCases = [System.Collections.ArrayList] @() + # foreach ($moduleFolderPath in $moduleFolderPaths) { + # $moduleFolderTestCases += @{ + # moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + # moduleFolderPath = $moduleFolderPath + # isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / + # } + # } - if (Test-Path (Join-Path $repoRootPath '.github')) { - It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + # if (Test-Path (Join-Path $repoRootPath '.github')) { + # It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - param( - [string] $moduleFolderName, - [string] $moduleFolderPath - ) + # param( + # [string] $moduleFolderName, + # [string] $moduleFolderPath + # ) - $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' - $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() - $workflowPath = Join-Path $workflowsFolderName $workflowFileName - Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." - } - } + # $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' + # $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() + # $workflowPath = Join-Path $workflowsFolderName $workflowFileName + # Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." + # } + # } - if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { - It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + # if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { + # It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - param( - [string] $moduleFolderName, - [string] $moduleFolderPath - ) + # param( + # [string] $moduleFolderName, + # [string] $moduleFolderPath + # ) - $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' - $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() - $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName - Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." - } - } + # $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' + # $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() + # $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName + # Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." + # } + # } - It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { + # It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { - param( [string] $moduleFolderPath ) + # param( [string] $moduleFolderPath ) - $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) - $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) - ($hasARM -or $hasBicep) | Should -Be $true - } + # $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) + # $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) + # ($hasARM -or $hasBicep) | Should -Be $true + # } - It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + # It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true - } + # param( [string] $moduleFolderPath ) + # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true + # } - It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + # It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - param( [string] $moduleFolderPath ) - Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true - } + # param( [string] $moduleFolderPath ) + # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true + # } - It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true - } - } + # param( [string] $moduleFolderPath ) + # (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + # } + # } - # Context '.test folder' { + Context '.test folder' { - # $folderTestCases = [System.Collections.ArrayList]@() - # foreach ($moduleFolderPath in $moduleFolderPaths) { - # if (Test-Path (Join-Path $moduleFolderPath '.test')) { - # $folderTestCases += @{ - # moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - # moduleFolderPath = $moduleFolderPath - # } - # } - # } + $folderTestCases = [System.Collections.ArrayList]@() + foreach ($moduleFolderPath in $moduleFolderPaths) { + if (Test-Path (Join-Path $moduleFolderPath '.test')) { + $folderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + moduleFolderPath = $moduleFolderPath + } + } + } - # It '[] Folder should contain one or more test files' -TestCases $folderTestCases { + It '[] Folder should contain one or more test files' -TestCases $folderTestCases { - # param( - # [string] $moduleFolderName, - # [string] $moduleFolderPath - # ) + param( + [string] $moduleFolderName, + [string] $moduleFolderPath + ) - # $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } - # $moduleTestFilePaths.Count | Should -BeGreaterThan 0 - # } + $moduleTestFilePaths = Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ } + $moduleTestFilePaths.Count | Should -BeGreaterThan 0 + } - # $testFolderFilesTestCases = [System.Collections.ArrayList] @() - # foreach ($moduleFolderPath in $moduleFolderPaths) { - # $testFolderPath = Join-Path $moduleFolderPath '.test' - # if (Test-Path $testFolderPath) { - # foreach ($testFilePath in (Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ })) { - # $testFolderFilesTestCases += @{ - # moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - # testFilePath = $testFilePath - # } - # } - # } - # } + $testFolderFilesTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + $testFolderPath = Join-Path $moduleFolderPath '.test' + if (Test-Path $testFolderPath) { + foreach ($testFilePath in (Get-ModuleTestFileList -ModulePath $moduleFolderPath | ForEach-Object { Join-Path $moduleFolderPath $_ })) { + $testFolderFilesTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + testFilePath = $testFilePath + } + } + } + } - # It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { + It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { - # param( - # [string] $moduleFolderName, - # [string] $testFilePath - # ) - # if ((Split-Path $testFilePath -Extension) -eq '.json') { - # { (Get-Content $testFilePath) | ConvertFrom-Json } | Should -Not -Throw - # } else { - # Set-ItResult -Skipped -Because 'the module has no JSON test files.' - # } - # } - # } + param( + [string] $moduleFolderName, + [string] $testFilePath + ) + if ((Split-Path $testFilePath -Extension) -eq '.json') { + { (Get-Content $testFilePath) | ConvertFrom-Json } | Should -Not -Throw + } else { + Set-ItResult -Skipped -Because 'the module has no JSON test files.' + } + } + } } Describe 'Readme tests' -Tag 'Readme' { From 5cdc740b7094b7b60417742d64ff58247cbe0d7a Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:50:00 +0100 Subject: [PATCH 12/22] Update to latest --- .../staticValidation/module.tests.ps1 | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 082c7cf102..a70869bf3a 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -39,74 +39,74 @@ Import-Module (Join-Path $PSScriptRoot 'helper' 'helper.psm1') -Force Describe 'File/folder tests' -Tag 'Modules' { - # Context 'General module folder tests' { - - # $moduleFolderTestCases = [System.Collections.ArrayList] @() - # foreach ($moduleFolderPath in $moduleFolderPaths) { - # $moduleFolderTestCases += @{ - # moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - # moduleFolderPath = $moduleFolderPath - # isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / - # } - # } - - # if (Test-Path (Join-Path $repoRootPath '.github')) { - # It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - - # param( - # [string] $moduleFolderName, - # [string] $moduleFolderPath - # ) - - # $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' - # $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() - # $workflowPath = Join-Path $workflowsFolderName $workflowFileName - # Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." - # } - # } - - # if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { - # It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - - # param( - # [string] $moduleFolderName, - # [string] $moduleFolderPath - # ) - - # $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' - # $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() - # $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName - # Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." - # } - # } - - # It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { - - # param( [string] $moduleFolderPath ) - - # $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) - # $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) - # ($hasARM -or $hasBicep) | Should -Be $true - # } - - # It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - - # param( [string] $moduleFolderPath ) - # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true - # } - - # It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - - # param( [string] $moduleFolderPath ) - # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true - # } - - # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - - # param( [string] $moduleFolderPath ) - # (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true - # } - # } + Context 'General module folder tests' { + + $moduleFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + $moduleFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] + moduleFolderPath = $moduleFolderPath + isTopLevelModule = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1].Split('/').Count -eq 2 # / + } + } + + if (Test-Path (Join-Path $repoRootPath '.github')) { + It '[] Module should have a GitHub workflow' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + + param( + [string] $moduleFolderName, + [string] $moduleFolderPath + ) + + $workflowsFolderName = Join-Path $repoRootPath '.github' 'workflows' + $workflowFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() + $workflowPath = Join-Path $workflowsFolderName $workflowFileName + Test-Path $workflowPath | Should -Be $true -Because "path [$workflowPath] should exist." + } + } + + if (Test-Path (Join-Path $repoRootPath '.azuredevops')) { + It '[] Module should have an Azure DevOps pipeline' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + + param( + [string] $moduleFolderName, + [string] $moduleFolderPath + ) + + $pipelinesFolderName = Join-Path $repoRootPath '.azuredevops' 'modulePipelines' + $pipelineFileName = '{0}.yml' -f $moduleFolderName.Replace('\', '/').Replace('/', '.').Replace('Microsoft', 'ms').ToLower() + $pipelinePath = Join-Path $pipelinesFolderName $pipelineFileName + Test-Path $pipelinePath | Should -Be $true -Because "path [$pipelinePath] should exist." + } + } + + # It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { + + # param( [string] $moduleFolderPath ) + + # $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) + # $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) + # ($hasARM -or $hasBicep) | Should -Be $true + # } + + # It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + + # param( [string] $moduleFolderPath ) + # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true + # } + + # It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + + # param( [string] $moduleFolderPath ) + # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true + # } + + # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + + # param( [string] $moduleFolderPath ) + # (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + # } + } Context '.test folder' { From 09ad1cb919cdd634308d3643ee766c54999185a0 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:53:33 +0100 Subject: [PATCH 13/22] Update to latest --- .../staticValidation/module.tests.ps1 | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index a70869bf3a..13a92c6c2b 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -89,23 +89,23 @@ Describe 'File/folder tests' -Tag 'Modules' { # ($hasARM -or $hasBicep) | Should -Be $true # } - # It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - # param( [string] $moduleFolderPath ) - # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true - # } + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true + } - # It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - # param( [string] $moduleFolderPath ) - # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true - # } + param( [string] $moduleFolderPath ) + Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true + } - # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - # param( [string] $moduleFolderPath ) - # (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true - # } + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + } } Context '.test folder' { From b07983cc78baeef34f158bfb427114bbaf0ed1cb Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 15:57:13 +0100 Subject: [PATCH 14/22] Update to latest --- .../staticValidation/module.tests.ps1 | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 13a92c6c2b..b6e87dda3f 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -80,32 +80,32 @@ Describe 'File/folder tests' -Tag 'Modules' { } } - # It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { - # param( [string] $moduleFolderPath ) + param( [string] $moduleFolderPath ) - # $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) - # $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) - # ($hasARM -or $hasBicep) | Should -Be $true - # } + $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) + $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) + ($hasARM -or $hasBicep) | Should -Be $true + } - It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + # It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true - } + # param( [string] $moduleFolderPath ) + # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true + # } - It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + # It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - param( [string] $moduleFolderPath ) - Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true - } + # param( [string] $moduleFolderPath ) + # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true + # } - It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true - } + # param( [string] $moduleFolderPath ) + # (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + # } } Context '.test folder' { From d30b742ca2b65f9e5151477473b2b60f1efb2698 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:03:37 +0100 Subject: [PATCH 15/22] Update to latest --- .../pipelines/staticValidation/module.tests.ps1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index b6e87dda3f..4fb51c940d 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -84,8 +84,8 @@ Describe 'File/folder tests' -Tag 'Modules' { param( [string] $moduleFolderPath ) - $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) - $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) + $hasARM = Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json') + $hasBicep = Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep') ($hasARM -or $hasBicep) | Should -Be $true } @@ -101,11 +101,11 @@ Describe 'File/folder tests' -Tag 'Modules' { # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true # } - # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - # param( [string] $moduleFolderPath ) - # (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true - # } + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + } } Context '.test folder' { From 3a7c0cbcc0577842a3b1e68d9a3b3130bc7c29a7 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:12:28 +0100 Subject: [PATCH 16/22] Update to latest --- .../staticValidation/module.tests.ps1 | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 4fb51c940d..0f631c351d 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -95,17 +95,25 @@ Describe 'File/folder tests' -Tag 'Modules' { # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true # } - # It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { - # param( [string] $moduleFolderPath ) - # Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true - # } - - It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + param( + [string] $moduleFolderPath + ) - param( [string] $moduleFolderPath ) - (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath '.test') + $pathExisting | Should -Be $true } + + # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + + # param( + # [string] $moduleFolderPath + # ) + + #$pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') + # $pathExisting | Should -Be $true + # } } Context '.test folder' { From ac3d073668b8363323f15c805485bc198d5f78f3 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:18:03 +0100 Subject: [PATCH 17/22] Update to latest --- .../pipelines/staticValidation/module.tests.ps1 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 0f631c351d..a4a50f8989 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -89,11 +89,15 @@ Describe 'File/folder tests' -Tag 'Modules' { ($hasARM -or $hasBicep) | Should -Be $true } - # It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { - # param( [string] $moduleFolderPath ) - # (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true - # } + param( + [string] $moduleFolderPath + ) + + $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'readme.md') + $pathExisting | Should -Be $true + } It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { From e8d85ae951d77ab7a731d62c2fb1c284dd0cc1df Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:23:42 +0100 Subject: [PATCH 18/22] Update to latest --- .../pipelines/staticValidation/module.tests.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index a4a50f8989..f484e25e0b 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -109,15 +109,15 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } - # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - # param( - # [string] $moduleFolderPath - # ) + param( + [string] $moduleFolderPath + ) - #$pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') - # $pathExisting | Should -Be $true - # } + $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') + $pathExisting | Should -Be $true + } } Context '.test folder' { From 2ae1a352c23568b6e541e8a1829e54c0c22d4b83 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:29:43 +0100 Subject: [PATCH 19/22] Update to latest --- .../pipelines/staticValidation/module.tests.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index f484e25e0b..c396bc6731 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -109,15 +109,15 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } - It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - param( - [string] $moduleFolderPath - ) + # param( + # [string] $moduleFolderPath + # ) - $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') - $pathExisting | Should -Be $true - } + # $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') + # $pathExisting | Should -Be $true + # } } Context '.test folder' { From cf075bf83c9f8ec22d5918eac65a2141d1f96ec5 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:38:37 +0100 Subject: [PATCH 20/22] Update to latest --- utilities/pipelines/staticValidation/module.tests.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index c396bc6731..fb0d511abb 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -109,6 +109,16 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } + It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + + param ( + [string] $moduleFolderPath + ) + + $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') + $pathExisting | Should -Be $true + } + # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { # param( From 60d62b12478b58f6ec5c50af8d2c0dd9ce060fc7 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:47:23 +0100 Subject: [PATCH 21/22] Tried whitespace --- .../staticValidation/module.tests.ps1 | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index fb0d511abb..28f7fbdf2c 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -80,7 +80,7 @@ Describe 'File/folder tests' -Tag 'Modules' { } } - It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [ `deploy.json` / `deploy.bicep` ] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath ) @@ -89,7 +89,7 @@ Describe 'File/folder tests' -Tag 'Modules' { ($hasARM -or $hasBicep) | Should -Be $true } - It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [ `readme.md` ] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath @@ -99,7 +99,7 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } - It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + It '[] Module should contain a [ `.test` ] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { param( [string] $moduleFolderPath @@ -109,7 +109,7 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } - It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [ `version.json` ] file' -TestCases $moduleFolderTestCases { param ( [string] $moduleFolderPath @@ -118,16 +118,6 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') $pathExisting | Should -Be $true } - - # It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { - - # param( - # [string] $moduleFolderPath - # ) - - # $pathExisting = Test-Path (Join-Path -Path $moduleFolderPath 'version.json') - # $pathExisting | Should -Be $true - # } } Context '.test folder' { From 28d3a16e0c19be843f68aeabbaae80ceac7d3b13 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 3 Feb 2023 16:51:23 +0100 Subject: [PATCH 22/22] Another try --- utilities/pipelines/staticValidation/module.tests.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index 28f7fbdf2c..80a15e2c3c 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -80,7 +80,7 @@ Describe 'File/folder tests' -Tag 'Modules' { } } - It '[] Module should contain a [ `deploy.json` / `deploy.bicep` ] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [` deploy.json ` / ` deploy.bicep `] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath ) @@ -89,7 +89,7 @@ Describe 'File/folder tests' -Tag 'Modules' { ($hasARM -or $hasBicep) | Should -Be $true } - It '[] Module should contain a [ `readme.md` ] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [` readme.md `] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath @@ -99,7 +99,7 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } - It '[] Module should contain a [ `.test` ] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + It '[] Module should contain a [` .test `] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { param( [string] $moduleFolderPath @@ -109,7 +109,7 @@ Describe 'File/folder tests' -Tag 'Modules' { $pathExisting | Should -Be $true } - It '[] Module should contain a [ `version.json` ] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [` version.json `] file' -TestCases $moduleFolderTestCases { param ( [string] $moduleFolderPath