Tests/Unit/Invoke-GEGit.Tests.ps1

# Generated by tools\Build-PrivateUnitTests.ps1. Re-run to regenerate.
BeforeAll {

$ProjectRoot   = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$RelativePath  = 'Private\Invoke-GEGit.ps1'
$SourcePath    = Join-Path $ProjectRoot $RelativePath
}

Describe 'Invoke-GEGit (private contract)' {

    BeforeAll {
        $script:Ast = $null
        $script:Fn  = $null
        if (Test-Path -LiteralPath $SourcePath -PathType Leaf) {
            $tokens = $null; $errors = $null
            $script:Ast = [System.Management.Automation.Language.Parser]::ParseFile($SourcePath, [ref]$tokens, [ref]$errors)
            $script:Fn  = @($script:Ast.FindAll({ param($n) $n -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)) | Select-Object -First 1
        }
    }

    It 'source file exists at the expected location' {
        Test-Path -LiteralPath $SourcePath -PathType Leaf | Should -Be $true
    }

    It 'declares a function whose name matches the file name' {
        $script:Fn.Name | Should -Be 'Invoke-GEGit'
    }

    It 'name uses the GE prefix convention' {
        $script:Fn.Name | Should -Match '^[A-Za-z]+-GE[A-Za-z0-9]+$'
    }

    It 'declares [CmdletBinding()]' {
        $hasBinding = $false
        if ($script:Fn.Body.ParamBlock -and $script:Fn.Body.ParamBlock.Attributes) {
            foreach ($attr in $script:Fn.Body.ParamBlock.Attributes) {
                if ($attr.TypeName.Name -eq 'CmdletBinding') { $hasBinding = $true }
            }
        }
        $hasBinding | Should -Be $true
    }

    It 'declares the -ArgumentList parameter' {
        $names = @()
        if ($script:Fn.Body.ParamBlock -and $script:Fn.Body.ParamBlock.Parameters) {
            $names = @($script:Fn.Body.ParamBlock.Parameters | ForEach-Object { $_.Name.VariablePath.UserPath })
        }
        $names -contains 'ArgumentList' | Should -Be $true
    }

    It '-ArgumentList is mandatory' {
        $param = $script:Fn.Body.ParamBlock.Parameters | Where-Object { $_.Name.VariablePath.UserPath -eq 'ArgumentList' } | Select-Object -First 1
        $isMandatory = $false
        foreach ($attr in $param.Attributes) {
            if ($attr.TypeName.Name -eq 'Parameter') {
                foreach ($na in $attr.NamedArguments) {
                    if ($na.ArgumentName -eq 'Mandatory') { $isMandatory = $true }
                }
            }
        }
        $isMandatory | Should -Be $true
    }

    It 'declares the -WorkingDirectory parameter' {
        $names = @()
        if ($script:Fn.Body.ParamBlock -and $script:Fn.Body.ParamBlock.Parameters) {
            $names = @($script:Fn.Body.ParamBlock.Parameters | ForEach-Object { $_.Name.VariablePath.UserPath })
        }
        $names -contains 'WorkingDirectory' | Should -Be $true
    }

    It 'declares the -AllowFailure parameter' {
        $names = @()
        if ($script:Fn.Body.ParamBlock -and $script:Fn.Body.ParamBlock.Parameters) {
            $names = @($script:Fn.Body.ParamBlock.Parameters | ForEach-Object { $_.Name.VariablePath.UserPath })
        }
        $names -contains 'AllowFailure' | Should -Be $true
    }

    It '-AllowFailure is a switch parameter' {
        $param = $script:Fn.Body.ParamBlock.Parameters | Where-Object { $_.Name.VariablePath.UserPath -eq 'AllowFailure' } | Select-Object -First 1
        $param.StaticType.Name | Should -Be 'SwitchParameter'
    }

    It 'declares the -LogPath parameter' {
        $names = @()
        if ($script:Fn.Body.ParamBlock -and $script:Fn.Body.ParamBlock.Parameters) {
            $names = @($script:Fn.Body.ParamBlock.Parameters | ForEach-Object { $_.Name.VariablePath.UserPath })
        }
        $names -contains 'LogPath' | Should -Be $true
    }

    It 'has comment-based help with .SYNOPSIS' {
        $body   = Get-Content -LiteralPath $SourcePath -Raw
        $hasCbh = ($body -match '(?ms)<#.*?\.SYNOPSIS\s+\S.*?#>')
        $hasCbh | Should -Be $true
    }

}