tests/DFPackageUniverse.Winget.Tests.ps1
|
BeforeAll { Import-Module powershell-yaml . "$PSScriptRoot/../build/Private/DFPackageUniverse.Winget.ps1" # Real content pulled from microsoft/winget-pkgs via `gh api` against # manifests/m/Microsoft/VisualStudioCode/1.105.0/ (2026-07-14), used # instead of a hand-guessed fixture per the design-spec correction: every # locale file (including the default) carries a BCP-47 tag. $script:VersionManifestYaml = @' PackageIdentifier: Microsoft.VisualStudioCode PackageVersion: 1.105.0 DefaultLocale: en-US ManifestType: version ManifestVersion: 1.10.0 '@ $script:DefaultLocaleManifestYaml = @' PackageIdentifier: Microsoft.VisualStudioCode PackageVersion: 1.105.0 PackageLocale: en-US Publisher: Microsoft Corporation PublisherUrl: https://www.microsoft.com/ PrivacyUrl: https://privacy.microsoft.com/ PackageName: Microsoft Visual Studio Code PackageUrl: https://code.visualstudio.com License: Microsoft Software License LicenseUrl: https://code.visualstudio.com/license ShortDescription: Microsoft Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications. Microsoft Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Moniker: vscode Tags: - developer-tools - editor ManifestType: defaultLocale ManifestVersion: 1.10.0 '@ $script:InstallerManifestYaml = @' PackageIdentifier: Microsoft.VisualStudioCode PackageVersion: 1.105.0 ManifestType: installer ManifestVersion: 1.10.0 '@ # Built from the (deprecated) singleton schema doc # (doc/manifest/schema/1.5.0/singleton.md) — no live example was found # via GitHub code search, so this fixture is schema-derived rather than # pulled from a real manifest. Note singleton's field list has no # PackageUrl equivalent, so homepage is expected to come back empty. $script:SingletonManifestYaml = @' PackageIdentifier: Foo.Bar PackageVersion: 1.0.0 PackageLocale: en-US Publisher: Foo Inc PackageName: Bar Tool License: MIT ShortDescription: A small tool that does bar things. Tags: - cli - utility ManifestType: singleton ManifestVersion: 1.5.0 '@ # A MINIMAL real-world defaultLocale manifest: Tags, PackageUrl and # Description are all optional in the winget schema, and a large minority of # the live catalog omits them. Mirrors the real # manifests/0/0state/scafld/2.5.0 -- the first package that broke when the # build script went strict on 2026-07-15, taking 4,734 of 13,763 packages # (~34%) with it. The two fixtures above BOTH declare Tags, which is exactly # why the unit tests stayed green through that regression. $script:MinimalLocaleManifestYaml = @' PackageIdentifier: 0state.scafld PackageVersion: 2.5.0 PackageLocale: en-US Publisher: 0state PublisherUrl: https://github.com/0state PackageName: scafld License: MIT ShortDescription: Project scaffolding tool. ManifestType: defaultLocale ManifestVersion: 1.10.0 '@ function New-WingetVersionFolder { param([string]$Dir, [string]$PackageId, [hashtable]$Files) New-Item -ItemType Directory -Path $Dir -Force | Out-Null foreach ($name in $Files.Keys) { Set-Content -Path (Join-Path $Dir $name) -Value $Files[$name] -Encoding UTF8 } } } Describe 'DFPackageUniverse.Winget' { Context 'ConvertFrom-DFPackageUniverseWingetLocaleYaml' { It 'maps a real defaultLocale manifest' { $fields = ConvertFrom-DFPackageUniverseWingetLocaleYaml -YamlText $script:DefaultLocaleManifestYaml $fields.name | Should -Be 'Microsoft Visual Studio Code' $fields.publisher | Should -Be 'Microsoft Corporation' $fields.description | Should -Match 'code editor redefined' $fields.homepage | Should -Be 'https://code.visualstudio.com' $fields.license | Should -Be 'Microsoft Software License' (ConvertFrom-Json $fields.tags) | Should -Be @('developer-tools', 'editor') } It 'maps a singleton manifest, leaving homepage empty (no PackageUrl field in that schema)' { $fields = ConvertFrom-DFPackageUniverseWingetLocaleYaml -YamlText $script:SingletonManifestYaml $fields.name | Should -Be 'Bar Tool' $fields.publisher | Should -Be 'Foo Inc' $fields.description | Should -Be 'A small tool that does bar things.' $fields.homepage | Should -BeNullOrEmpty $fields.license | Should -Be 'MIT' (ConvertFrom-Json $fields.tags) | Should -Be @('cli', 'utility') } It 'maps a manifest omitting the optional Tags/PackageUrl fields UNDER STRICT MODE' { # Set-StrictMode here on purpose: Build-DFPackageUniverseRaw.ps1 runs # Set-StrictMode -Version Latest, and StrictMode is dynamically # scoped, so this mapper executes strict in production but non-strict # under a default Pester run. That gap let a 4,734-package data loss # pass a fully green suite on 2026-07-15: $content.Tags throws on a # manifest with no Tags, and the caller logged a warning and skipped # the package. Absent optional fields must map to empty, not throw. Set-StrictMode -Version Latest $fields = ConvertFrom-DFPackageUniverseWingetLocaleYaml -YamlText $script:MinimalLocaleManifestYaml $fields.name | Should -Be 'scafld' $fields.publisher | Should -Be '0state' $fields.description | Should -Be 'Project scaffolding tool.' $fields.license | Should -Be 'MIT' $fields.tags | Should -BeNullOrEmpty $fields.homepage | Should -BeNullOrEmpty } It 'captures the full manifest into extra, including fields Phase A dropped (PublisherUrl, Moniker, PrivacyUrl, LicenseUrl)' { $fields = ConvertFrom-DFPackageUniverseWingetLocaleYaml -YamlText $script:DefaultLocaleManifestYaml $extra = $fields.extra | ConvertFrom-Json $extra.PublisherUrl | Should -Be 'https://www.microsoft.com/' $extra.PrivacyUrl | Should -Be 'https://privacy.microsoft.com/' $extra.Moniker | Should -Be 'vscode' $extra.LicenseUrl | Should -Be 'https://code.visualstudio.com/license' $extra.PackageUrl | Should -Be 'https://code.visualstudio.com' } It 'captures only present fields into extra for a minimal manifest, under strict mode' { Set-StrictMode -Version Latest $fields = ConvertFrom-DFPackageUniverseWingetLocaleYaml -YamlText $script:MinimalLocaleManifestYaml $extra = $fields.extra | ConvertFrom-Json $extra.PublisherUrl | Should -Be 'https://github.com/0state' $extra.PSObject.Properties.Name | Should -Not -Contain 'Moniker' $extra.PSObject.Properties.Name | Should -Not -Contain 'PackageUrl' } It 'resolves a full version folder whose locale manifest omits Tags, under strict mode' { Set-StrictMode -Version Latest $dir = Join-Path $TestDrive 'strict/0state.scafld/2.5.0' New-WingetVersionFolder -Dir $dir -Files @{ '0state.scafld.yaml' = @' PackageIdentifier: 0state.scafld PackageVersion: 2.5.0 DefaultLocale: en-US ManifestType: version ManifestVersion: 1.10.0 '@ '0state.scafld.locale.en-US.yaml' = $script:MinimalLocaleManifestYaml } $row = Resolve-DFPackageUniverseWingetVersionRow -VersionDir $dir -Log { param($l, $p, $m) } $row | Should -Not -BeNullOrEmpty $row.package_id | Should -Be '0state.scafld' $row.version | Should -Be '2.5.0' $row.tags | Should -BeNullOrEmpty ($row.extra | ConvertFrom-Json).PublisherUrl | Should -Be 'https://github.com/0state' } } Context 'Select-DFPackageUniverseWingetLatestVersion' { It 'picks the highest semver-parseable version' { $folders = 'C:\pkgs\1.2.0', 'C:\pkgs\1.10.0', 'C:\pkgs\1.9.0' Select-DFPackageUniverseWingetLatestVersion -VersionFolders $folders | Should -Be 'C:\pkgs\1.10.0' } It 'falls back to ordinal string comparison for non-parseable names' { $folders = 'C:\pkgs\2023a', 'C:\pkgs\2023b' Select-DFPackageUniverseWingetLatestVersion -VersionFolders $folders | Should -Be 'C:\pkgs\2023b' } It 'returns the only folder when there is exactly one' { Select-DFPackageUniverseWingetLatestVersion -VersionFolders @('C:\pkgs\1.0.0') | Should -Be 'C:\pkgs\1.0.0' } } Context 'Get-DFPackageUniverseWingetPackageDirectories' { BeforeEach { $script:SnapshotRoot = Join-Path $TestDrive 'winget-pkgs' } AfterEach { Remove-Item $script:SnapshotRoot -Recurse -Force -ErrorAction Ignore } It 'finds a 2-segment package (Publisher/Package)' { $dir = Join-Path $script:SnapshotRoot 'manifests/m/Microsoft/VisualStudioCode/1.105.0' New-WingetVersionFolder -Dir $dir -PackageId 'Microsoft.VisualStudioCode' -Files @{ 'Microsoft.VisualStudioCode.yaml' = $script:VersionManifestYaml } $dirs = @(Get-DFPackageUniverseWingetPackageDirectories -SnapshotRoot $script:SnapshotRoot) $dirs.Count | Should -Be 1 $dirs[0].VersionFolders.Count | Should -Be 1 $dirs[0].VersionFolders[0] | Should -Be $dir } It 'finds a deeper dotted-identifier package (Publisher/Package/Sub/Sub)' { $dir = Join-Path $script:SnapshotRoot 'manifests/m/Microsoft/VisualStudio/2022/Community/17.8.0' New-WingetVersionFolder -Dir $dir -PackageId 'Microsoft.VisualStudio.2022.Community' -Files @{ 'Microsoft.VisualStudio.2022.Community.yaml' = $script:VersionManifestYaml } $dirs = @(Get-DFPackageUniverseWingetPackageDirectories -SnapshotRoot $script:SnapshotRoot) $dirs.Count | Should -Be 1 $dirs[0].Path | Should -Be (Split-Path $dir -Parent) } It 'finds multiple version folders under the same package' { $pkgRoot = Join-Path $script:SnapshotRoot 'manifests/m/Microsoft/VisualStudioCode' New-WingetVersionFolder -Dir (Join-Path $pkgRoot '1.104.0') -PackageId 'x' -Files @{ 'x.yaml' = $script:VersionManifestYaml } New-WingetVersionFolder -Dir (Join-Path $pkgRoot '1.105.0') -PackageId 'x' -Files @{ 'x.yaml' = $script:VersionManifestYaml } $dirs = @(Get-DFPackageUniverseWingetPackageDirectories -SnapshotRoot $script:SnapshotRoot) $dirs.Count | Should -Be 1 $dirs[0].VersionFolders.Count | Should -Be 2 } } Context 'Resolve-DFPackageUniverseWingetVersionRow' { BeforeEach { $script:VersionDir = Join-Path $TestDrive 'version-dir' $script:logged = @() $script:log = { param($Level, $PackageId, $Message) $script:logged += , @($Level, $PackageId, $Message) } } AfterEach { Remove-Item $script:VersionDir -Recurse -Force -ErrorAction Ignore } It 'resolves a multi-file manifest via its tagged default-locale file' { New-WingetVersionFolder -Dir $script:VersionDir -PackageId 'Microsoft.VisualStudioCode' -Files @{ 'Microsoft.VisualStudioCode.yaml' = $script:VersionManifestYaml 'Microsoft.VisualStudioCode.installer.yaml' = $script:InstallerManifestYaml 'Microsoft.VisualStudioCode.locale.en-US.yaml' = $script:DefaultLocaleManifestYaml } $row = Resolve-DFPackageUniverseWingetVersionRow -VersionDir $script:VersionDir -Log $script:log $row.source | Should -Be 'winget' $row.package_id | Should -Be 'Microsoft.VisualStudioCode' $row.version | Should -Be '1.105.0' $row.name | Should -Be 'Microsoft Visual Studio Code' $row.homepage | Should -Be 'https://code.visualstudio.com' $script:logged.Count | Should -Be 0 } It 'resolves a singleton manifest directly' { New-WingetVersionFolder -Dir $script:VersionDir -PackageId 'Foo.Bar' -Files @{ 'Foo.Bar.yaml' = $script:SingletonManifestYaml } $row = Resolve-DFPackageUniverseWingetVersionRow -VersionDir $script:VersionDir -Log $script:log $row.source | Should -Be 'winget' $row.package_id | Should -Be 'Foo.Bar' $row.version | Should -Be '1.0.0' $row.name | Should -Be 'Bar Tool' $script:logged.Count | Should -Be 0 } It 'logs a review row and returns $null when the default-locale file is missing' { New-WingetVersionFolder -Dir $script:VersionDir -PackageId 'Microsoft.VisualStudioCode' -Files @{ 'Microsoft.VisualStudioCode.yaml' = $script:VersionManifestYaml 'Microsoft.VisualStudioCode.installer.yaml' = $script:InstallerManifestYaml } $row = Resolve-DFPackageUniverseWingetVersionRow -VersionDir $script:VersionDir -Log $script:log $row | Should -BeNullOrEmpty $script:logged.Count | Should -Be 1 $script:logged[0][0] | Should -Be 'review' } It 'logs a review row and returns $null when there is no root manifest at all' { New-WingetVersionFolder -Dir $script:VersionDir -PackageId 'x' -Files @{ 'x.installer.yaml' = $script:InstallerManifestYaml } $row = Resolve-DFPackageUniverseWingetVersionRow -VersionDir $script:VersionDir -Log $script:log $row | Should -BeNullOrEmpty $script:logged.Count | Should -Be 1 $script:logged[0][0] | Should -Be 'review' } } Context 'Get-DFPackageUniverseWingetRows' { BeforeEach { $script:SnapshotRoot = Join-Path $TestDrive 'winget-pkgs-rows' $script:logged = @() $script:log = { param($Level, $PackageId, $Message) $script:logged += , @($Level, $PackageId, $Message) } $script:neverFetch = { throw 'FetchSnapshot should not be invoked when -WingetPkgsSnapshot is supplied' } } AfterEach { Remove-Item $script:SnapshotRoot -Recurse -Force -ErrorAction Ignore } It 'never invokes FetchSnapshot when a snapshot path is supplied' { $dir = Join-Path $script:SnapshotRoot 'manifests/m/Microsoft/VisualStudioCode/1.105.0' New-WingetVersionFolder -Dir $dir -PackageId 'Microsoft.VisualStudioCode' -Files @{ 'Microsoft.VisualStudioCode.yaml' = $script:VersionManifestYaml 'Microsoft.VisualStudioCode.locale.en-US.yaml' = $script:DefaultLocaleManifestYaml } $rows = @(Get-DFPackageUniverseWingetRows -WingetPkgsSnapshot $script:SnapshotRoot -FetchSnapshot $script:neverFetch -Log $script:log) $rows.Count | Should -Be 1 $rows[0].package_id | Should -Be 'Microsoft.VisualStudioCode' } It 'logs an error and returns no rows when the snapshot path does not exist' { $rows = @(Get-DFPackageUniverseWingetRows -WingetPkgsSnapshot (Join-Path $TestDrive 'does-not-exist') -FetchSnapshot $script:neverFetch -Log $script:log) $rows.Count | Should -Be 0 $script:logged.Count | Should -Be 1 $script:logged[0][0] | Should -Be 'error' } } } |