diff --git a/JiraPS/Private/Convert-Result.ps1 b/JiraPS/Private/Convert-Result.ps1 new file mode 100644 index 00000000..5067eb65 --- /dev/null +++ b/JiraPS/Private/Convert-Result.ps1 @@ -0,0 +1,27 @@ +function Convert-Result { + [CmdletBinding()] + param( + [Parameter( ValueFromPipeline )] + $InputObject, + + $OutputType + ) + + process { + $InputObject | ForEach-Object { + $item = $_ + if ($OutputType) { + $converter = "ConvertTo-$OutputType" + } + + if ($converter -and (Test-Path function:\$converter)) { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Outputting `$result as $OutputType" + $item | & $converter + } + else { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Outputting `$result" + $item + } + } + } +} diff --git a/JiraPS/Private/Expand-Result.ps1 b/JiraPS/Private/Expand-Result.ps1 new file mode 100644 index 00000000..ea15dddc --- /dev/null +++ b/JiraPS/Private/Expand-Result.ps1 @@ -0,0 +1,16 @@ +function Expand-Result { + [CmdletBinding()] + param( + [Parameter( Mandatory, ValueFromPipeline )] + $InputObject + ) + + process { + foreach ($container in $script:PagingContainers) { + if (($InputObject) -and ($InputObject | Get-Member -Name $container)) { + Write-DebugMessage "Extracting data from [$container] containter" + $InputObject.$container + } + } + } +} diff --git a/JiraPS/Public/Invoke-JiraMethod.ps1 b/JiraPS/Public/Invoke-JiraMethod.ps1 index a67fb80a..6b5cc9f4 100644 --- a/JiraPS/Public/Invoke-JiraMethod.ps1 +++ b/JiraPS/Public/Invoke-JiraMethod.ps1 @@ -1,8 +1,7 @@ function Invoke-JiraMethod { # .ExternalHelp ..\JiraPS-help.xml [CmdletBinding( SupportsPaging )] - param - ( + param( [Parameter( Mandatory )] [Uri] $URI, @@ -207,12 +206,7 @@ function Invoke-JiraMethod { do { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Invoking pagination [currentTotal: $total]" - foreach ($container in $script:PagingContainers) { - if (($response) -and ($response | Get-Member -Name $container)) { - Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Extracting data from [$container] containter" - $result = $response.$container - } - } + $result = Expand-Result -InputObject $response $total += @($result).Count $pageSize = $response.maxResults @@ -222,15 +216,12 @@ function Invoke-JiraMethod { $result = $result | Select-Object -First ($PSCmdlet.PagingParameters.First % $pageSize) } - $converter = "ConvertTo-$($OutputType)" - if (Test-Path function:\$converter) { - # Results shall be casted to custom objects (see ValidateSet) - Write-Debug "[$($MyInvocation.MyCommand.Name)] Outputting `$result as $($OutputType)" - Write-Output ($result | & $converter) - } - else { - Write-Debug "[$($MyInvocation.MyCommand.Name)] Outputting `$result" - Write-Output ($result) + Convert-Result -InputObject $result -OutputType $OutputType + Write-DebugMessage ($result | Out-String) + + if (@($result).Count -lt $response.maxResults) { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] Stopping paging, as page had less entries than $($response.maxResults)" + break } if ($total -ge $PSCmdlet.PagingParameters.First) { @@ -249,14 +240,8 @@ function Invoke-JiraMethod { # Inquire the next page $response = Invoke-JiraMethod @PSBoundParameters - # Expand data container of paged results - $result = @() - foreach ($container in $script:PagingContainers) { - if (($response) -and ($response | Get-Member -Name $container)) { - $result = $response.$container - } - } - } while ($result.Count) + $result = Expand-Result -InputObject $response + } while (@($result).Count -gt 0) if ($PSCmdlet.PagingParameters.IncludeTotalCount) { [double]$Accuracy = 1.0 @@ -264,7 +249,7 @@ function Invoke-JiraMethod { } } else { - Write-Output $response + $response } } else { diff --git a/Tests/Invoke-JiraMethod.Tests.ps1 b/Tests/Invoke-JiraMethod.Tests.ps1 index a72639a9..6749f9a2 100644 --- a/Tests/Invoke-JiraMethod.Tests.ps1 +++ b/Tests/Invoke-JiraMethod.Tests.ps1 @@ -54,6 +54,8 @@ Describe "Invoke-JiraMethod" { Mock Join-Hashtable -ModuleName JiraPS { @{ } } Mock Set-TlsLevel -ModuleName JiraPS { } Mock Resolve-ErrorWebResponse -ModuleName JiraPS { } + Mock Expand-Result -ModuleName JiraPS { } + Mock Convert-Result -ModuleName JiraPS { } Mock Get-JiraSession -ModuleName JiraPS { [PSCustomObject]@{ WebSession = New-Object -TypeName Microsoft.PowerShell.Commands.WebRequestSession @@ -300,13 +302,29 @@ Describe "Invoke-JiraMethod" { It "uses ConvertTo-$type to transform the results" { Invoke-JiraMethod -Method get -URI "https://postman-echo.com/get" -OutputType $type -Paging -ErrorAction Stop - Assert-MockCalled -CommandName "ConvertTo-$type" -ModuleName JiraPS -Exactly -Times 1 -Scope It + $assertMockCalledSplat = @{ + CommandName = "Convert-Result" + ModuleName = 'JiraPS' + ParameterFilter = { $OutputType -eq $type} + Exactly = $true + Times = 1 + Scope = 'It' + } + Assert-MockCalled @assertMockCalledSplat } It "only uses -OutputType with -Paging [$type]" { Invoke-JiraMethod -Method get -URI "https://postman-echo.com/get" -OutputType $type -ErrorAction Stop - Assert-MockCalled -CommandName "ConvertTo-$type" -ModuleName JiraPS -Exactly -Times 0 -Scope It + $assertMockCalledSplat = @{ + CommandName = "Convert-Result" + ModuleName = 'JiraPS' + ParameterFilter = { $OutputType -eq $type} + Exactly = $true + Times = 0 + Scope = 'It' + } + Assert-MockCalled @assertMockCalledSplat } } @@ -493,7 +511,7 @@ Describe "Invoke-JiraMethod" { $response = "" if ($Uri -match "startAt\=(\d+)") { switch ($matches[1]) { - 5 {$response = $pagedResponse2; break } + 5 { $response = $pagedResponse2; break } 7 { $response = $pagedResponse3; break } } } @@ -521,6 +539,12 @@ Describe "Invoke-JiraMethod" { } $table } + Mock Convert-Result -ModuleName JiraPS { + $InputObject + } + Mock Expand-Result -ModuleName JiraPS { + $InputObject.issues + } It "requests each page of the results" { { @@ -537,7 +561,7 @@ Describe "Invoke-JiraMethod" { CommandName = 'Invoke-WebRequest' ModuleName = 'JiraPS' Exactly = $true - Times = 3 + Times = 2 Scope = 'It' } Assert-MockCalled @assertMockCalledSplat @@ -550,12 +574,16 @@ Describe "Invoke-JiraMethod" { Paging = $true ErrorAction = "Stop" } - $result = Invoke-JiraMethod @invokeJiraMethodSplat + $null = Invoke-JiraMethod @invokeJiraMethodSplat - $result.Count | Should -Be 7 - - { $result | Get-Member -Name Id } | Should -Not -Throw - { $result | Get-Member -Name Id } | Should -Not -BeNullOrEmpty + $assertMockCalledSplat = @{ + CommandName = 'Expand-Result' + ModuleName = 'JiraPS' + Exactly = $true + Times = 3 + Scope = 'It' + } + Assert-MockCalled @assertMockCalledSplat } It "fetches only the necessary amount of pages when -First is used" { @@ -618,7 +646,7 @@ Describe "Invoke-JiraMethod" { CommandName = 'Invoke-WebRequest' ModuleName = 'JiraPS' Exactly = $true - Times = 2 + Times = 1 Scope = 'It' } Assert-MockCalled @assertMockCalledSplat