From 44521776badf589812070f1b210c221faeb755a1 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 28 Aug 2024 16:40:38 -0500 Subject: [PATCH] Update configs.Tests.ps1 --- pester/configs.Tests.ps1 | 187 +++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 86 deletions(-) diff --git a/pester/configs.Tests.ps1 b/pester/configs.Tests.ps1 index 950d0db4..99905da1 100644 --- a/pester/configs.Tests.ps1 +++ b/pester/configs.Tests.ps1 @@ -3,114 +3,129 @@ $VerbosePreference = "Continue" # Import Config Files $global:importedConfigs = @{} -$configFiles = Get-ChildItem .\config -Filter *.json -ErrorAction SilentlyContinue -if ($configFiles) { - foreach ($file in $configFiles) { - try { - $global:importedConfigs[$file.BaseName] = Get-Content $file.FullName | ConvertFrom-Json - Write-Verbose "Successfully imported config file: $($file.FullName)" - } catch { - Write-Error "Failed to import config file: $($file.FullName). Error: $_" - } +Get-ChildItem .\config -Filter *.json | ForEach-Object { + try { + $global:importedConfigs[$_.BaseName] = Get-Content $_.FullName | ConvertFrom-Json + Write-Verbose "Successfully imported config file: $($_.FullName)" + } catch { + Write-Error "Failed to import config file: $($_.FullName). Error: $_" } -} else { - Write-Warning "No config files found in the .\config directory" } Describe "Config Files Validation" { - $configSchemas = @{ - applications = @{ - Type = "Object" - Properties = @{ - winget = @{ Type = "String" } - choco = @{ Type = "String" } - category = @{ Type = "String" } - content = @{ Type = "String" } - description = @{ Type = "String" } - link = @{ Type = "String" } + BeforeAll { + $script:configSchemas = @{ + applications = @{ + Type = "Object" + Properties = @{ + winget = @{ Type = "String" } + choco = @{ Type = "String" } + category = @{ Type = "String" } + content = @{ Type = "String" } + description = @{ Type = "String" } + link = @{ Type = "String" } + } + Required = @("winget", "choco", "category", "content", "description", "link") + } + tweaks = @{ + Type = "Object" + Properties = @{ + registry = @{ + Type = "Object" + Properties = @{ + Path = @{ Type = "String" } + Name = @{ Type = "String" } + Type = @{ Type = "String" } + Value = @{ Type = "String" } + OriginalValue = @{ Type = "String" } + } + Required = @("Path", "Name", "Type", "Value", "OriginalValue") + } + service = @{ + Type = "Object" + Properties = @{ + Name = @{ Type = "String" } + StartupType = @{ Type = "String" } + OriginalType = @{ Type = "String" } + } + Required = @("Name", "StartupType", "OriginalType") + } + ScheduledTask = @{ + Type = "Object" + Properties = @{ + Name = @{ Type = "String" } + State = @{ Type = "String" } + OriginalState = @{ Type = "String" } + } + Required = @("Name", "State", "OriginalState") + } + } } - Required = @("winget", "choco", "category", "content", "description", "link") } - tweaks = @{ - Type = "Object" - Properties = @{ - registry = @{ - Type = "Object" - Properties = @{ - Path = @{ Type = "String" } - Name = @{ Type = "String" } - Type = @{ Type = "String" } - Value = @{ Type = "String" } - OriginalValue = @{ Type = "String" } - } - Required = @("Path", "Name", "Type", "Value", "OriginalValue") + + function Test-Schema { + param ( + $Object, + $Schema + ) + + $errors = @() + + $Object.PSObject.Properties | ForEach-Object { + $propName = $_.Name + $propValue = $_.Value + + $propSchema = $Schema.Properties[$propName] + if (-not $propSchema) { + $errors += "Property '$propName' is not defined in the schema" + return } - service = @{ - Type = "Object" - Properties = @{ - Name = @{ Type = "String" } - StartupType = @{ Type = "String" } - OriginalType = @{ Type = "String" } + + switch ($propSchema.Type) { + "String" { + if ($propValue -isnot [string]) { + $errors += "Property '$propName' should be a string but is $($propValue.GetType())" + } } - Required = @("Name", "StartupType", "OriginalType") - } - ScheduledTask = @{ - Type = "Object" - Properties = @{ - Name = @{ Type = "String" } - State = @{ Type = "String" } - OriginalState = @{ Type = "String" } + "Object" { + if ($propValue -isnot [PSCustomObject]) { + $errors += "Property '$propName' should be an object but is $($propValue.GetType())" + } else { + $errors += Test-Schema -Object $propValue -Schema $propSchema + } } - Required = @("Name", "State", "OriginalState") } } + + foreach ($requiredProp in $Schema.Required) { + if (-not $Object.PSObject.Properties.Name.Contains($requiredProp)) { + $errors += "Required property '$requiredProp' is missing" + } + } + + return $errors } } Context "Config File Structure" { It "Should import all config files without errors" { $global:importedConfigs | Should -Not -BeNullOrEmpty -Because "No config files were imported successfully" - Write-Verbose "Imported configs: $($global:importedConfigs.Keys -join ', ')" } - foreach ($configName in $configSchemas.Keys) { - It "Should have the correct structure for $configName" { - $global:importedConfigs | Should -Not -BeNullOrEmpty - $global:importedConfigs.ContainsKey($configName) | Should -BeTrue -Because "Config file '$configName' is missing" - $config = $global:importedConfigs[$configName] - $config | Should -Not -BeNullOrEmpty -Because "Config file '$configName' is empty" - - $schema = $configSchemas[$configName] + It "Should have the correct structure for all configs" { + $results = $configSchemas.Keys | ForEach-Object -Parallel { + $configName = $_ + $config = $using:global:importedConfigs[$configName] + $schema = $using:configSchemas[$configName] - function Test-Schema { - param ( - $Object, - $Schema - ) - - $Object.PSObject.Properties | ForEach-Object { - $propName = $_.Name - $propValue = $_.Value - - $propSchema = $Schema.Properties[$propName] - $propSchema | Should -Not -BeNullOrEmpty -Because "Property '$propName' is not defined in the schema" - - switch ($propSchema.Type) { - "String" { $propValue | Should -BeOfType [string] } - "Object" { - $propValue | Should -BeOfType [PSCustomObject] - Test-Schema -Object $propValue -Schema $propSchema - } - } - } - - foreach ($requiredProp in $Schema.Required) { - $Object.PSObject.Properties.Name | Should -Contain $requiredProp -Because "Required property '$requiredProp' is missing" - } + if (-not $config) { + return "Config file '$configName' is missing or empty" } - Test-Schema -Object $config -Schema $schema - } + & $using:Test-Schema -Object $config -Schema $schema + } -ThrottleLimit 4 + + $results | Should -BeNullOrEmpty -Because "The following schema violations were found: $($results -join '; ')" } } }