winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Microsoft.WinGet.Client.Tests.ps1 (37887B)


      1 # Copyright (c) Microsoft Corporation. All rights reserved.
      2 # Licensed under the MIT License.
      3 
      4 <#
      5 .Synopsis
      6    Pester tests related to the Microsoft.WinGet.Client PowerShell module.
      7    The tests require the localhost web server to be running and serving the test data.
      8    'Invoke-Pester' should be called in an admin PowerShell window.
      9 #>
     10 [CmdletBinding()]
     11 param(
     12     # Whether to use production or developement targets.
     13     [switch]$TargetProduction
     14 )
     15 
     16 BeforeAll {
     17     if ($TargetProduction)
     18     {
     19         $wingetExeName = "winget.exe"
     20     }
     21     else
     22     {
     23         $wingetExeName = "wingetdev.exe"
     24     }
     25 
     26     $settingsFilePath = (ConvertFrom-Json (& $wingetExeName settings export)).userSettingsFile
     27     $originalSettingsContent = Get-Content -Path $settingsFilePath -Raw
     28 
     29     $deviceGroupPolicyRoot = "HKLM:\Software\Policies\Microsoft\Windows"
     30     $wingetPolicyKeyName = "AppInstaller"
     31     $wingetGroupPolicyRegistryRoot = $deviceGroupPolicyRoot + "\" + $wingetPolicyKeyName
     32 
     33     Import-Module Microsoft.WinGet.Client
     34 
     35     function SetWinGetSettingsHelper($settings) {
     36         $content = ConvertTo-Json $settings -Depth 4
     37         Set-Content -Path $settingsFilePath -Value $content
     38     }
     39 
     40     function RestoreWinGetSettings() {
     41         Set-Content -Path $settingsFilePath -Value $originalSettingsContent
     42     }
     43 
     44     # Source Add requires admin privileges, this will only execute successfully in an elevated PowerShell.
     45     function AddTestSource {
     46         try {
     47             Get-WinGetSource -Name 'TestSource'
     48         }
     49         catch {
     50             Add-WinGetSource -Name 'TestSource' -Arg 'https://localhost:5001/TestKit/' -TrustLevel 'Trusted'
     51         }
     52     }
     53 
     54     # This is a workaround to an issue where the server takes longer than expected to terminate when
     55     # running from PowerShell. This can cause other E2E tests to fail when attempting to reset the test source.
     56     function RemoveTestSource {
     57         try {
     58             # Source Remove requires admin privileges, this will only execute successfully in an elevated PowerShell.
     59             $testSource = Get-WinGetSource | Where-Object -Property 'Name' -eq 'TestSource'
     60             if ($null -ne $testSource)
     61             {
     62                 # Source Remove requires admin privileges
     63                 Remove-WinGetSource -Name 'TestSource'
     64             }
     65         }
     66         catch {
     67             # Non-admin
     68             Start-Process -FilePath $wingetExeName -ArgumentList "source remove TestSource"
     69         }
     70     }
     71 
     72     function CreatePolicyKeyIfNotExists()
     73     {
     74         $registryExists = test-path  -Path $wingetGroupPolicyRegistryRoot
     75 
     76        if(-Not($registryExists))
     77        {
     78            New-Item -Path $deviceGroupPolicyRoot -Name $wingetPolicyKeyName
     79        }
     80     }
     81 
     82     function CleanupGroupPolicyKeyIfExists()
     83     {
     84         $registryExists = test-path  -Path $wingetGroupPolicyRegistryRoot
     85 
     86         if($registryExists)
     87         {
     88            Remove-Item -Path  $wingetGroupPolicyRegistryRoot -Recurse
     89         }
     90     }
     91 
     92     function CleanupGroupPolicies()
     93     {
     94         $registryExists = test-path  -Path $wingetGroupPolicyRegistryRoot
     95 
     96         if($registryExists)
     97         {
     98             Remove-ItemProperty -Path $wingetGroupPolicyRegistryRoot -Name *
     99         }
    100     }
    101 
    102     function WaitForWindowsPackageManagerServer([bool]$force = $false)
    103     {
    104         $processes = Get-Process | Where-Object { $_.Name -eq "WindowsPackageManagerServer" }
    105         foreach ($p in $processes)
    106         {
    107             if ($force)
    108             {
    109                 Stop-Process $p
    110             }
    111 
    112             $timeout = 300
    113             $secondsToWait = 5
    114             $time = 0
    115             while ($p.HasExited -eq $false)
    116             {
    117                 $time += $secondsToWait
    118                 if ($time -ge $timeout )
    119                 {
    120                     throw "Timeout waiting for $($p.Id) to exit"
    121                 }
    122                 Start-Sleep -Seconds 5
    123             }
    124         }
    125     }
    126 
    127     function GetRandomTestDirectory()
    128     {
    129         return Join-Path -Path $env:Temp -ChildPath "WingetPwshTest-$(New-Guid)"
    130     }
    131 
    132     function Validate-WinGetResultCommonFields([psobject]$result, [psobject]$expected) {
    133         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    134         $result.Id | Should -Be $expected.Id
    135         $result.Name | Should -Be $expected.Name
    136         $result.Source | Should -Be $expected.Source
    137         $result.Status | Should -Be $expected.Status
    138     }
    139 
    140     function Validate-WinGetPackageOperationResult([psobject]$result, [psobject]$expected, [string]$operationType)
    141     {
    142         Validate-WinGetResultCommonFields $result $expected
    143         $result.RebootRequired | Should -Be $expected.RebootRequired
    144 
    145         switch ($operationType) {
    146             'install' {
    147                 $result.InstallerErrorCode | Should -Be $expected.InstallerErrorCode
    148             }
    149             'update' {
    150                 $result.InstallerErrorCode | Should -Be $expected.InstallerErrorCode
    151             }
    152             'repair' {
    153                 $result.RepairErrorCode | Should -Be $expected.RepairErrorCode
    154             }
    155             'uninstall' {
    156                 $result.UninstallerErrorCode | Should -Be $expected.UninstallerErrorCode
    157             }
    158             default {
    159                 throw "Unknown operation type: $operationType"
    160             }
    161         }
    162     }
    163 }
    164 
    165 Describe 'Get-WinGetVersion' {
    166 
    167     It 'Get-WinGetVersion' {
    168         $version = Get-WinGetVersion
    169         $version | Should -Not -BeNullOrEmpty -ErrorAction Stop
    170     }
    171 }
    172 
    173 Describe 'Reset-WinGetSource' {
    174     BeforeAll {
    175         AddTestSource
    176     }
    177 
    178     # Requires admin
    179     It 'Resets all sources' {
    180         Reset-WinGetSource -All
    181     }
    182 
    183     It 'Test source should be removed' {
    184         { Get-WinGetSource -Name 'TestSource' } | Should -Throw
    185     }
    186 }
    187 
    188 Describe 'Get|Add|Reset-WinGetSource' {
    189 
    190     BeforeAll {
    191         Add-WinGetSource -Name 'TestSource' -Arg 'https://localhost:5001/TestKit/' -TrustLevel 'Trusted' -Explicit
    192     }
    193 
    194     It 'Get Test source' {
    195         $source = Get-WinGetSource -Name 'TestSource'
    196 
    197         $source | Should -Not -BeNullOrEmpty -ErrorAction Stop
    198         $source.Name | Should -Be 'TestSource'
    199         $source.Argument | Should -Be 'https://localhost:5001/TestKit/'
    200         $source.Type | Should -Be 'Microsoft.PreIndexed.Package'
    201         $source.TrustLevel | Should -Be 'Trusted'
    202         $source.Explicit | Should -Be $true
    203     }
    204 
    205     It 'Get fake source' {
    206         { Get-WinGetSource -Name 'Fake' } | Should -Throw
    207     }
    208 
    209     # This tests require admin
    210     It 'Reset Test source' {
    211         Reset-WinGetSource -Name TestSource
    212     }
    213 }
    214 
    215 Describe 'Find-WinGetPackage' {
    216 
    217     BeforeAll {
    218         AddTestSource
    219     }
    220 
    221     It 'Given no parameters, lists all available packages' {
    222         $allPackages = Find-WinGetPackage -Source TestSource
    223         $allPackages.Count | Should -BeGreaterThan 0
    224     }
    225 
    226     It 'Find by Id' {
    227         $package = Find-WinGetPackage -Source 'TestSource' -Id 'AppInstallerTest.TestExampleInstaller'
    228 
    229         $package | Should -Not -BeNullOrEmpty -ErrorAction Stop
    230         $package.Name | Should -Be 'TestExampleInstaller'
    231         $package.Id | Should -Be 'AppInstallerTest.TestExampleInstaller'
    232         $package.Version | Should -Be '1.2.3.4'
    233         $package.Source | Should -Be 'TestSource'
    234     }
    235 
    236     It 'Find by Name' {
    237         $package = Find-WinGetPackage -Source 'TestSource' -Name 'TestPortableExe'
    238 
    239         $package | Should -Not -BeNullOrEmpty -ErrorAction Stop
    240         $package[0].Name | Should -Be 'TestPortableExe'
    241         $package[1].Name | Should -Be 'TestPortableExeWithCommand'
    242     }
    243 
    244     It 'Find by Name sort by Version' {
    245         $package = Find-WinGetPackage -Source 'TestSource' -Name 'TestPortableExe' | Sort-Object 'Version'
    246 
    247         $package | Should -Not -BeNullOrEmpty -ErrorAction Stop
    248         $package[0].Name | Should -Be 'TestPortableExeWithCommand'
    249         $package[1].Name | Should -Be 'TestPortableExe'
    250     }
    251 
    252     It 'Find package and verify PackageVersionInfo' {
    253         $package = Find-WinGetPackage -Source 'TestSource' -Id 'AppInstallerTest.TestPortableExe' -MatchOption Equals
    254 
    255         $package | Should -Not -BeNullOrEmpty -ErrorAction Stop
    256         $package.AvailableVersions[0] | Should -Be '3.0.0.0'
    257         $package.AvailableVersions[1] | Should -Be '2.0.0.0'
    258         $package.AvailableVersions.Count | Should -Be 4
    259 
    260         $packageVersionInfo = $package.GetPackageVersionInfo("3.0.0.0")
    261         $packageVersionInfo.DisplayName | Should -Be 'TestPortableExe'
    262         $packageVersionInfo.Id | Should -Be 'AppInstallerTest.TestPortableExe'
    263         $packageVersionInfo.CompareToVersion("2.0.0.0") | Should -Be 'Greater'
    264         $packageVersionInfo.CompareToVersion("4.0.0.0") | Should -Be 'Lesser'
    265     }
    266 }
    267 
    268 Describe 'Install|Update|Uninstall-WinGetPackage' {
    269 
    270     BeforeAll {
    271         AddTestSource
    272     }
    273 
    274     BeforeEach {
    275         $expectedExeInstallerResult = [PSCustomObject]@{
    276             Id = "AppInstallerTest.TestExeInstaller"
    277             Name = "TestExeInstaller"
    278             Source = "TestSource"
    279             Status = 'Ok'
    280             RebootRequired = 'False'
    281             InstallerErrorCode = 0
    282             UninstallerErrorCode = 0
    283         }
    284 
    285         $expectedPortableInstallerResult = [PSCustomObject]@{
    286             Id = "AppInstallerTest.TestPortableExe"
    287             Name = "TestPortableExe"
    288             Source = "TestSource"
    289             Status = 'Ok'
    290             RebootRequired = 'False'
    291             InstallerErrorCode = 0
    292             UninstallerErrorCode = 0
    293         }
    294     }
    295 
    296     It 'Install by Id' {
    297         $result = Install-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1.0.0.0'
    298         Validate-WinGetPackageOperationResult $result $expectedExeInstallerResult 'install'
    299     }
    300 
    301     It 'Install by exact Name and Version' {
    302         $result = Install-WinGetPackage -Name TestPortableExe -Version '2.0.0.0' -MatchOption Equals
    303         Validate-WinGetPackageOperationResult $result $expectedPortableInstallerResult 'install'
    304     }
    305 
    306     It 'Update by Id' {
    307         $result = Update-WinGetPackage -Id AppInstallerTest.TestExeInstaller
    308         Validate-WinGetPackageOperationResult $result $expectedExeInstallerResult 'update'
    309     }
    310 
    311     It 'Update by Name' {
    312         $result = Update-WinGetPackage -Name TestPortableExe
    313         Validate-WinGetPackageOperationResult $result $expectedPortableInstallerResult 'update'
    314     }
    315 
    316     It 'Uninstall by Id' {
    317         $result = Uninstall-WinGetPackage -Id AppInstallerTest.TestExeInstaller
    318         Validate-WinGetPackageOperationResult $result $expectedExeInstallerResult 'uninstall'
    319     }
    320 
    321     It 'Uninstall by Name' {
    322         $result = Uninstall-WinGetPackage -Name TestPortableExe
    323         Validate-WinGetPackageOperationResult $result $expectedPortableInstallerResult 'uninstall'
    324     }
    325 
    326     AfterAll {
    327         # Uninstall all test packages after each  for proper cleanup.
    328         $testExe = Get-WinGetPackage -Id AppInstallerTest.TestExeInstaller -MatchOption Equals
    329         if ($testExe.Count -gt 0)
    330         {
    331             Uninstall-WinGetPackage -Id AppInstallerTest.TestExeInstaller 
    332         }
    333 
    334         $testPortable = Get-WinGetPackage -Id AppInstallerTest.TestPortableExe -MatchOption Equals
    335         if ($testPortable.Count -gt 0)
    336         {
    337             Uninstall-WinGetPackage -Id AppInstallerTest.TestPortableExe
    338         }
    339     }
    340 }
    341 
    342 Describe 'Install|Repair|Uninstall-WinGetPackage' {
    343 
    344     BeforeAll {
    345         AddTestSource
    346     }
    347 
    348     Context 'MSIX Repair Scenario' {
    349         BeforeEach {
    350             $expectedResult = [PSCustomObject]@{
    351                 Id = "AppInstallerTest.TestMsixInstaller"
    352                 Name = "TestMsixInstaller"
    353                 Source = "TestSource"
    354                 Status = 'Ok'
    355                 RebootRequired = 'False'
    356                 InstallerErrorCode = 0
    357                 RepairErrorCode = 0
    358                 UninstallerErrorCode = 0
    359             }
    360         }
    361 
    362         It 'Install MSIX By Id' {
    363             $result = Install-WinGetPackage -Id AppInstallerTest.TestMsixInstaller
    364             Validate-WinGetPackageOperationResult $result $expectedResult 'install'
    365         }
    366 
    367         It 'Repair MSIX By Id' {
    368             $result = Repair-WinGetPackage -Id AppInstallerTest.TestMsixInstaller
    369             Validate-WinGetPackageOperationResult $result $expectedResult 'repair'
    370         }
    371 
    372         It 'Uninstall MSIX By Id' {
    373             $result = Uninstall-WinGetPackage -Id AppInstallerTest.TestMsixInstaller
    374             Validate-WinGetPackageOperationResult $result $expectedResult 'uninstall'
    375         }
    376     }
    377 
    378     Context 'Burn installer "Modify" Repair Scenario' {
    379         BeforeEach {
    380             $expectedResult = [PSCustomObject]@{
    381                 Id = "AppInstallerTest.TestModifyRepair"
    382                 Name = "TestModifyRepair"
    383                 Source = "TestSource"
    384                 Status = 'Ok'
    385                 RebootRequired = 'False'
    386                 InstallerErrorCode = 0
    387                 RepairErrorCode = 0
    388                 UninstallerErrorCode = 0
    389             }
    390         }
    391 
    392         It 'Install Burn Installer By Id' {
    393             $result = Install-WinGetPackage -Id AppInstallerTest.TestModifyRepair
    394             Validate-WinGetPackageOperationResult $result $expectedResult 'install'
    395         }
    396 
    397         It 'Repair Burn Installer By Id' {
    398             $result = Repair-WinGetPackage -Id AppInstallerTest.TestModifyRepair
    399             Validate-WinGetPackageOperationResult $result $expectedResult 'repair'
    400         }
    401 
    402         It 'Uninstall Burn Installer By Id' {
    403             $result = Uninstall-WinGetPackage -Id AppInstallerTest.TestModifyRepair
    404             Validate-WinGetPackageOperationResult $result $expectedResult 'uninstall'
    405         }
    406     }
    407 
    408     Context 'Exe Installer "Uninstaller" Repair Scenario' {
    409         BeforeEach {
    410             $expectedResult = [PSCustomObject]@{
    411                 Id = "AppInstallerTest.UninstallerRepair"
    412                 Name = "UninstallerRepair"
    413                 Source = "TestSource"
    414                 Status = 'Ok'
    415                 RebootRequired = 'False'
    416                 InstallerErrorCode = 0
    417                 RepairErrorCode = 0
    418                 UninstallerErrorCode = 0
    419             }
    420         }
    421 
    422         It 'Install Exe Installer By Id' {
    423             $result = Install-WinGetPackage -Id AppInstallerTest.UninstallerRepair
    424             Validate-WinGetPackageOperationResult $result $expectedResult 'install'
    425         }
    426 
    427         It 'Uninstaller Repair Exe Installer By Id' {
    428             $result = Repair-WinGetPackage -Id AppInstallerTest.UninstallerRepair
    429             Validate-WinGetPackageOperationResult $result $expectedResult 'repair'
    430         }
    431 
    432         It "Uninstall Exe Installer By Id" {
    433             $result = Uninstall-WinGetPackage -Id AppInstallerTest.UninstallerRepair
    434             Validate-WinGetPackageOperationResult $result $expectedResult 'uninstall'
    435         }
    436     }
    437 
    438     Context 'Inno "Installer" Repair Scenario' {
    439         BeforeEach {
    440             $expectedResult = [PSCustomObject]@{
    441                 Id = "AppInstallerTest.TestInstallerRepair"
    442                 Name = "TestInstallerRepair"
    443                 Source = "TestSource"
    444                 Status = 'Ok'
    445                 RebootRequired = 'False'
    446                 InstallerErrorCode = 0
    447                 RepairErrorCode = 0
    448                 UninstallerErrorCode = 0
    449             }
    450         }
    451 
    452         It 'Install Exe Installer By Id' {
    453             $result = Install-WinGetPackage -Id AppInstallerTest.TestInstallerRepair
    454             Validate-WinGetPackageOperationResult $result $expectedResult 'install'
    455         }
    456 
    457         It 'Installer Repair Exe Installer By Id' {
    458             $result = Repair-WinGetPackage -Id AppInstallerTest.TestInstallerRepair
    459             Validate-WinGetPackageOperationResult $result $expectedResult 'repair'
    460         }
    461 
    462         It "Uninstall Exe Installer By Id" {
    463             $result = Uninstall-WinGetPackage -Id AppInstallerTest.TestInstallerRepair
    464             Validate-WinGetPackageOperationResult $result $expectedResult 'uninstall'
    465         }
    466     }
    467 
    468     AfterAll {
    469         # Uninstall all test packages after each  for proper cleanup.
    470         $testMsix = Get-WinGetPackage -Id AppInstallerTest.TestMsixInstaller
    471         if ($testMsix.Count -gt 0)
    472         {
    473             Uninstall-WinGetPackage -Id AppInstallerTest.TestMsixInstaller
    474         }
    475 
    476         $testBurn = Get-WinGetPackage -Id AppInstallerTest.TestModifyRepair
    477         if ($testBurn.Count -gt 0)
    478         {
    479             Uninstall-WinGetPackage -Id AppInstallerTest.TestModifyRepair
    480         }
    481 
    482         $testExe = Get-WinGetPackage -Id AppInstallerTest.UninstallerRepair
    483         if ($testExe.Count -gt 0)
    484         {
    485             Uninstall-WinGetPackage -Id AppInstallerTest.UninstallerRepair
    486         }
    487 
    488         $testInno = Get-WinGetPackage -Id AppInstallerTest.TestInstallerRepair
    489         if ($testInno.Count -gt 0)
    490         {
    491             Uninstall-WinGetPackage -Id AppInstallerTest.TestInstallerRepair
    492         }
    493     }
    494 }
    495 
    496 Describe 'Get-WinGetPackage' {
    497 
    498     BeforeAll {
    499         AddTestSource
    500     }
    501 
    502     It 'Install by Id' {
    503         $result = Install-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1.0.0.0'
    504 
    505         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    506         $result.Id | Should -Be "AppInstallerTest.TestExeInstaller"
    507         $result.Name | Should -Be "TestExeInstaller"
    508         $result.Source | Should -Be "TestSource"
    509         $result.InstallerErrorCode | Should -Be 0
    510         $result.Status | Should -Be 'Ok'
    511         $result.RebootRequired | Should -Be 'False'
    512     }
    513 
    514     It 'Get package by Id' {
    515         $result = Get-WinGetPackage -Id AppInstallerTest.TestExeInstaller
    516 
    517         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    518         $result.Name | Should -Be 'TestExeInstaller'
    519         $result.Id | Should -Be 'AppInstallerTest.TestExeInstaller'
    520         $result.InstalledVersion | Should -Be '1.0.0.0'
    521         $result.Source | Should -Be 'TestSource'
    522         $result.AvailableVersions[0] | Should -Be '2.0.0.0'
    523     }
    524 
    525     It 'Get package by Name' {
    526         $result = Get-WinGetPackage -Name TestExeInstaller
    527 
    528         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    529         $result.Name | Should -Be 'TestExeInstaller'
    530         $result.Id | Should -Be 'AppInstallerTest.TestExeInstaller'
    531         $result.InstalledVersion | Should -Be '1.0.0.0'
    532         $result.Source | Should -Be 'TestSource'
    533         $result.AvailableVersions[0] | Should -Be '2.0.0.0'
    534     }
    535 
    536     AfterAll {
    537         # Uninstall all test packages after each  for proper cleanup.
    538         $testExe = Get-WinGetPackage -Id AppInstallerTest.TestExeInstaller
    539         if ($testExe.Count -gt 0)
    540         {
    541             Uninstall-WinGetPackage -Id AppInstallerTest.TestExeInstaller 
    542         } 
    543    }
    544 }
    545 
    546 Describe 'Export-WinGetPackage' {
    547 
    548     BeforeAll {
    549         AddTestSource
    550     }
    551 
    552     It 'Download by Id' {
    553         $testDirectory = GetRandomTestDirectory
    554         $result = Export-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1.0.0.0' -DownloadDirectory $testDirectory
    555         
    556         $result | Should -Not -BeNullOrEmpty
    557         $result.Id | Should -Be "AppInstallerTest.TestExeInstaller"
    558         $result.Name | Should -Be "TestExeInstaller"
    559         $result.Source | Should -Be "TestSource"
    560         $result.Status | Should -Be 'Ok'
    561 
    562         # Download directory should be created and have exactly two files (installer and manifest file).
    563         Test-Path -Path $testDirectory | Should -Be $true
    564         (Get-ChildItem -Path $testDirectory -Force | Measure-Object).Count | Should -Be 2
    565     }
    566 
    567     It 'Download by Locale' {
    568         $testDirectory = GetRandomTestDirectory
    569         $result = Export-WinGetPackage -Id AppInstallerTest.TestMultipleInstallers -Locale 'zh-CN' -DownloadDirectory $testDirectory
    570 
    571         $result | Should -Not -BeNullOrEmpty
    572         $result.Id | Should -Be "AppInstallerTest.TestMultipleInstallers"
    573         $result.Name | Should -Be "TestMultipleInstallers"
    574         $result.Source | Should -Be "TestSource"
    575         $result.Status | Should -Be 'Ok'
    576 
    577         Test-Path -Path $testDirectory | Should -Be $true
    578         (Get-ChildItem -Path $testDirectory -Force | Measure-Object).Count | Should -Be 2
    579     }
    580 
    581     It 'Download by InstallerType' {
    582         $testDirectory = GetRandomTestDirectory
    583         $result = Export-WinGetPackage -Id AppInstallerTest.TestMultipleInstallers -InstallerType 'msi' -DownloadDirectory $testDirectory
    584 
    585         $result | Should -Not -BeNullOrEmpty
    586         $result.Id | Should -Be "AppInstallerTest.TestMultipleInstallers"
    587         $result.Name | Should -Be "TestMultipleInstallers"
    588         $result.Source | Should -Be "TestSource"
    589         $result.Status | Should -Be 'Ok'
    590 
    591         Test-Path -Path $testDirectory | Should -Be $true
    592         (Get-ChildItem -Path $testDirectory -Force | Measure-Object).Count | Should -Be 2
    593     }
    594 
    595     It 'Download by InstallerType that does not exist' {
    596         $testDirectory = GetRandomTestDirectory
    597         $result = Export-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1.0.0.0' -InstallerType 'zip' -DownloadDirectory $testDirectory
    598 
    599         $result | Should -Not -BeNullOrEmpty
    600         $result.Id | Should -Be "AppInstallerTest.TestExeInstaller"
    601         $result.Name | Should -Be "TestExeInstaller"
    602         $result.Source | Should -Be "TestSource"
    603         $result.Status | Should -Be 'NoApplicableInstallers'
    604         $result.ExtendedErrorCode | Should -Not -BeNullOrEmpty
    605         Test-Path -Path $testDirectory | Should -Be $false
    606     }
    607 
    608     It 'Download with short Version' {
    609         $testDirectory = GetRandomTestDirectory
    610         $result = Export-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1' -DownloadDirectory $testDirectory
    611         
    612         $result | Should -Not -BeNullOrEmpty
    613         $result.Id | Should -Be "AppInstallerTest.TestExeInstaller"
    614         $result.Name | Should -Be "TestExeInstaller"
    615         $result.Source | Should -Be "TestSource"
    616         $result.Status | Should -Be 'Ok'
    617 
    618         # Download directory should be created and have exactly two files (installer and manifest file).
    619         Test-Path -Path $testDirectory | Should -Be $true
    620         (Get-ChildItem -Path $testDirectory -Force | Measure-Object).Count | Should -Be 2
    621     }
    622 
    623     AfterEach {
    624         if (Test-Path $testDirectory) {
    625             Remove-Item $testDirectory -Force -Recurse
    626         }
    627     }
    628 }
    629 
    630 Describe 'Get-WinGetUserSetting' {
    631 
    632     It 'Get setting' {
    633         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    634         SetWinGetSettingsHelper $ogSettings
    635 
    636         $userSettings = Get-WinGetUserSetting
    637         $userSettings | Should -Not -BeNullOrEmpty -ErrorAction Stop
    638         $userSettings.Count | Should -Be 2
    639         $userSettings.visual.progressBar | Should -Be 'rainbow'
    640         $userSettings.experimentalFeatures.experimentalArg | Should -Be $false
    641         $userSettings.experimentalFeatures.experimentalCmd | Should -Be $true
    642     }
    643 
    644     It 'Get settings. Bad json file' {
    645         Set-Content -Path $settingsFilePath -Value "Hi, im not a json. Thank you, Test."
    646         { Get-WinGetUserSetting } | Should -Throw
    647     }
    648 
    649     AfterAll {
    650         RestoreWinGetSettings
    651     }
    652 }
    653 
    654 Describe 'Test-WinGetUserSetting' {
    655 
    656     It 'Bad json file' {
    657         Set-Content -Path $settingsFilePath -Value "Hi, im not a json. Thank you, Test."
    658 
    659         $inputSettings = @{ visual= @{ progressBar="retro"} }
    660         Test-WinGetUserSetting -UserSettings $inputSettings | Should -Be $false
    661     }
    662 
    663     It 'Equal' {
    664         $ogSettings = @{ visual= @{ progressBar="retro"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    665         SetWinGetSettingsHelper $ogSettings
    666 
    667         Test-WinGetUserSetting -UserSettings $ogSettings | Should -Be $true
    668     }
    669 
    670     It 'Equal. Ignore schema' {
    671         Set-Content -Path $settingsFilePath -Value '{ "$schema": "https://aka.ms/winget-settings.schema.json", "visual": { "progressBar": "retro" } }'
    672 
    673         $inputSettings = @{ visual= @{ progressBar="retro"} }
    674         Test-WinGetUserSetting -UserSettings $inputSettings | Should -Be $true
    675     }
    676 
    677     It 'Not Equal string' {
    678         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    679         SetWinGetSettingsHelper $ogSettings
    680 
    681         $inputSettings = @{ visual= @{ progressBar="retro"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    682         Test-WinGetUserSetting -UserSettings $inputSettings | Should -Be $false
    683     }
    684 
    685     It 'Not Equal bool' {
    686         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$true ; experimentalCmd=$true}}
    687         SetWinGetSettingsHelper $ogSettings
    688 
    689         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    690         Test-WinGetUserSetting -UserSettings $inputSettings | Should -Be $false
    691     }
    692 
    693     It 'Not Equal. More settings' {
    694         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true }}
    695         SetWinGetSettingsHelper $ogSettings
    696 
    697         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false }}
    698         Test-WinGetUserSetting -UserSettings $inputSettings | Should -Be $false
    699     }
    700 
    701     It 'Not Equal. More settings input' {
    702         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; }}
    703         SetWinGetSettingsHelper $ogSettings
    704 
    705         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    706         Test-WinGetUserSetting -UserSettings $inputSettings | Should -Be $false
    707     }
    708 
    709     It 'Equal IgnoreNotSet' {
    710         $ogSettings = @{ visual= @{ progressBar="retro"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    711         SetWinGetSettingsHelper $ogSettings
    712 
    713         Test-WinGetUserSetting -UserSettings $ogSettings -IgnoreNotSet | Should -Be $true
    714     }
    715 
    716     It 'Equal IgnoreNotSet. More settings' {
    717         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true }}
    718         SetWinGetSettingsHelper $ogSettings
    719 
    720         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false }}
    721         Test-WinGetUserSetting -UserSettings $inputSettings -IgnoreNotSet | Should -Be $true
    722     }
    723 
    724     It 'Not Equal IgnoreNotSet. More settings input' {
    725         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; }}
    726         SetWinGetSettingsHelper $ogSettings
    727 
    728         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    729         Test-WinGetUserSetting -UserSettings $inputSettings -IgnoreNotSet | Should -Be $false
    730     }
    731 
    732     It 'Not Equal bool IgnoreNotSet' {
    733         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$true ; experimentalCmd=$true}}
    734         SetWinGetSettingsHelper $ogSettings
    735 
    736         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$false ; experimentalCmd=$true}}
    737         Test-WinGetUserSetting -UserSettings $inputSettings -IgnoreNotSet | Should -Be $false
    738     }
    739 
    740     It 'Not Equal array IgnoreNotSet' {
    741         $ogSettings = @{ installBehavior= @{ preferences= @{ architectures = @("x86", "x64")} }}
    742         SetWinGetSettingsHelper $ogSettings
    743 
    744         $inputSettings = @{ installBehavior= @{ preferences= @{ architectures = @("x86", "arm64")} }}
    745         Test-WinGetUserSetting -UserSettings $inputSettings -IgnoreNotSet | Should -Be $false
    746     }
    747 
    748     It 'Not Equal wrong type IgnoreNotSet' {
    749         $ogSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$true ; experimentalCmd=$true}}
    750         SetWinGetSettingsHelper $ogSettings
    751 
    752         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=4 ; experimentalCmd=$true}}
    753         Test-WinGetUserSetting -UserSettings $inputSettings -IgnoreNotSet | Should -Be $false
    754     }
    755 
    756     AfterAll {
    757         RestoreWinGetSettings
    758     }
    759 }
    760 
    761 Describe 'Set-WinGetUserSetting' {
    762 
    763     It 'Overwrites' {
    764         $ogSettings = @{ source= @{ autoUpdateIntervalInMinutes=3}}
    765         SetWinGetSettingsHelper $ogSettings
    766 
    767         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$true ; experimentalCmd=$false}}
    768         $result = Set-WinGetUserSetting -UserSettings $inputSettings
    769 
    770         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    771         $result.'$schema' | Should -Not -BeNullOrEmpty 
    772         $result.visual | Should -Not -BeNullOrEmpty -ErrorAction Stop
    773         $result.visual.progressBar | Should -Be "rainbow"
    774         $result.experimentalFeatures | Should -Not -BeNullOrEmpty -ErrorAction Stop
    775         $result.experimentalFeatures.experimentalArg | Should -Be $true
    776         $result.experimentalFeatures.experimentalCmd | Should -Be $false
    777         $result.source | Should -BeNullOrEmpty
    778     }
    779 
    780     It 'Merge' {
    781         $ogSettings = @{ source= @{ autoUpdateIntervalInMinutes=3}}
    782         SetWinGetSettingsHelper $ogSettings
    783 
    784         $inputSettings = @{ visual= @{ progressBar="rainbow"} ; experimentalFeatures= @{experimentalArg=$true ; experimentalCmd=$false}}
    785         $result = Set-WinGetUserSetting -UserSettings $inputSettings -Merge
    786 
    787         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    788         $result.'$schema' | Should -Not -BeNullOrEmpty 
    789         $result.visual | Should -Not -BeNullOrEmpty -ErrorAction Stop
    790         $result.visual.progressBar | Should -Be "rainbow"
    791         $result.experimentalFeatures | Should -Not -BeNullOrEmpty -ErrorAction Stop
    792         $result.experimentalFeatures.experimentalArg | Should -Be $true
    793         $result.experimentalFeatures.experimentalCmd | Should -Be $false
    794         $result.source | Should -Not -BeNullOrEmpty -ErrorAction Stop
    795         $result.source.autoUpdateIntervalInMinutes | Should -Be 3
    796     }
    797 
    798     It 'Schema.' {
    799         Set-Content -Path $settingsFilePath -Value '{ "$schema": "https://aka.ms/winget-settings.schema.json", "visual": { "progressBar": "retro" } }'
    800 
    801         $inputSettings = @{ visual= @{ progressBar="retro"} }
    802         $result = Set-WinGetUserSetting -UserSettings $inputSettings
    803 
    804         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    805         $result.'$schema' | Should -Not -BeNullOrEmpty 
    806         $result.visual.progressBar | Should -Be "retro"
    807     }
    808 
    809     It 'Overwrites Bad json file' {
    810         Set-Content -Path $settingsFilePath -Value "Hi, im not a json. Thank you, Test."
    811 
    812         $inputSettings = @{ visual= @{ progressBar="retro"} }
    813         $result = Set-WinGetUserSetting -UserSettings $inputSettings
    814 
    815         $result | Should -Not -BeNullOrEmpty -ErrorAction Stop
    816         $result.'$schema' | Should -Not -BeNullOrEmpty 
    817         $result.visual.progressBar | Should -Be "retro"
    818     }
    819 
    820     It 'Overwrites Bad json file' {
    821         Set-Content -Path $settingsFilePath -Value "Hi, im not a json. Thank you, Test."
    822 
    823         $inputSettings = @{ visual= @{ progressBar="retro"} }
    824         { Set-WinGetUserSetting -UserSettings $inputSettings -Merge } | Should -Throw
    825     }
    826 
    827     AfterAll {
    828         RestoreWinGetSettings
    829     }
    830 }
    831 
    832 Describe 'Get|Enable|Disable-WinGetSetting' {
    833 
    834     It 'Get-WinGetSetting' {
    835         $settings = Get-WinGetSetting
    836         $settings | Should -Not -BeNullOrEmpty -ErrorAction Stop
    837         $settings.'$schema' | Should -Not -BeNullOrEmpty 
    838         $settings.adminSettings | Should -Not -BeNullOrEmpty
    839         $settings.userSettingsFile | Should -Be $settingsFilePath
    840     }
    841 
    842     # This tests require admin
    843     It 'Enable|Disable' {
    844         $settings = Get-WinGetSetting
    845         $settings | Should -Not -BeNullOrEmpty -ErrorAction Stop
    846         $settings.adminSettings | Should -Not -BeNullOrEmpty
    847         $settings.adminSettings.LocalManifestFiles | Should -Be $false
    848 
    849         Enable-WinGetSetting -Name LocalManifestFiles
    850 
    851         $afterEnable = Get-WinGetSetting
    852         $afterEnable | Should -Not -BeNullOrEmpty -ErrorAction Stop
    853         $afterEnable.adminSettings | Should -Not -BeNullOrEmpty
    854         $afterEnable.adminSettings.LocalManifestFiles | Should -Be $true
    855 
    856         Disable-WingetSetting -Name LocalManifestFiles
    857 
    858         $afterDisable = Get-WinGetSetting
    859         $afterDisable | Should -Not -BeNullOrEmpty -ErrorAction Stop
    860         $afterDisable.adminSettings | Should -Not -BeNullOrEmpty
    861         $afterDisable.adminSettings.LocalManifestFiles | Should -Be $false
    862     }
    863 }
    864 
    865 Describe 'Test-GroupPolicies' {
    866     BeforeAll {
    867         CleanupGroupPolicies
    868         CreatePolicyKeyIfNotExists
    869     }
    870 
    871     It "Disable WinGetPolicy and run Get-WinGetVersion" {
    872         $policyKeyValueName =  "EnableAppInstaller"
    873 
    874         Set-ItemProperty -Path $wingetGroupPolicyRegistryRoot -Name $policyKeyValueName -Value 0
    875         $registryKey  =  Get-ItemProperty -Path $wingetGroupPolicyRegistryRoot -Name $policyKeyValueName
    876         $registryKey | Should -Not -BeNullOrEmpty
    877         $registryKey.EnableAppInstaller | Should -Be 0
    878 
    879         { Get-WinGetVersion } | Should -Throw "This operation is disabled by Group Policy : Enable Windows Package Manager"
    880 
    881         CleanupGroupPolicies
    882     }
    883 
    884     It "Disable EnableWindowsPackageManagerCommandLineInterfaces Policy and run Get-WinGetVersion" {
    885        $policyKeyValueName =  "EnableWindowsPackageManagerCommandLineInterfaces"
    886 
    887         Set-ItemProperty -Path $wingetGroupPolicyRegistryRoot -Name $policyKeyValueName -Value 0
    888         $registryKey  =  Get-ItemProperty -Path $wingetGroupPolicyRegistryRoot -Name $policyKeyValueName
    889         $registryKey | Should -Not -BeNullOrEmpty
    890         $registryKey.EnableWindowsPackageManagerCommandLineInterfaces | Should -Be 0
    891 
    892         { Get-WinGetVersion } | Should -Throw "This operation is disabled by Group Policy : Enable Windows Package Manager command line interfaces"
    893 
    894         CleanupGroupPolicies
    895     }
    896 
    897     AfterAll {
    898         CleanupGroupPolicies
    899         CleanupGroupPolicyKeyIfExists
    900     }
    901 }
    902 
    903 Describe 'WindowsPackageManagerServer' -Skip:($PSEdition -eq "Desktop") {
    904 
    905     BeforeEach {
    906         AddTestSource
    907         WaitForWindowsPackageManagerServer $true
    908     }
    909 
    910     # When WindowsPackageManagerServer dies, we should not fail.
    911     It 'Forced termination' {
    912         $source = Get-WinGetSource -Name 'TestSource'
    913         $source | Should -Not -BeNullOrEmpty
    914         $source.Name | Should -Be 'TestSource'
    915 
    916         $process = Get-Process -Name "WindowsPackageManagerServer"
    917         $process | Should -Not -BeNullOrEmpty
    918 
    919         # At least one is running.
    920         $process | Where-Object { $_.HasExited -eq $false } | Should -Not -BeNullOrEmpty
    921 
    922         WaitForWindowsPackageManagerServer $true
    923 
    924         # From the ones we got, at least one exited
    925         $process | Where-Object { $_.HasExited -eq $true } | Should -Not -BeNullOrEmpty
    926 
    927         $source2 = Get-WinGetSource -Name 'TestSource'
    928         $source2 | Should -Not -BeNullOrEmpty
    929         $source2.Name | Should -Be 'TestSource'
    930 
    931         $process2 = Get-Process -Name "WindowsPackageManagerServer"
    932         $process2 | Should -Not -BeNullOrEmpty
    933         $process2.Id | Should -Not -Be $process.Id
    934     }
    935 
    936     # The Microsoft.WinGet.Client has static proxy objects of WindowsPackageManagerServer
    937     # This tests does all the Microsoft.WinGet.Client calls in a different pwsh instance.
    938     It 'Graceful termination' {
    939         $typeTable = [System.Management.Automation.Runspaces.TypeTable]::LoadDefaultTypeFiles()
    940         $oopRunspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateOutOfProcessRunspace($typeTable)
    941         $oopRunspace.Open()
    942         $oopPwsh = [PowerShell]::Create()
    943         $oopPwsh.Runspace = $oopRunspace
    944         $oopPwshPid = $oopPwsh.AddScript("`$PID").Invoke()
    945         $oopPwshProcess = Get-Process -Id $oopPwshPid
    946         $oopPwshProcess.HasExited | Should -Be $false
    947 
    948         $source = $oopPwsh.AddScript("Get-WinGetSource -Name TestSource").Invoke()
    949         $source | Should -Not -BeNullOrEmpty
    950         $source.Name | Should -Be 'TestSource'
    951 
    952         $wingetProcess = Get-Process -Name "WindowsPackageManagerServer"
    953         $wingetProcess | Should -Not -BeNullOrEmpty
    954 
    955         # At least one is running.
    956         $wingetProcess | Where-Object { $_.HasExited -eq $false } | Should -Not -BeNullOrEmpty
    957 
    958         $oopRunspace.Close()
    959 
    960         Start-Sleep -Seconds 30
    961         $oopPwshProcess.HasExited | Should -Be $true
    962 
    963         # From the ones we got, at least one exited
    964         WaitForWindowsPackageManagerServer
    965         $wingetProcess | Where-Object { $_.HasExited -eq $true } | Should -Not -BeNullOrEmpty
    966     }
    967 }
    968 
    969 AfterAll {
    970     RestoreWinGetSettings
    971     RemoveTestSource
    972 }