Tests/Resolve-GitHubReleases.Tests.ps1
|
Import-Module "$PSScriptRoot/../ChocoForge.psd1" -Force Describe 'Resolve-GitHubReleases (unit tests)' { InModuleScope 'ChocoForge' { BeforeAll { # Minimal release fixtures for pure unit testing (no file I/O) $script:releases = @( [PSCustomObject]@{ tag_name = 'v5.0.2' name = 'Release 5.0.2' html_url = 'https://github.com/owner/repo/releases/tag/v5.0.2' prerelease = $false published_at = '2025-02-12T11:19:52Z' assets = @( [PSCustomObject]@{ name = 'app-x64.exe'; size = 100; digest = $null; browser_download_url = 'https://example.com/app-x64.exe' }, [PSCustomObject]@{ name = 'app-x86.exe'; size = 80; digest = $null; browser_download_url = 'https://example.com/app-x86.exe' }, [PSCustomObject]@{ name = 'app-src.tar.gz'; size = 50; digest = $null; browser_download_url = 'https://example.com/app-src.tar.gz' } ) }, [PSCustomObject]@{ tag_name = 'v4.0.1' name = 'Release 4.0.1' html_url = 'https://github.com/owner/repo/releases/tag/v4.0.1' prerelease = $false published_at = '2024-06-01T00:00:00Z' assets = @( [PSCustomObject]@{ name = 'app-x64.exe'; size = 90; digest = $null; browser_download_url = 'https://example.com/v4-x64.exe' }, [PSCustomObject]@{ name = 'app-x86.exe'; size = 70; digest = $null; browser_download_url = 'https://example.com/v4-x86.exe' } ) }, [PSCustomObject]@{ tag_name = 'v3.0.5' name = 'Release 3.0.5' html_url = 'https://github.com/owner/repo/releases/tag/v3.0.5' prerelease = $false published_at = '2023-01-15T00:00:00Z' assets = @( [PSCustomObject]@{ name = 'app-x64.exe'; size = 60; digest = $null; browser_download_url = 'https://example.com/v3-x64.exe' } ) }, [PSCustomObject]@{ tag_name = 'nightly-2025-01-01' name = 'Nightly build' html_url = 'https://github.com/owner/repo/releases/tag/nightly-2025-01-01' prerelease = $true published_at = '2025-01-01T00:00:00Z' assets = @() } ) } It 'Extracts version from tag_name using VersionPattern' { $result = $script:releases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+)$' $result | Should -HaveCount 3 $result[0].version | Should -Be ([version]'5.0.2') $result[1].version | Should -Be ([version]'4.0.1') $result[2].version | Should -Be ([version]'3.0.5') } It 'Skips releases that do not match VersionPattern' { $result = $script:releases | Resolve-GitHubReleases -VersionPattern 'v(5\.\d+\.\d+)$' $result | Should -HaveCount 1 $result[0].version | Should -Be ([version]'5.0.2') } It 'Filters by MinimumVersion' { $result = $script:releases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+)$' -MinimumVersion '4.0.0' $result | Should -HaveCount 2 $result[0].version | Should -Be ([version]'5.0.2') $result[1].version | Should -Be ([version]'4.0.1') } It 'Filters assets by AssetPattern' { $result = $script:releases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+)$' -AssetPattern '\.exe$' $result | Should -HaveCount 3 # v5.0.2 should have 2 .exe assets (not the .tar.gz) $result[0].assets | Should -HaveCount 2 } It 'Adds named capture groups as asset properties' { $result = $script:releases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+)$' -AssetPattern 'app-(?<arch>x64|x86)\.exe$' $result | Should -HaveCount 3 foreach ($r in $result) { foreach ($a in $r.assets) { $a.arch | Should -BeIn @('x64', 'x86') } } } It 'Transposes assets by named property' { $result = $script:releases | Resolve-GitHubReleases -VersionPattern 'v(5\.\d+\.\d+)$' -AssetPattern 'app-(?<arch>x64|x86)\.exe$' -TransposeProperty 'arch' $result | Should -HaveCount 1 $result[0].assets.Keys | Should -Contain 'x64' $result[0].assets.Keys | Should -Contain 'x86' # Transposed property should be removed from assets $result[0].assets['x64'].PSObject.Properties.Name | Should -Not -Contain 'arch' $result[0].assets['x86'].PSObject.Properties.Name | Should -Not -Contain 'arch' } It 'Transposes by a non-arch property correctly' { # Build releases with a different named capture group $testReleases = @( [PSCustomObject]@{ tag_name = 'v1.0.0' name = 'Test' html_url = 'https://example.com' prerelease = $false published_at = '2025-01-01T00:00:00Z' assets = @( [PSCustomObject]@{ name = 'pkg-linux.tar.gz'; size = 10; digest = $null; browser_download_url = 'https://example.com/linux.tar.gz' }, [PSCustomObject]@{ name = 'pkg-windows.zip'; size = 20; digest = $null; browser_download_url = 'https://example.com/windows.zip' } ) } ) $result = $testReleases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+)$' -AssetPattern 'pkg-(?<platform>linux|windows)\.' -TransposeProperty 'platform' $result | Should -HaveCount 1 $result[0].assets.Keys | Should -Contain 'linux' $result[0].assets.Keys | Should -Contain 'windows' $result[0].assets['linux'].PSObject.Properties.Name | Should -Not -Contain 'platform' } It 'Skips releases with no matching assets and warns' { $noMatchReleases = @( [PSCustomObject]@{ tag_name = 'v1.0.0' name = 'Test' html_url = 'https://example.com' prerelease = $false published_at = '2025-01-01T00:00:00Z' assets = @( [PSCustomObject]@{ name = 'readme.txt'; size = 1; digest = $null; browser_download_url = 'https://example.com/readme.txt' } ) } ) $result = $noMatchReleases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+)$' -AssetPattern '\.exe$' 3>&1 # The function warns and skips — result should be empty or contain just the warning $warnings = $result | Where-Object { $_ -is [System.Management.Automation.WarningRecord] } $warnings | Should -Not -BeNullOrEmpty } It 'Handles 4-part versions' { $fourPartReleases = @( [PSCustomObject]@{ tag_name = 'v2.0.1.5' name = 'Test' html_url = 'https://example.com' prerelease = $false published_at = '2025-01-01T00:00:00Z' assets = @() } ) $result = $fourPartReleases | Resolve-GitHubReleases -VersionPattern 'v(\d+\.\d+\.\d+\.\d+)$' $result | Should -HaveCount 1 $result[0].version | Should -Be ([version]'2.0.1.5') } It 'Returns all releases when no VersionPattern given' { $result = $script:releases | Resolve-GitHubReleases $result | Should -HaveCount 4 } } } |