refactor(PageMeta): move page metadata stuff to seperate module
test(PageMeta): fix scoping of page metadata module tests fix(PageMeta): update for support of new manifest format
This commit is contained in:
parent
35c1afdc64
commit
852b4f1d95
2 changed files with 455 additions and 0 deletions
256
PSConfluencePublisher/PageMeta.Tests.ps1
Executable file
256
PSConfluencePublisher/PageMeta.Tests.ps1
Executable file
|
|
@ -0,0 +1,256 @@
|
||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
BeforeAll {
|
||||||
|
Import-Module (Join-Path $PSScriptRoot 'PSConfluencePublisher.psd1') -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Describe 'Get-PageMetaCache' `
|
||||||
|
{
|
||||||
|
Context 'default' `
|
||||||
|
{
|
||||||
|
It 'uses index' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
$mockIndex = @{
|
||||||
|
'foobar' = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = Get-PageMetaCache `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Manifest $mockManifest `
|
||||||
|
-Index $mockIndex
|
||||||
|
|
||||||
|
$meta | Should -Be $mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'returns page meta when title exists' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
$meta = Get-PageMetaCache `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Manifest $mockManifest
|
||||||
|
|
||||||
|
$meta | Should -Be $mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'returns null, if page with supplied title does not exist' `
|
||||||
|
{
|
||||||
|
$mockManifest = @(
|
||||||
|
@{}
|
||||||
|
)
|
||||||
|
|
||||||
|
$meta = Get-PageMetaCache `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Manifest $mockManifest
|
||||||
|
|
||||||
|
$meta | Should -Be $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Describe 'Get-PageMeta' `
|
||||||
|
{
|
||||||
|
Context 'default' `
|
||||||
|
{
|
||||||
|
BeforeAll `
|
||||||
|
{
|
||||||
|
Mock -ModuleName 'PageMeta' Get-PersonalAccessToken {
|
||||||
|
'012345678901234567890'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'returns cache when page id present' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
'PageId' = '0123456789'
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
Mock -ModuleName 'PageMeta' Get-PageMetaCache {
|
||||||
|
$mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = Get-PageMeta `
|
||||||
|
-Host 'foobar' `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Space 'foobar' `
|
||||||
|
-Manifest $mockManifest
|
||||||
|
|
||||||
|
$meta | Should -Be $mockPageMeta
|
||||||
|
|
||||||
|
Should -Invoke -CommandName 'Get-PageMetaCache' `
|
||||||
|
-ModuleName 'PageMeta' `
|
||||||
|
-Exact `
|
||||||
|
-Times 1
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'gets a page id remotely if there is exactly one result' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Version' = 'version'
|
||||||
|
'Hash' = 'hash'
|
||||||
|
'Ref' = 'ref'
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock -ModuleName 'PageMeta' Get-PageMetaCache {
|
||||||
|
$mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock -ModuleName 'PageMeta' Update-PageMeta {
|
||||||
|
$PageId | Should -Be '123'
|
||||||
|
|
||||||
|
$Version | Should -Be 9
|
||||||
|
|
||||||
|
$Title | Should -Be 'foobar'
|
||||||
|
|
||||||
|
$mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock -ModuleName 'PageMeta' Invoke-WebRequest {
|
||||||
|
@{
|
||||||
|
'Content' = '{"results": [{"id": "123","_expandable":{"version": 9}}]}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = Get-PageMeta `
|
||||||
|
-Host 'confluence.contoso.com' `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Space 'foobar' `
|
||||||
|
-Manifest @{'Pages'= {}}
|
||||||
|
|
||||||
|
$meta | Should -Be $mockPageMeta
|
||||||
|
|
||||||
|
Should -Invoke 'Get-PageMetaCache' `
|
||||||
|
-ModuleName 'PageMeta' `
|
||||||
|
-Exactly `
|
||||||
|
-Times 1
|
||||||
|
|
||||||
|
Should -Invoke 'Invoke-WebRequest' `
|
||||||
|
-ModuleName 'PageMeta' `
|
||||||
|
-Exactly `
|
||||||
|
-Times 1
|
||||||
|
|
||||||
|
Should -Invoke 'Update-PageMeta' `
|
||||||
|
-ModuleName 'PageMeta' `
|
||||||
|
-Exactly `
|
||||||
|
-Times 1
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'throws an exception, if there is more than one result' `
|
||||||
|
{
|
||||||
|
Mock -ModuleName 'PageMeta' Invoke-WebRequest {
|
||||||
|
@{
|
||||||
|
'Content' = '{"results": [{}, {}]}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Get-PageMeta `
|
||||||
|
-Host 'confluence.contoso.com' `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Space 'foobar' `
|
||||||
|
-Manifest @{'Pages'= {}}
|
||||||
|
} | Should -Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'throws an exception, if there is no result' `
|
||||||
|
{
|
||||||
|
Mock Invoke-WebRequest {
|
||||||
|
@{
|
||||||
|
'Content' = '{"results": []}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Get-PageMeta `
|
||||||
|
-Host 'confluence.contoso.com' `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Space 'foobar' `
|
||||||
|
-Manifest @{'Pages'= {}}
|
||||||
|
} | Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Describe 'Update-PageMeta' `
|
||||||
|
{
|
||||||
|
Context 'default' `
|
||||||
|
{
|
||||||
|
It 'fails, if page meta index does not exist' `
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Update-PageMeta `
|
||||||
|
-PageId '0123456789' `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-Manifest @{}
|
||||||
|
} | Should -Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'updates minimal' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
$pageMeta = Update-PageMeta `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-PageId '0123456789' `
|
||||||
|
-Manifest $mockManifest
|
||||||
|
|
||||||
|
$mockPageMeta.PageId | Should -Be '0123456789'
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'updates extended' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
Update-PageMeta `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-PageId 'pageId' `
|
||||||
|
-Version 9001 `
|
||||||
|
-AncestorTitle 'ancestorTitle' `
|
||||||
|
-Hash 'hash' `
|
||||||
|
-Manifest $mockManifest
|
||||||
|
|
||||||
|
$mockPageMeta.PageId | Should -Be 'pageId'
|
||||||
|
|
||||||
|
$mockPageMeta.Version | Should -Be 9001
|
||||||
|
|
||||||
|
$mockPageMeta.AncestorTitle | Should -Be 'ancestorTitle'
|
||||||
|
|
||||||
|
$mockPageMeta.Hash | Should -Be 'hash'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
199
PSConfluencePublisher/PageMeta.psm1
Executable file
199
PSConfluencePublisher/PageMeta.psm1
Executable file
|
|
@ -0,0 +1,199 @@
|
||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
|
||||||
|
function Get-PageMetaCache
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Get a locally indexed/cached Confluence page id
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-PageMetaCache `
|
||||||
|
-Title 'Page Title' `
|
||||||
|
-Manifest @() `
|
||||||
|
-Index @{}
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
To test or not to test, that is the question... Since the
|
||||||
|
`Test-JSON` cmdlet requires serialized JSON, but we are working with
|
||||||
|
the deserialized Hashtable, it's too computationally intense to
|
||||||
|
always test the input upon every call. We therefore only make sure,
|
||||||
|
that correct data is written to the filesystem. For the rest, each
|
||||||
|
function is responsible for themself (learned that that's a valid
|
||||||
|
reflexive pronoun today 🤓).
|
||||||
|
|
||||||
|
This function is lucky to get this note, because it's at the top 💯.
|
||||||
|
Of course this applies to every function.
|
||||||
|
#>
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)] [string] $Title,
|
||||||
|
[Parameter(Mandatory)] [Array] $Manifest,
|
||||||
|
[Parameter()] [Collections.Hashtable] $Index
|
||||||
|
)
|
||||||
|
|
||||||
|
Process
|
||||||
|
{
|
||||||
|
If ($Index -And $Manifest.Count -gt 0 -And $Manifest[$Index.$Title])
|
||||||
|
{
|
||||||
|
$Manifest[$Index.$Title]
|
||||||
|
}
|
||||||
|
|
||||||
|
Else
|
||||||
|
{
|
||||||
|
For ($i = 0; $i -lt $Manifest.Count; $i += 1)
|
||||||
|
{
|
||||||
|
If ($Manifest[$i].Title -eq $Title)
|
||||||
|
{
|
||||||
|
$Manifest[$i]
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Get-PageMeta
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Get a Confluence page id
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
First, tries to retrieve from local page id index (cache) through
|
||||||
|
the local alias. If no cache hit, then polls the Confluence
|
||||||
|
instance host for the id by providing a space key and page title.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-PageMeta `
|
||||||
|
-Host 'confluence.contoso.com' `
|
||||||
|
-Title 'Testitest' `
|
||||||
|
-Space 'TIARA' `
|
||||||
|
-CacheIndexFile 'confluence-page-cache.json'
|
||||||
|
#>
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)] [string] $Host,
|
||||||
|
[Parameter(Mandatory)] [string] $Title,
|
||||||
|
[Parameter(Mandatory)] [string] $Space,
|
||||||
|
[Parameter(Mandatory)] [Array] $Manifest,
|
||||||
|
[Parameter()] [Collections.Hashtable] $Index
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin
|
||||||
|
{
|
||||||
|
$pageMeta = Get-PageMetaCache `
|
||||||
|
-Title $Title `
|
||||||
|
-Manifest $Manifest `
|
||||||
|
-Index $Index
|
||||||
|
}
|
||||||
|
|
||||||
|
Process
|
||||||
|
{
|
||||||
|
If ($pageMeta -And $pageMeta.PageId)
|
||||||
|
{
|
||||||
|
$pageMeta
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$escapedTitle = [Uri]::EscapeDataString($Title)
|
||||||
|
|
||||||
|
#TODO: move this to a separate function
|
||||||
|
$query = "title=${escapedTitle}&spaceKey=${Space}&expand=history"
|
||||||
|
|
||||||
|
Invoke-WebRequest `
|
||||||
|
-Uri "https://${Host}/rest/api/content?$query" `
|
||||||
|
-Method 'Get' `
|
||||||
|
-Headers @{
|
||||||
|
'Authorization' = "Bearer $(Get-PersonalAccessToken $Host)"
|
||||||
|
} `
|
||||||
|
-OutVariable response | Out-Null
|
||||||
|
|
||||||
|
$results = ($response.Content | ConvertFrom-JSON).results
|
||||||
|
|
||||||
|
if ($results.Count -gt 1)
|
||||||
|
{
|
||||||
|
throw "more than one result for query: $query"
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($results.Count -eq 1)
|
||||||
|
{
|
||||||
|
Update-PageMeta `
|
||||||
|
-PageId $results[0].id `
|
||||||
|
-Version ($results[0]._expandable | Select -ExpandProperty 'version') `
|
||||||
|
-Title $Title `
|
||||||
|
-Manifest $Manifest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Update-PageMeta
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Register a Confluence page's metadata in the local cache
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Synchronizes the locally cached page metadata (in manifest) with the
|
||||||
|
data stored by the Confluence instance. Therefore it is required to
|
||||||
|
supply a page id, since this is the reference linking the locally
|
||||||
|
cached page to a published instance of a page.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Update-PageMeta `
|
||||||
|
-Title 'foobar' `
|
||||||
|
-PageId 'pageId' `
|
||||||
|
-Version 9001 `
|
||||||
|
-AncestorTitle 'ancestorTitle' `
|
||||||
|
-Hash 'hash' `
|
||||||
|
-Manifest $mockManifest
|
||||||
|
#>
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory)] [String] $Title,
|
||||||
|
[Parameter(Mandatory)] [String] $PageId,
|
||||||
|
[Parameter()] [Int] $Version,
|
||||||
|
[Parameter()] [String] $AncestorTitle,
|
||||||
|
[Parameter()] [String] $Hash,
|
||||||
|
[Parameter(Mandatory)] [Array] $Manifest,
|
||||||
|
[Parameter()] [Collections.Hashtable] $Index
|
||||||
|
)
|
||||||
|
|
||||||
|
Process
|
||||||
|
{
|
||||||
|
$pageMeta = Get-PageMetaCache `
|
||||||
|
-Title $Title `
|
||||||
|
-Manifest $Manifest `
|
||||||
|
-Index $Index
|
||||||
|
|
||||||
|
If (-Not $pageMeta)
|
||||||
|
{
|
||||||
|
throw "page titled `$Title` not indexed in Manifest."
|
||||||
|
}
|
||||||
|
|
||||||
|
$pageMeta.PageId = $PageId
|
||||||
|
|
||||||
|
If ($Version)
|
||||||
|
{
|
||||||
|
$pageMeta.Version = $Version
|
||||||
|
}
|
||||||
|
|
||||||
|
If ($AncestorTitle)
|
||||||
|
{
|
||||||
|
$pageMeta.AncestorTitle = $AncestorTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
# if content didn't update, hash stays the same
|
||||||
|
If ($Hash)
|
||||||
|
{
|
||||||
|
$pageMeta.Hash = $Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Debug "register: $Title -> $PageId"
|
||||||
|
|
||||||
|
$pageMeta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue