Functions/Connect-GSuiteAdminAccount.Tests.ps1

Describe "GSuite/Connect-GSuiteAdminAccount" -Tag "task", "unit" {

    # Import the function to test
    . "$($PSScriptRoot)\Connect-GSuiteAdminAccount.ps1"

    # Declare external functions and mocks
    function Invoke-RestMethod {
        param ($Uri, $Headers, $Body, $Method)
        return @{
            expires_in   = 3600
            access_token = "token"
        }
    }

    # Declare the endpoint
    $GSuiteEndpoint = [PSCustomObject]@{
        Name       = "GoogleCredentials"
        Credential = [PSCredential]::new(
            'id',
            ('ClientSecret:secret User:userRefreshToken Group:groupRefreshToken Domain:domainRefreshToken' | ConvertTo-SecureString -AsPlainText -Force)
        )
    }

    context "when there are no issues" {
        # Declare mocks
        mock Invoke-RestMethod {
            param ($Uri, $Headers, $Body, $Method)
            return @{
                expires_in   = 3600
                access_token = "token"
            }
        }

        it "retrieves all the authentication tokens using the refresh tokens stored in the endpoint" {
            # Call the function
            $output = Connect-GSuiteAdminAccount -Endpoint $GSuiteEndpoint -ErrorAction SilentlyContinue -ErrorVariable errorVariable

            # Construct the expected request bodies
            $UserBody = @{
                client_id     = "id"
                client_secret = "secret"
                grant_type    = "refresh_token"
                refresh_token = "groupRefreshToken"
            } | ConvertTo-Json
            $GroupBody = @{
                client_id     = "id"
                client_secret = "secret"
                grant_type    = "refresh_token"
                refresh_token = "userRefreshToken"
            } | ConvertTo-Json
            $DomainBody = @{
                client_id     = "id"
                client_secret = "secret"
                grant_type    = "refresh_token"
                refresh_token = "domainRefreshToken"
            } | ConvertTo-Json

            # Verify the mocks
            Assert-MockCalled Invoke-RestMethod -Times 1 -Exactly -ParameterFilter {
                $Uri -eq "https://www.googleapis.com/oauth2/v4/token" -and
                $Headers.'Content-Type' -eq "application/json" -and
                $Method -eq "POST" -and
                $Body -eq $UserBody
            } -Scope it
            Assert-MockCalled Invoke-RestMethod -Times 1 -Exactly -ParameterFilter {
                $Uri -eq "https://www.googleapis.com/oauth2/v4/token" -and
                $Headers.'Content-Type' -eq "application/json" -and
                $Method -eq "POST" -and
                $Body -eq $GroupBody
            } -Scope it
            Assert-MockCalled Invoke-RestMethod -Times 1 -Exactly -ParameterFilter {
                $Uri -eq "https://www.googleapis.com/oauth2/v4/token" -and
                $Headers.'Content-Type' -eq "application/json" -and
                $Method -eq "POST" -and
                $Body -eq $DomainBody
            } -Scope it

            # Verify the output
            $output | Should Be $true
            $errorVariable | Should BeNullOrEmpty
        }

        it "only retrieves the specified authentication tokens" {
            # Call the function
            $output = Connect-GSuiteAdminAccount -Endpoint $GSuiteEndpoint -User -ErrorAction SilentlyContinue -ErrorVariable errorVariable

            # Verify the mocks
            Assert-MockCalled Invoke-RestMethod -Times 1 -Exactly -ParameterFilter {
                $Uri -eq "https://www.googleapis.com/oauth2/v4/token" -and
                $Headers.'Content-Type' -eq "application/json" -and
                $Method -eq "POST" -and
                $Body -eq @{
                    client_id     = "id"
                    client_secret = "secret"
                    grant_type    = "refresh_token"
                    refresh_token = "userRefreshToken"
                } | ConvertTo-Json
            } -Scope it

            # Verify the output
            $output | Should Be $true
            $errorVariable | Should BeNullOrEmpty
        }
    }

    context "when the endpoint does not contain the refresh token of the specified scope" {
        # Declare the endpoint
        $GSuiteEndpoint = [PSCustomObject]@{
            Name       = "GoogleCredentials"
            Credential = [PSCredential]::new(
                'id',
                ('ClientSecret:secret User: Group:groupRefreshToken Domain:domainRefreshToken' | ConvertTo-SecureString -AsPlainText -Force)
            )
        }

        it "outputs an error and returns false" {
            # Call the function
            $output = Connect-GSuiteAdminAccount -Endpoint $GSuiteEndpoint -ErrorAction SilentlyContinue -ErrorVariable errorVariable 2>$null

            # Verify the output
            $output | Should Be $false
            $errorVariable | Should Not BeNullOrEmpty
        }
    }

    context "when Invoke-RestMethod throws an exception" {
        # Declare mocks
        mock Invoke-RestMethod {
            throw "error"
        }

        it "outputs an error and returns false" {
            # Call the function
            $output = Connect-GSuiteAdminAccount -Endpoint $GSuiteEndpoint -ErrorAction SilentlyContinue -ErrorVariable errorVariable 2>$null

            # Verify the output
            $output | Should Be $false
            $errorVariable | Should Not BeNullOrEmpty
        }
    }

    context "when Invoke-RestMethod does not return the token" {
        # Declare mocks
        mock Invoke-RestMethod {
            return @{
                expires_in = 3600
            }
        }

        it "outputs an error and returns false" {
            # Call the function
            $output = Connect-GSuiteAdminAccount -Endpoint $GSuiteEndpoint -ErrorAction SilentlyContinue -ErrorVariable errorVariable 2>$null

            # Verify the output
            $output | Should Be $false
            $errorVariable | Should Not BeNullOrEmpty
        }
    }
}