qbuild.tests.ps1
|
BeforeDiscovery { . "$PSScriptRoot\test-utils.ps1" } BeforeAll { Get-Module ConfigMap -ErrorAction SilentlyContinue | Remove-Module Import-Module $PSScriptRoot\configmap.psm1 } Describe "qbuild" { BeforeAll { function Invoke-Build { param($ctx, [bool][switch]$noRestore) } Mock Invoke-Build { param($ctx, [bool][switch]$noRestore) $bound = $PSBoundParameters Write-Host "build script body" Write-Host "ctx=$($ctx | ConvertTo-Json)" Write-Host "noRestore=$noRestore" Write-Host "bound=$($bound | ConvertTo-Json)" } $targets = @{ "build" = { param($ctx, [bool][switch]$noRestore) Invoke-Build @PSBoundParameters } } } Describe "script custom parameters" { It "should return parameters" { $parameters = Get-ScriptArgs $targets.build $parameters.Keys | Should -Be @("ctx", "noRestore") } It "should invoke with correct parameters" { qbuild -map $targets "build" -NoRestore Should -Invoke Invoke-Build -Times 1 -ParameterFilter { $noRestore -eq $true } } } } Describe "qbuild dynamic parameters" { BeforeAll { Mock Write-Host $buildTargets = @{ "push:short" = { param([switch]$NewVersion, [string]$path = $null) Write-Host "Running push/publish workflow with args: NewVersion=$NewVersion, path=$path" } "push:exec" = @{ exec = { param([switch]$NewVersion, [string]$path = $null) Write-Host "Running push/publish workflow with args: NewVersion=$NewVersion, path=$path" } description = "Push/publish module (runs tests first)" } } } It "should recognize <EntryType> command parameters" -TestCases @( @{ EntryType = "push:short"; } @{ EntryType = "push:exec"; } ) { param($EntryType) $entry = Get-MapEntry $buildTargets $EntryType $scriptBlock = Get-EntryCommand $entry $parameters = Get-ScriptArgs $ScriptBlock $parameters.Keys | Should -Contain "NewVersion" $parameters.Keys | Should -Contain "path" } It "should handle <EntryType> command with -path parameter" -TestCases @( @{ EntryType = "push:short" } @{ EntryType = "push:exec" } ) { param($EntryType) qbuild -map $buildTargets $EntryType -path ".\src\configmap\" Should -Invoke Write-Host -ParameterFilter { $Object -eq "Running push/publish workflow with args: NewVersion=False, path=.\src\configmap\" } } It "should handle <EntryType> command with -NewVersion and -path parameters" -TestCases @( @{ EntryType = "push:short" } @{ EntryType = "push:exec" } ) { param($EntryType) qbuild -map $buildTargets $EntryType -NewVersion -path ".\src\configmap\" Should -Invoke Write-Host -ParameterFilter { $Object -eq "Running push/publish workflow with args: NewVersion=True, path=.\src\configmap\" } } } Describe "unified" { BeforeAll { Mock Write-Host $targets = @{ "write:simple" = { param([string] $message) Write-Host "SIMPLE: '$message'" } "write:wrapped" = @{ exec = { param([string] $message) Write-Host "WRAPPED: '$message'" } other = { param([string] $message) Write-Host "OTHER: '$message'" } } "write:custom" = @{ go = { param([string] $message) return "CUSTOM: '$message'" } } "write:getset" = @{ go = { param([string] $message) return "GO: '$message'" } get = { param([string] $message) return "GET: '$message'" } set = { param([string] $message) Write-Host "SET: '$message'" } } "write:options" = { options = { return @{ "option1" = "value1" "option2" = "value2" } } get = { param([string] $message) return "GET: '$message'" } set = { param([string] $value, [string] $key) Write-Host "SET: '$key' to '$value'" } } } } It "should write message with scriptblock" { qbuild -map $targets "write:simple" -message "Hello, World!" Should -Invoke Write-Host -Exactly 1 -ParameterFilter { $Object -eq "SIMPLE: 'Hello, World!'" } } It "should write message with wrapped scriptblock" { qbuild -map $targets "write:wrapped" -command "exec" -message "Hello, World!" Should -Invoke Write-Host -Exactly 1 -ParameterFilter { $Object -eq "WRAPPED: 'Hello, World!'" } } It "should handle ordered parameters" { qbuild -map $targets "write:wrapped" "exec" -message "Hello, World!" Should -Invoke Write-Host -Exactly 1 -ParameterFilter { $Object -eq "WRAPPED: 'Hello, World!'" } } } Describe "hierarchical" { BeforeAll { Mock Write-Host $targets = @{ "parent" = @{ "write:simple" = { param([string] $message) Write-Host "SIMPLE: '$message'" } "write:wrapped" = @{ exec = { param([string] $message) Write-Host "WRAPPED: '$message'" } other = { param([string] $message) Write-Host "OTHER: '$message'" } } "write:custom" = @{ go = { param([string] $message) return "CUSTOM: '$message'" } } "write:getset" = @{ go = { param([string] $message) return "GO: '$message'" } get = { param([string] $message) return "GET: '$message'" } set = { param([string] $message) Write-Host "SET: '$message'" } } "write:options" = { options = { return @{ "option1" = "value1" "option2" = "value2" } } get = { param([string] $message) return "GET: '$message'" } set = { param([string] $value, [string] $key) Write-Host "SET: '$key' to '$value'" } } } } } It "should write message with scriptblock" { qbuild -map $targets "parent.write:simple" -message "Hello, World!" Should -Invoke Write-Host -Exactly 1 -ParameterFilter { $Object -eq "SIMPLE: 'Hello, World!'" } } } Describe "hierarchical completion" { BeforeAll { $targets = @{ "parent" = @{ "write:simple" = { param([string] $message) Write-Host "SIMPLE: '$message'" } "write:wrapped" = @{ exec = { param([string] $message) Write-Host "WRAPPED: '$message'" } } "other:command" = { Write-Host "Other command" } } "regular" = { Write-Host "Regular command" } "another" = @{ "nested:cmd" = { Write-Host "Nested command" } } } } It "should complete partial parent name 'paren' to show all parent.* commands" { $completions = Get-EntryCompletion $targets $null $null "paren" $null @{} $completions | Should -Contain "parent.write:simple" $completions | Should -Contain "parent.write:wrapped" $completions | Should -Contain "parent.other:command" $completions | Should -Contain "parent*" } It "should complete 'parent.' to show all parent child commands" { $completions = Get-EntryCompletion $targets $null $null "parent." $null @{} $completions | Should -Contain "parent.write:simple" $completions | Should -Contain "parent.write:wrapped" $completions | Should -Contain "parent.other:command" $completions | Should -Not -Contain "regular" $completions | Should -Not -Contain "another.nested:cmd" } It "should complete 'parent.write' to show only matching write commands" { $completions = Get-EntryCompletion $targets $null $null "parent.write" $null @{} $completions | Should -Contain "parent.write:simple" $completions | Should -Contain "parent.write:wrapped" $completions | Should -Not -Contain "parent.other:command" $completions | Should -Not -Contain "regular" } It "should complete regular commands normally" { $completions = Get-EntryCompletion $targets $null $null "reg" $null @{} $completions | Should -Contain "regular" $completions | Should -Not -Contain "parent.write:simple" } It "should complete partial parent names to multiple parent groups" { $completions = Get-EntryCompletion $targets $null $null "" $null @{} $completions | Should -Contain "parent.write:simple" $completions | Should -Contain "another.nested:cmd" $completions | Should -Contain "regular" $completions | Should -Contain "parent*" $completions | Should -Contain "another*" } It "should handle empty completion to show all available commands" { $completions = Get-EntryCompletion $targets $null $null "" $null @{} # Should contain both hierarchical and flat commands $completions.Count | Should -BeGreaterThan 5 $completions | Should -Contain "regular" $completions | Should -Contain "parent.write:simple" $completions | Should -Contain "another.nested:cmd" } } |