Tests/Unit/Public/Authentication/New-SCASession.Tests.ps1

Import-Module (Join-Path $PSScriptRoot '../../../../psSCA.psd1') -Force

Describe 'New-SCASession' {
    InModuleScope psSCA {
        BeforeEach {
            $script:SCASessions = [ordered]@{}
            $script:SCACurrentSessionName = $null
            # PSScriptAnalyzer disable-next-line PSAvoidUsingConvertToSecureStringWithPlainText
            $cred = [pscredential]::new('svc-user', (ConvertTo-SecureString -String 'svc-password' -AsPlainText -Force))
            $script:testCredential = $cred
        }

        It 'requests a token from the platform token endpoint and stores the session' {
            Mock Invoke-WebRequest {
                [pscustomobject]@{
                    Content = '{"access_token":"new-token-value","token_type":"Bearer","expires_in":900}'
                }
            }

            $session = New-SCASession -IdentityTenantId 'aaf1234' -Credential $testCredential -Confirm:$false

            $session.Name | Should -Be 'Default'
            $session.TenantSubdomain | Should -Be 'aaf1234'
            $session.TokenType | Should -Be 'Bearer'
            [System.Net.NetworkCredential]::new('', $session.AccessToken).Password | Should -Be 'new-token-value'

            Should -Invoke Invoke-WebRequest -ParameterFilter {
                $Uri -eq 'https://aaf1234.id.cyberark.cloud/oauth2/platformtoken' -and
                $Body -match 'grant_type=client_credentials' -and
                $Body -match 'client_id=svc-user' -and
                $Body -match 'client_secret=svc-password'
            }
        }

        It 'stores the session under the store keyed by -Name and marks the first session as current' {
            Mock Invoke-WebRequest {
                [pscustomobject]@{ Content = '{"access_token":"tok","token_type":"Bearer","expires_in":900}' }
            }

            New-SCASession -Name 'Production' -IdentityTenantId 'aaf1234' -Credential $testCredential -Confirm:$false | Out-Null

            $script:SCASessions.Contains('Production') | Should -BeTrue
            $script:SCACurrentSessionName | Should -Be 'Production'
        }

        It 'defaults TenantSubdomain to IdentityTenantId when not specified' {
            Mock Invoke-WebRequest {
                [pscustomobject]@{ Content = '{"access_token":"tok","token_type":"Bearer","expires_in":900}' }
            }

            $session = New-SCASession -IdentityTenantId 'aaf1234' -Credential $testCredential -Confirm:$false
            $session.TenantSubdomain | Should -Be 'aaf1234'
        }

        It 'honors an explicit -TenantSubdomain distinct from -IdentityTenantId' {
            Mock Invoke-WebRequest {
                [pscustomobject]@{ Content = '{"access_token":"tok","token_type":"Bearer","expires_in":900}' }
            }

            $session = New-SCASession -IdentityTenantId 'aaf1234' -TenantSubdomain 'contoso' -Credential $testCredential -Confirm:$false
            $session.TenantSubdomain | Should -Be 'contoso'
        }

        It 'sets ExpiresAt based on the returned expires_in value' {
            Mock Invoke-WebRequest {
                [pscustomobject]@{ Content = '{"access_token":"tok","token_type":"Bearer","expires_in":300}' }
            }

            $before = [DateTime]::UtcNow
            $session = New-SCASession -IdentityTenantId 'aaf1234' -Credential $testCredential -Confirm:$false
            $session.ExpiresAt | Should -BeGreaterThan $before.AddSeconds(299)
            $session.ExpiresAt | Should -BeLessThan $before.AddSeconds(301)
        }

        It 'does not call the token endpoint when -WhatIf is specified' {
            Mock Invoke-WebRequest { [pscustomobject]@{ Content = '{"access_token":"tok","token_type":"Bearer","expires_in":900}' } }

            New-SCASession -IdentityTenantId 'aaf1234' -Credential $testCredential -WhatIf | Out-Null

            Should -Invoke Invoke-WebRequest -Times 0 -Exactly
            $script:SCASessions.Count | Should -Be 0
        }
    }
}