functions/_Install-Vendir.Tests.ps1
|
# <copyright file="_Install-Vendir.Tests.ps1" company="Endjin Limited"> # Copyright (c) Endjin Limited. All rights reserved. # </copyright> Describe "_Install-Vendir" { BeforeAll { $sut = "$PSScriptRoot\_Install-Vendir.ps1" . $sut # Set up the script-scoped variable used as default $script:VendirVersion = '0.41.0' # Default mocks for checksum verification (most tests don't care about checksums) Mock Write-Warning { } Mock Get-FileHash { return @{ Hash = 'fakehash' } } } Context "OS Detection" { BeforeAll { Mock Test-Path { return $true } Mock Invoke-WebRequest { } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should use correct OS string in download URL for current platform" { $capturedUri = $null Mock Invoke-WebRequest { $script:capturedUri = $Uri } -ParameterFilter { $OutFile } _Install-Vendir if ($IsWindows) { $script:capturedUri | Should -Match 'vendir-windows-' } elseif ($IsMacOS) { $script:capturedUri | Should -Match 'vendir-darwin-' } elseif ($IsLinux) { $script:capturedUri | Should -Match 'vendir-linux-' } } } Context "Architecture Mapping" { BeforeAll { Mock Test-Path { return $true } Mock Invoke-WebRequest { } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should use correct architecture string in download URL" { $capturedUri = $null Mock Invoke-WebRequest { $script:capturedUri = $Uri } -ParameterFilter { $OutFile } _Install-Vendir $arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture switch ($arch) { 'X64' { $script:capturedUri | Should -Match '-amd64' } 'Arm64' { $script:capturedUri | Should -Match '-arm64' } } } } Context "Download URL Construction" { BeforeAll { Mock Test-Path { return $true } Mock Invoke-WebRequest { } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should construct URL with correct format including version, OS, and architecture" { $capturedUri = $null Mock Invoke-WebRequest { $script:capturedUri = $Uri } -ParameterFilter { $OutFile } _Install-Vendir -Version '0.45.1' $script:capturedUri | Should -Match '^https://github\.com/carvel-dev/vendir/releases/download/v0\.45\.1/vendir-' } It "Should use default version when not specified" { $capturedUri = $null Mock Invoke-WebRequest { $script:capturedUri = $Uri } -ParameterFilter { $OutFile } _Install-Vendir $script:capturedUri | Should -Match "/v$script:VendirVersion/" } } Context "Directory Creation" { BeforeAll { Mock Invoke-WebRequest { } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should create bin/ directory if missing" { Mock Test-Path { return $false } Mock New-Item { } _Install-Vendir Should -Invoke New-Item -ParameterFilter { $ItemType -eq 'Directory' -and $Path -match 'bin$' } } It "Should not create bin/ directory if it exists" { Mock Test-Path { return $true } Mock New-Item { } _Install-Vendir Should -Invoke New-Item -Times 0 } } Context "Binary Download - Golden Path" { BeforeAll { Mock Test-Path { return $true } Mock Invoke-WebRequest { } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should call Invoke-WebRequest with correct parameters" { Mock Invoke-WebRequest { } -Verifiable _Install-Vendir Should -Invoke Invoke-WebRequest -ParameterFilter { $Uri -match 'github\.com/carvel-dev/vendir' -and $OutFile -match 'vendir' -and $ErrorAction -eq 'Stop' } } It "Should return the destination path" { $result = _Install-Vendir $result | Should -Match 'bin[/\\]vendir' } It "Should write information about download progress" { _Install-Vendir Should -Invoke Write-Information -ParameterFilter { $MessageData -like '*Downloading vendir*' } } It "Should write information about installation completion" { _Install-Vendir Should -Invoke Write-Information -ParameterFilter { $MessageData -like '*installed to*' } } } Context "Binary Download - Error Handling" { BeforeAll { Mock Test-Path { return $true } Mock Write-Information { } } It "Should throw descriptive error when download fails" { Mock Invoke-WebRequest { throw "404 Not Found" } { _Install-Vendir } | Should -Throw "*Failed to download vendir*" } It "Should include URL in error message" { Mock Invoke-WebRequest { throw "Connection refused" } { _Install-Vendir } | Should -Throw "*github.com/carvel-dev/vendir*" } } Context "Executable Permissions" { BeforeAll { Mock Test-Path { return $true } Mock Invoke-WebRequest { } Mock Write-Information { } } # Note: $IsWindows, $IsMacOS, $IsLinux are automatic variables that cannot be mocked # We test the actual behavior on the current platform It "Should handle executable permissions appropriately for current platform" { if ($IsWindows) { # On Windows, chmod should not be called function chmod {} # You cannot mock a non-existent command Mock chmod { throw "chmod should not be called on Windows" } { _Install-Vendir } | Should -Not -Throw } else { # On non-Windows, chmod +x should be called $chmodCalled = $false Mock chmod { $script:chmodCalled = $true } _Install-Vendir $script:chmodCalled | Should -Be $true } } } Context "Unsupported Architecture" { It "Should throw for unsupported architecture" { # We can't mock [RuntimeInformation]::OSArchitecture, so inline the switch logic # to verify the default branch behavior $arch = 'RISC-V' { switch ($arch) { 'X64' { $archStr = 'amd64' } 'Arm64' { $archStr = 'arm64' } default { throw "Unsupported architecture: $arch" } } } | Should -Throw "Unsupported architecture: RISC-V" } } Context "Checksum Verification" { BeforeAll { Mock Test-Path { return $true } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should verify SHA256 checksum after download" { Mock Invoke-WebRequest { } -ParameterFilter { $Uri -match 'vendir-' } Mock Invoke-WebRequest { return @{ Content = "abc123def456 vendir-linux-amd64`nfed789 vendir-windows-amd64.exe`n000aaa vendir-darwin-amd64" } } -ParameterFilter { $Uri -match 'checksums\.txt' } Mock Get-FileHash { $hash = $IsWindows ? 'fed789' : 'abc123def456' return @{ Hash = $hash } } { _Install-Vendir } | Should -Not -Throw Should -Invoke Get-FileHash -Times 1 } It "Should throw when checksum does not match" { Mock Invoke-WebRequest { } -ParameterFilter { $Uri -match 'vendir-' -and $Uri -notmatch 'checksums' } Mock Invoke-WebRequest { return @{ Content = "expectedhash vendir-linux-amd64`nfed789 vendir-windows-amd64.exe`n000aaa vendir-darwin-amd64" } } -ParameterFilter { $Uri -match 'checksums\.txt' } Mock Get-FileHash { return @{ Hash = 'wronghash' } } { _Install-Vendir } | Should -Throw "*Checksum mismatch*" } It "Should warn and continue when checksums.txt download fails" { Mock Invoke-WebRequest { } -ParameterFilter { $Uri -match 'vendir-' -and $Uri -notmatch 'checksums' } Mock Invoke-WebRequest { throw "404 Not Found" } -ParameterFilter { $Uri -match 'checksums\.txt' } Mock Write-Warning { } { _Install-Vendir } | Should -Not -Throw Should -Invoke Write-Warning -Times 1 } } Context "Custom Version" { BeforeAll { Mock Test-Path { return $true } Mock Invoke-WebRequest { } Mock Write-Information { } if (-not $IsWindows) { Mock chmod { } } } It "Should use provided version parameter in URL" { $capturedUri = $null Mock Invoke-WebRequest { $script:capturedUri = $Uri } -ParameterFilter { $OutFile } _Install-Vendir -Version '0.99.0' $script:capturedUri | Should -Match '/v0\.99\.0/' } It "Should include custom version in information message" { Mock Write-Information { } -Verifiable _Install-Vendir -Version '0.99.0' Should -Invoke Write-Information -ParameterFilter { $MessageData -like '*0.99.0*' } } } } |