diff --git a/CHANGELOG.md b/CHANGELOG.md index 8db4292..4b8a6e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `Get-ConfluenceSpace` no longer requests unused space label metadata, avoiding HTTP 500 responses from Confluence Data Center 8.9.x when listing spaces (#214) - `Get-ConfluencePage -Label` now quotes label values in generated CQL so labels containing hyphens are accepted by Confluence (#175, #185, [@ehrenfeu]) - Fixed pagination so GET filters such as `spaceKey` and `title` are preserved when requesting follow-up pages (#157). +- `Get-ConfluencePage -Label` now returns only current pages by default and supports `-Status` to request one or more page statuses (#213) - `Invoke-Method` now handles JSON payloads with duplicate key casing (for example `subType` and `subtype`) without failing parsing (#216, [@codethief]) - Fixed `-PersonalAccessToken` authentication on PowerShell 6+ by forwarding it as a bearer authorization header (#208, #209, [@sebmaurer]) - Fixed Confluence Cloud attachment downloads on PowerShell 6+ by preserving authorization across Atlassian download redirects. diff --git a/ConfluencePS/Public/Get-Page.ps1 b/ConfluencePS/Public/Get-Page.ps1 index 38db707..e12dc57 100644 --- a/ConfluencePS/Public/Get-Page.ps1 +++ b/ConfluencePS/Public/Get-Page.ps1 @@ -69,6 +69,10 @@ [ValidateNotNullOrEmpty()] [String[]]$Label, + [Parameter(ParameterSetName = "byLabel")] + [ValidateSet('current', 'archived', 'trashed')] + [String[]]$Status = 'current', + [Parameter( Position = 0, Mandatory = $true, @@ -146,7 +150,7 @@ if ($SpaceKey) { $CQLparameters += "space=$SpaceKey" } $iwParameters["GetParameters"]["cql"] = ($CQLparameters -join " AND ") - Invoke-Method @iwParameters + Invoke-Method @iwParameters | Where-Object { $_.Status -in $Status } break } "byQuery" { diff --git a/Tests/Functions/Get-Page.Tests.ps1 b/Tests/Functions/Get-Page.Tests.ps1 index bbffc65..4994eb6 100644 --- a/Tests/Functions/Get-Page.Tests.ps1 +++ b/Tests/Functions/Get-Page.Tests.ps1 @@ -50,6 +50,52 @@ InModuleScope ConfluencePS { $script:lastCql | Should -Be 'type=page AND label="labelA" AND label="labelB" AND space=HOTH' } + It "returns only current pages by default for byLabel results" { + Mock Invoke-Method -ModuleName ConfluencePS { + $currentPage = [ConfluencePS.Page]::new() + $currentPage.ID = 1 + $currentPage.Status = 'current' + + $trashedPage = [ConfluencePS.Page]::new() + $trashedPage.ID = 2 + $trashedPage.Status = 'trashed' + + $archivedPage = [ConfluencePS.Page]::new() + $archivedPage.ID = 3 + $archivedPage.Status = 'archived' + + $currentPage, $trashedPage, $archivedPage + } + + $result = Get-Page -ApiUri "https://example.com/wiki/rest/api" -Label "labelA" + + $result | Should -HaveCount 1 + $result.ID | Should -Be 1 + } + + It "returns pages matching the requested byLabel status values" { + Mock Invoke-Method -ModuleName ConfluencePS { + $currentPage = [ConfluencePS.Page]::new() + $currentPage.ID = 1 + $currentPage.Status = 'current' + + $trashedPage = [ConfluencePS.Page]::new() + $trashedPage.ID = 2 + $trashedPage.Status = 'trashed' + + $archivedPage = [ConfluencePS.Page]::new() + $archivedPage.ID = 3 + $archivedPage.Status = 'archived' + + $currentPage, $trashedPage, $archivedPage + } + + $result = Get-Page -ApiUri "https://example.com/wiki/rest/api" -Label "labelA" -Status current, trashed + + $result | Should -HaveCount 2 + $result.ID | Should -Be 1, 2 + } + It "prefixes byQuery CQL with type=page without pre-encoding" { $null = Get-Page -ApiUri "https://example.com/wiki/rest/api" -Query 'space=HOTH and title~"*Object"' diff --git a/Tests/Integration.Tests.ps1 b/Tests/Integration.Tests.ps1 index 5b42582..9ae152e 100644 --- a/Tests/Integration.Tests.ps1 +++ b/Tests/Integration.Tests.ps1 @@ -447,7 +447,6 @@ Describe 'Integration Tests' -Tag Integration, Cloud, DataCenter { $script:GetID1 = Get-ConfluencePage -PageID $GetTitle1.ID -ErrorAction SilentlyContinue $script:GetID2 = Get-ConfluencePage -PageID $GetTitle2.ID -ErrorAction SilentlyContinue $script:Query = "id in ($($GetID1.ID), $($GetID2.ID))" - $script:GetKeys = Get-ConfluencePage -SpaceKey $SpaceKey -ErrorAction SilentlyContinue | Sort-Object ID $script:GetByLabel = @() $script:GetByQuery = @() $maxSearchRetries = if ($script:integrationEnvironment.IsCloud) { 24 } else { 6 } @@ -466,6 +465,7 @@ Describe 'Integration Tests' -Tag Integration, Cloud, DataCenter { $script:GetByQueryIndexed = @($GetByQuery).Count -eq 2 $script:GetByQueryRequired = -not $script:integrationEnvironment.IsCloud $script:GetByQueryCanBeAsserted = $script:GetByQueryIndexed -or $script:GetByQueryRequired + $script:GetKeys = Get-ConfluencePage -SpaceKey $SpaceKey -ErrorAction SilentlyContinue | Sort-Object ID $script:GetSpacePage = Get-ConfluencePage -Space (Get-ConfluenceSpace -SpaceKey $SpaceKey) -ErrorAction SilentlyContinue $script:GetSpacePiped = Get-ConfluenceSpace -SpaceKey $SpaceKey | Get-ConfluencePage -ErrorAction SilentlyContinue $script:GetSpacePaged = Get-ConfluencePage -SpaceKey $SpaceKey -PageSize 1 -ErrorAction SilentlyContinue @@ -798,6 +798,14 @@ Describe 'Integration Tests' -Tag Integration, Cloud, DataCenter { $script:SetPage2 = $Page2.ID | Set-ConfluencePage -Body $NewContent2 -ErrorAction Stop # make a non-relevant change just to bump page version $script:SetPage3 = $Page3.ID | Set-ConfluencePage -Body "..." -ErrorAction Stop + for ($retry = 0; $retry -lt 12; $retry++) { + $script:Page3 = Get-ConfluencePage -PageID $Page3.ID -ErrorAction Stop + if ($Page3.Version.Number -ge $SetPage3.Version.Number) { + break + } + + Start-Sleep -Seconds 5 + } # change the title of a page by property - this page should have version 4 $script:SetPage3 = $Page3.ID | Set-ConfluencePage -Body $RawContent3 -Convert -ErrorAction Stop # change the parent page by object @@ -1292,10 +1300,42 @@ Describe 'Integration Tests' -Tag Integration, Cloud, DataCenter { $script:SpaceKey = "PESTER$SpaceID" $script:Title = "Pester New Page Orphan" $script:PageID = Get-ConfluencePage -Title $Title -SpaceKey $SpaceKey -ErrorAction Stop + $script:DeletedPageLabel = "deletedlabel$SpaceID" + $script:PageID | Add-ConfluenceLabel -Label $DeletedPageLabel -ErrorAction Stop + $script:DeletedPageByLabelBefore = @() + $maxSearchRetries = if ($script:integrationEnvironment.IsCloud) { 24 } else { 6 } + for ($retry = 0; $retry -lt $maxSearchRetries; $retry++) { + $script:DeletedPageByLabelBefore = Get-ConfluencePage -Label $DeletedPageLabel -SpaceKey $SpaceKey -ErrorAction SilentlyContinue + if (@($DeletedPageByLabelBefore).ID -contains $PageID.ID) { + break + } + + Start-Sleep -Seconds 5 + } $script:Before = Get-ConfluencePage -SpaceKey $SpaceKey -ErrorAction Stop # ACT Remove-ConfluencePage -PageID $PageID.ID -ErrorAction SilentlyContinue + $script:DeletedPageByLabelAfter = @() + for ($retry = 0; $retry -lt $maxSearchRetries; $retry++) { + $script:DeletedPageByLabelAfter = Get-ConfluencePage -Label $DeletedPageLabel -SpaceKey $SpaceKey -ErrorAction SilentlyContinue + if (@($DeletedPageByLabelAfter).ID -notcontains $PageID.ID) { + break + } + + Start-Sleep -Seconds 5 + } + if (-not $script:integrationEnvironment.IsCloud) { + $script:DeletedPageByLabelWithStatus = @() + for ($retry = 0; $retry -lt $maxSearchRetries; $retry++) { + $script:DeletedPageByLabelWithStatus = Get-ConfluencePage -Label $DeletedPageLabel -SpaceKey $SpaceKey -Status trashed -ErrorAction SilentlyContinue + if (@($DeletedPageByLabelWithStatus).ID -contains $PageID.ID) { + break + } + + Start-Sleep -Seconds 5 + } + } Get-ConfluencePage -SpaceKey $SpaceKey | Remove-ConfluencePage -ErrorAction SilentlyContinue $script:After = Get-ConfluencePage -SpaceKey $SpaceKey -ErrorAction SilentlyContinue @@ -1306,6 +1346,19 @@ Describe 'Integration Tests' -Tag Integration, Cloud, DataCenter { It 'has pages before' { $Before | Should -Not -BeNullOrEmpty } + It 'does not return the deleted page for label searches' { + if (-not $script:integrationEnvironment.IsCloud) { + @($DeletedPageByLabelBefore).ID | Should -Contain $PageID.ID + } + @($DeletedPageByLabelAfter).ID | Should -Not -Contain $PageID.ID + } + It 'returns the deleted page when requesting trashed label search results on Data Center' { + if ($script:integrationEnvironment.IsCloud) { + Set-ItResult -Skipped -Because 'Confluence Cloud content search does not return trashed labeled pages.' + } + + @($DeletedPageByLabelWithStatus).ID | Should -Contain $PageID.ID + } It 'space does not have pages after' { $After | Should -BeNullOrEmpty } diff --git a/docs/en-US/commands/Get-Page.md b/docs/en-US/commands/Get-Page.md index c50be87..37d66b7 100644 --- a/docs/en-US/commands/Get-Page.md +++ b/docs/en-US/commands/Get-Page.md @@ -29,8 +29,9 @@ Get-ConfluencePage -ApiUri [-Credential ] ```powershell Get-ConfluencePage -ApiUri [-Credential ] [-PersonalAccessToken ] [-Certificate ] - [-SpaceKey ] [-Space ] -Label [-PageSize ] - [-IncludeTotalCount] [-Skip ] [-First ] [-ExcludePageBody] + [-SpaceKey ] [-Space ] -Label [-Status ] + [-PageSize ] [-IncludeTotalCount] [-Skip ] [-First ] + [-ExcludePageBody] ``` ### bySpace @@ -103,6 +104,7 @@ Get-ConfluencePage -Label 'skywalker' Return all pages containing the label "skywalker" (case-insensitive). Label text must match exactly; no wildcards are applied. +Only current pages are returned by default; use -Status to request archived or trashed pages. ### -------------------------- EXAMPLE 5 -------------------------- @@ -112,13 +114,30 @@ Get-ConfluencePage -Query "mention = jSmith and creator != jSmith" Return all pages matching the query. -### -------------------------- EXAMPLE 5 -------------------------- +### -------------------------- EXAMPLE 6 -------------------------- ```powershell Get-ConfluencePage -Label 'skywalker' -ExcludePageBody ``` -Return all pages containing the label "skywalker" (case-insensitive) without their page content. +Return all current pages containing the label "skywalker" (case-insensitive) without their page content. + +### -------------------------- EXAMPLE 7 -------------------------- + +```powershell +Get-ConfluencePage -Label 'skywalker' -Status trashed +``` + +Return trashed pages containing the label "skywalker" when Confluence content search returns trashed label results. +Confluence Cloud content search may not return trashed pages for label queries. + +### -------------------------- EXAMPLE 8 -------------------------- + +```powershell +Get-ConfluencePage -Label 'skywalker' -Status current, archived, trashed +``` + +Return all current, archived, and trashed pages containing the label "skywalker". ## PARAMETERS @@ -299,6 +318,25 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Status + +Filter label search results by one or more page statuses. + +The default is current, which excludes archived and trashed pages. +This filters statuses returned by Confluence content search; Confluence Cloud content search may not return trashed pages for label queries. + +```yaml +Type: String[] +Parameter Sets: byLabel +Aliases: + +Required: False +Position: Named +Default value: current +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Query Use Confluences advanced search: [CQL](https://developer.atlassian.com/cloud/confluence/advanced-searching-using-cql/).