Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing container-parameters to Data #1986

Merged
merged 13 commits into from
Jun 23, 2021
33 changes: 33 additions & 0 deletions src/Pester.Runtime.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2398,6 +2398,8 @@ function New-BlockContainerObject {
$Data
)

if ($null -eq $Data) { $Data = @{} }

$type, $item = switch ($PSCmdlet.ParameterSetName) {
"ScriptBlock" { "ScriptBlock", $ScriptBlock }
"Path" { "File", (& $SafeCommands['Get-Item'] $Path) }
Expand Down Expand Up @@ -2624,3 +2626,34 @@ function Invoke-InNewScriptScope ([ScriptBlock] $ScriptBlock, $SessionState) {

. $wrapper $Path $Data
}

function Add-MissingContainerParameters ($RootBlock, $Container, $CallingFunction) {
# Adds default values for container parameters not provided by the user.
# Also adds real parameter name as variable in Run-phase when alias was used, just like normal PowerShell will.

# Using AST to get parameter-names as $PSCmdLet.MyInvocation.MyCommand only works for advanced functions/scripts/cmdlets.
# No need to filter on parameter sets OR whether default values are set because Powershell adds all parameters (not aliases) as variables
# with default value or $null if not specified (probably to avoid error caused by inheritance).
$Ast = switch ($Container.Type) {
"ScriptBlock" { $container.Item.Ast }
"File" {
$externalScriptInfo = $CallingFunction.SessionState.InvokeCommand.GetCommand($Container.Item.PSPath, [System.Management.Automation.CommandTypes]::ExternalScript)
$externalScriptInfo.ScriptBlock.Ast
}
default { throw [System.ArgumentOutOfRangeException]"" }
}

if ($null -ne $Ast -and $null -ne $Ast.ParamBlock -and $Ast.ParamBlock.Parameters.Count -gt 0) {
$parametersToCheck = foreach ($param in $Ast.ParamBlock.Parameters) { $param.Name.VariablePath.UserPath }

foreach ($param in $parametersToCheck) {
$v = $CallingFunction.SessionState.PSVariable.Get($param)
if ((-not $RootBlock.Data.ContainsKey($param)) -and $v) {
if ($PesterPreference.Debug.WriteDebugMessages.Value) {
Write-PesterDebugMessage -Scope Discovery "Container parameter '$param' is undefined, adding to container Data with default value $(Format-Nicely $v.Value)."
fflaten marked this conversation as resolved.
Show resolved Hide resolved
}
$RootBlock.Data.Add($param, $v.Value)
}
}
}
}
5 changes: 5 additions & 0 deletions src/functions/Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ https://pester.dev/docs/usage/testdrive
}

if ($ExecutionContext.SessionState.PSVariable.Get('invokedViaInvokePester')) {
if ($state.CurrentBlock.IsRoot -and $state.CurrentBlock.Blocks.Count -eq 0) {
# For undefined parameters in container, add parameter's default value to Data
Add-MissingContainerParameters -RootBlock $state.CurrentBlock -Container $container -CallingFunction $PSCmdlet
}

if ($PSBoundParameters.ContainsKey('ForEach')) {
if ($null -ne $ForEach -and 0 -lt @($ForEach).Count) {
New-ParametrizedBlock -Name $Name -ScriptBlock $Fixture -StartLine $MyInvocation.ScriptLineNumber -Tag $Tag -FrameworkData @{ CommandUsed = 'Context'; WrittenToScreen = $false } -Focus:$Focus -Skip:$Skip -Data $ForEach
Expand Down
6 changes: 5 additions & 1 deletion src/functions/Describe.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,12 @@ https://pester.dev/docs/usage/testdrive
}
}


if ($ExecutionContext.SessionState.PSVariable.Get('invokedViaInvokePester')) {
if ($state.CurrentBlock.IsRoot -and $state.CurrentBlock.Blocks.Count -eq 0) {
# For undefined parameters in container, add parameter's default value to Data
Add-MissingContainerParameters -RootBlock $state.CurrentBlock -Container $container -CallingFunction $PSCmdlet
}

if ($PSBoundParameters.ContainsKey('ForEach')) {
if ($null -ne $ForEach -and 0 -lt @($ForEach).Count) {
New-ParametrizedBlock -Name $Name -ScriptBlock $Fixture -StartLine $MyInvocation.ScriptLineNumber -Tag $Tag -FrameworkData @{ CommandUsed = 'Describe'; WrittenToScreen = $false } -Focus:$Focus -Skip:$Skip -Data $ForEach
Expand Down
4 changes: 2 additions & 2 deletions tst/Pester.RSpec.InNewProcess.ts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ i -PassThru:$PassThru {
$testpath = Join-Path $temp "$([Guid]::NewGuid().Guid).tests.ps1"

try {
$c = 'param([Parameter(Mandatory)]$File) Describe "d - <File>" { It "i" { 1 | Should -Be 1 } }'
$c = 'param([Parameter(Mandatory)]$File, $MyValue = 1) Describe "d - <File>" { It "i" { $MyValue | Should -Be 1 } }'
Set-Content -Path $testpath -Value $c

$sb = [scriptblock]::Create("`$global:PesterPreference = [PesterConfiguration]@{Output=@{Verbosity='Detailed'}}; & $testpath -File 'demo.ps1'")
Expand All @@ -110,7 +110,7 @@ i -PassThru:$PassThru {
$testpath = Join-Path $temp "$([Guid]::NewGuid().Guid).tests.ps1"

try {
$c = 'param([Parameter(Mandatory)]$File) Context "c - <File>" { It "i" { 1 | Should -Be 1 } }'
$c = 'param([Parameter(Mandatory)]$File, $MyValue = 1) Context "c - <File>" { It "i" { $MyValue | Should -Be 1 } }'
Set-Content -Path $testpath -Value $c

$sb = [scriptblock]::Create("`$global:PesterPreference = [PesterConfiguration]@{Output=@{Verbosity='Detailed'}}; & $testpath -File 'demo.ps1'")
Expand Down