Tests/GitHubContents.tests.ps1
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. <# .Synopsis Tests for GitHubContents.ps1 module #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification='Suppress false positives in Pester code blocks')] param() # This is common test code setup logic for all Pester test files $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent . (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1') try { # Define Script-scoped, readonly, hidden variables. @{ repoGuid = [Guid]::NewGuid().Guid readmeFileName = "README.md" }.GetEnumerator() | ForEach-Object { Set-Variable -Force -Scope Script -Option ReadOnly -Visibility Private -Name $_.Key -Value $_.Value } # Need two separate blocks to set constants because we need to reference a constant from the first block in this block. @{ htmlOutputStart = '<div id="file" class="md" data-path="README.md">' rawOutput = "# $repoGuid" }.GetEnumerator() | ForEach-Object { Set-Variable -Force -Scope Script -Option ReadOnly -Visibility Private -Name $_.Key -Value $_.Value } Describe 'Getting file and folder content' { BeforeAll { # AutoInit will create a readme with the GUID of the repo name $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit } AfterAll { Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false } Context 'For getting folder contents with parameters' { $folderOutput = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name It "Should have the expected name" { $folderOutput.name | Should -BeNullOrEmpty } It "Should have the expected path" { $folderOutput.path | Should -BeNullOrEmpty } It "Should have the expected type" { $folderOutput.type | Should -Be "dir" } It "Should have the expected entries" { $folderOutput.entries.length | Should -Be 1 } It "Should have the expected entry data" { $folderOutput.entries[0].name | Should -Be $readmeFileName $folderOutput.entries[0].path | Should -Be $readmeFileName } It "Should have the expected type and additional properties" { $folderOutput.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $folderOutput.RepositoryUrl | Should -Be $repo.RepositoryUrl } } Context 'For getting folder contents via URL' { $folderOutput = Get-GitHubContent -Uri "https://github.com/$($script:ownerName)/$($repo.name)" It "Should have the expected name" { $folderOutput.name | Should -BeNullOrEmpty } It "Should have the expected path" { $folderOutput.path | Should -BeNullOrEmpty } It "Should have the expected type" { $folderOutput.type | Should -Be "dir" } It "Should have the expected entries" { $folderOutput.entries.length | Should -Be 1 } It "Should have the expected entry data" { $folderOutput.entries[0].name | Should -Be $readmeFileName $folderOutput.entries[0].path | Should -Be $readmeFileName } It "Should have the expected type" { $folderOutput.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $folderOutput.RepositoryUrl | Should -Be $repo.RepositoryUrl } } Context 'For getting folder contents with the repo on the pipeline' { $folderOutput = $repo | Get-GitHubContent It "Should have the expected name" { $folderOutput.name | Should -BeNullOrEmpty } It "Should have the expected path" { $folderOutput.path | Should -BeNullOrEmpty } It "Should have the expected type" { $folderOutput.type | Should -Be "dir" } It "Should have the expected entries" { $folderOutput.entries.length | Should -Be 1 } It "Should have the expected entry data" { $folderOutput.entries[0].name | Should -Be $readmeFileName $folderOutput.entries[0].path | Should -Be $readmeFileName } It "Should have the expected type" { $folderOutput.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $folderOutput.RepositoryUrl | Should -Be $repo.RepositoryUrl } } Context 'For getting raw (byte) file contents' { $readmeFileBytes = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name -Path $readmeFileName -MediaType Raw $readmeFileString = [System.Text.Encoding]::UTF8.GetString($readmeFileBytes) It "Should have the expected content" { $readmeFileString | Should -Be $rawOutput } It "Should have the expected type" { $readmeFileString.PSObject.TypeNames[0] | Should -Not -Be 'GitHub.Content' $readmeFileString.RepositoryUrl | Should -BeNullOrEmpty } } Context 'For getting raw (string) file contents' { $readmeFileString = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name -Path $readmeFileName -MediaType Raw -ResultAsString It "Should have the expected content" { $readmeFileString | Should -Be $rawOutput } It "Should have the expected type" { $readmeFileString.PSObject.TypeNames[0] | Should -Not -Be 'GitHub.Content' $readmeFileString.RepositoryUrl | Should -BeNullOrEmpty } } Context 'For getting html (byte) file contents' { $readmeFileBytes = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name -Path $readmeFileName -MediaType Html $readmeFileString = [System.Text.Encoding]::UTF8.GetString($readmeFileBytes) # Replace newlines with empty for comparison purposes $readmeNoBreaks = $readmeFileString.Replace("`n", "").Replace("`r", "") It "Should have the expected content" { # GitHub changes the syntax for this file too frequently, so we'll just do some # partial matches to make sure we're getting HTML output for the right repo. $readmeNoBreaks.StartsWith($htmlOutputStart) | Should -BeTrue $readmeNoBreaks.IndexOf($repoGuid) | Should -BeGreaterOrEqual 0 } It "Should have the expected type" { $readmeNoBreaks.PSObject.TypeNames[0] | Should -Not -Be 'GitHub.Content' $readmeNoBreaks.RepositoryUrl | Should -BeNullOrEmpty } } Context 'For getting html (string) file contents' { $readmeFileString = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name -Path $readmeFileName -MediaType Html -ResultAsString # Replace newlines with empty for comparison purposes $readmeNoBreaks = $readmeFileString.Replace("`n", "").Replace("`r", "") It "Should have the expected content" { # GitHub changes the syntax for this file too frequently, so we'll just do some # partial matches to make sure we're getting HTML output for the right repo. $readmeNoBreaks.StartsWith($htmlOutputStart) | Should -BeTrue $readmeNoBreaks.IndexOf($repoGuid) | Should -BeGreaterOrEqual 0 } It "Should have the expected type" { $readmeFileString.PSObject.TypeNames[0] | Should -Not -Be 'GitHub.Content' $readmeFileString.RepositoryUrl | Should -BeNullOrEmpty } } Context 'For getting object (default) file result' { $readmeFileObject = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name -Path $readmeFileName It "Should have the expected name" { $readmeFileObject.name | Should -Be $readmeFileName } It "Should have the expected path" { $readmeFileObject.path | Should -Be $readmeFileName } It "Should have the expected type" { $readmeFileObject.type | Should -Be "file" } It "Should have the expected encoding" { $readmeFileObject.encoding | Should -Be "base64" } It "Should have the expected content" { # Convert from base64 $readmeFileString = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($readmeFileObject.content)) $readmeFileString | Should -Be $rawOutput } It "Should have the expected type" { $readmeFileObject.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $readmeFileObject.RepositoryUrl | Should -Be $repo.RepositoryUrl } } Context 'For getting object file result as string' { $readmeFileObject = Get-GitHubContent -OwnerName $script:ownerName -RepositoryName $repo.name -Path $readmeFileName -MediaType Object -ResultAsString It "Should have the expected name" { $readmeFileObject.name | Should -Be $readmeFileName } It "Should have the expected path" { $readmeFileObject.path | Should -Be $readmeFileName } It "Should have the expected type" { $readmeFileObject.type | Should -Be "file" } It "Should have the expected encoding" { $readmeFileObject.encoding | Should -Be "base64" } It "Should have the expected content" { $readmeFileObject.contentAsString | Should -Be $rawOutput } It "Should have the expected type" { $readmeFileObject.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $readmeFileObject.RepositoryUrl | Should -Be $repo.RepositoryUrl } } } Describe 'GitHubContents/Set-GitHubContent' { BeforeAll { $repoName = [Guid]::NewGuid().Guid $repo = New-GitHubRepository -RepositoryName $repoName -AutoInit } Context 'When setting new file content' { BeforeAll { $filePath = 'notes' $fileName = 'hello.txt' $commitMessage = 'Commit Message' $content = 'This is the content for test.txt' $branchName = 'master' $committerName = 'John Doe' $committerEmail = 'john.doe@testdomain.com' $authorName = 'Jane Doe' $authorEmail = 'jane.doe@testdomain.com' $setGitHubContentParms = @{ Path = "$filePath/$fileName" CommitMessage = $commitMessage Branch = $branchName Content = $content Uri = $repo.svn_url CommitterName = $committerName CommitterEmail = $committerEmail authorName = $authorName authorEmail = $authorEmail } $result = Set-GitHubContent @setGitHubContentParms -PassThru } It 'Should have the expected type and additional properties' { $result.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $result.content.name | Should -Be $fileName $result.content.path | Should -Be "$filePath/$fileName" $result.content.url | Should -Be ("https://api.github.com/repos/$($script:ownerName)" + "/$repoName/contents/$filePath/$($fileName)?ref=$BranchName") $result.commit.author.name | Should -Be $authorName $result.commit.author.email | Should -Be $authorEmail $result.commit.committer.name | Should -Be $committerName $result.commit.committer.email | Should -Be $committerEmail $result.commit.message | Should -Be $commitMessage } It 'Should have written the correct content' { $getGitHubContentParms = @{ Path = "$filePath/$fileName" Uri = $repo.svn_url MediaType = 'Raw' ResultAsString = $true } $writtenContent = Get-GitHubContent @getGitHubContentParms $content | Should -Be $writtenContent } It 'Should support pipeline input' { $getGitHubContentParms = @{ Path = "$filePath/$fileName" Uri = $repo.svn_url } $writtenContent = Get-GitHubContent @getGitHubContentParms $setGitHubContentParms = @{ CommitMessage = $commitMessage Content = $content CommitterName = $committerName CommitterEmail = $committerEmail authorName = $authorName authorEmail = $authorEmail } { $writtenContent | Set-GitHubContent @setGitHubContentParms -WhatIf } | Should -Not -Throw } } Context 'When overwriting file content' { BeforeAll { $filePath = 'notes' $fileName = 'hello.txt' $commitMessage = 'Commit Message 2' $content = 'This is the new content for test.txt' $branchName = 'master' $committerName = 'John Doe' $committerEmail = 'john.doe@testdomain.com' $authorName = 'Jane Doe' $authorEmail = 'jane.doe@testdomain.com' $setGitHubContentParms = @{ Path = "$filePath/$fileName" CommitMessage = $commitMessage BranchName = $branchName Content = $content Uri = $repo.svn_url CommitterName = $committerName CommitterEmail = $committerEmail authorName = $authorName authorEmail = $authorEmail } $result = Set-GitHubContent @setGitHubContentParms -PassThru } It 'Should have the expected type and additional properties' { $result.PSObject.TypeNames[0] | Should -Be 'GitHub.Content' $result.content.name | Should -Be $fileName $result.content.path | Should -Be "$filePath/$fileName" $result.content.url | Should -Be ("https://api.github.com/repos/$($script:ownerName)" + "/$repoName/contents/$filePath/$($fileName)?ref=$BranchName") $result.commit.author.name | Should -Be $authorName $result.commit.author.email | Should -Be $authorEmail $result.commit.committer.name | Should -Be $committerName $result.commit.committer.email | Should -Be $committerEmail $result.commit.message | Should -Be $commitMessage } It 'Should have written the correct content' { $getGitHubContentParms = @{ Path = "$filePath/$fileName" Uri = $repo.svn_url MediaType = 'Raw' ResultAsString = $true } $writtenContent = Get-GitHubContent @getGitHubContentParms $content | Should -Be $writtenContent } } Context 'When Specifying only one Committer parameter' { $setGitHubContentParms = @{ Path = "$filePath/$fileName" CommitMessage = $commitMessage BranchName = $branchName Content = $content Uri = $repo.svn_url CommitterName = $committerName } It 'Shoud throw the correct exception' { $errorMessage = 'Both CommiterName and CommitterEmail need to be specified.' { Set-GitHubContent @setGitHubContentParms } | Should -Throw $errorMessage } } Context 'When Specifying only one Author parameter' { $setGitHubContentParms = @{ Path = "$filePath/$fileName" Uri = $repo.svn_url CommitMessage = $commitMessage BranchName = $branchName Content = $content AuthorName = $authorName } It 'Shoud throw the correct exception' { $errorMessage = 'Both AuthorName and AuthorEmail need to be specified.' { Set-GitHubContent @setGitHubContentParms } | Should -Throw $errorMessage } } Context 'When Invoke-GHRestMethod returns an unexpected error' { It 'Should throw' { $setGitHubContentParms = @{ Path = "$filePath/$fileName" OwnerName = $script:ownerName RepositoryName = 'IncorrectRepositoryName' BranchName = $branchName CommitMessage = $commitMessage Content = $content } { Set-GitHubContent @setGitHubContentParms } | Should -Throw } } AfterAll { Remove-GitHubRepository -Uri $repo.svn_url -Force } } } finally { if (Test-Path -Path $script:originalConfigFile -PathType Leaf) { # Restore the user's configuration to its pre-test state Restore-GitHubConfiguration -Path $script:originalConfigFile $script:originalConfigFile = $null } } |