Functions/Invoke-RestMethodWithRetry.Tests.ps1

describe "BitTitan.Runbooks.Common/Invoke-RestMethodWithRetry" -Tag "module", "unit" {

    # Import the function to test
    . "$($PSScriptRoot)\Invoke-RestMethodWithRetry.ps1"

    # Declare our own Invoke-RestMethod
    $defaultRestResponse = [PSCustomObject]@{
        Result = "Success"
    }
    function Invoke-RestMethod {
        param ($Uri, $Headers, $Body, $Method)
        return $defaultRestResponse
    }

    context "when there are no issues" {
        # Mock Invoke-RestMethod
        mock Invoke-RestMethod {
            return [PSCustomObject]@{
                Result = "Success"
            }
        }

        it "invokes the REST method once" {
            # Call the function
            $output = Invoke-RestMethodWithRetry -Uri "uri" -Headers "headers" -Body "body" -Method "post" `
                -IntervalMilliseconds 0 -MaximumNumberOfCalls 1 -ReturnUnsuccessfulResponseObject `
                -ErrorAction SilentlyContinue -ErrorVariable errorVariable

            # Verify the mocks
            Assert-MockCalled Invoke-RestMethod -Times 1 -Exactly -ParameterFilter {
                $Uri -eq "uri" -and $Headers -eq "headers" -and $Body -eq "body" -and $Method -eq "post"
            }

            # Verify the output
            $errorVariable | Should BeNullOrEmpty
            Compare-Object $defaultRestResponse $output | Should Be $null
        }
    }

    context "when Invoke-RestMethod continuously throws exceptions" {
        # Mock Invoke-RestMethod
        mock Invoke-RestMethod {
            throw "throwing exception"
        }

        it "invokes the REST method the maximum number of times" {
            # Call the function
            $output = Invoke-RestMethodWithRetry -Uri "uri" -Headers "headers" -Body "body" -Method "post" `
                -IntervalMilliseconds 0 -MaximumNumberOfCalls 10 -ReturnUnsuccessfulResponseObject `
                -ErrorAction SilentlyContinue -ErrorVariable errorVariable

            # Verify the mocks
            Assert-MockCalled Invoke-RestMethod -Times 10 -Exactly -ParameterFilter {
                $Uri -eq "uri" -and $Headers -eq "headers" -and $Body -eq "body" -and $Method -eq "post"
            } -Scope it

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

    context "when the REST call is unsuccessful" {
        # Mock Invoke-RestMethod
        $failedRestResponse = [PSCustomObject]@{
            Result = "Failed"
        }
        mock Invoke-RestMethod {
            return $failedRestResponse
        }

        it "invokes the REST method the maximum number of times" {
            # Call the function
            $output = Invoke-RestMethodWithRetry -Uri "uri" -Headers "headers" -Body "body" -Method "post" `
                -IntervalMilliseconds 0 -MaximumNumberOfCalls 10 -ReturnUnsuccessfulResponseObject `
                -ErrorAction SilentlyContinue -ErrorVariable errorVariable

            # Verify the mocks
            Assert-MockCalled Invoke-RestMethod -Times 10 -Exactly -ParameterFilter {
                $Uri -eq "uri" -and $Headers -eq "headers" -and $Body -eq "body" -and $Method -eq "post"
            } -Scope it

            # Verify the output
            $errorVariable | Should Not BeNullOrEmpty
            Compare-Object $failedRestResponse $output | Should Be $null
        }
    }
}