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:
Rodweil, Theodor 2023-08-06 18:47:16 +02:00
parent 35c1afdc64
commit 852b4f1d95
No known key found for this signature in database
GPG key ID: F8BC1B0EB1F9CCF5
2 changed files with 455 additions and 0 deletions

View 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'
}
}
}

View 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
}
}