Tests/Sync-ForgePackage.Tests.ps1
|
Import-Module "$PSScriptRoot/../ChocoForge.psd1" -Force Describe 'Sync-ForgePackage' { InModuleScope 'ChocoForge' { BeforeEach { Mock Invoke-RestMethod { Get-Content "$PSScriptRoot/assets/qemu-img-mocks/github-releases.json" -Raw | ConvertFrom-Json } # SAFETY: publishing is always mocked. A real push to community.chocolatey.org # cannot be undone, so no test in this file may reach the network. Mock Publish-ChocolateyPackage { $Path } # Build-ChocolateyPackage has its own coverage; return predictable paths so the # assertions here are about Sync's own build/publish/skip logic. Mock Build-ChocolateyPackage { $version = $Context.version.ToString() Join-Path 'C:/out' "qemu-img.$version.nupkg" } $script:configPath = "$PSScriptRoot/assets/qemu-img-package/qemu-img.forge.yaml" } Context 'all sources usable' { BeforeEach { Mock Expand-EnvironmentVariables { 'fake-api-key' } Mock Invoke-Chocolatey { if ($PesterBoundParameters.Arguments[0] -ne 'search') { return [PSCustomObject]@{ ExitCode = 0; StdOut = ''; StdErr = '' } } if ($PesterBoundParameters.Arguments -contains '--version') { # The moderation probe. Real choco returns a zero-length string when the # version is not present, so nothing is in moderation here. return [PSCustomObject]@{ ExitCode = 0; StdOut = ''; StdErr = '' } } $mockFile = if ($PesterBoundParameters.Arguments[5].StartsWith('https://community.chocolatey.org/api/v2')) { 'chocolatey-packages.txt' } else { 'github-packages.txt' } [PSCustomObject]@{ ExitCode = 0 StdOut = Get-Content "$PSScriptRoot/assets/qemu-img-mocks/$mockFile" -Raw StdErr = '' } } } It 'Builds only the versions that are missing somewhere' { # community has 2.3.0; github and gitlab have nothing. Union of missing = all 3. $null = Sync-ForgePackage -Path $script:configPath Should -Invoke Build-ChocolateyPackage -Times 3 -Exactly } It 'Publishes each missing version to each source that needs it' { $null = Sync-ForgePackage -Path $script:configPath # community already has 2.3.0 so needs 10.0.0 + 9.2.0; github and gitlab need all 3 each. Should -Invoke Publish-ChocolateyPackage -Times 8 -Exactly Should -Invoke Publish-ChocolateyPackage -Times 2 -Exactly -ParameterFilter { $SourceUrl -like 'https://community.chocolatey.org*' } } It 'Does not publish a version a source already has' { $null = Sync-ForgePackage -Path $script:configPath Should -Invoke Publish-ChocolateyPackage -Times 0 -Exactly -ParameterFilter { $SourceUrl -like 'https://community.chocolatey.org*' -and $Path -like '*2.3.0.nupkg' } } It 'Auto-discovers the configuration when given a directory' { { Sync-ForgePackage -Path "$PSScriptRoot/assets/qemu-img-package" } | Should -Not -Throw Should -Invoke Build-ChocolateyPackage -Times 3 -Exactly } It 'Derives the nuspec path from the configuration it actually read' { $null = Sync-ForgePackage -Path $script:configPath Should -Invoke Build-ChocolateyPackage -ParameterFilter { $NuspecPath -like '*qemu-img.nuspec' } } } Context 'Chocolatey community moderation' { BeforeEach { Mock Expand-EnvironmentVariables { 'fake-api-key' } } It 'Skips publishing when the exact version is already in moderation' { Mock Invoke-Chocolatey { if ($PesterBoundParameters.Arguments[0] -ne 'search') { return [PSCustomObject]@{ ExitCode = 0; StdOut = ''; StdErr = '' } } # The per-version moderation probe carries --version; report a hit for it. if ($PesterBoundParameters.Arguments -contains '--version') { return [PSCustomObject]@{ ExitCode = 0; StdOut = 'qemu-img|10.0.0'; StdErr = '' } } $mockFile = if ($PesterBoundParameters.Arguments[5].StartsWith('https://community.chocolatey.org/api/v2')) { 'chocolatey-packages.txt' } else { 'github-packages.txt' } [PSCustomObject]@{ ExitCode = 0 StdOut = Get-Content "$PSScriptRoot/assets/qemu-img-mocks/$mockFile" -Raw StdErr = '' } } $null = Sync-ForgePackage -Path $script:configPath # Nothing goes to the community feed; github and gitlab still receive all 3 each. Should -Invoke Publish-ChocolateyPackage -Times 0 -Exactly -ParameterFilter { $SourceUrl -like 'https://community.chocolatey.org*' } Should -Invoke Publish-ChocolateyPackage -Times 6 -Exactly } It 'Throws when the moderation probe fails' { Mock Invoke-Chocolatey { if ($PesterBoundParameters.Arguments[0] -ne 'search') { return [PSCustomObject]@{ ExitCode = 0; StdOut = ''; StdErr = '' } } if ($PesterBoundParameters.Arguments -contains '--version') { return [PSCustomObject]@{ ExitCode = 1; StdOut = 'network exploded'; StdErr = '' } } $mockFile = if ($PesterBoundParameters.Arguments[5].StartsWith('https://community.chocolatey.org/api/v2')) { 'chocolatey-packages.txt' } else { 'github-packages.txt' } [PSCustomObject]@{ ExitCode = 0 StdOut = Get-Content "$PSScriptRoot/assets/qemu-img-mocks/$mockFile" -Raw StdErr = '' } } { Sync-ForgePackage -Path $script:configPath } | Should -Throw '*choco search failed*' } } Context 'sources without credentials' { BeforeEach { # No tokens at all: every source acquires a skipReason. Mock Expand-EnvironmentVariables { $null } Mock Invoke-Chocolatey { [PSCustomObject]@{ ExitCode = 0 StdOut = Get-Content "$PSScriptRoot/assets/qemu-img-mocks/chocolatey-packages.txt" -Raw StdErr = '' } } } It 'Publishes nothing' { $null = Sync-ForgePackage -Path $script:configPath Should -Invoke Publish-ChocolateyPackage -Times 0 -Exactly } It 'Reports the skipped sources' { $output = (Sync-ForgePackage -Path $script:configPath 6>&1 | Out-String) $output | Should -Match 'Skipped sources' $output | Should -Match 'github' $output | Should -Match 'gitlab' } It 'Completes without throwing' { { Sync-ForgePackage -Path $script:configPath } | Should -Not -Throw } } Context 'nothing to do' { BeforeEach { Mock Expand-EnvironmentVariables { 'fake-api-key' } # Every source reports all three versions as already published. Mock Invoke-Chocolatey { [PSCustomObject]@{ ExitCode = 0 StdOut = "qemu-img|10.0.0`nqemu-img|9.2.0`nqemu-img|2.3.0`n" StdErr = '' } } } It 'Builds nothing and says so' { $output = (Sync-ForgePackage -Path $script:configPath 6>&1 | Out-String) Should -Invoke Build-ChocolateyPackage -Times 0 -Exactly Should -Invoke Publish-ChocolateyPackage -Times 0 -Exactly $output | Should -Match 'No versions to publish' } } } } |