diff --git a/JiraPS/Public/Get-JiraIssueWorklog.ps1 b/JiraPS/Public/Get-JiraIssueWorklog.ps1 new file mode 100644 index 00000000..899a9625 --- /dev/null +++ b/JiraPS/Public/Get-JiraIssueWorklog.ps1 @@ -0,0 +1,66 @@ +function Get-JiraIssueWorklog { + # .ExternalHelp ..\JiraPS-help.xml + [CmdletBinding()] + param( + [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] + [ValidateNotNullOrEmpty()] + [ValidateScript( + { + if (("JiraPS.Issue" -notin $_.PSObject.TypeNames) -and (($_ -isnot [String]))) { + $exception = ([System.ArgumentException]"Invalid Type for Parameter") #fix code highlighting] + $errorId = 'ParameterType.NotJiraIssue' + $errorCategory = 'InvalidArgument' + $errorTarget = $_ + $errorItem = New-Object -TypeName System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $errorTarget + $errorItem.ErrorDetails = "Wrong object type provided for Issue. Expected [JiraPS.Issue] or [String], but was $($_.GetType().Name)" + $PSCmdlet.ThrowTerminatingError($errorItem) + <# + #ToDo:CustomClass + Once we have custom classes, this check can be done with Type declaration + #> + } + else { + return $true + } + } + )] + [Alias('Key')] + [Object] + $Issue, + + [Parameter()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential = [System.Management.Automation.PSCredential]::Empty + ) + + begin { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started" + } + + process { + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] ParameterSetName: $($PsCmdlet.ParameterSetName)" + Write-DebugMessage "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)" + + # Find the proper object for the Issue + $issueObj = Resolve-JiraIssueObject -InputObject $Issue -Credential $Credential + + $parameter = @{ + URI = "{0}/worklog" -f $issueObj.RestURL + Method = "GET" + GetParameter = @{ + maxResults = $PageSize + } + OutputType = "JiraWorklogItem" + Paging = $true + Credential = $Credential + } + + Write-Debug "[$($MyInvocation.MyCommand.Name)] Invoking JiraMethod with `$parameter" + Invoke-JiraMethod @parameter + } + + end { + Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete" + } +} diff --git a/JiraPS/Public/Invoke-JiraMethod.ps1 b/JiraPS/Public/Invoke-JiraMethod.ps1 index bf11ca16..48a2ec2b 100644 --- a/JiraPS/Public/Invoke-JiraMethod.ps1 +++ b/JiraPS/Public/Invoke-JiraMethod.ps1 @@ -37,7 +37,8 @@ function Invoke-JiraMethod { "JiraComment", "JiraIssue", "JiraUser", - "JiraVersion" + "JiraVersion", + "JiraWorklogItem" )] [String] $OutputType, diff --git a/Tests/Functions/Get-JiraIssueWorklog.Unit.Tests.ps1 b/Tests/Functions/Get-JiraIssueWorklog.Unit.Tests.ps1 new file mode 100644 index 00000000..42a1aeca --- /dev/null +++ b/Tests/Functions/Get-JiraIssueWorklog.Unit.Tests.ps1 @@ -0,0 +1,141 @@ +#requires -modules BuildHelpers +#requires -modules @{ ModuleName = "Pester"; ModuleVersion = "4.4.0" } + +Describe "Get-JiraIssueWorklog" -Tag 'Unit' { + + BeforeAll { + Remove-Item -Path Env:\BH* + $projectRoot = (Resolve-Path "$PSScriptRoot/../..").Path + if ($projectRoot -like "*Release") { + $projectRoot = (Resolve-Path "$projectRoot/..").Path + } + + Import-Module BuildHelpers + Set-BuildEnvironment -BuildOutput '$ProjectPath/Release' -Path $projectRoot -ErrorAction SilentlyContinue + + $env:BHManifestToTest = $env:BHPSModuleManifest + $script:isBuild = $PSScriptRoot -like "$env:BHBuildOutput*" + if ($script:isBuild) { + $Pattern = [regex]::Escape($env:BHProjectPath) + + $env:BHBuildModuleManifest = $env:BHPSModuleManifest -replace $Pattern, $env:BHBuildOutput + $env:BHManifestToTest = $env:BHBuildModuleManifest + } + + Import-Module "$env:BHProjectPath/Tools/BuildTools.psm1" + + Remove-Module $env:BHProjectName -ErrorAction SilentlyContinue + Import-Module $env:BHManifestToTest + } + AfterAll { + Remove-Module $env:BHProjectName -ErrorAction SilentlyContinue + Remove-Module BuildHelpers -ErrorAction SilentlyContinue + Remove-Item -Path Env:\BH* + } + + InModuleScope JiraPS { + + . "$PSScriptRoot/../Shared.ps1" + + + $jiraServer = 'http://jiraserver.example.com' + $issueID = 41701 + $issueKey = 'IT-3676' + + $restResult = @" +{ + "startAt": 0, + "maxResults": 1, + "total": 1, + "worklogs": [ + { + "self": "$jiraServer/rest/api/2/issue/$issueID/worklog/90730", + "id": "90730", + "comment": "Test comment", + "created": "2015-05-01T16:24:38.000-0500", + "updated": "2015-05-01T16:24:38.000-0500", + "visibility": { + "type": "role", + "value": "Developers" + }, + "timeSpent": "3m", + "timeSpentSeconds": 180 + } + ] +} +"@ + + #region Mocks + Mock Get-JiraConfigServer -ModuleName JiraPS { + Write-Output $jiraServer + } + + Mock Get-JiraIssue -ModuleName JiraPS { + $object = [PSCustomObject] @{ + ID = $issueID + Key = $issueKey + RestUrl = "$jiraServer/rest/api/2/issue/$issueID" + } + $object.PSObject.TypeNames.Insert(0, 'JiraPS.Issue') + return $object + } + + Mock Resolve-JiraIssueObject -ModuleName JiraPS { + Get-JiraIssue -Key $Issue + } + + # Obtaining worklog from an issue...this is IT-3676 in the test environment + Mock Invoke-JiraMethod -ModuleName JiraPS -ParameterFilter {$Method -eq 'Get' -and $URI -eq "$jiraServer/rest/api/2/issue/$issueID/worklog"} { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + (ConvertFrom-Json -InputObject $restResult).worklogs + } + + # Generic catch-all. This will throw an exception if we forgot to mock something. + Mock Invoke-JiraMethod -ModuleName JiraPS { + ShowMockInfo 'Invoke-JiraMethod' 'Method', 'Uri' + throw "Unidentified call to Invoke-JiraMethod" + } + #endregion Mocks + + ############# + # Tests + ############# + + It "Obtains all Jira worklogs from a Jira issue if the issue key is provided" { + $worklogs = Get-JiraIssueWorklog -Issue $issueKey + + $worklogs | Should Not BeNullOrEmpty + @($worklogs).Count | Should Be 1 + $worklogs.ID | Should Be 90730 + $worklogs.Comment | Should Be 'Test comment' + $worklogs.TimeSpent | Should Be '3m' + $worklogs.TimeSpentSeconds | Should Be 180 + + # Get-JiraIssue should be called to identify the -Issue parameter + Assert-MockCalled -CommandName Get-JiraIssue -ModuleName JiraPS -Exactly -Times 1 -Scope It + + # Normally, this would be called once in Get-JiraIssue and a second time in Get-JiraIssueComment, but + # since we've mocked Get-JiraIssue out, it will only be called once. + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + + It "Obtains all Jira worklogs from a Jira issue if the Jira object is provided" { + $issue = Get-JiraIssue -Key $issueKey + $worklogs = Get-JiraIssueWorklog -Issue $issue + + $worklogs | Should Not BeNullOrEmpty + $worklogs.ID | Should Be 90730 + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + + It "Handles pipeline input from Get-JiraIssue" { + $worklogs = Get-JiraIssue -Key $issueKey | Get-JiraIssueWorklog + + $worklogs | Should Not BeNullOrEmpty + $worklogs.ID | Should Be 90730 + + Assert-MockCalled -CommandName Invoke-JiraMethod -ModuleName JiraPS -Exactly -Times 1 -Scope It + } + } +} diff --git a/docs/en-US/commands/Add-JiraIssueWorklog.md b/docs/en-US/commands/Add-JiraIssueWorklog.md index 89c125b0..cb08d36d 100644 --- a/docs/en-US/commands/Add-JiraIssueWorklog.md +++ b/docs/en-US/commands/Add-JiraIssueWorklog.md @@ -226,6 +226,8 @@ If neither are supplied, this function will run with anonymous access to JIRA. ## RELATED LINKS +[Get-JiraIssueWorklog](../Get-JiraIssueWorklog) + [Get-JiraIssue](../Get-JiraIssue/) [Format-Jira](../Format-Jira/) diff --git a/docs/en-US/commands/Get-JiraIssueWorklog.md b/docs/en-US/commands/Get-JiraIssueWorklog.md new file mode 100644 index 00000000..f6043e54 --- /dev/null +++ b/docs/en-US/commands/Get-JiraIssueWorklog.md @@ -0,0 +1,105 @@ +--- +external help file: JiraPS-help.xml +Module Name: JiraPS +online version: https://atlassianps.org/docs/JiraPS/commands/Get-JiraIssueWorklog/ +locale: en-US +schema: 2.0.0 +layout: documentation +permalink: /docs/JiraPS/commands/Get-JiraIssueWorklog/ +--- +# Get-JiraIssueWorklog + +## SYNOPSIS + +Returns worklogs from an issue in JIRA. +**** + +## SYNTAX + +```powershell +Get-JiraIssueWorklog [-Issue] [[-Credential] ] [] +``` + +## DESCRIPTION + +This function obtains worklogs from existing issues in JIRA. + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Get-JiraIssueWorklog -Key TEST-001 +``` + +This example returns all worklogs from issue TEST-001. + +### EXAMPLE 2 + +```powershell +Get-JiraIssue TEST-002 | Get-JiraIssueWorklog +``` + +This example illustrates use of the pipeline to return all worklogs from issue TEST-002. + +## PARAMETERS + +### -Issue + +JIRA issue to check for worklogs. + +Can be a `JiraPS.Issue` object, issue key, or internal issue ID. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: Key + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -Credential + +Credentials to use to connect to JIRA. +If not specified, this function will use anonymous access. + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### [JiraPS.Issue] / [String] + +## OUTPUTS + +### [JiraPS.WorklogItem] + +## NOTES + +This function requires either the `-Credential` parameter to be passed or a persistent JIRA session. +See `New-JiraSession` for more details. +If neither are supplied, this function will run with anonymous access to JIRA. + +## RELATED LINKS + +[Add-JiraIssueWorklog](../Add-JiraIssueWorklog/) + +[Get-JiraIssue](../Get-JiraIssue/)