From 2340e77e65fa0ad7aeb8d924ce3d9932cf363537 Mon Sep 17 00:00:00 2001 From: Rain Sallow Date: Mon, 29 Apr 2024 17:18:46 -0400 Subject: [PATCH] (#310) Add tests for some helper commands --- Invoke-Tests.ps1 | 12 ++- tests/packages/add-path/add-path.nuspec | 77 +++++++++++++++++ .../add-path/tools/chocolateyinstall.ps1 | 17 ++++ .../add-path/tools/chocolateyuninstall.ps1 | 17 ++++ .../Get-EnvironmentVariable.Tests.ps1 | 29 +++++++ .../Get-EnvironmentVariableNames.Tests.ps1 | 19 +++++ .../Install-ChocolateyPath.Tests.ps1 | 82 +++++++++++++++++++ .../Set-EnvironmentVariable.Tests.ps1 | 37 +++++++++ .../Test-ProcessAdminRights.Tests.ps1 | 12 +++ .../Uninstall-ChocolateyPath.Tests.ps1 | 77 +++++++++++++++++ .../Update-SessionEnvironment.Tests.ps1 | 28 +++++++ 11 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 tests/packages/add-path/add-path.nuspec create mode 100644 tests/packages/add-path/tools/chocolateyinstall.ps1 create mode 100644 tests/packages/add-path/tools/chocolateyuninstall.ps1 create mode 100644 tests/pester-tests/powershell-commands/Get-EnvironmentVariable.Tests.ps1 create mode 100644 tests/pester-tests/powershell-commands/Get-EnvironmentVariableNames.Tests.ps1 create mode 100644 tests/pester-tests/powershell-commands/Install-ChocolateyPath.Tests.ps1 create mode 100644 tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 create mode 100644 tests/pester-tests/powershell-commands/Test-ProcessAdminRights.Tests.ps1 create mode 100644 tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 create mode 100644 tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 diff --git a/Invoke-Tests.ps1 b/Invoke-Tests.ps1 index 3ba4e5bb58..d6ce96f030 100644 --- a/Invoke-Tests.ps1 +++ b/Invoke-Tests.ps1 @@ -22,7 +22,11 @@ param( # Indicate to skip packaging all of the tests packages. Useful for running tests after you've performed the tests previously. [switch] - $SkipPackaging + $SkipPackaging, + + # Specific tag(s) of tests to run + [string[]] + $Tag ) $packageRegex = 'chocolatey\.\d.*\.nupkg' @@ -124,11 +128,15 @@ try { } } + if ($Tag) { + $PesterConfiguration.Filter.Tag = $Tag + } + Invoke-Pester -Configuration $PesterConfiguration } finally { # For some reason we need to import this again... I'm not 100% sure on why... - Import-Module $TestPath/Chocolatey/tools/ChocolateyInstall/helpers/chocolateyInstaller.psm1 + Import-Module $TestPath/Chocolatey/tools/ChocolateyInstall/helpers/chocolateyInstaller.psm1 -Force # Put back Path and Chocolatey Set-EnvironmentVariable -Name 'PATH' -Scope 'User' -Value $environmentVariables.UserPath Set-EnvironmentVariable -Name 'ChocolateyInstall' -Scope 'User' -Value $environmentVariables.UserChocolateyInstall diff --git a/tests/packages/add-path/add-path.nuspec b/tests/packages/add-path/add-path.nuspec new file mode 100644 index 0000000000..8021a8069d --- /dev/null +++ b/tests/packages/add-path/add-path.nuspec @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + add-path + + + + 1.0.0 + + + + + + + + add-path (Install) + __REPLACE_AUTHORS_OF_SOFTWARE_COMMA_SEPARATED__ + + https://_Software_Location_REMOVE_OR_FILL_OUT_ + + + + + + + + + + + add-path SPACE_SEPARATED + __REPLACE__ + __REPLACE__MarkDown_Okay + + + + + + + + + + + + + + + + diff --git a/tests/packages/add-path/tools/chocolateyinstall.ps1 b/tests/packages/add-path/tools/chocolateyinstall.ps1 new file mode 100644 index 0000000000..3627a1aecf --- /dev/null +++ b/tests/packages/add-path/tools/chocolateyinstall.ps1 @@ -0,0 +1,17 @@ +$params = Get-PackageParameters +$path = $params["Path"] +$scope = $params["Scope"] + +if (-not $path) { + throw "You must specify the package parameter /Path" +} + +if (-not $scope) { + $scope = "User" +} + +Write-Host "Adding '$path' to PATH at scope $scope" + +Install-ChocolateyPath -PathToInstall $path -PathType $scope + +Write-Host "$scope PATH after install: $env:PATH" \ No newline at end of file diff --git a/tests/packages/add-path/tools/chocolateyuninstall.ps1 b/tests/packages/add-path/tools/chocolateyuninstall.ps1 new file mode 100644 index 0000000000..14bc57b767 --- /dev/null +++ b/tests/packages/add-path/tools/chocolateyuninstall.ps1 @@ -0,0 +1,17 @@ +$params = Get-PackageParameters +$path = $params["Path"] +$scope = $params["Scope"] + +if (-not $path) { + throw "You must specify the package parameter /Path" +} + +if (-not $scope) { + $scope = "User" +} + +Write-Host "Removing '$path' from PATH at scope $scope" + +Uninstall-ChocolateyPath -PathToUninstall $path -PathType $scope + +Write-Host "$scope PATH after removal: $env:PATH" \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Get-EnvironmentVariable.Tests.ps1 b/tests/pester-tests/powershell-commands/Get-EnvironmentVariable.Tests.ps1 new file mode 100644 index 0000000000..d0bf326a46 --- /dev/null +++ b/tests/pester-tests/powershell-commands/Get-EnvironmentVariable.Tests.ps1 @@ -0,0 +1,29 @@ +Describe 'Get-EnvironmentVariable helper function tests' -Tags Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + Context 'Gets the named environment variable value at the scope' -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + BeforeDiscovery { + $variables = [Environment]::GetEnvironmentVariables($Scope).Keys | ForEach-Object { @{ Name = $_ } } + } + + It 'Gets the environment variable ""' -TestCases $variables { + $expectedValue = [Environment]::GetEnvironmentVariable($Name, $Scope) + Get-EnvironmentVariable -Name $Name -Scope $Scope | Should -BeExactly $expectedValue + } + } + + Context 'Can retrieve the PATH variable without expanding environment names for the scope' { + It 'Retrieves the PATH value with un-expanded environment names' { + Get-EnvironmentVariable -Name 'PATH' -Scope 'Machine' | Should -Match '%[^%;\]+%' + } + } +} \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Get-EnvironmentVariableNames.Tests.ps1 b/tests/pester-tests/powershell-commands/Get-EnvironmentVariableNames.Tests.ps1 new file mode 100644 index 0000000000..927b95bc69 --- /dev/null +++ b/tests/pester-tests/powershell-commands/Get-EnvironmentVariableNames.Tests.ps1 @@ -0,0 +1,19 @@ +Describe 'Get-EnvironmentVariable helper function tests' -Tags Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + Context 'Gets the named environment variable value at the target scope' -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + It 'Gets the complete list of environment variables in the scope"' -ForEach $variables { + $expectedValue = [Environment]::GetEnvironmentVariables($Scope).Keys + Get-EnvironmentVariableNames -Scope $Scope | Should -Be $expectedValue + } + } +} \ 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 new file mode 100644 index 0000000000..81706033bf --- /dev/null +++ b/tests/pester-tests/powershell-commands/Install-ChocolateyPath.Tests.ps1 @@ -0,0 +1,82 @@ +Describe 'Install-ChocolateyPath helper function tests' -Tags Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + AfterAll { + Remove-Module "chocolateyInstaller" -Force + } + + Context 'Adding and removing PATH values' -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + Context 'Path "<_>"' -ForEach @("C:\test", "C:\tools") { + It 'stores the value in the desired PATH scope' { + Install-ChocolateyPath -Path $_ -Scope $Scope + [Environment]::GetEnvironmentVariable('PATH', $_, $Scope) -split [IO.Path]::PathSeparator | Should -Contain $_ + } + } + } + + Context 'Edge cases' { + AfterEach { + Uninstall-ChocolateyPath -Path "C:\test" -Scope Process + } + + It 'successfully detects that a path is already present when it is missing a trailing slash that is present in PATH' { + Install-ChocolateyPath -Path "C:\test\" -Scope Process + Install-ChocolateyPath -Path "C:\test" -Scope Process + + @($env:PATH -split [IO.Path]::PathSeparator) -match "C:\\test" | Should -HaveCount 1 -Because "Install-ChocolateyPath should not add the same path more than once" + } + + It 'successfully detects that a path is already present when it has a trailing slash that is not present in PATH' { + Install-ChocolateyPath -Path "C:\test" -Scope Process + Install-ChocolateyPath -Path "C:\test\" -Scope Process + + @($env:PATH -split [IO.Path]::PathSeparator) -match "C:\\test" | Should -HaveCount 1 -Because "Install-ChocolateyPath should not add the same path more than once" + } + + It 'allows a subpath of a path already in PATH to be added' { + Install-ChocolateyPath -Path "C:\test" -Scope Process + Install-ChocolateyPath -Path "C:\test\subpath" -Scope Process + + @($env:PATH -split [IO.Path]::PathSeparator) | Should -Contain "C:\test\subpath" + } + } +} + +Describe 'Install-ChocolateyPath end-to-end tests with add-path package modifying PATH' -Tags Cmdlet -ForEach @( + @{ Scope = 'User' } + @{ Scope = 'Machine' } +) { + BeforeAll { + Initialize-ChocolateyTestInstall + $PackageUnderTest = 'add-path' + Restore-ChocolateyInstallSnapshot + $OriginalPath = [Environment]::GetEnvironmentVariable('PATH', $Scope) + $Output = Invoke-Choco install $PackageUnderTest --confirm --params "/Path=C:\test /Scope=$Scope" + } + + AfterAll { + Remove-ChocolateyInstallSnapshot + [Environment]::SetEnvironmentVariable('PATH', $OriginalPath, $Scope) + } + + It 'Exits with Success (0)' { + $Output.ExitCode | Should -Be 0 -Because $Output.String + } + + It 'Shows the path being added and the scope' { + $Output.String | Should -MatchExactly "Adding 'C:\\test' to PATH at scope $Scope" + } + + It 'Correctly modifies the PATH' { + [Environment]::GetEnvironmentVariable("PATH", $Scope) | Should -Match "C:\\test" + } +} \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 b/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 new file mode 100644 index 0000000000..6b5cc580cd --- /dev/null +++ b/tests/pester-tests/powershell-commands/Set-EnvironmentVariable.Tests.ps1 @@ -0,0 +1,37 @@ +Describe 'Set-EnvironmentVariable helper function tests' -Tags Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + Context 'Sets an environment variable value at the target scope' -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + BeforeDiscovery { + $variables = @( + @{ Name = "Test"; Value = "TestValue" } + @{ Name = "Environment"; Value = "1234" } + @{ Name = "Variable"; Value = "C:\test\path" } + ) + } + + Describe 'Setting environment variable ' -ForEach $variables { + It 'Sets the target environment variable in the proper scope, as well as current process scope' { + Set-EnvironmentVariable -Name $Name -Value $Value -Scope $Scope + [Environment]::GetEnvironmentVariable($Name, $Scope) | Should -BeExactly $Value + + if ($Scope -ne 'Process') { + [Environment]::GetEnvironmentVariable($Name) | Should -BeExactly $Value + } + } + + AfterAll { + Set-EnvironmentVariable -Name $Name -Value "" -Scope $Scope + } + } + } +} \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Test-ProcessAdminRights.Tests.ps1 b/tests/pester-tests/powershell-commands/Test-ProcessAdminRights.Tests.ps1 new file mode 100644 index 0000000000..c8f89cd905 --- /dev/null +++ b/tests/pester-tests/powershell-commands/Test-ProcessAdminRights.Tests.ps1 @@ -0,0 +1,12 @@ +Describe 'Test-ProcessAdminRights helper function tests' -Tags Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + It 'should report true in an admin context' { + Test-ProcessAdminRights | Should -BeTrue -Because "We should run these tests exclusively as admin" + } +} \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 b/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 new file mode 100644 index 0000000000..6d15ff28c1 --- /dev/null +++ b/tests/pester-tests/powershell-commands/Uninstall-ChocolateyPath.Tests.ps1 @@ -0,0 +1,77 @@ +Describe 'Uninstall-ChocolateyPath helper function tests' -Tags Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + Context 'Adding and removing PATH values' -ForEach @( + @{ Scope = 'Process' } + @{ Scope = 'User' } + @{ Scope = 'Machine' } + ) { + Context 'Path "<_>"' -ForEach @("C:\test", "C:\tools") { + BeforeEach { + Install-ChocolateyPath -Path $_ -Scope $Scope + } + + It 'removes a stored PATH value in the desired PATH scope' { + Uninstall-ChocolateyPath -Path $_ -Scope $Scope + [Environment]::GetEnvironmentVariable('PATH', $_, $Scope) -split [IO.Path]::PathSeparator | Should -Not -Contain $_ + } + } + } + + Context 'Edge cases' { + It 'successfully detects that a path is present and removes it when it is missing a trailing slash that is present in PATH' { + Install-ChocolateyPath -Path "C:\test\" -Scope Process + Uninstall-ChocolateyPath -Path "C:\test" -Scope Process + + @($env:PATH -split [IO.Path]::PathSeparator) -match "C:\\test" | Should -BeNullOrEmpty + } + + It 'successfully detects that a path is present and removes it when it has a trailing slash that is not present in PATH' { + Install-ChocolateyPath -Path "C:\test" -Scope Process + Uninstall-ChocolateyPath -Path "C:\test\" -Scope Process + + @($env:PATH -split [IO.Path]::PathSeparator) -match "C:\\test" | Should -BeNullOrEmpty + } + } +} + +Describe 'Uninstall-ChocolateyPath end-to-end tests with add-path package' -Tags Cmdlet -ForEach @( + @{ Scope = 'User' } + @{ Scope = 'Machine' } +) { + BeforeAll { + Initialize-ChocolateyTestInstall + $PackageUnderTest = 'add-path' + Restore-ChocolateyInstallSnapshot + $OriginalPath = [Environment]::GetEnvironmentVariable('PATH', $Scope) + $install = Invoke-Choco install $PackageUnderTest --confirm --params "/Path=C:\test /Scope=$Scope" + + if ($install.ExitCode -ne 0) { + throw "Setup failed, could not install ${PackageUnderTest}: $($install.String)" + } + + $Output = Invoke-Choco uninstall $PackageUnderTest --confirm --params "/Path=C:\test /Scope=$Scope" + } + + AfterAll { + Remove-ChocolateyInstallSnapshot + [Environment]::SetEnvironmentVariable('PATH', $OriginalPath, $Scope) + } + + It 'Exits with Success (0)' { + $Output.ExitCode | Should -Be 0 -Because $Output.String + } + + It 'Shows the path being added and the scope' { + $Output.String | Should -MatchExactly "Removing 'C:\\test' from PATH at scope $Scope" + } + + It 'Correctly modifies the PATH' { + [Environment]::GetEnvironmentVariable("PATH", $Scope) | Should -BeExactly $OriginalPath + } +} \ No newline at end of file diff --git a/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 b/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 new file mode 100644 index 0000000000..742bc3da5f --- /dev/null +++ b/tests/pester-tests/powershell-commands/Update-SessionEnvironment.Tests.ps1 @@ -0,0 +1,28 @@ +Describe 'Update-SessionEnvironment helper function tests' -Tag Cmdlets { + BeforeAll { + Initialize-ChocolateyTestInstall + + $testLocation = Get-ChocolateyTestLocation + Import-Module "$testLocation\helpers\chocolateyInstaller.psm1" + } + + Context 'Refreshing environment' { + BeforeAll { + [Environment]::SetEnvironmentVariable("Test", "user-value", "User") + [Environment]::SetEnvironmentVariable("Test2", "machine-value", "Machine") + $env:Test3 = "process-value" + } + + It 'successfully refreshes values into the process' { + Update-SessionEnvironment + $env:Test | Should -BeExactly 'user-value' + $env:Test2 | Should -BeExactly 'machine-value' + $env:Test3 | Should -BeNullOrEmpty -Because 'Process-only values should not be preserved' + } + + AfterAll { + [Environment]::SetEnvironmentVariable("Test", [string]::Empty, "User") + [Environment]::SetEnvironmentVariable("Test2", [string]::Empty, "Machine") + } + } +} \ No newline at end of file