2026-07-19 22:06:07 +02:00
|
|
|
BeforeAll {
|
|
|
|
|
function Get-RegistryFilePathForFeature { param($RegistryKey) $RegistryKey }
|
|
|
|
|
function Invoke-RegistryOperationsFromRegFile { param($RegFilePath) }
|
|
|
|
|
function Invoke-WithTargetUserHive { param($TargetUserName, $ScriptBlock, $ArgumentObject, [switch]$PassHiveContext) }
|
|
|
|
|
function Invoke-NonBlocking { param($ScriptBlock, $ArgumentList) }
|
|
|
|
|
. (Join-Path $PSScriptRoot '..\Scripts\Features\Import-RegistryFile.ps1')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Describe 'Import-RegistryFile' {
|
|
|
|
|
BeforeEach {
|
|
|
|
|
$script:Params = @{}
|
|
|
|
|
$script:regPath = Join-Path $TestDrive 'feature.reg'
|
|
|
|
|
'' | Set-Content -LiteralPath $script:regPath
|
|
|
|
|
Mock Get-RegistryFilePathForFeature { $script:regPath }
|
2026-08-15 17:08:00 +02:00
|
|
|
Mock Invoke-RegistryOperationsFromRegFile { $true }
|
2026-07-19 22:06:07 +02:00
|
|
|
Mock Invoke-WithTargetUserHive {}
|
|
|
|
|
Mock Invoke-NonBlocking { [PSCustomObject]@{ Output = @(); ExitCode = 0; Error = $null } }
|
|
|
|
|
Mock Write-Host {}
|
|
|
|
|
Mock Write-Warning {}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-15 17:08:00 +02:00
|
|
|
It 'returns false when the registry file is missing' {
|
2026-07-19 22:06:07 +02:00
|
|
|
Mock Get-RegistryFilePathForFeature { Join-Path $TestDrive 'missing.reg' }
|
2026-08-15 17:08:00 +02:00
|
|
|
|
|
|
|
|
Import-RegistryFile -message 'Apply' -path 'missing.reg' | Should -BeFalse
|
2026-07-19 22:06:07 +02:00
|
|
|
Should -Invoke Invoke-NonBlocking -Times 0 -Exactly
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-22 19:29:54 +02:00
|
|
|
It 'returns false when registry file resolution throws' {
|
|
|
|
|
Mock Get-RegistryFilePathForFeature { throw 'path resolution failed' }
|
|
|
|
|
|
|
|
|
|
Import-RegistryFile -message 'Apply' -path 'feature.reg' | Should -BeFalse
|
|
|
|
|
Should -Invoke Invoke-NonBlocking -Times 0 -Exactly
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-19 22:06:07 +02:00
|
|
|
It 'uses the PowerShell writer only in WhatIf mode' {
|
|
|
|
|
$script:Params = @{ WhatIf = $true }
|
2026-08-15 17:08:00 +02:00
|
|
|
Import-RegistryFile -message 'Apply' -path 'feature.reg' | Should -BeTrue
|
2026-07-19 22:06:07 +02:00
|
|
|
Should -Invoke Invoke-RegistryOperationsFromRegFile -Times 1 -Exactly -ParameterFilter { $RegFilePath -eq $script:regPath }
|
|
|
|
|
Should -Invoke Invoke-NonBlocking -Times 0 -Exactly
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It 'uses the PowerShell writer for an already-loaded target-user hive' {
|
|
|
|
|
$script:Params = @{ User = 'Alice' }
|
|
|
|
|
Mock Invoke-WithTargetUserHive {
|
|
|
|
|
param($TargetUserName, $ScriptBlock, $ArgumentObject, $PassHiveContext)
|
|
|
|
|
& $ScriptBlock $ArgumentObject ([PSCustomObject]@{ WasAlreadyLoaded = $true })
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-15 17:08:00 +02:00
|
|
|
Import-RegistryFile -message 'Apply' -path 'feature.reg' | Should -BeTrue
|
2026-07-19 22:06:07 +02:00
|
|
|
|
|
|
|
|
Should -Invoke Invoke-WithTargetUserHive -Times 1 -Exactly -ParameterFilter { $TargetUserName -eq 'Alice' -and $PassHiveContext }
|
|
|
|
|
Should -Invoke Invoke-RegistryOperationsFromRegFile -Times 1 -Exactly
|
|
|
|
|
Should -Invoke Invoke-NonBlocking -Times 0 -Exactly
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It 'falls back to the PowerShell writer when reg import fails' {
|
|
|
|
|
Mock Invoke-NonBlocking { [PSCustomObject]@{ Output = @('denied'); ExitCode = 5; Error = 'access denied' } }
|
|
|
|
|
|
2026-08-15 17:08:00 +02:00
|
|
|
Import-RegistryFile -message 'Apply' -path 'feature.reg' | Should -BeTrue
|
2026-07-19 22:06:07 +02:00
|
|
|
|
|
|
|
|
Should -Invoke Invoke-RegistryOperationsFromRegFile -Times 1 -Exactly
|
|
|
|
|
Should -Invoke Write-Warning -Times 1 -Exactly -ParameterFilter { $Message -like "reg import failed*" }
|
2026-08-15 17:08:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It 'returns false when the fallback cannot apply every registry operation' {
|
|
|
|
|
Mock Invoke-NonBlocking { [PSCustomObject]@{ Output = @('denied'); ExitCode = 5; Error = 'access denied' } }
|
|
|
|
|
Mock Invoke-RegistryOperationsFromRegFile { $false }
|
|
|
|
|
|
|
|
|
|
Import-RegistryFile -message 'Apply' -path 'feature.reg' | Should -BeFalse
|
2026-07-19 22:06:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It 'does not invoke the fallback after a successful reg import' {
|
2026-08-15 17:08:00 +02:00
|
|
|
Import-RegistryFile -message 'Apply' -path 'feature.reg' | Should -BeTrue
|
2026-07-19 22:06:07 +02:00
|
|
|
Should -Invoke Invoke-NonBlocking -Times 1 -Exactly
|
|
|
|
|
Should -Invoke Invoke-RegistryOperationsFromRegFile -Times 0 -Exactly
|
|
|
|
|
}
|
|
|
|
|
}
|