tests/Get-UpdateStatusDrift.Tests.ps1
|
BeforeAll { $modulePath = (Resolve-Path "$PSScriptRoot\..\modules\System.psm1").Path Import-Module $modulePath -Force } AfterAll { Remove-Module System -Force -ErrorAction SilentlyContinue } Describe "Get-UpdateStatusDrift" { Context "Parameter Validation" { BeforeEach { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } Mock Write-Log { } } } It "accepts default parameters" { InModuleScope System { { Get-UpdateStatusDrift -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts ComputerName parameter" { InModuleScope System { { Get-UpdateStatusDrift -ComputerName 'localhost' -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts Profile parameter with Basis" { InModuleScope System { { Get-UpdateStatusDrift -Profile Basis -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts Profile parameter with Recommended" { InModuleScope System { { Get-UpdateStatusDrift -Profile Recommended -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts Profile parameter with Strict" { InModuleScope System { { Get-UpdateStatusDrift -Profile Strict -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "rejects invalid Profile parameter" { InModuleScope System { { Get-UpdateStatusDrift -Profile 'InvalidProfile' -ErrorAction Stop } | Should -Throw } } It "accepts Detailed switch" { InModuleScope System { { Get-UpdateStatusDrift -Detailed -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts ReportDriftOnly switch" { InModuleScope System { { Get-UpdateStatusDrift -ReportDriftOnly -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts AutoUpdateEnabled parameter" { InModuleScope System { { Get-UpdateStatusDrift -AutoUpdateEnabled $true -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts RequireScheduledRestart parameter" { InModuleScope System { { Get-UpdateStatusDrift -RequireScheduledRestart $true -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "accepts MaxDaysSinceLastUpdate parameter with valid range" { InModuleScope System { { Get-UpdateStatusDrift -MaxDaysSinceLastUpdate 14 -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "rejects MaxDaysSinceLastUpdate below 1" { InModuleScope System { { Get-UpdateStatusDrift -MaxDaysSinceLastUpdate 0 -ErrorAction Stop } | Should -Throw } } It "rejects MaxDaysSinceLastUpdate above 365" { InModuleScope System { { Get-UpdateStatusDrift -MaxDaysSinceLastUpdate 366 -ErrorAction Stop } | Should -Throw } } It "accepts MaxDaysSinceLastUpdate boundary values" { InModuleScope System { { Get-UpdateStatusDrift -MaxDaysSinceLastUpdate 1 -ErrorAction SilentlyContinue } | Should -Not -Throw { Get-UpdateStatusDrift -MaxDaysSinceLastUpdate 365 -ErrorAction SilentlyContinue } | Should -Not -Throw } } } Context "Function Execution - Local" { BeforeEach { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } Mock Write-Log { } } } It "returns results without error" { InModuleScope System { { Get-UpdateStatusDrift -ErrorAction SilentlyContinue } | Should -Not -Throw } } It "returns a collection or null" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue ($result -is [System.Collections.IEnumerable] -or $null -eq $result) | Should -Be $true } } It "respects WhatIf parameter" { InModuleScope System { $result = Get-UpdateStatusDrift -WhatIf -ErrorAction SilentlyContinue $result.Count | Should -Be 0 } } } Context "Return Value Structure" { BeforeEach { InModuleScope System { Mock Get-ItemProperty -ParameterFilter { $Name -eq 'NoAutoUpdate' } { [PSCustomObject]@{ NoAutoUpdate = 1 } } Mock Get-ItemProperty { [PSCustomObject]@{ } } Mock Write-Log { } } } It "includes Category property" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result[0].Category | Should -Be 'Windows Updates' } } It "includes Setting property" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result[0].Setting | Should -Match 'Automatic Updates' } } It "includes Status property (DRIFT or COMPLIANT)" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result[0].Status | Should -Match '^(DRIFT|COMPLIANT)$' } } It "includes Severity property" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result[0].Severity | Should -Match '^(CRITICAL|HIGH|MEDIUM|LOW|INFO)$' } } It "includes ComputerName property" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result[0].ComputerName | Should -Not -BeNullOrEmpty } } } Context "Automatic Updates Detection" { BeforeEach { InModuleScope System { Mock Write-Log { } } } It "detects compliant when auto-updates enabled and expected enabled" { InModuleScope System { Mock Get-ItemProperty -ParameterFilter { $Name -eq 'NoAutoUpdate' } { [PSCustomObject]@{ NoAutoUpdate = 0 } } Mock Get-ItemProperty { [PSCustomObject]@{ } } $result = Get-UpdateStatusDrift -AutoUpdateEnabled $true -ErrorAction SilentlyContinue $autoItem = $result | Where-Object { $_.Setting -match 'Automatic Updates' } $autoItem.Status | Should -Be 'COMPLIANT' $autoItem.Actual | Should -Be 'Enabled' $autoItem.Expected | Should -Be 'Enabled' } } It "reports compliant status when settings match expectations" { InModuleScope System { Mock Write-Log { } Mock Get-ItemProperty { [PSCustomObject]@{ NoAutoUpdate = 0 } } $result = Get-UpdateStatusDrift -AutoUpdateEnabled $true -ErrorAction SilentlyContinue $autoItem = $result | Where-Object { $_.Setting -match 'Automatic Updates' } $autoItem.Status | Should -Match '^(DRIFT|COMPLIANT)$' $autoItem.Expected | Should -Not -BeNullOrEmpty $autoItem.Actual | Should -Not -BeNullOrEmpty } } It "returns findings with severity levels" { InModuleScope System { Mock Write-Log { } Mock Get-ItemProperty { [PSCustomObject]@{ } } $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result | ForEach-Object { $_.Severity | Should -Match '^(CRITICAL|HIGH|MEDIUM|LOW|INFO)$' } } } It "formats actual and expected values correctly" { InModuleScope System { Mock Write-Log { } Mock Get-ItemProperty { [PSCustomObject]@{ NoAutoUpdate = 0 } } $result = Get-UpdateStatusDrift -AutoUpdateEnabled $true -ErrorAction SilentlyContinue $result | Where-Object { $_.Setting -match 'Automatic' } | ForEach-Object { $_.Actual | Should -Match 'Enabled|Disabled' $_.Expected | Should -Match 'Enabled|Disabled' } } } It "handles null NoAutoUpdate as 0 (enabled)" { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } $result = Get-UpdateStatusDrift -AutoUpdateEnabled $true -ErrorAction SilentlyContinue $autoItem = $result | Where-Object { $_.Setting -match 'Automatic Updates' } $autoItem.Status | Should -Be 'COMPLIANT' } } } Context "Profile-Based Checks" { BeforeEach { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } Mock Write-Log { } } } It "Basis profile checks only auto-updates" { InModuleScope System { $result = Get-UpdateStatusDrift -Profile Basis -ErrorAction SilentlyContinue $result | Where-Object { $_.Setting -match 'Automatic Updates' } | Should -Not -BeNullOrEmpty $result | Where-Object { $_.Setting -match 'Scheduled' } | Should -BeNullOrEmpty } } It "Recommended profile includes scheduled install check" { InModuleScope System { $result = Get-UpdateStatusDrift -Profile Recommended -ErrorAction SilentlyContinue $result | Where-Object { $_.Setting -match 'Automatic Updates' } | Should -Not -BeNullOrEmpty $result | Where-Object { $_.Setting -match 'Scheduled Install' } | Should -Not -BeNullOrEmpty } } It "Strict profile includes more checks than Recommended" { InModuleScope System { $result = Get-UpdateStatusDrift -Profile Strict -ErrorAction SilentlyContinue $checkCount = ($result | Select-Object -ExpandProperty Setting).Count $checkCount | Should -BeGreaterThan 2 } } } Context "Scheduled Install Detection" { BeforeEach { InModuleScope System { Mock Write-Log { } } } It "detects missing scheduled install configuration" { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } $result = Get-UpdateStatusDrift -Profile Recommended -ErrorAction SilentlyContinue $schedItem = $result | Where-Object { $_.Setting -match 'Scheduled Install' } $schedItem.Status | Should -Be 'DRIFT' $schedItem.Actual | Should -Be 'Not Configured' } } It "detects configured scheduled install" { InModuleScope System { Mock Get-ItemProperty -ParameterFilter { $Name -eq 'ScheduledInstallDay' } { [PSCustomObject]@{ ScheduledInstallDay = 2 } } Mock Get-ItemProperty -ParameterFilter { $Name -eq 'ScheduledInstallTime' } { [PSCustomObject]@{ ScheduledInstallTime = 3 } } Mock Get-ItemProperty { [PSCustomObject]@{ } } $result = Get-UpdateStatusDrift -Profile Recommended -ErrorAction SilentlyContinue $schedItem = $result | Where-Object { $_.Setting -match 'Scheduled Install' } $schedItem.Status | Should -Be 'COMPLIANT' $schedItem.Actual | Should -Match 'Monday' } } } Context "Report Filtering" { BeforeEach { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } Mock Write-Log { } } } It "filters to DRIFT only with ReportDriftOnly" { InModuleScope System { $result = Get-UpdateStatusDrift -ReportDriftOnly -ErrorAction SilentlyContinue if ($result) { $result | Where-Object { $_.Status -eq 'COMPLIANT' } | Should -BeNullOrEmpty $result[0].Status | Should -Be 'DRIFT' } } } It "returns all findings without ReportDriftOnly" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue ($result | Measure-Object).Count | Should -BeGreaterThan 0 } } } Context "Error Handling" { BeforeEach { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } Mock Write-Log { } } } It "continues processing after registry access issues" { InModuleScope System { $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result | Should -Not -BeNullOrEmpty $result.Count | Should -BeGreaterThan 0 } } It "handles missing registry values gracefully" { InModuleScope System { Mock Get-ItemProperty { [PSCustomObject]@{ } } $result = Get-UpdateStatusDrift -ErrorAction SilentlyContinue $result | Should -Not -BeNullOrEmpty } } } Context "Documentation" { It "has complete help documentation" { $help = Get-Help Get-UpdateStatusDrift $help.Synopsis | Should -Not -BeNullOrEmpty $help.Synopsis | Should -Match 'drift' } It "documents all parameters" { $help = Get-Help Get-UpdateStatusDrift $help.Parameters.Parameter.Name | Should -Contain 'Profile' $help.Parameters.Parameter.Name | Should -Contain 'ComputerName' $help.Parameters.Parameter.Name | Should -Contain 'Detailed' } It "includes examples" { $help = Get-Help Get-UpdateStatusDrift $help.Examples.Example.Count | Should -BeGreaterThan 0 } It "includes dependency notes" { $help = Get-Help Get-UpdateStatusDrift $help.Notes | Should -Not -BeNullOrEmpty $help.Notes | Should -Match '(Core|Logging|Write-Log)' } } } |