functions/Publish-NewDscModuleVersion.Tests.ps1
Describe 'Publish-NewDscModuleVersion' -Tag 'Unit' { BeforeDiscovery { $ModuleRootPath = Split-Path -Parent $PSCommandPath | Split-Path -Parent Import-Module "$ModuleRootPath/Puppet.Dsc.psd1" } InModuleScope puppet.dsc { Context 'Basic verification' { BeforeAll { $UnpuppetizedModuleVersions = @( [PSCustomObject]@{ Name = 'Foo' ; Versions = @('1.2.3.0', '1.2.0.0', '1.1.0.0', '1.0.0.0') } [PSCustomObject]@{ Name = 'Bar' ; Versions = @('2.1.0.0', '2.0.0.0', '1.1.0.0', '0.1.0.0') } [PSCustomObject]@{ Name = 'Baz' ; Versions = @('2.0.0.0', '1.0.0.0', '0.1.0.0') } ) $UnpuppetizedModuleVersionsNewerOnly = @( [PSCustomObject]@{ Name = 'Foo' ; Versions = @('1.2.3.0', '1.2.0.0', '1.1.0.0', '1.0.0.0') } [PSCustomObject]@{ Name = 'Bar' ; Versions = @('2.1.0.0', '2.0.0.0') } [PSCustomObject]@{ Name = 'Baz' ; Versions = @('2.0.0.0') } ) Mock Get-UnpuppetizedDscModuleVersion { return $UnpuppetizedModuleVersions } Mock Get-UnpuppetizedDscModuleVersion -ParameterFilter { $OnlyNewer.IsPresent } { return $UnpuppetizedModuleVersionsNewerOnly } Mock Get-UnpuppetizedDscModuleVersion -ParameterFilter { $MinimumVersion -match '^2\.0$' } { return @( [PSCustomObject]@{ Name = 'Bar' ; Versions = @('2.1.0.0', '2.0.0.0') } [PSCustomObject]@{ Name = 'Baz' ; Versions = @('2.0.0.0') } ) } Mock Get-UnpuppetizedDscModuleVersion -ParameterFilter { ![string]::IsNullOrEmpty($Name) } { If ($Name.Count -gt 1) { return $ForgeModules | Where-Object -FilterScript { $_.Name -in $Name } } Else { return $ForgeModules | Where-Object -FilterScript { $_.Name -eq $Name } } } Mock Get-UnpuppetizedDscModuleVersion -ParameterFilter { $ForgeNameSpace -eq 'EmptyNameSpace' } {} # Pester equivalent of mock-and-call-original Mock Get-PuppetizedModuleName { $GetPuppetizedModuleNameFunction = Get-Command Get-PuppetizedModuleName -CommandType Function return & $GetPuppetizedModuleNameFunction -Name $Name } Mock New-PuppetDscModule { return [PSCustomObject]@{ FullName = "TestDrive:\import\$(Get-PuppetizedModuleName -Name $PowerShellModuleName)\" } } Mock Get-Content { @{ version = '1.2.3-0-0' } | ConvertTo-Json } Mock Publish-PuppetModule Mock Write-PSFMessage Mock Stop-PSFFunction Publish-NewDscModuleVersion -ForgeNameSpace 'foo' } It 'requires the ForgeNameSpace parameter' { $Command = Get-Command Publish-NewDscModuleVersion $Command.Parameters.ForgeNameSpace.Attributes | Where-Object -FilterScript { $_.TypeId.Name -eq 'ParameterAttribute' } | Select-Object -ExpandProperty Mandatory -Unique | Should -Be $true } It 'searches for unpuppetized DSC Modules' { Should -Invoke Get-UnpuppetizedDscModuleVersion -Scope Context -Times 1 -ParameterFilter { $ForgeNameSpace -eq 'foo' } } It 'puppetizes each unreleased version only once' { Should -Invoke New-PuppetDscModule -Scope Context -Times 4 -ParameterFilter { $PowerShellModuleName -eq 'Foo' } Should -Invoke New-PuppetDscModule -Scope Context -Times 11 } It 'builds and publishes each unreleased version' { Should -Invoke Publish-PuppetModule -Scope Context -Times 4 -ParameterFilter { $PuppetModuleFolderPath -match 'foo' } Should -Invoke Publish-PuppetModule -Scope Context -Times 11 } Context 'when something goes wrong' { BeforeAll { Mock Get-UnpuppetizedDscModuleVersion -ParameterFilter { $ForgeNameSpace -eq 'will_error' } { return [PSCustomObject]@{ Name = 'WillError' Versions = @('1.2.3.0') } } Mock New-PuppetDscModule -ParameterFilter { $PowerShellModuleName -eq 'WillError' } { Throw 'Error! Here are some details.' } } It 'calls Stop-PSFunction for error-handling' { Publish-NewDscModuleVersion -ForgeNameSpace 'will_error' Should -Invoke Stop-PSFFunction -ParameterFilter { $Message -match 'WillError' -and $Message -match '1.2.3.0' -and $ErrorRecord -match 'Error!' } } It 'calls Stop-PSFunction with EnableException if ErrorAction is "Stop"' { Publish-NewDscModuleVersion -ForgeNameSpace 'will_error' -ErrorAction Stop Should -Invoke Stop-PSFFunction -ParameterFilter { $EnableException -eq $True } } } Context 'when the Name parameter is specified' { It 'searches for modules to update by Name' { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -Name 'foo' Should -Invoke Get-UnpuppetizedDscModuleVersion -Times 1 -ParameterFilter { $Name -eq 'foo' } } } Context 'when the ForgeApiUri parameter is specified' -Tag 'api' { BeforeAll { $TestForgeApiUri = 'https://myforge.acme.inc/v3' Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -ForgeApiUri $TestForgeApiUri } It 'passes the specified URI for search' { Should -Invoke Get-UnpuppetizedDscModuleVersion -Scope Context -Times 1 -ParameterFilter { $ForgeSearchUri -eq "$TestForgeApiUri/modules" } } It 'passes the specified URI for publish' { Should -Invoke Publish-PuppetModule -Scope Context -Times 1 -ParameterFilter { $ForgeUploadUrl -eq "$TestForgeApiUri/releases" } } } Context 'when the ForgeToken parameter is specified' { BeforeAll { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -ForgeToken 'MyToken' -Verbose } It 'passes the token to Publish-PuppetModule' { Should -Invoke Publish-PuppetModule -Scope Context -Times 1 -ParameterFilter { $ForgeToken -eq 'MyToken' } } It 'does not leak the token in logging' { Should -Invoke Write-PSFMessage -Scope Context Should -Invoke Write-PSFMessage -Scope Context -Times 0 -ParameterFilter { $Message -match 'MyToken' } } } Context 'when the BuildFolderPath parameter is specified' { BeforeAll { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -BuildFolder 'TestDrive:\import' } It 'passes the path as the OutputDirectory to New-PuppetDscModule' { Should -Invoke New-PuppetDscModule -Scope Context -ParameterFilter { $OutputDirectory -eq 'TestDrive:\import' } } It 'leverages the path for Publish-PuppetModule' { Should -Invoke Publish-PuppetModule -Scope Context -ParameterFilter { $PuppetModuleFolderPath -match '^TestDrive:\\import' } } } Context 'when the PackageFolderPath parameter is specified' { It 'passes the path as the ExportFolderPath to Publish-PuppetModule' { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -PackageFolderPath 'TestDrive:\packages' Should -Invoke Publish-PuppetModule -ParameterFilter { $ExportFolderPath -eq 'TestDrive:\packages' } } } Context 'when the OnlyNewer parameter is specified' { It 'only puppetizes and releases versions newer than any published to the Forge' { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -OnlyNewer Should -Invoke Get-UnpuppetizedDscModuleVersion -ParameterFilter { $OnlyNewer.IsPresent -eq $true } } } Context 'when the MinimumVersion parameter is specified' { It 'only puppetizes and releases versions greater than or equal to the value specified' { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -MinimumVersion '1.0.0' Should -Invoke Get-UnpuppetizedDscModuleVersion -ParameterFilter { $MinimumVersion -eq '1.0.0' } } } Context 'when the MaxBuildCount parameter is specified' { It 'only puppetizes and releases a number of modules up to the specified value' { Publish-NewDscModuleVersion -ForgeNameSpace 'foo' -MaxBuildCount 5 Should -Invoke Get-UnpuppetizedDscModuleVersion -Times 1 Should -Invoke New-PuppetDscModule -Times 5 Should -Invoke Publish-PuppetModule -Times 5 } } } } } |