PowerShellForGitHub/Tests/GitHubCodespaces.tests.ps1

451 строка
17 KiB
PowerShell
Исходник Постоянная ссылка Обычный вид История

Add support for codespaces (#407) Adds initial support for GitHub Codespaces. #### References Endpoints ~~excluded~~ below will be added in subsequent PRs **[Codespaces/codespaces](https://docs.github.com/en/rest/codespaces/codespaces)** - [x] [List codespaces in a repository for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#list-codespaces-in-a-repository-for-the-authenticated-user) - [x] [Create a codespace in a repository](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#create-a-codespace-in-a-repository) ~~[List devcontainer configurations in a repository for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#list-devcontainer-configurations-in-a-repository-for-the-authenticated-user)~~ ~~[Get default attributes for a codespace](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#get-default-attributes-for-a-codespace)~~ - [x] [Create a codespace from a pull request](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#create-a-codespace-from-a-pull-request) - [x] [List codespaces for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#list-codespaces-for-the-authenticated-user) - [x] [Create a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#create-a-codespace-for-the-authenticated-user) - [x] [Get a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#get-a-codespace-for-the-authenticated-user) ~~[Update a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#update-a-codespace-for-the-authenticated-user)~~ - [x] [Delete a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#delete-a-codespace-for-the-authenticated-user) ~~[Export a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#export-a-codespace-for-the-authenticated-user)~~ ~~[Get details about a codespace export](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#get-details-about-a-codespace-export)~~ ~~[Create a repository from an unpublished codespace](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#create-a-repository-from-an-unpublished-codespace)~~ - [x] [Start a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#start-a-codespace-for-the-authenticated-user) - [x] [Stop a codespace for the authenticated user](https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#stop-a-codespace-for-the-authenticated-user) **[Codespaces/organizations](https://docs.github.com/en/rest/codespaces/organizations)** - [x] [List codespaces for the organization](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#list-codespaces-for-the-organization) ~~[Manage access control for organization codespaces](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#manage-access-control-for-organization-codespaces)~~ ~~[Add users to Codespaces billing for an organization](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#add-users-to-codespaces-billing-for-an-organization)~~ ~~[Removes users from Codespaces billing for an organization](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#removes-users-from-codespaces-billing-for-an-organization)~~ - [x] [List codespaces for a user in organization](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#list-codespaces-for-a-user-in-organization) - [x] [Delete a codespace from the organization](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#delete-a-codespace-from-the-organization) ~~[Stop a codespace for an organization user](https://docs.github.com/en/rest/codespaces/organizations?apiVersion=2022-11-28#stop-a-codespace-for-an-organization-user)~~
2023-08-29 20:21:13 +03:00
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
<#
.Synopsis
Tests for GitHubCodespaces.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
BeforeAll {
$moduleRootPath = Split-Path -Path $PSScriptRoot -Parent
. (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1')
# Define Script-scoped, readonly, hidden variables.
@{
defaultRepositoryName = ([Guid]::NewGuid().Guid)
}.GetEnumerator() | ForEach-Object {
Set-Variable -Force -Scope Script -Option ReadOnly -Visibility Private -Name $_.Key -Value $_.Value
}
$newGitHubRepositoryParms = @{
AutoInit = $true
Private = $true
RepositoryName = $defaultRepositoryName
OrganizationName = $script:organizationName
}
$repo = New-GitHubRepository @newGitHubRepositoryParms
# Get the main/master branch name
$mainBranchName = $repo | Get-GitHubRepositoryBranch | Select-Object -ExpandProperty name -First 1
}
Describe 'GitHubCodespaces\Delete-GitHubCodespace' {
Context 'When deleting a codespace for the authenticated user' {
BeforeEach {
# Suppress HTTP 202 warning for codespace creation
# TODO: Suppression is not working as intended here.
$WarningPreference = 'SilentlyContinue'
$newGitHubCodespaceParms = @{
OwnerName = $repo.owner.login
RepositoryName = $defaultRepositoryName
}
$codespace = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
It 'Should get no content using -Confirm:$false' {
# Also asserts pipeline input
$codespace | Remove-GitHubCodespace -Confirm:$false
{ Get-GitHubCodespace -CodespaceName $codespace.name } | Should -Throw
}
It 'Should get no content using -Force' {
# Also assert CodespaceName input
Remove-GitHubCodespace -CodespaceName $codespace.name -Force
{ Get-GitHubCodespace -CodespaceName $codespace.name } | Should -Throw
}
}
}
Describe 'GitHubCodespaces\Get-GitHubCodespace' {
BeforeAll {
# Suppress HTTP 202 warning for codespace creation
$WarningPreference = 'SilentlyContinue'
$newGitHubCodespaceParms = @{
OwnerName = $repo.owner.login
RepositoryName = $defaultRepositoryName
}
$null = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
Context 'When getting codespaces for the authenticated user' {
BeforeAll {
$codespaces = Get-GitHubCodespace |
Where-Object { $_.repository.name -eq $defaultRepositoryName }
}
It 'Should return objects of the correct type' {
$codespaces[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Codespace'
}
It 'Should return one or more results' {
@($codespaces | Where-Object { $_ }).Count | Should -BeGreaterOrEqual 1
}
It 'Should return the correct properties' {
foreach ($codespace in $codespaces)
{
$codespace.owner.login | Should -Be $script:OwnerName
$codespace.repository.name | Should -Be $newGitHubCodespaceParms.RepositoryName
}
}
}
Context 'When getting a codespace for a specified owner and repository' {
BeforeAll {
$codespaces = Get-GitHubCodespace @newGitHubCodespaceParms
}
It 'Should return objects of the correct type' {
$codespaces[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Codespace'
}
It 'Should return one or more results' {
@($codespaces | Where-Object { $_ }).Count | Should -BeGreaterOrEqual 1
}
It 'Should return the correct properties' {
foreach ($codespace in $codespaces)
{
$codespace.owner.login | Should -Be $script:OwnerName
$codespace.repository.name | Should -Be $newGitHubCodespaceParms.RepositoryName
}
}
}
Context 'When getting a codespace for a specified organization user' {
BeforeAll {
$codespaces = Get-GitHubCodespace -OrganizationName $script:organizationName
$userCodespaces = Get-GitHubCodespace -OrganizationName $script:organizationName -UserName $script:OwnerName
}
It 'Should have results for the organization user' {
$userCodespaces.name | Should -BeIn $codespaces.name
}
It 'Should return the correct properties' {
foreach ($codespace in $userCodespaces)
{
$codespace.owner.login | Should -Be $script:OwnerName
}
}
}
Context 'When getting a codespace for a specified codespace name' {
BeforeAll {
$codespaces = Get-GitHubCodespace
$codespace = Get-GitHubCodespace -CodespaceName $codespaces[0].name
}
It 'Should return objects of the correct type' {
$codespace.PSObject.TypeNames[0] | Should -Be 'GitHub.Codespace'
}
It 'Should return the correct properties' {
$codespace.owner.login | Should -Be $script:OwnerName
}
}
Context 'When specifiying the Uri parameter' {
BeforeAll {
$codespace = Get-GitHubCodespace -Uri $repo.RepositoryUrl
}
It 'Should return objects of the correct type' {
$codespace.PSObject.TypeNames[0] | Should -Be 'GitHub.Codespace'
}
It 'Should return the correct properties' {
$codespace.owner.login | Should -Be $script:OwnerName
$codespace.repository.name | Should -Be $repo.name
}
}
Context "When specifiying the Uri parameter from the pipeline" {
BeforeAll {
$codespace = $repo | Get-GitHubCodespace
}
It 'Should return objects of the correct type' {
$codespace.PSObject.TypeNames[0] | Should -Be 'GitHub.Codespace'
}
It 'Should return the correct properties' {
$codespace.repository.name | Should -Be $repo.name
}
}
AfterAll {
Get-GitHubCodespace @newGitHubCodespaceParms | Remove-GitHubCodespace -Confirm:$false -Force
}
}
Describe 'GitHubCodespaces\New-GitHubCodespace' {
Context -Name 'When creating a repository for the authenticated user' {
Context -Name 'When creating a codespace with default settings with RepositoryId' {
BeforeAll {
$newGitHubCodespaceParms = @{
RepositoryId = $repo.Id
}
$codespace = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
It 'Should return an object of the correct type' {
$codespace | Should -BeOfType PSCustomObject
}
It 'Should return the correct properties' {
$codespace.display_name | Should -Not -BeNullOrEmpty
$codespace.repository.name | Should -Be $repo.name
$codespace.owner.UserName | Should -Be $script:OwnerName
$codespace.template | Should -BeNullOrEmpty
}
AfterAll {
if ($codespace)
{
Remove-GitHubCodespace -CodespaceName $codespace.name -Confirm:$false
}
}
}
Context -Name 'When creating a codespace with default settings with Ref' {
BeforeAll {
$prBranchName = 'testCodespaceByRef'
$prBranch = $repo | New-GitHubRepositoryBranch -BranchName $mainBranchName -TargetBranchName $prBranchName
$setContentParms = @{
Path = 'README.md'
Content = 'When creating a codespace with default settings with Ref'
CommitMessage = $prBranchName
BranchName = $prBranchName
}
$repo | Set-GitHubContent @setContentParms
$pullRequest = $prBranch | New-GitHubPullRequest -Title $prBranchName -Head $prBranchName -Base $mainBranchName
$newGitHubCodespaceParms = @{
Ref = $pullRequest.head.ref
RepositoryId = $repo.Id
}
$codespace = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
It 'Should return an object of the correct type' {
$codespace | Should -BeOfType PSCustomObject
}
It 'Should return the correct properties' {
$codespace.display_name | Should -Not -BeNullOrEmpty
$codespace.git_status.ref | Should -Be $pullRequest.head.ref
$codespace.repository.name | Should -Be $repo.name
$codespace.owner.UserName | Should -Be $script:OwnerName
$codespace.template | Should -BeNullOrEmpty
}
AfterAll {
if ($codespace)
{
Remove-GitHubCodespace -CodespaceName $codespace.name -Confirm:$false
}
}
}
Context -Name 'When creating a codespace with default settings from a PullRequest' {
BeforeAll {
$prBranchName = 'testCodespaceFromPR'
$prBranch = $repo | New-GitHubRepositoryBranch -BranchName $mainBranchName -TargetBranchName $prBranchName
$setContentParms = @{
Path = 'README.md'
Content = 'When creating a codespace with default settings from a PullRequest'
CommitMessage = $prBranchName
BranchName = $prBranchName
}
$repo | Set-GitHubContent @setContentParms
$pullRequest = $prBranch | New-GitHubPullRequest -Title $prBranchName -Head $prBranchName -Base $mainBranchName
$newGitHubCodespaceParms = @{
PullRequest = $pullRequest.number
RepositoryId = $repo.Id
}
$codespace = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
It 'Should return an object of the correct type' {
$codespace | Should -BeOfType PSCustomObject
}
It 'Should return the correct properties' {
$codespace.display_name | Should -Not -BeNullOrEmpty
$codespace.repository.name | Should -Be $repo.name
$codespace.owner.UserName | Should -Be $script:OwnerName
$codespace.pulls_url | Should -Be $pullRequest.url
$codespace.template | Should -BeNullOrEmpty
}
AfterAll {
if ($codespace)
{
Remove-GitHubCodespace -CodespaceName $codespace.name -Confirm:$false
}
}
}
Context -Name 'When creating a codespace with all possible settings' {
BeforeAll {
$newGitHubCodespaceParms = @{
# ClientIp = 'TODO ???? - should be instead of rather than in addition to Geo, perhaps add some param validation to the function'
# DevContainerPath = 'Will add to test in the future when Get-GitHubDevContainer is implemented and the test repo includes one'
DisplayName = 'PowerShellForGitHub pester test'
Geo = 'UsWest' # location was deprecated in favor of Geo
Machine = 'basicLinux32gb'
NoMultipleRepoPermissions = $true # Not sure how to assert this, but this proves it accepts the switch without error
IdleRetentionPeriodMinutes = 10
TimeoutMinutes = 5
# WorkingDirectory = 'TODO ???? - not sure how to handle this'
}
$codespace = $repo | New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
It 'Should return an object of the correct type' {
$codespace | Should -BeOfType PSCustomObject
}
It 'Should return the correct properties' {
# $codespace.devcontainer_path | Should -Be
$codespace.display_name | Should -Be $newGitHubCodespaceParms.DisplayName
$codespace.idle_timeout_minutes | Should -Be $newGitHubCodespaceParms.TimeoutMinutes
$codespace.location | Should -Match 'WestUs' # location should align with our requested Geo
$codespace.machine.name | Should -Be $newGitHubCodespaceParms.Machine
$codespace.owner.UserName | Should -Be $script:OwnerName
$codespace.repository.name | Should -Be $repo.name
$codespace.retention_period_minutes | Should -Be $newGitHubCodespaceParms.IdleRetentionPeriodMinutes
$codespace.template | Should -BeNullOrEmpty
}
AfterAll {
if ($codespace)
{
Remove-GitHubCodespace -CodespaceName $codespace.name -Confirm:$false
}
}
}
Context -Name 'When creating a codespace with default settings with Repository Elements' {
BeforeAll {
$newGitHubCodespaceParms = @{
RepositoryName = $repo.name
OwnerName = $repo.owner.login
}
$codespace = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
It 'Should return an object of the correct type' {
$codespace | Should -BeOfType PSCustomObject
}
It 'Should return the correct properties' {
$codespace.display_name | Should -Not -BeNullOrEmpty
$codespace.repository.name | Should -Be $repo.name
$codespace.owner.UserName | Should -Be $script:OwnerName
$codespace.template | Should -BeNullOrEmpty
}
AfterAll {
if ($codespace)
{
Remove-GitHubCodespace -CodespaceName $codespace.name -Confirm:$false
}
}
}
}
}
Describe 'GitHubCodespaces\Start-GitHubCodespace' {
BeforeAll {
# Suppress HTTP 202 warning for codespace creation
$WarningPreference = 'SilentlyContinue'
$newGitHubCodespaceParms = @{
OwnerName = $repo.owner.login
RepositoryName = $defaultRepositoryName
}
$null = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
Context 'When starting a codespace for the authenticated user' {
BeforeAll {
$codespace = Get-GitHubCodespace @newGitHubCodespaceParms | Select-Object -First 1
}
It 'Should not throw' {
# Also asserts pipeline input
{ $codespace | Start-GitHubCodespace } | Should -Not -Throw
}
It 'Should become Available' {
# Also asserts Wait and PassThru
$result = $codespace | Start-GitHubCodespace -Wait -PassThru
$result.State | Should -Be 'Available'
}
}
AfterAll {
Get-GitHubCodespace @newGitHubCodespaceParms | Remove-GitHubCodespace -Confirm:$false -Force
}
}
Describe 'GitHubCodespaces\Stop-GitHubCodespace' {
BeforeAll {
# Suppress HTTP 202 warning for codespace creation
$WarningPreference = 'SilentlyContinue'
$newGitHubCodespaceParms = @{
OwnerName = $repo.owner.login
RepositoryName = $defaultRepositoryName
}
$null = New-GitHubCodespace @newGitHubCodespaceParms -Wait
}
Context 'When stopping a codespace for the authenticated user' {
BeforeAll {
$codespace = Get-GitHubCodespace @newGitHubCodespaceParms | Select-Object -First 1
}
It 'Should not throw' {
# Also asserts pipeline input
{ $codespace | Stop-GitHubCodespace } | Should -Not -Throw
}
It 'Should become Shutdown' {
# Also asserts Wait and PassThru
$result = $codespace | Stop-GitHubCodespace -Wait -PassThru
$result.State | Should -Be 'Shutdown'
}
}
AfterAll {
Get-GitHubCodespace @newGitHubCodespaceParms | Remove-GitHubCodespace -Confirm:$false -Force
}
}
AfterAll {
if (Get-Variable -Name repo -ErrorAction SilentlyContinue)
{
# Should delete any corresponding codespaces along with it
$repo | Remove-GitHubRepository -Confirm:$false
}
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
}
}