Tests/Invoke-PSClaudeCode.Tests.ps1

BeforeAll {
    # Import the module
    $ModulePath = Join-Path $PSScriptRoot '..' 'PSClaudeCode.psd1'
    Import-Module $ModulePath -Force

    # Store original API key
    $script:OriginalApiKey = $env:ANTHROPIC_API_KEY

    # Load function content once for all tests
    $script:FunctionPath = Join-Path $PSScriptRoot '..' 'Public' 'Invoke-PSClaudeCode.ps1'
    $script:FunctionContent = Get-Content $script:FunctionPath -Raw
}

AfterAll {
    # Restore original API key
    $env:ANTHROPIC_API_KEY = $script:OriginalApiKey
}

Describe 'Invoke-PSClaudeCode' {
    Context 'Parameter Validation' {
        It 'Should have a Task parameter' {
            $command = Get-Command Invoke-PSClaudeCode
            $command.Parameters.Keys | Should -Contain 'Task'
        }

        It 'Should have a Model parameter with default value' {
            $command = Get-Command Invoke-PSClaudeCode
            $command.Parameters.Keys | Should -Contain 'Model'
            $command.Parameters['Model'].Attributes.TypeId.Name | Should -Contain 'ParameterAttribute'
        }

        It 'Should have a dangerouslySkipPermissions switch parameter' {
            $command = Get-Command Invoke-PSClaudeCode
            $command.Parameters.Keys | Should -Contain 'dangerouslySkipPermissions'
            $command.Parameters['dangerouslySkipPermissions'].SwitchParameter | Should -Be $true
        }
    }

    Context 'API Key Validation' {
        BeforeEach {
            # Clear API key for these tests
            $env:ANTHROPIC_API_KEY = $null
        }

        AfterEach {
            # Restore API key
            $env:ANTHROPIC_API_KEY = $script:OriginalApiKey
        }

        It 'Should validate API key is set' {
            # We can't directly test the exit behavior in Pester easily,
            # but we can verify the function requires the environment variable
            $env:ANTHROPIC_API_KEY | Should -BeNullOrEmpty
        }
    }

    Context 'Tool Definitions' {
        It 'Should define Read-File tool' {
            $script:FunctionContent | Should -Match 'name\s*=\s*"Read-File"'
        }

        It 'Should define Write-File tool' {
            $script:FunctionContent | Should -Match 'name\s*=\s*"Write-File"'
        }

        It 'Should define Run-Command tool' {
            $script:FunctionContent | Should -Match 'name\s*=\s*"Run-Command"'
        }

        It 'Should define Delegate-Task tool' {
            $script:FunctionContent | Should -Match 'name\s*=\s*"Delegate-Task"'
        }
    }

    Context 'Execute-Tool Function Behavior' {
        BeforeAll {
            # Create test files for Execute-Tool testing
            $script:TestFilePath = Join-Path $TestDrive 'test-file.txt'
            $script:TestContent = 'Hello, World!'
            Set-Content -Path $script:TestFilePath -Value $script:TestContent
        }

        It 'Should have Execute-Tool function defined' {
            $script:FunctionContent | Should -Match 'function Execute-Tool'
        }

        It 'Should handle Read-File tool execution' {
            $script:FunctionContent | Should -Match '"Read-File"[\s\S]*Get-Content'
        }

        It 'Should handle Write-File tool execution' {
            $script:FunctionContent | Should -Match '"Write-File"[\s\S]*Set-Content'
        }

        It 'Should handle Run-Command tool execution' {
            $script:FunctionContent | Should -Match '"Run-Command"[\s\S]*Invoke-Expression'
        }

        It 'Should handle Delegate-Task tool execution' {
            $script:FunctionContent | Should -Match '"Delegate-Task"[\s\S]*Run-SubAgent'
        }
    }

    Context 'Check-Permission Function Behavior' {
        It 'Should have Check-Permission function defined' {
            $script:FunctionContent | Should -Match 'function Check-Permission'
        }

        It 'Should check dangerous commands in Run-Command tool' {
            $script:FunctionContent | Should -Match 'rm|del|Remove-Item'
        }

        It 'Should prompt for Write-File permissions' {
            $script:FunctionContent | Should -Match '"Write-File"'
            $script:FunctionContent | Should -Match 'Read-Host'
        }

        It 'Should respect dangerouslySkipPermissions flag' {
            $script:FunctionContent | Should -Match 'dangerouslySkipPermissions.*return \$true'
        }
    }

    Context 'Run-SubAgent Function Behavior' {
        It 'Should have Run-SubAgent function defined' {
            $script:FunctionContent | Should -Match 'function Run-SubAgent'
        }

        It 'Should have MaxTurns parameter with default value' {
            $script:FunctionContent | Should -Match 'MaxTurns.*=.*10'
        }

        It 'Should call Anthropic API in sub-agent' {
            $script:FunctionContent | Should -Match 'api\.anthropic\.com/v1/messages'
        }
    }

    Context 'Main Function Behavior' {
        It 'Should use default Claude model when not specified' {
            $script:FunctionContent | Should -Match 'Model\s*=\s*"claude-sonnet-4-5-20250929"'
        }

        It 'Should call Anthropic API endpoint' {
            $script:FunctionContent | Should -Match 'https://api\.anthropic\.com/v1/messages'
        }

        It 'Should set correct API headers' {
            $script:FunctionContent | Should -Match 'x-api-key'
            $script:FunctionContent | Should -Match 'anthropic-version'
        }

        It 'Should process tool uses from API response' {
            $script:FunctionContent | Should -Match 'tool_use'
        }

        It 'Should handle text content in responses' {
            $script:FunctionContent | Should -Match 'type.*-eq.*"text"'
        }
    }

    Context 'Module Integration' {
        It 'Should be exported from the module' {
            $exportedCommands = (Get-Module PSClaudeCode).ExportedCommands.Keys
            $exportedCommands | Should -Contain 'Invoke-PSClaudeCode'
        }

        It 'Should have alias ipcc' {
            $alias = Get-Alias -Name ipcc -ErrorAction SilentlyContinue
            $alias | Should -Not -BeNullOrEmpty
            $alias.ResolvedCommandName | Should -Be 'Invoke-PSClaudeCode'
        }
    }
}