tests/Undo.Tests.ps1
|
$moduleRoot = Split-Path -Parent $PSScriptRoot Import-Module (Join-Path $moduleRoot 'Octa.psd1') -Force . (Join-Path $moduleRoot 'private\ActionHelpers.ps1') . (Join-Path $moduleRoot 'private\StateSnapshot.ps1') . (Join-Path $moduleRoot 'private\ElevationCheck.ps1') # Get-WindowsOptionalFeature -Online requires elevation even to read. $isElevated = Test-OctaElevation Describe 'Save-OctaActionSnapshot / Restore-OctaActionSnapshot round-trip (registry)' { $testKey = 'HKCU:\Software\OctaPesterTest' $tempFolder = Join-Path $env:TEMP ('octa-undo-test-{0}' -f [guid]::NewGuid()) New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null New-Item -Path $testKey -Force | Out-Null Set-ItemProperty -Path $testKey -Name 'Marker' -Value 1 -Type DWord It 'snapshots the prior value, then restores it after a change' { $action = New-OctaAction -TargetType Registry -TargetIdentifier "$testKey|Marker" ` -CurrentValue 1 -PlannedValue 0 -Reversible $true $snapshot = Save-OctaActionSnapshot -Action $action -RunFolder $tempFolder $snapshot | Should Not Be $null Set-ItemProperty -Path $testKey -Name 'Marker' -Value 0 -Type DWord (Get-ItemProperty -Path $testKey -Name 'Marker').Marker | Should Be 0 Restore-OctaActionSnapshot -Snapshot $snapshot -RunFolder $tempFolder (Get-ItemProperty -Path $testKey -Name 'Marker').Marker | Should Be 1 } Remove-Item -Path $testKey -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $tempFolder -Recurse -Force -ErrorAction SilentlyContinue } Describe 'Save-OctaActionSnapshot / Restore-OctaActionSnapshot round-trip (key created from scratch)' { $testKey = 'HKCU:\Software\OctaPesterTestNewKey' $tempFolder = Join-Path $env:TEMP ('octa-undo-test-{0}' -f [guid]::NewGuid()) New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null Remove-Item -Path $testKey -Recurse -Force -ErrorAction SilentlyContinue It 'restores a key that did not exist before applying back to absent' { $action = New-OctaAction -TargetType Registry -TargetIdentifier "$testKey|Marker" ` -CurrentValue $null -PlannedValue 1 -Reversible $true $snapshot = Save-OctaActionSnapshot -Action $action -RunFolder $tempFolder $snapshot | Should Not Be $null $snapshot.Type | Should Be 'RegistryKeyAbsent' New-Item -Path $testKey -Force | Out-Null Set-ItemProperty -Path $testKey -Name 'Marker' -Value 1 -Type DWord (Test-Path $testKey) | Should Be $true Restore-OctaActionSnapshot -Snapshot $snapshot -RunFolder $tempFolder (Test-Path $testKey) | Should Be $false } Remove-Item -Path $testKey -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $tempFolder -Recurse -Force -ErrorAction SilentlyContinue } Describe 'Save-OctaActionSnapshot / Restore-OctaActionSnapshot round-trip (value created under an existing key)' { # Real bug found via VM validation (008): the key existed but the specific value did not # yet - `reg import` only adds/overwrites values present in the exported .reg, it never # deletes a value absent from it, so a value Octa creates from scratch under a pre-existing # key used to survive "undo" silently (Undo-OctaRun still reported Success/Restored). $testKey = 'HKCU:\Software\OctaPesterTestExistingKey' $tempFolder = Join-Path $env:TEMP ('octa-undo-test-{0}' -f [guid]::NewGuid()) New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null New-Item -Path $testKey -Force | Out-Null Remove-ItemProperty -Path $testKey -Name 'NewMarker' -ErrorAction SilentlyContinue It 'deletes a value that did not exist before applying, even though the key did' { $action = New-OctaAction -TargetType Registry -TargetIdentifier "$testKey|NewMarker" ` -CurrentValue $null -PlannedValue 1 -Reversible $true $snapshot = Save-OctaActionSnapshot -Action $action -RunFolder $tempFolder $snapshot | Should Not Be $null $snapshot.Type | Should Be 'Registry' $snapshot.ValueExisted | Should Be $false Set-ItemProperty -Path $testKey -Name 'NewMarker' -Value 1 -Type DWord (Get-ItemProperty -Path $testKey -Name 'NewMarker').NewMarker | Should Be 1 Restore-OctaActionSnapshot -Snapshot $snapshot -RunFolder $tempFolder (Get-ItemProperty -Path $testKey -Name 'NewMarker' -ErrorAction SilentlyContinue) | Should Be $null (Test-Path $testKey) | Should Be $true } Remove-Item -Path $testKey -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $tempFolder -Recurse -Force -ErrorAction SilentlyContinue } Describe 'Save-OctaOptionalFeatureState' { It 'captures a real Windows optional feature state without throwing or mutating it' { if (-not $isElevated) { return } # Real Enable/Disable-WindowsOptionalFeature round-trip needs elevation and is slow # (DISM) - deferred to the disposable VM per standing project practice, same as every # other elevated mutation. This only verifies the snapshot shape against real state. $state = Save-OctaOptionalFeatureState -FeatureName 'Microsoft-Windows-Subsystem-Linux' $state | Should Not Be $null $state.Type | Should Be 'OptionalFeature' $state.PriorState | Should Not BeNullOrEmpty } It 'returns $null for a feature name that does not exist' { if (-not $isElevated) { return } $state = Save-OctaOptionalFeatureState -FeatureName 'NotARealFeatureName-Octa-Test' $state | Should Be $null } } Describe 'Undo-OctaRun' { It 'reports NotFound for a run id that does not exist' { $result = Undo-OctaRun -RunId 'this-run-id-does-not-exist' $result.Status | Should Be 'NotFound' } } |