tests/functions/Get-MtGitHubAppDeviceToken.Tests.ps1
|
BeforeAll { Import-Module "$PSScriptRoot/../../Maester.psd1" -Force } Describe 'Get-MtGitHubAppDeviceToken' { It 'Completes GitHub App device flow and returns an access token' { $script:pollCount = 0 Mock Start-Sleep -ModuleName Maester {} Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/device/code' } { [PSCustomObject]@{ Content = '{"device_code":"device-code","user_code":"ABCD-1234","verification_uri":"https://github.com/login/device","expires_in":900,"interval":1}' } } Mock Read-Host -ModuleName Maester { '' } Mock Open-MtBrowserUrl -ModuleName Maester { $true } Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/oauth/access_token' } { $script:pollCount++ if ($script:pollCount -eq 1) { [PSCustomObject]@{ Content = '{"error":"authorization_pending"}' } } else { [PSCustomObject]@{ Content = '{"access_token":"ghu_test","expires_in":28800,"token_type":"bearer","scope":""}' } } } InModuleScope Maester { $result = Get-MtGitHubAppDeviceToken -ClientId 'Iv23liV3mw0hSq0gn957' 6>$null $result.AccessToken | Should -Be 'ghu_test' $result.FailureReason | Should -BeNullOrEmpty $result.ExpiresAt | Should -Not -BeNullOrEmpty } Should -Invoke Invoke-WebRequest -ModuleName Maester -Times 1 -ParameterFilter { $Uri -eq 'https://github.com/login/device/code' -and $Body.client_id -eq 'Iv23liV3mw0hSq0gn957' } Should -Invoke Open-MtBrowserUrl -ModuleName Maester -Times 1 -Exactly -ParameterFilter { $Uri -eq 'https://github.com/login/device' } Should -Invoke Read-Host -ModuleName Maester -Times 1 -Exactly -ParameterFilter { $Prompt -eq 'Press Enter to open https://github.com/login/device in your browser' } Should -Invoke Invoke-WebRequest -ModuleName Maester -Times 2 -ParameterFilter { $Uri -eq 'https://github.com/login/oauth/access_token' -and $Body.client_id -eq 'Iv23liV3mw0hSq0gn957' -and $Body.device_code -eq 'device-code' -and $Body.grant_type -eq 'urn:ietf:params:oauth:grant-type:device_code' } } It 'Returns GitHubDeviceFlowDenied when the user denies authorization' { Mock Start-Sleep -ModuleName Maester {} Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/device/code' } { [PSCustomObject]@{ Content = '{"device_code":"device-code","user_code":"ABCD-1234","verification_uri":"https://github.com/login/device","expires_in":900,"interval":1}' } } Mock Read-Host -ModuleName Maester { '' } Mock Open-MtBrowserUrl -ModuleName Maester { $true } Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/oauth/access_token' } { [PSCustomObject]@{ Content = '{"error":"access_denied"}' } } InModuleScope Maester { $result = Get-MtGitHubAppDeviceToken -ClientId 'Iv23liV3mw0hSq0gn957' 6>$null $result.AccessToken | Should -BeNullOrEmpty $result.FailureReason | Should -Be 'GitHubDeviceFlowDenied' } } It 'Displays the device code without trailing punctuation when the browser opens' { Mock Start-Sleep -ModuleName Maester {} Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/device/code' } { [PSCustomObject]@{ Content = '{"device_code":"device-code","user_code":"ABCD-1234","verification_uri":"https://github.com/login/device","expires_in":900,"interval":1}' } } Mock Read-Host -ModuleName Maester { '' } Mock Open-MtBrowserUrl -ModuleName Maester { $true } Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/oauth/access_token' } { [PSCustomObject]@{ Content = '{"error":"access_denied"}' } } $output = InModuleScope Maester { Get-MtGitHubAppDeviceToken -ClientId 'Iv23liV3mw0hSq0gn957' 6>&1 | Out-String } $output | Should -Match '! First copy your one-time code: ABCD-1234' $output | Should -Not -Match 'Opened https://github\.com/login/device in your browser\.' $output | Should -Not -Match 'ABCD-1234\.' } It 'Displays the device code without trailing punctuation when the browser does not open' { Mock Start-Sleep -ModuleName Maester {} Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/device/code' } { [PSCustomObject]@{ Content = '{"device_code":"device-code","user_code":"ABCD-1234","verification_uri":"https://github.com/login/device","expires_in":900,"interval":1}' } } Mock Read-Host -ModuleName Maester { '' } Mock Open-MtBrowserUrl -ModuleName Maester { $false } Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/oauth/access_token' } { [PSCustomObject]@{ Content = '{"error":"access_denied"}' } } $output = InModuleScope Maester { Get-MtGitHubAppDeviceToken -ClientId 'Iv23liV3mw0hSq0gn957' 6>&1 | Out-String } $output | Should -Match '! First copy your one-time code: ABCD-1234' $output | Should -Match 'Open https://github\.com/login/device and enter code ABCD-1234' $output | Should -Not -Match 'ABCD-1234\.' } It 'Waits for the user before opening the device sign-in page' { $script:deviceFlowEvents = @() Mock Start-Sleep -ModuleName Maester {} Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/device/code' } { [PSCustomObject]@{ Content = '{"device_code":"device-code","user_code":"ABCD-1234","verification_uri":"https://github.com/login/device","expires_in":900,"interval":1}' } } Mock Read-Host -ModuleName Maester { $script:deviceFlowEvents += 'prompt' '' } Mock Open-MtBrowserUrl -ModuleName Maester { $script:deviceFlowEvents += 'open' $true } Mock Invoke-WebRequest -ModuleName Maester -ParameterFilter { $Uri -eq 'https://github.com/login/oauth/access_token' } { [PSCustomObject]@{ Content = '{"error":"access_denied"}' } } InModuleScope Maester { Get-MtGitHubAppDeviceToken -ClientId 'Iv23liV3mw0hSq0gn957' 6>$null } ($script:deviceFlowEvents -join ',') | Should -Be 'prompt,open' } } |