tests/Resolve-DFToolIdentityLinkage.Tests.ps1
|
BeforeAll { # Resolve-DFToolIdentityCandidateRepo must be a real defined command before # `Mock` can intercept it below — Pester cannot mock a command that has # never existed in any scope. . "$PSScriptRoot/../Private/Resolve-DFToolIdentityCandidateRepo.ps1" . "$PSScriptRoot/../Private/Resolve-DFToolIdentityLinkage.ps1" } Describe 'Resolve-DFToolIdentityLinkage' { It 'links via repo when two or more candidates resolve to the same repo' { Mock Resolve-DFToolIdentityCandidateRepo { param($Source, $PackageId, [switch]$Fresh) [pscustomobject]@{ Repo = 'burntsushi/ripgrep'; Homepage = $null } } $packages = [pscustomobject]@{ scoop = 'ripgrep'; winget = 'BurntSushi.ripgrep.MSVC' } $result = Resolve-DFToolIdentityLinkage -ToolName ripgrep -Packages $packages $result.LinkedVia | Should -Be 'repo' $result.Repo | Should -Be 'https://github.com/burntsushi/ripgrep' } It 'does not claim the repo tier when only one candidate resolves a repo' { Mock Resolve-DFToolIdentityCandidateRepo { param($Source, $PackageId, [switch]$Fresh) if ($Source -eq 'scoop') { [pscustomobject]@{ Repo = 'burntsushi/ripgrep'; Homepage = $null } } else { [pscustomobject]@{ Repo = $null; Homepage = $null } } } $packages = [pscustomobject]@{ scoop = 'ripgrep'; winget = 'BurntSushi.ripgrep.MSVC' } $result = Resolve-DFToolIdentityLinkage -ToolName ripgrep -Packages $packages $result.LinkedVia | Should -Be 'curated' } It 'does not claim the repo tier when candidates disagree' { Mock Resolve-DFToolIdentityCandidateRepo { param($Source, $PackageId, [switch]$Fresh) if ($Source -eq 'scoop') { [pscustomobject]@{ Repo = 'owner-a/tool'; Homepage = $null } } else { [pscustomobject]@{ Repo = 'owner-b/tool'; Homepage = $null } } } $packages = [pscustomobject]@{ scoop = 'tool'; winget = 'Owner.Tool' } $result = Resolve-DFToolIdentityLinkage -ToolName tool -Packages $packages $result.LinkedVia | Should -Be 'curated' } It 'falls back to the homepage tier when no repo corroborates but homepages agree' { Mock Resolve-DFToolIdentityCandidateRepo { param($Source, $PackageId, [switch]$Fresh) [pscustomobject]@{ Repo = $null; Homepage = 'zed.dev' } } $packages = [pscustomobject]@{ scoop = 'extras/zed'; winget = 'Zed.Zed' } $result = Resolve-DFToolIdentityLinkage -ToolName zed -Packages $packages $result.LinkedVia | Should -Be 'homepage' $result.Repo | Should -BeNullOrEmpty } It 'defaults to curated when nothing automated corroborates' { Mock Resolve-DFToolIdentityCandidateRepo { param($Source, $PackageId, [switch]$Fresh) [pscustomobject]@{ Repo = $null; Homepage = $null } } $packages = [pscustomobject]@{ scoop = 'mystery'; winget = 'Some.Mystery' } $result = Resolve-DFToolIdentityLinkage -ToolName mystery -Packages $packages $result.LinkedVia | Should -Be 'curated' $result.Repo | Should -BeNullOrEmpty } It 'skips a null or empty package value without calling the resolver for it' { Mock Resolve-DFToolIdentityCandidateRepo { param($Source, $PackageId, [switch]$Fresh) [pscustomobject]@{ Repo = 'a/b'; Homepage = $null } } $packages = [pscustomobject]@{ scoop = 'thing'; winget = $null; choco = '' } $null = Resolve-DFToolIdentityLinkage -ToolName thing -Packages $packages Should -Invoke Resolve-DFToolIdentityCandidateRepo -Times 1 -Exactly } } |