Files

157 lines
6.4 KiB
PowerShell
Raw Permalink Normal View History

BeforeAll {
function Invoke-NonBlocking { param($ScriptBlock, $ArgumentList) }
function Enable-WindowsOptionalFeature {
param([switch]$Online, $FeatureName, [switch]$All, [switch]$NoRestart)
[void]$global:OptionalFeatureCalls.Add([PSCustomObject]@{ Action = 'Enable'; Online = $Online; FeatureName = $FeatureName; All = $All; NoRestart = $NoRestart })
}
function Disable-WindowsOptionalFeature {
param([switch]$Online, $FeatureName, [switch]$NoRestart)
[void]$global:OptionalFeatureCalls.Add([PSCustomObject]@{ Action = 'Disable'; Online = $Online; FeatureName = $FeatureName; All = $false; NoRestart = $NoRestart })
}
function Get-WindowsOptionalFeature {
param([switch]$Online, $FeatureName, $ErrorAction)
[void]$global:OptionalFeatureQueryCalls.Add([PSCustomObject]@{ Online = $Online; FeatureName = $FeatureName; ErrorAction = $ErrorAction })
if ($global:OptionalFeatureQueryThrows) {
throw 'feature service unavailable'
}
return [PSCustomObject]@{ State = $global:OptionalFeatureQueryState }
}
. (Join-Path $PSScriptRoot '..\Scripts\Features\Windows-OptionalFeatures.ps1')
}
Describe 'Enable-WindowsFeature' {
BeforeEach {
$script:Params = @{}
Mock Invoke-NonBlocking { @() }
Mock Write-Host {}
}
It 'schedules the requested feature with the non-blocking runner' {
Enable-WindowsFeature -FeatureName 'Feature.One'
Should -Invoke Invoke-NonBlocking -Times 1 -Exactly -ParameterFilter { $ArgumentList -eq 'Feature.One' }
}
It 'calls Enable-WindowsOptionalFeature with the expected arguments' {
$global:OptionalFeatureCalls = [System.Collections.Generic.List[object]]::new()
Mock Invoke-NonBlocking {
param($ScriptBlock, $ArgumentList)
$script:optionalFeatureBlock = $ScriptBlock
$script:optionalFeatureArguments = $ArgumentList
}
Enable-WindowsFeature -FeatureName 'Feature.One'
& $script:optionalFeatureBlock $script:optionalFeatureArguments
$global:OptionalFeatureCalls | Should -HaveCount 1
$global:OptionalFeatureCalls[0].Action | Should -Be 'Enable'
$global:OptionalFeatureCalls[0].Online | Should -BeTrue
$global:OptionalFeatureCalls[0].FeatureName | Should -Be 'Feature.One'
$global:OptionalFeatureCalls[0].All | Should -BeTrue
$global:OptionalFeatureCalls[0].NoRestart | Should -BeTrue
}
It 'does not schedule changes in WhatIf mode' {
$script:Params = @{ WhatIf = $true }
Enable-WindowsFeature -FeatureName 'Feature.One'
Should -Invoke Invoke-NonBlocking -Times 0 -Exactly
}
It 'surfaces an optional-feature enable failure from the scheduled script block' {
Mock Invoke-NonBlocking {
param($ScriptBlock, $ArgumentList)
$script:optionalFeatureBlock = $ScriptBlock
$script:optionalFeatureArguments = $ArgumentList
}
Mock Enable-WindowsOptionalFeature { throw 'feature servicing failed' }
Enable-WindowsFeature -FeatureName 'Feature.One'
{ & $script:optionalFeatureBlock $script:optionalFeatureArguments } | Should -Throw 'feature servicing failed'
}
}
Describe 'Disable-WindowsFeature' {
BeforeEach {
$script:Params = @{}
Mock Invoke-NonBlocking { @() }
Mock Write-Host {}
}
It 'schedules the requested feature with the non-blocking runner' {
Disable-WindowsFeature -FeatureName 'Feature.One'
Should -Invoke Invoke-NonBlocking -Times 1 -Exactly -ParameterFilter { $ArgumentList -eq 'Feature.One' }
}
It 'calls Disable-WindowsOptionalFeature with the expected arguments' {
$global:OptionalFeatureCalls = [System.Collections.Generic.List[object]]::new()
Mock Invoke-NonBlocking {
param($ScriptBlock, $ArgumentList)
$script:optionalFeatureBlock = $ScriptBlock
$script:optionalFeatureArguments = $ArgumentList
}
Disable-WindowsFeature -FeatureName 'Feature.One'
& $script:optionalFeatureBlock $script:optionalFeatureArguments
$global:OptionalFeatureCalls | Should -HaveCount 1
$global:OptionalFeatureCalls[0].Action | Should -Be 'Disable'
$global:OptionalFeatureCalls[0].Online | Should -BeTrue
$global:OptionalFeatureCalls[0].FeatureName | Should -Be 'Feature.One'
$global:OptionalFeatureCalls[0].All | Should -BeFalse
$global:OptionalFeatureCalls[0].NoRestart | Should -BeTrue
}
It 'does not schedule changes in WhatIf mode' {
$script:Params = @{ WhatIf = $true }
Disable-WindowsFeature -FeatureName 'Feature.One'
Should -Invoke Invoke-NonBlocking -Times 0 -Exactly
}
It 'surfaces an optional-feature disable failure from the scheduled script block' {
Mock Invoke-NonBlocking {
param($ScriptBlock, $ArgumentList)
$script:optionalFeatureBlock = $ScriptBlock
$script:optionalFeatureArguments = $ArgumentList
}
Mock Disable-WindowsOptionalFeature { throw 'feature servicing failed' }
Disable-WindowsFeature -FeatureName 'Feature.One'
{ & $script:optionalFeatureBlock $script:optionalFeatureArguments } | Should -Throw 'feature servicing failed'
}
}
Describe 'Test-WindowsOptionalFeatureEnabled' {
BeforeEach {
$global:OptionalFeatureQueryCalls = [System.Collections.Generic.List[object]]::new()
$global:OptionalFeatureQueryThrows = $false
$global:OptionalFeatureQueryState = 'Disabled'
}
It 'returns true for an enabled optional feature' {
$global:OptionalFeatureQueryState = 'Enabled'
Test-WindowsOptionalFeatureEnabled -FeatureName 'Feature.One' | Should -BeTrue
$global:OptionalFeatureQueryCalls | Should -HaveCount 1
$global:OptionalFeatureQueryCalls[0].Online | Should -BeTrue
$global:OptionalFeatureQueryCalls[0].FeatureName | Should -Be 'Feature.One'
$global:OptionalFeatureQueryCalls[0].ErrorAction | Should -Be 'Stop'
}
It 'returns false for a non-enabled optional feature' {
Test-WindowsOptionalFeatureEnabled -FeatureName 'Feature.One' | Should -BeFalse
}
It 'returns false when the optional-feature query fails' {
$global:OptionalFeatureQueryThrows = $true
Test-WindowsOptionalFeatureEnabled -FeatureName 'Feature.One' | Should -BeFalse
}
}