Functions/Invoke-UIAutomationScript.Tests.ps1

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

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

    # Declare external functions and mocks
    mock Get-Location {}
    mock Set-Location {}
    mock Out-File {}
    mock Invoke-Expression {
        $Global:LastExitCode = 0
    }

    context "when there are no issues" {

        it "indicates that the invoke was a success" {
            # Call the function
            $output = Invoke-UIAutomationScript -Script "script" -Name "name" -NodePackagePath "C:\temp"

            # Verify mocks
            Assert-MockCalled Invoke-Expression -Times 1 -Exactly -ParameterFilter {
                $Command -eq "node name.js *>&1"
            } -Scope it

            # Verify output
            $output.Success | Should Be $true
            $output.Result | Should BeNullOrEmpty
        }
    }

    context "when the invoke fails due to a selector timeout error" {
        # Declare mocks
        mock Invoke-Expression {
            $Global:LastExitCode = 1
            'Error: waiting for selector "#selector" failed, timeout 30s exceeded.'
        }

        it "returns a custom result message" {
            # Call the function
            $output = Invoke-UIAutomationScript -Script "script" -Name "name" -NodePackagePath "C:\temp"

            # Verify mocks
            Assert-MockCalled Invoke-Expression -Times 1 -Exactly -ParameterFilter {
                $Command -eq "node name.js *>&1"
            } -Scope it

            # Verify output
            $output.Success | Should Be $false
            $output.Result | Should Be "Timeout on selector '#selector'."
        }
    }

    context "when the invoke fails due to a non-selector timeout error" {
        # Declare mocks
        mock Invoke-Expression {
            $Global:LastExitCode = 1
            "timeout 30s exceeded"
        }

        it "returns a custom result message" {
            # Call the function
            $output = Invoke-UIAutomationScript -Script "script" -Name "name" -NodePackagePath "C:\temp"

            # Verify mocks
            Assert-MockCalled Invoke-Expression -Times 1 -Exactly -ParameterFilter {
                $Command -eq "node name.js *>&1"
            } -Scope it

            # Verify output
            $output.Success | Should Be $false
            $output.Result | Should Be "timeout 30s exceeded`r`n"
        }
    }

    context "when the invoke fails due to a non-timeout error" {
        # Declare mocks
        mock Invoke-Expression {
            $Global:LastExitCode = 1
            "unknown error"
        }

        it "returns a custom result message" {
            # Call the function
            $output = Invoke-UIAutomationScript -Script "script" -Name "name" -NodePackagePath "C:\temp"

            # Verify mocks
            Assert-MockCalled Invoke-Expression -Times 1 -Exactly -ParameterFilter {
                $Command -eq "node name.js *>&1"
            } -Scope it

            # Verify output
            $output.Success | Should Be $false
            $output.Result | Should Be "unknown error`r`n"
        }
    }

    context "when an exception occurs while invoking the script" {
        # Declare mocks
        mock Invoke-Expression {
            throw "up"
        }

        it "outputs an error and returns the exception message" {
            # Call the function
            $output = Invoke-UIAutomationScript -Script "script" -Name "name" -NodePackagePath "C:\temp" `
                -ErrorAction SilentlyContinue -ErrorVariable errorVariable

            # Verify mocks
            Assert-MockCalled Invoke-Expression -Times 1 -Exactly -ParameterFilter {
                $Command -eq "node name.js *>&1"
            } -Scope it

            # Verify output
            $output.Success | Should Be $false
            $output.Result | Should BeLike "Exception occurred*up"
        }
    }
}