refactor(Page): add test suite and adapt to manifest schema
This commit is contained in:
parent
1cebecaed1
commit
52369d540d
3 changed files with 270 additions and 621 deletions
|
|
@ -1,262 +1,55 @@
|
||||||
#!/usr/bin/env pwsh
|
#!/usr/bin/env pwsh
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
Import-Module (Join-Path $PSScriptRoot 'PSConfluencePublisher.psd1') -Force
|
Import-Module (Join-Path $PSScriptRoot 'PSConfluencePublisher.psd1') -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AfterAll {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Describe 'Get-CachedPageMeta' `
|
|
||||||
{
|
|
||||||
Context 'Parameterized' `
|
|
||||||
{
|
|
||||||
It 'returns page meta when title exists' `
|
|
||||||
{
|
|
||||||
$mockPageName = 'Testitest'
|
|
||||||
|
|
||||||
$mockPageMeta = @{
|
|
||||||
'foo' = 'bar'
|
|
||||||
}
|
|
||||||
|
|
||||||
$mockManifest = @{
|
|
||||||
'pages' = @{
|
|
||||||
$mockPageName = $mockPageMeta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$meta = Get-CachedPageMeta `
|
|
||||||
-Title $mockPageName `
|
|
||||||
-Manifest $mockManifest
|
|
||||||
|
|
||||||
$meta | Should -Be $mockPageMeta
|
|
||||||
}
|
|
||||||
|
|
||||||
It 'returns null of title does not exist' `
|
|
||||||
{
|
|
||||||
$mockPageName = 'Testitest'
|
|
||||||
|
|
||||||
|
|
||||||
$mockManifest = @{
|
|
||||||
'pages' = @{}
|
|
||||||
}
|
|
||||||
|
|
||||||
$meta = Get-CachedPageMeta `
|
|
||||||
-Title $mockPageName `
|
|
||||||
-Manifest $mockManifest
|
|
||||||
|
|
||||||
$meta | Should -Be $null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Describe 'Get-PageMeta' `
|
|
||||||
{
|
|
||||||
Context 'Parameterized' `
|
|
||||||
{
|
|
||||||
It 'returns cache when present' `
|
|
||||||
{
|
|
||||||
InModuleScope Page `
|
|
||||||
{
|
|
||||||
$mockPageMeta = @{
|
|
||||||
'foo' = 'bar'
|
|
||||||
}
|
|
||||||
|
|
||||||
Mock Get-CachedPageMeta {
|
|
||||||
$mockPageMeta
|
|
||||||
}
|
|
||||||
|
|
||||||
$meta = Get-PageMeta `
|
|
||||||
-Host 'foobar' `
|
|
||||||
-Title 'foobar' `
|
|
||||||
-Space 'foobar' `
|
|
||||||
-Manifest @{}
|
|
||||||
|
|
||||||
$meta | Should -Be $mockPageMeta
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
It 'gets a page id remotely if there is exactly one result' `
|
|
||||||
{
|
|
||||||
InModuleScope Page `
|
|
||||||
{
|
|
||||||
$mockPageMeta = @{
|
|
||||||
'PageId' = 'page_id'
|
|
||||||
'Version' = 'version'
|
|
||||||
'Hash' = 'hash'
|
|
||||||
'Ref' = 'ref'
|
|
||||||
}
|
|
||||||
|
|
||||||
Mock Get-PersonalAccessToken {"012345678901234567890"}
|
|
||||||
|
|
||||||
Mock Update-PageMeta {
|
|
||||||
#FIXME: wrong scope
|
|
||||||
Should -Invoke 'Update-PageMeta' -Exactly -Times 1
|
|
||||||
|
|
||||||
$PageId | Should -Be '123'
|
|
||||||
|
|
||||||
$Version | Should -Be 9
|
|
||||||
|
|
||||||
$Title | Should -Be 'foobar'
|
|
||||||
|
|
||||||
$mockPageMeta
|
|
||||||
}
|
|
||||||
|
|
||||||
Mock 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
It 'throws an exception, if there is more than one result' `
|
|
||||||
{
|
|
||||||
InModuleScope Page `
|
|
||||||
{
|
|
||||||
Mock Get-PersonalAccessToken {"012345678901234567890"}
|
|
||||||
|
|
||||||
Mock 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' `
|
|
||||||
{
|
|
||||||
InModuleScope Page `
|
|
||||||
{
|
|
||||||
Mock Get-PersonalAccessToken {"012345678901234567890"}
|
|
||||||
|
|
||||||
Mock Invoke-WebRequest {
|
|
||||||
@{
|
|
||||||
'Content' = '{"results": [{}, {}]}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Get-PageMeta `
|
|
||||||
-Host 'confluence.contoso.com' `
|
|
||||||
-Title 'foobar' `
|
|
||||||
-Space 'foobar' `
|
|
||||||
-Manifest @{'Pages'= {}}
|
|
||||||
} | Should -Throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Describe 'Update-PageMeta' `
|
|
||||||
{
|
|
||||||
Context 'Parameterized' `
|
|
||||||
{
|
|
||||||
It 'fails, if page meta index does not exist' `
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Update-PageMeta `
|
|
||||||
-PageId 'foobar' `
|
|
||||||
-Title 'foobar' `
|
|
||||||
-Manifest @{}
|
|
||||||
} | Should -Throw
|
|
||||||
}
|
|
||||||
|
|
||||||
It 'fails, if page title is not indexed' `
|
|
||||||
{
|
|
||||||
{
|
|
||||||
Update-PageMeta `
|
|
||||||
-PageId 'foobar' `
|
|
||||||
-Title 'foobar' `
|
|
||||||
-Manifest @{'Pages' = @{}}
|
|
||||||
} | Should -Throw
|
|
||||||
}
|
|
||||||
|
|
||||||
It 'updates minimal' `
|
|
||||||
{
|
|
||||||
$mockManifest = @{'Pages' = @{'foobar' = @{}}}
|
|
||||||
|
|
||||||
Update-PageMeta `
|
|
||||||
-Title 'foobar' `
|
|
||||||
-PageId 'pageId' `
|
|
||||||
-Manifest $mockManifest
|
|
||||||
|
|
||||||
$mockManifest.Pages.foobar.PageId | Should -Be 'pageId'
|
|
||||||
}
|
|
||||||
|
|
||||||
It 'updates extended' `
|
|
||||||
{
|
|
||||||
$mockManifest = @{'Pages' = @{'foobar' = @{}}}
|
|
||||||
|
|
||||||
Update-PageMeta `
|
|
||||||
-Title 'foobar' `
|
|
||||||
-PageId 'pageId' `
|
|
||||||
-Version 9001 `
|
|
||||||
-AncestorTitle 'ancestorTitle' `
|
|
||||||
-Hash 'hash' `
|
|
||||||
-Manifest $mockManifest
|
|
||||||
|
|
||||||
$mockManifest.Pages.foobar.PageId | Should -Be 'pageId'
|
|
||||||
|
|
||||||
$mockManifest.Pages.foobar.Version | Should -Be 9001
|
|
||||||
|
|
||||||
$mockManifest.Pages.foobar.AncestorTitle | Should -Be 'ancestorTitle'
|
|
||||||
|
|
||||||
$mockManifest.Pages.foobar.Hash | Should -Be 'hash'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Describe 'New-Page' `
|
Describe 'New-Page' `
|
||||||
{
|
{
|
||||||
Context 'Parameterized' `
|
Context 'default' `
|
||||||
{
|
{
|
||||||
It 'fails, if page meta index does not exist' `
|
BeforeAll `
|
||||||
{
|
{
|
||||||
InModuleScope Page `
|
Mock -ModuleName 'Page' Get-Content {
|
||||||
{
|
'foobar content'
|
||||||
$mockManifest = @{
|
|
||||||
'Pages' = @{
|
|
||||||
'title' = @{
|
|
||||||
'Ref' = 'pages/320okffs.xml'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mock Get-Content {
|
Mock -ModuleName 'Page' Get-PersonalAccessToken {
|
||||||
$Path | Should -Be 'pages/320okffs.xml'
|
|
||||||
|
|
||||||
'foobar'
|
|
||||||
}
|
|
||||||
|
|
||||||
Mock Get-PersonalAccessToken {
|
|
||||||
'01234567890123456789'
|
'01234567890123456789'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mock Invoke-WebRequest {
|
It 'succeeds' `
|
||||||
|
{
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
'Ref' = 'pages/320okffs.xml'
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Get-PageMeta {
|
||||||
|
$mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Update-PageMeta {
|
||||||
|
$Id | Should -Be '123'
|
||||||
|
|
||||||
|
$mockPageMeta.Id = '123'
|
||||||
|
|
||||||
|
$mockPageMeta.Version = 1
|
||||||
|
|
||||||
|
$mockPageMeta.Hash = 'NOTAREALHASH'
|
||||||
|
|
||||||
|
$mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Invoke-WebRequest {
|
||||||
$Uri | Should -Be 'https://confluence.contoso.com/rest/api/content'
|
$Uri | Should -Be 'https://confluence.contoso.com/rest/api/content'
|
||||||
|
|
||||||
$body_ = $Body | ConvertFrom-JSON
|
$body_ = $Body | ConvertFrom-JSON
|
||||||
|
|
@ -265,14 +58,14 @@ Describe 'New-Page' `
|
||||||
|
|
||||||
$body_.body.storage.representation | Should -Be 'storage'
|
$body_.body.storage.representation | Should -Be 'storage'
|
||||||
|
|
||||||
$body_.body.storage.value | Should -Be 'foobar'
|
$body_.body.storage.value | Should -Be 'foobar content'
|
||||||
|
|
||||||
$body_.space.key | Should -Be 'testitest'
|
$body_.space.key | Should -Be 'testitest'
|
||||||
|
|
||||||
$body_.title | Should -Be 'title'
|
$body_.title | Should -Be 'title'
|
||||||
|
|
||||||
@{
|
@{
|
||||||
'Content' = '{"Id": "123", "version": {"number": "1"}}'
|
'Content' = '{"Id": "123", "version": {"number": 1}}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,7 +74,24 @@ Describe 'New-Page' `
|
||||||
-Space 'testitest' `
|
-Space 'testitest' `
|
||||||
-Title 'title' `
|
-Title 'title' `
|
||||||
-Manifest $mockManifest
|
-Manifest $mockManifest
|
||||||
}
|
|
||||||
|
$mockPageMeta.Id | Should -Be "123"
|
||||||
|
|
||||||
|
$mockPageMeta.Version | Should -Be 1
|
||||||
|
|
||||||
|
$mockPageMeta.Hash | Should -Be (
|
||||||
|
'NOTAREALHASH'
|
||||||
|
)
|
||||||
|
|
||||||
|
Should -Invoke -CommandName 'Get-PageMeta' `
|
||||||
|
-ModuleName 'Page' `
|
||||||
|
-Exactly `
|
||||||
|
-Times 1
|
||||||
|
|
||||||
|
Should -Invoke -CommandName 'Update-PageMeta' `
|
||||||
|
-ModuleName 'Page' `
|
||||||
|
-Exactly `
|
||||||
|
-Times 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -289,43 +99,52 @@ Describe 'New-Page' `
|
||||||
|
|
||||||
Describe 'Update-Page' `
|
Describe 'Update-Page' `
|
||||||
{
|
{
|
||||||
Context 'Parameterized' `
|
BeforeAll `
|
||||||
{
|
{
|
||||||
It 'succeeds' `
|
Mock -ModuleName 'Page' Get-Content {
|
||||||
{
|
'foobar content'
|
||||||
InModuleScope Page `
|
|
||||||
{
|
|
||||||
$mockManifest = @{
|
|
||||||
'Pages' = @{
|
|
||||||
'mockTitle' = @{
|
|
||||||
'Ref' = 'pages/320okffs.xml'
|
|
||||||
'Id' = '0123456789'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mock Get-Content {
|
Mock -ModuleName 'Page' Get-PersonalAccessToken {
|
||||||
$Path | Should -Be 'pages/320okffs.xml'
|
|
||||||
|
|
||||||
'foobar'
|
|
||||||
}
|
|
||||||
|
|
||||||
Mock Get-FileHash {
|
|
||||||
$Path | Should -Be 'pages/320okffs.xml'
|
|
||||||
|
|
||||||
$Algorithm | Should -Be 'SHA256'
|
|
||||||
|
|
||||||
@{
|
|
||||||
'Hash' = 'HASH0123456789'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Mock Get-PersonalAccessToken {
|
|
||||||
'01234567890123456789'
|
'01234567890123456789'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mock Invoke-WebRequest {
|
Context 'default' `
|
||||||
$Uri | Should -Be 'https://confluence.contoso.com/rest/api/content/'
|
{
|
||||||
|
BeforeAll `
|
||||||
|
{
|
||||||
|
Mock -ModuleName 'Page' Get-StringHash {
|
||||||
|
@{
|
||||||
|
'Hash' = 'NOTAREALHASH'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'succeeds' `
|
||||||
|
{
|
||||||
|
$mockPageId = '0123456789'
|
||||||
|
|
||||||
|
$mockPageMeta = @{
|
||||||
|
'Title' = 'foobar'
|
||||||
|
'Ref' = 'pages/320okffs.xml'
|
||||||
|
'Id' = $mockPageId
|
||||||
|
'Version' = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Get-PageMeta {
|
||||||
|
$mockPageMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Invoke-WebRequest {
|
||||||
|
$Uri | Should -Be (
|
||||||
|
'https://confluence.contoso.com/rest/api/content/' + `
|
||||||
|
$mockPageId
|
||||||
|
)
|
||||||
|
|
||||||
$body_ = $Body | ConvertFrom-JSON
|
$body_ = $Body | ConvertFrom-JSON
|
||||||
|
|
||||||
|
|
@ -333,59 +152,48 @@ Describe 'Update-Page' `
|
||||||
|
|
||||||
$body_.body.storage.representation | Should -Be 'storage'
|
$body_.body.storage.representation | Should -Be 'storage'
|
||||||
|
|
||||||
$body_.body.storage.value | Should -Be 'foobar'
|
$body_.body.storage.value | Should -Be 'foobar content'
|
||||||
|
|
||||||
$body_.space.key | Should -Be 'testitest'
|
$body_.space.key | Should -Be 'testitest'
|
||||||
|
|
||||||
$body_.title | Should -Be 'mockTitle'
|
$body_.title | Should -Be 'foobar'
|
||||||
|
|
||||||
|
$body_.version.number | Should -Be 4
|
||||||
|
|
||||||
@{
|
@{
|
||||||
'Content' = '{"Id": "123", "version": {"number": 2}}'
|
'Content' = '{"Id": "123", "version": {"number": 4}}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Update-Page `
|
Update-Page `
|
||||||
-Host 'confluence.contoso.com' `
|
-Host 'confluence.contoso.com' `
|
||||||
-Space 'testitest' `
|
-Space 'testitest' `
|
||||||
-Title 'mockTitle' `
|
-Title 'foobar' `
|
||||||
-Manifest $mockManifest
|
-Manifest $mockManifest
|
||||||
|
|
||||||
$mockMeta = $mockManifest.Pages.mockTitle
|
$mockPageMeta.Hash | Should -Be 'NOTAREALHASH'
|
||||||
|
|
||||||
$mockMeta.Hash | Should -Be 'HASH0123456789'
|
$mockPageMeta.Version | Should -Be 4
|
||||||
|
|
||||||
$mockMeta.Version | Should -Be 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'skips, if hash unchanged' `
|
It 'skips, if hash unchanged' `
|
||||||
{
|
{
|
||||||
InModuleScope Page `
|
$mockPageId = '0123456789'
|
||||||
{
|
|
||||||
$mockManifest = @{
|
$mockPageMeta = @{
|
||||||
'Pages' = @{
|
'Title' = 'foobar'
|
||||||
'mockTitle' = @{
|
|
||||||
'Ref' = 'pages/320okffs.xml'
|
'Ref' = 'pages/320okffs.xml'
|
||||||
'Id' = '0123456789'
|
'Id' = $mockPageId
|
||||||
'Hash' = 'HASH0123456789'
|
'Version' = 3
|
||||||
}
|
'Hash' = 'NOTAREALHASH'
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mock Get-Content {
|
$mockManifest = @(
|
||||||
$Path | Should -Be 'pages/320okffs.xml'
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
'foobar'
|
Mock -ModuleName 'Page' Get-PageMeta {
|
||||||
}
|
$mockPageMeta
|
||||||
|
|
||||||
Mock Get-FileHash {
|
|
||||||
$Path | Should -Be 'pages/320okffs.xml'
|
|
||||||
|
|
||||||
$Algorithm | Should -Be 'SHA256'
|
|
||||||
|
|
||||||
@{
|
|
||||||
'Hash' = 'HASH0123456789'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Update-Page `
|
Update-Page `
|
||||||
|
|
@ -394,18 +202,23 @@ Describe 'Update-Page' `
|
||||||
-Title 'mockTitle' `
|
-Title 'mockTitle' `
|
||||||
-Manifest $mockManifest
|
-Manifest $mockManifest
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
It 'fails, if page meta has no reference' `
|
It 'fails, if page meta has no reference' `
|
||||||
{
|
{
|
||||||
InModuleScope Page `
|
$mockPageId = '0123456789'
|
||||||
{
|
|
||||||
$mockManifest = @{
|
$mockPageMeta = @{
|
||||||
'Pages' = @{
|
'Title' = 'foobar'
|
||||||
'mockTitle' = @{
|
'Id' = $mockPageId
|
||||||
'Id' = '0123456789'
|
'Version' = 3
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Get-PageMeta {
|
||||||
|
$mockPageMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -414,20 +227,24 @@ Describe 'Update-Page' `
|
||||||
-Space 'testitest' `
|
-Space 'testitest' `
|
||||||
-Title 'mockTitle' `
|
-Title 'mockTitle' `
|
||||||
-Manifest $mockManifest
|
-Manifest $mockManifest
|
||||||
} | Should -Throw
|
} | Should -Throw "no reference to local content for page*"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'fails, if page meta has no id' `
|
It 'fails, if page meta has no id' `
|
||||||
{
|
{
|
||||||
InModuleScope Page `
|
$mockPageId = '0123456789'
|
||||||
{
|
|
||||||
$mockManifest = @{
|
$mockPageMeta = @{
|
||||||
'Pages' = @{
|
'Title' = 'foobar'
|
||||||
'mockTitle' = @{
|
'Ref' = 'foo/bar'
|
||||||
'Ref' = 'pages/320okffs.xml'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mockManifest = @(
|
||||||
|
$mockPageMeta
|
||||||
|
)
|
||||||
|
|
||||||
|
Mock -ModuleName 'Page' Get-PageMeta {
|
||||||
|
$mockPageMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -436,8 +253,7 @@ Describe 'Update-Page' `
|
||||||
-Space 'testitest' `
|
-Space 'testitest' `
|
||||||
-Title 'mockTitle' `
|
-Title 'mockTitle' `
|
||||||
-Manifest $mockManifest
|
-Manifest $mockManifest
|
||||||
} | Should -Throw
|
} | Should -Throw "no id for page*"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,188 +2,6 @@
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
|
||||||
function Get-CachedPageMeta
|
|
||||||
{
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Get a locally indexed/cached Confluence page id
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Get-CachedPageMeta `
|
|
||||||
-Title 'Page Title' `
|
|
||||||
-Manifest @{...}
|
|
||||||
|
|
||||||
.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)] [Collections.Hashtable] $Manifest
|
|
||||||
)
|
|
||||||
|
|
||||||
Process
|
|
||||||
{
|
|
||||||
#it's fine this fails, if no `Pages` property is provided, since the
|
|
||||||
#object (according to the schema) would be invalid anyway.
|
|
||||||
$pages = $Manifest | Select -ExpandProperty 'Pages'
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$pageMeta = $pages | Select -ExpandProperty $Title
|
|
||||||
|
|
||||||
Write-Debug "page id cache hit: $Title -> $($pageMeta.PageId)"
|
|
||||||
|
|
||||||
$pageMeta
|
|
||||||
}
|
|
||||||
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Write-Debug "page id cache miss: $Title"
|
|
||||||
|
|
||||||
$null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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)] [Collections.Hashtable] $Manifest
|
|
||||||
)
|
|
||||||
|
|
||||||
Process
|
|
||||||
{
|
|
||||||
if ($Title)
|
|
||||||
{
|
|
||||||
$cachedPageMeta = Get-CachedPageMeta `
|
|
||||||
-Title $Title `
|
|
||||||
-Manifest $Manifest
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cachedPageMeta)
|
|
||||||
{
|
|
||||||
return $cachedPageMeta
|
|
||||||
}
|
|
||||||
|
|
||||||
$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
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
Add-ConfluencePage
|
|
||||||
-Host 'confluence.contoso.com' `
|
|
||||||
-Space 'TIARA' `
|
|
||||||
-Title 'Testitest' `
|
|
||||||
-Content @{}
|
|
||||||
#>
|
|
||||||
Param(
|
|
||||||
[Parameter(Mandatory)] [string] $Title,
|
|
||||||
[Parameter(Mandatory)] [string] $PageId,
|
|
||||||
[Parameter()] [int] $Version,
|
|
||||||
[Parameter()] [string] $AncestorTitle,
|
|
||||||
[Parameter()] [string] $Hash,
|
|
||||||
[Parameter(Mandatory)] [Collections.Hashtable] $Manifest
|
|
||||||
)
|
|
||||||
|
|
||||||
Process
|
|
||||||
{
|
|
||||||
$metaPages = $Manifest.Pages
|
|
||||||
|
|
||||||
if ((-Not $metaPages) -Or (-Not $metaPages.$Title))
|
|
||||||
{
|
|
||||||
throw "page titled `$Title` not indexed in Manifest."
|
|
||||||
}
|
|
||||||
|
|
||||||
$meta = $metaPages.$Title
|
|
||||||
|
|
||||||
$meta['PageId'] = $PageId
|
|
||||||
|
|
||||||
if ($Version)
|
|
||||||
{
|
|
||||||
$meta['Version'] = $Version
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($AncestorTitle)
|
|
||||||
{
|
|
||||||
$meta['AncestorTitle'] = $AncestorTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
# if content didn't update, hash stays the same
|
|
||||||
if ($Hash)
|
|
||||||
{
|
|
||||||
$meta['Hash'] = $Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Debug "register: $Title -> $PageId"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function New-Page
|
function New-Page
|
||||||
{
|
{
|
||||||
<#
|
<#
|
||||||
|
|
@ -206,20 +24,27 @@ function New-Page
|
||||||
[Parameter(Mandatory)] [string] $Space,
|
[Parameter(Mandatory)] [string] $Space,
|
||||||
# title of page to be published
|
# title of page to be published
|
||||||
[Parameter(Mandatory)] [string] $Title,
|
[Parameter(Mandatory)] [string] $Title,
|
||||||
# manifest
|
# pages manifest
|
||||||
[Parameter(Mandatory)] [Collections.Hashtable] $Manifest
|
[Parameter(Mandatory)] [Array] $Manifest,
|
||||||
|
# pages manifest index
|
||||||
|
[Parameter()] [Collections.Hashtable] $Index
|
||||||
)
|
)
|
||||||
|
|
||||||
Process
|
Process
|
||||||
{
|
{
|
||||||
$meta = $Manifest.Pages.$Title
|
$pageMeta = Get-PageMeta `
|
||||||
|
-Host $Host `
|
||||||
|
-Space $Space `
|
||||||
|
-Title $Title `
|
||||||
|
-Manifest $Manifest `
|
||||||
|
-Index $Index
|
||||||
|
|
||||||
if (-Not $meta.Ref)
|
if (-Not $pageMeta.Ref)
|
||||||
{
|
{
|
||||||
throw "no reference to local content for page `$Title`."
|
throw "no reference to local content for page `$Title`."
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = Get-Content -Path $meta.Ref
|
$content = Get-Content -Path $pageMeta.Ref
|
||||||
|
|
||||||
$transportBody = @{
|
$transportBody = @{
|
||||||
'type' = 'page'
|
'type' = 'page'
|
||||||
|
|
@ -250,11 +75,13 @@ function New-Page
|
||||||
{
|
{
|
||||||
$response = ($rawResponse.Content | ConvertFrom-JSON)
|
$response = ($rawResponse.Content | ConvertFrom-JSON)
|
||||||
|
|
||||||
$meta.PageId = $response.Id
|
Update-PageMeta `
|
||||||
|
-Title $Title `
|
||||||
$meta.Version = $response.version | Select -ExpandProperty 'number'
|
-Id $response.Id `
|
||||||
|
-Version $response.version.number `
|
||||||
$meta
|
-Hash (Get-StringHash $content).Hash `
|
||||||
|
-Manifest $Manifest `
|
||||||
|
-Index $Index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,30 +107,36 @@ function Update-Page
|
||||||
[Parameter(Mandatory)] [string] $Space,
|
[Parameter(Mandatory)] [string] $Space,
|
||||||
# title of page to be published
|
# title of page to be published
|
||||||
[Parameter(Mandatory)] [string] $Title,
|
[Parameter(Mandatory)] [string] $Title,
|
||||||
# manifest
|
# pages manifest
|
||||||
[Parameter(Mandatory)] [Collections.Hashtable] $Meta
|
[Parameter(Mandatory)] [Array] $Manifest,
|
||||||
|
# pages manifest index
|
||||||
|
[Parameter()] [Collections.Hashtable] $Index
|
||||||
)
|
)
|
||||||
|
|
||||||
Process
|
Process
|
||||||
{
|
{
|
||||||
$meta = $Manifest.Pages.$Title
|
$pageMeta = Get-PageMeta `
|
||||||
|
-Host $Host `
|
||||||
|
-Space $Space `
|
||||||
|
-Title $Title `
|
||||||
|
-Manifest $Manifest `
|
||||||
|
-Index $Index
|
||||||
|
|
||||||
if (-Not $meta.Ref)
|
if (-Not $pageMeta.Ref)
|
||||||
{
|
{
|
||||||
throw "no reference to local content for page '$Title'."
|
throw "no reference to local content for page '$Title'."
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-Not $meta.Id)
|
if (-Not $pageMeta.Id)
|
||||||
{
|
{
|
||||||
throw "no id for page '$Title'."
|
throw "no id for page '$Title'."
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = Get-Content -Path $meta.Ref
|
$content = Get-Content -Path $pageMeta.Ref
|
||||||
|
|
||||||
#FIXME: create a stream instead of reading from filesystem again
|
$hash = (Get-StringHash $content).Hash
|
||||||
$hash = (Get-FileHash -Path $meta.Ref -Algorithm SHA256).Hash
|
|
||||||
|
|
||||||
if ($hash -eq $meta.Hash)
|
if ($hash -eq $pageMeta.Hash)
|
||||||
{
|
{
|
||||||
Write-Host "content unchanged, skipping: '$Title'"
|
Write-Host "content unchanged, skipping: '$Title'"
|
||||||
|
|
||||||
|
|
@ -316,10 +149,10 @@ function Update-Page
|
||||||
|
|
||||||
# we're not updating this in place, so that we don't have to reset the
|
# we're not updating this in place, so that we don't have to reset the
|
||||||
# value opon failure
|
# value opon failure
|
||||||
$version = $meta.Version + 1
|
$version = $pageMeta.Version + 1
|
||||||
|
|
||||||
$transportBody = @{
|
$transportBody = @{
|
||||||
'id' = $PageId
|
'id' = $PageMeta.Id
|
||||||
'type' = 'page'
|
'type' = 'page'
|
||||||
'title' = $Title
|
'title' = $Title
|
||||||
'space' = @{
|
'space' = @{
|
||||||
|
|
@ -327,7 +160,7 @@ function Update-Page
|
||||||
}
|
}
|
||||||
'body' = @{
|
'body' = @{
|
||||||
'storage' = @{
|
'storage' = @{
|
||||||
'value' = $Content
|
'value' = $content
|
||||||
'representation' = 'storage'
|
'representation' = 'storage'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -337,7 +170,7 @@ function Update-Page
|
||||||
} | ConvertTo-JSON
|
} | ConvertTo-JSON
|
||||||
|
|
||||||
Invoke-WebRequest `
|
Invoke-WebRequest `
|
||||||
-Uri "https://${Host}/rest/api/content/$PageId" `
|
-Uri "https://${Host}/rest/api/content/$($PageMeta.Id)" `
|
||||||
-Method 'Put' `
|
-Method 'Put' `
|
||||||
-Headers @{
|
-Headers @{
|
||||||
'Authorization' = "Bearer $(Get-PersonalAccessToken $Host)"
|
'Authorization' = "Bearer $(Get-PersonalAccessToken $Host)"
|
||||||
|
|
@ -351,11 +184,13 @@ function Update-Page
|
||||||
{
|
{
|
||||||
$response = ($rawResponse.Content | ConvertFrom-JSON)
|
$response = ($rawResponse.Content | ConvertFrom-JSON)
|
||||||
|
|
||||||
$meta.Version = $response.version | Select -ExpandProperty 'number'
|
Update-PageMeta `
|
||||||
|
-Title $Title `
|
||||||
$meta.Hash = $hash
|
-Id $pageMeta.Id `
|
||||||
|
-Version $response.version.number `
|
||||||
$meta
|
-Hash $hash `
|
||||||
|
-Manifest $Manifest `
|
||||||
|
-Index $Index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -439,8 +274,6 @@ function Publish-Page
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,24 +171,24 @@ Describe 'Get-PageMeta' `
|
||||||
-Title 'foobar' `
|
-Title 'foobar' `
|
||||||
-Space 'foobar' `
|
-Space 'foobar' `
|
||||||
-Manifest @{'Pages'= {}}
|
-Manifest @{'Pages'= {}}
|
||||||
} | Should -Throw
|
} | Should -Throw 'more than one result for query*'
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'throws an exception, if there is no result' `
|
It 'throws an exception, if there is no result' `
|
||||||
{
|
{
|
||||||
Mock Invoke-WebRequest {
|
Mock -ModuleName 'PageMeta' Invoke-WebRequest {
|
||||||
@{
|
@{
|
||||||
'Content' = '{"results": []}'
|
'Content' = '{"results": []}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
$result = Get-PageMeta `
|
||||||
Get-PageMeta `
|
|
||||||
-Host 'confluence.contoso.com' `
|
-Host 'confluence.contoso.com' `
|
||||||
-Title 'foobar' `
|
-Title 'foobar' `
|
||||||
-Space 'foobar' `
|
-Space 'foobar' `
|
||||||
-Manifest @{'Pages'= {}}
|
-Manifest @{'Pages'= {}}
|
||||||
} | Should -Throw
|
|
||||||
|
$result | Should -Be $null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue