From a523d823fe7b2a06a12a5c0882538ce9983ebd98 Mon Sep 17 00:00:00 2001 From: Rain Sallow Date: Mon, 21 Oct 2024 16:14:09 -0400 Subject: [PATCH] (#3318) Add -WhatIf unit tests for helper commands Update-SessionEnvironment, Set-EnvironmentVariable, and (Un)Install-ChocolateyPath implement ShouldProcess, so we can use -WhatIf to verify their behaviour with unit tests. --- tests/helpers/common/Get-WhatIfResult.ps1 | 29 +++++++++++++++ .../Install-ChocolateyPath.Tests.ps1 | 36 +++++++++++++++++-- .../Set-EnvironmentVariable.Tests.ps1 | 22 +++++++++++- .../Uninstall-ChocolateyPath.Tests.ps1 | 32 +++++++++++++++-- .../Update-SessionEnvironment.Tests.ps1 | 12 ++++++- 5 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 tests/helpers/common/Get-WhatIfResult.ps1 diff --git a/tests/helpers/common/Get-WhatIfResult.ps1 b/tests/helpers/common/Get-WhatIfResult.ps1 new file mode 100644 index 0000000000..53e38590d3 --- /dev/null +++ b/tests/helpers/common/Get-WhatIfResult.ps1 @@ -0,0 +1,29 @@ +function Get-WhatIfResult { + <# + .SYNOPSIS + Runs a $Command in a new powershell.exe process, and then returns *only* + the output lines that are prefixed with 'What if:' which are written as + console output. + #> + [CmdletBinding()] + param( + # The script to execute in the new process. + [Parameter(Mandatory)] + [scriptblock] + $Command, + + # Any setup scripts that are required for running. All output from this + # script block will be suppressed, if possible. + [Parameter()] + [scriptblock] + $Preamble + ) + + $commandString = @' +. {{ {0} }} *>&1 > $null +& {{ {1} }} +'@ -f $Preamble, $Command + + powershell -NoProfile -NonInteractive -Command $commandString | + Where-Object { $_ -like "What if:*" } +} \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Install-ChocolateyPath.Tests.ps1 b/tests/pester-tests/powershell-commands/Install-ChocolateyPath.Tests.ps1 index 379a73db76..d6e4d094c2 100644 --- a/tests/pester-tests/powershell-commands/Install-ChocolateyPath.Tests.ps1 +++ b/tests/pester-tests/powershell-commands/Install-ChocolateyPath.Tests.ps1 @@ -1,4 +1,4 @@ -Describe 'Install-ChocolateyPath helper function tests' -Tags Cmdlets { +Describe 'Install-ChocolateyPath helper function tests' -Tags InstallChocolateyPath, Cmdlets { BeforeAll { Initialize-ChocolateyTestInstall @@ -10,7 +10,37 @@ Remove-Module "chocolateyInstaller" -Force } - Context 'Adding and removing PATH values' -ForEach @( + Context 'Unit tests' -Tags WhatIf -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + Context 'Path "<_>"' -ForEach @("C:\test", "C:\tools") { + BeforeAll { + $Preamble = [scriptblock]::Create("Import-Module '$testLocation\helpers\chocolateyInstaller.psm1'") + } + + It 'stores the value in the desired PATH scope' { + $Command = [scriptblock]::Create("Install-ChocolateyPath -Path '$_' -Scope $Scope -WhatIf") + + $results = @( Get-WhatIfResult -Preamble $Preamble -Command $Command ) + $results[0] | Should -BeExactly "What if: Performing the operation ""Set $Scope environment variable"" on target ""PATH""." + + if ($Scope -ne 'Process') { + $results[1] | Should -BeExactly 'What if: Performing the operation "Notify system of changes" on target "Environment variables".' + $results[2] | Should -BeExactly 'What if: Performing the operation "Refresh all environment variables" on target "Current process".' + } + } + + It 'skips adding the value if it is already present' { + $targetPathEntry = [Environment]::GetEnvironmentVariable('PATH', $Scope) -split ';' | Select-Object -First 1 + $Command = [scriptblock]::Create("Install-ChocolateyPath -Path '$targetPathEntry' -Scope $Scope -WhatIf") + Get-WhatIfResult -Preamble $Preamble -Command $Command | Should -BeNullOrEmpty -Because 'we should skip adding values that already exist' + } + } + } + + Context 'Adding and removing PATH values' -Tag VMOnly -ForEach @( @{ Scope = 'Process' } @{ Scope = 'User' } @{ Scope = 'Machine' } @@ -55,7 +85,7 @@ } } -Describe 'Install-ChocolateyPath end-to-end tests with add-path package modifying PATH' -Tags Cmdlet -ForEach @( +Describe 'Install-ChocolateyPath end-to-end tests with add-path package modifying PATH' -Tags Cmdlet, UninstallChocolateyPath, VMOnly -ForEach @( @{ Scope = 'User' } @{ Scope = 'Machine' } ) { diff --git a/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 b/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 index 7e67ca9e2a..f750e75aaf 100644 --- a/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 +++ b/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 @@ -1,4 +1,4 @@ -Describe 'Set-EnvironmentVariable helper function tests' -Tags Cmdlets { +Describe 'Set-EnvironmentVariable helper function tests' -Tags SetEnvironmentVariable, Cmdlets { BeforeAll { Initialize-ChocolateyTestInstall @@ -6,6 +6,26 @@ Describe 'Set-EnvironmentVariable helper function tests' -Tags Cmdlets { Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" } + Context 'Unit tests' -Tags WhatIf -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + It 'Sets an environment variable value at the target ' { + $testVariableName = 'testVariable' + $Preamble = [scriptblock]::Create("Import-Module '$testLocation\helpers\chocolateyInstaller.psm1'") + $Command = [scriptblock]::Create("Set-EnvironmentVariable -Name $testVariableName -Value 'TEST' -Scope $Scope -WhatIf") + + $results = @( Get-WhatIfResult -Preamble $Preamble -Command $Command ) + $results[0] | Should -BeExactly "What if: Performing the operation ""Set $Scope environment variable"" on target ""testVariable""." + + if ($Scope -ne 'Process') { + $results[1] | Should -BeExactly 'What if: Performing the operation "Notify system of changes" on target "Environment variables".' + $results[2] | Should -BeExactly 'What if: Performing the operation "Refresh all environment variables" on target "Current process".' + } + } + } + Context 'Sets an environment variable value at the target ' -ForEach @( @{ Scope = 'Process' } @{ Scope = 'User' } diff --git a/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 b/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 index 29dbeec65b..489a170fb4 100644 --- a/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 +++ b/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 @@ -1,4 +1,4 @@ -Describe 'Uninstall-ChocolateyPath helper function tests' -Tags Cmdlets { +Describe 'Uninstall-ChocolateyPath helper function tests' -Tags UninstallChocolateyPath, Cmdlets { BeforeAll { Initialize-ChocolateyTestInstall @@ -6,7 +6,33 @@ Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" } - Context 'Adding and removing PATH values' -ForEach @( + Context 'Unit tests' -Tags WhatIf -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + It 'removes a stored PATH value in the desired PATH scope' { + $targetPathEntry = [Environment]::GetEnvironmentVariable('PATH', $Scope) -split ';' | Select-Object -First 1 + $Preamble = [scriptblock]::Create("Import-Module '$testLocation\helpers\chocolateyInstaller.psm1'") + $Command = [scriptblock]::Create("Uninstall-ChocolateyPath -Path '$targetPathEntry' -Scope $Scope -WhatIf") + + $results = @( Get-WhatIfResult -Preamble $Preamble -Command $Command ) + $results[0] | Should -BeExactly "What if: Performing the operation ""Set $Scope environment variable"" on target ""PATH""." + + if ($Scope -ne 'Process') { + $results[1] | Should -BeExactly 'What if: Performing the operation "Notify system of changes" on target "Environment variables".' + $results[2] | Should -BeExactly 'What if: Performing the operation "Refresh all environment variables" on target "Current process".' + } + } + + It 'skips removing the value if it is not present' { + $targetPathEntry = [Environment]::GetEnvironmentVariable('PATH', $Scope) -split ';' | Select-Object -First 1 + $Command = [scriptblock]::Create("Uninstall-ChocolateyPath -Path 'C:\ThisShouldNotBePresent' -Scope $Scope -WhatIf") + Get-WhatIfResult -Preamble $Preamble -Command $Command | Should -BeNullOrEmpty -Because 'we should skip removing a value that does not exist' + } + } + + Context 'Adding and removing PATH values' -Tags VMOnly -ForEach @( @{ Scope = 'Process' } @{ Scope = 'User' } @{ Scope = 'Machine' } @@ -40,7 +66,7 @@ } } -Describe 'Uninstall-ChocolateyPath end-to-end tests with add-path package' -Tags Cmdlet -ForEach @( +Describe 'Uninstall-ChocolateyPath end-to-end tests with add-path package' -Tags Cmdlet, UninstallChocolateyPath, VMOnly -ForEach @( @{ Scope = 'User' } @{ Scope = 'Machine' } ) { diff --git a/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 b/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 index 9f8bcccbc6..7a1c081a18 100644 --- a/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 +++ b/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 @@ -1,10 +1,20 @@ -Describe 'Update-SessionEnvironment helper function tests' -Tag Cmdlets { +Describe 'Update-SessionEnvironment helper function tests' -Tag UpdateSessionEnvironment, Cmdlets { BeforeAll { Initialize-ChocolateyTestInstall $testLocation = Get-ChocolateyTestLocation Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" } + + Context 'Unit tests' -Tag WhatIf { + It 'refreshes the current session environment variables' { + $Preamble = [scriptblock]::Create("Import-Module '$testLocation\helpers\chocolateyInstaller.psm1'") + $Command = [scriptblock]::Create("Update-SessionEnvironment -WhatIf") + + $results = Get-WhatIfResult -Preamble $Preamble -Command $Command + $results | Should -BeExactly 'What if: Performing the operation "refresh all environment variables" on target "current process".' + } + } Context 'Refreshing environment' { BeforeAll {