Skip to content

Commit

Permalink
Test and fix Get-ParameterValue
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaykul committed Aug 22, 2023
1 parent b47292d commit 786ab69
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 102 deletions.
28 changes: 15 additions & 13 deletions Source/Public/Get-ParameterValue.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function Get-ParameterValue {
PSVariable = $PSCmdlet.SessionState.PSVariable
ErrorAction = "SilentlyContinue"
}
Write-Debug "Importing $FromFile"
$FileValues = Import-Metadata $FromFile @MetadataOptions
if ($CommandKey) {
$FileValues = $FileValues.$CommandKey
Expand All @@ -57,9 +58,10 @@ function Get-ParameterValue {
Write-Debug " Parameter: $($parameter.key)"
$key = $parameter.Key

# Support parameter aliases in the config file by changing the alias to the parameter name
# If the value is not in the file defaults AND was not set by the user ...
if (-not $FileDefaults.ContainsKey($key) -and -not $BoundParameters.ContainsKey($key)) {
# Support parameter aliases in the config file (by changing their names)
if ($FromFile -and -not $FileDefaults.ContainsKey($key) -and -not $BoundParameters.ContainsKey($key)) {
# Check if any of the aliases are in the file defaults
Write-Debug " Aliases: $($parameter.Value.Aliases -join ', ')"
foreach ($k in @($parameter.Value.Aliases)) {
if ($null -ne $k -and $FileDefaults.ContainsKey($k)) {
Expand All @@ -71,30 +73,30 @@ function Get-ParameterValue {
}
}

# Bound parameter values > build.psd1 values > default parameters values
if ($CallersInvocation) {
# If it's in the defaults AND it was not already set at a higher precedence
if ($FileDefaults.ContainsKey($Parameter) -and -not ($BoundParameters.ContainsKey($Parameter))) {
# If it's in the file defaults (now) AND it was not already set at a higher precedence
if ($FromFile -and $FileDefaults.ContainsKey($Parameter) -and -not ($BoundParameters.ContainsKey($Parameter))) {
Write-Debug "Export $Parameter = $($FileDefaults[$Parameter])"
$BoundParameters[$Parameter] = $FileDefaults[$Parameter]
# Set the variable in the _callers_ SessionState as well as our return hashtable
$PSCmdlet.SessionState.PSVariable.Set($Parameter, $FileDefaults[$Parameter])
}

# Bound parameter values > build.psd1 values > default parameters values
if (-not $FileDefaults.ContainsKey($key) -and -not $BoundParameters.ContainsKey($key)) {
# If it's still NOT in the file defaults and was not already set, check if there's a default value
} elseif (-not $FileDefaults.ContainsKey($key) -and -not $BoundParameters.ContainsKey($key)) {
# Reading the current value of the $key variable returns either the bound parameter or the default
if ($null -ne ($value = $PSCmdlet.SessionState.PSVariable.Get($key).Value)) {
Write-Debug " From Default: $($BoundParameters[$key] -join ', ')"
if ($value -ne ($null -as $parameter.Value.ParameterType)) {
$BoundParameters[$key] = $value
}
}
if ($BoundParameters.ContainsKey($key)) {
Write-Debug " From Parameter: $($BoundParameters[$key] -join ', ')"
} elseif ($BoundParameters[$key]) {
Write-Debug " From Default: $($BoundParameters[$key] -join ', ')"
}
# Otherwise, it was set by the user, or ...
} elseif ($BoundParameters[$key]) {
Write-Debug " From Parameter: $($BoundParameters[$key] -join ', ')"
# We'll set it from the file
} elseif ($FileDefaults[$key]) {
Write-Debug " From File: $($FileDefaults[$key] -join ', ')"
$BoundParameters[$key] = $FileDefaults[$key]
}
}
}
Expand Down
22 changes: 21 additions & 1 deletion Specs/Configuration.Steps.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ Then "a settings file named (\S+) should exist(?:(?: in the (?<Scope>\S+) folder
}

Given "a passthru command '(?<Command>[A-Z][a-z]+-[A-Z][a-z]+)' with (?<Parameters>.*) parameters" {
param($Command, $Parameters)
param($Command, $Parameters)

[string[]]$Parameters = $Parameters -split "\s*and\s*" | % { $_.Trim("['`"]") }

Expand All @@ -787,6 +787,26 @@ Given "a passthru command '(?<Command>[A-Z][a-z]+-[A-Z][a-z]+)' with (?<Paramete
Invoke-Expression $Function
}

Given "a passthru command '(?<Command>[A-Z][a-z]+-[A-Z][a-z]+)' with (?<Parameters>.*) parameters that calls Get-ParameterValue(?<FromFile> with a file config)?" {
param($Command, $Parameters, $FromFile)

[string[]]$Parameters = $Parameters -split "\s*and\s*"

$Function = "
function $Command {
param(
`$$($Parameters -join ", `$"),
[Alias('Alias')]
`$ExtraParameter
)
`$global:DebugPreference = 'Continue'
Get-ParameterValue $(if($FromFile){ "-FromFile Verb.psd1" })
`$global:DebugPreference = 'SilentlyContinue'
}
"
Invoke-Expression $Function
}

Given "an example New-User command" {
function New-User {
[CmdletBinding()]
Expand Down
113 changes: 113 additions & 0 deletions Specs/ConfiguredParameters.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
Feature: Configure Command From Working Directory

There is a command to support loading default parameter values from the working directory

Background:
Given the configuration module is imported with testing paths:
| Enterprise | User | Machine |
| TestDrive:/EnterprisePath | TestDrive:/UserPath | TestDrive:/MachinePath |

@Functions @Import
Scenario: Loading Default Settings
Given a passthru command 'Test-Verb' with UserName and Age parameters
And a settings file named Verb.psd1 in the current folder
"""
@{
UserName = 'Joel'
Age = 42
}
"""
When I call Test-Verb
Then the output object's use rName should be Joel
And the output object's Age should be 42

@Functions @Import
Scenario: Overriding Default Settings
Given a passthru command 'Test-Verb' with UserName and Age parameters
And a settings file named Verb.psd1 in the current folder
"""
@{
UserName = 'Joel'
Age = 42
}
"""
When I call Test-Verb Mark
Then the output object's userName should be Mark
And the output object's Age should be 42

@Functions @Import
Scenario: Overriding Default Settings Works on any Parameter
Given a passthru command 'Test-Verb' with UserName and Age parameters
And a settings file named Verb.psd1 in the current folder
"""
@{
UserName = 'Joel'
Age = 42
}
"""
When I call Test-Verb -Age 10
Then the output object's userName should be Joel
And the output object's Age should be 10

@Functions @Import
Scenario: New-User Example
Given an example New-User command
And a settings file named User.psd1 in the current folder
"""
@{
Domain = 'HuddledMasses.org'
}
"""
When I call New-User Joel Bennett
Then the output object's EMail should be Joel.Bennett@HuddledMasses.org

@Functions @Import
Scenario: New-User Example Two (overwriting)
Given an example New-User command
And a settings file named User.psd1 in the current folder
"""
@{
Permissions = @{
Access = "Administrator"
}
}
"""
And a settings file named User.psd1 in the parent folder
"""
@{
Department = "Security"
Permissions = @{
Access = "User"
}
}
"""
And a settings file named User.psd1
"""
@{
Domain = "HuddledMasses.org"
}
"""
When I call New-User Joel Bennett
Then the output object's EMail should be Joel.Bennett@HuddledMasses.org
And the output object's Department should be Security
And the output object's Permissions should be of type [hashtable]
And the output object's Permissions.Access should be Administrator


@Functions @Import
Scenario: New-User Example Three
Given an example New-User command
And a settings file named SecurityUser.psd1 in the current folder
"""
@{
Domain = 'HuddledMasses.org'
Permissions = @{
Access = "Administrator"
}
}
"""
When I call New-User Joel Bennett -Department Security
Then the output object's EMail should be Joel.Bennett@HuddledMasses.org
And the output object's Permissions should be of type [hashtable]
And the output object's Permissions.Access should be of type [string]
And the output object's Permissions.Access should be Administrator
119 changes: 32 additions & 87 deletions Specs/DefaultParameters.feature
Original file line number Diff line number Diff line change
@@ -1,113 +1,58 @@
Feature: Configure Command From Working Directory
Feature: Get PSBoundParameters plus default values plus a config file

There is a command to support loading default parameter values from the working directory
There is a command to support merging PSBoundParameters with parmeter default values
That command supports overwriting the default values with values from a config file

Background:
Given the configuration module is imported with testing paths:
| Enterprise | User | Machine |
| TestDrive:/EnterprisePath | TestDrive:/UserPath | TestDrive:/MachinePath |
Given the configuration module is imported

@Functions @Import
@Functions @ParameterValue
Scenario: Loading Default Settings
Given a passthru command 'Test-Verb' with UserName and Age parameters
And a settings file named Verb.psd1 in the current folder
"""
@{
UserName = 'Joel'
Age = 42
}
"""
When I call Test-Verb
Then the output object's userName should be Joel
Given a passthru command 'Test-Verb' with UserName and Age=42 parameters that calls Get-ParameterValue
When I call Test-Verb Joel
Then the output object's UserName should be Joel
And the output object's Age should be 42

@Functions @Import
@Functions @ParameterValue
Scenario: Loading Default Settings
Given a passthru command 'Test-Verb' with UserName and Age=12 parameters that calls Get-ParameterValue
When I call Test-Verb Joel
Then the output object's UserName should be Joel
And the output object's Age should be 12

@Functions @ParameterValue
Scenario: Overriding Default Settings
Given a passthru command 'Test-Verb' with UserName and Age parameters
Given a passthru command 'Test-Verb' with UserName='Sarah' and Age=12 parameters that calls Get-ParameterValue
When I call Test-Verb Joel 24
Then the output object's UserName should be Joel
And the output object's Age should be 24

@Functions @ParameterValue
Scenario: Configuration file
Given a passthru command 'Test-Verb' with UserName='Sarah' and Age=12 parameters that calls Get-ParameterValue with a file config
And a settings file named Verb.psd1 in the current folder
"""
@{
UserName = 'Joel'
Age = 42
}
"""
When I call Test-Verb Mark
Then the output object's userName should be Mark
And the output object's Age should be 42
When I call Test-Verb -Age 10
Then the output object's userName should be Joel
And the output object's Age should be 10

@Functions @Import
Scenario: Overriding Default Settings Works on any Parameter
Given a passthru command 'Test-Verb' with UserName and Age parameters
@Functions @ParameterValue
Scenario: Configuration file with aliases
Given a passthru command 'Test-Verb' with UserName='Sarah' and Age=12 parameters that calls Get-ParameterValue with a file config
And a settings file named Verb.psd1 in the current folder
"""
@{
UserName = 'Joel'
Age = 42
Alias = 'Supports Aliases'
}
"""
When I call Test-Verb -Age 10
Then the output object's userName should be Joel
And the output object's Age should be 10

@Functions @Import
Scenario: New-User Example
Given an example New-User command
And a settings file named User.psd1 in the current folder
"""
@{
Domain = 'HuddledMasses.org'
}
"""
When I call New-User Joel Bennett
Then the output object's EMail should be Joel.Bennett@HuddledMasses.org

@Functions @Import
Scenario: New-User Example Two (overwriting)
Given an example New-User command
And a settings file named User.psd1 in the current folder
"""
@{
Permissions = @{
Access = "Administrator"
}
}
"""
And a settings file named User.psd1 in the parent folder
"""
@{
Department = "Security"
Permissions = @{
Access = "User"
}
}
"""
And a settings file named User.psd1
"""
@{
Domain = "HuddledMasses.org"
}
"""
When I call New-User Joel Bennett
Then the output object's EMail should be Joel.Bennett@HuddledMasses.org
And the output object's Department should be Security
And the output object's Permissions should be of type [hashtable]
And the output object's Permissions.Access should be Administrator


@Functions @Import
Scenario: New-User Example Three
Given an example New-User command
And a settings file named SecurityUser.psd1 in the current folder
"""
@{
Domain = 'HuddledMasses.org'
Permissions = @{
Access = "Administrator"
}
}
"""
When I call New-User Joel Bennett -Department Security
Then the output object's EMail should be Joel.Bennett@HuddledMasses.org
And the output object's Permissions should be of type [hashtable]
And the output object's Permissions.Access should be of type [string]
And the output object's Permissions.Access should be Administrator
And the output object's ExtraParameter should be Supports Aliases
3 changes: 2 additions & 1 deletion Specs/ScriptAnalyzer.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Feature: Passes Script Analyzer

Scenario: ScriptAnalyzer on the compiled module output
Given the configuration module is imported
When we run ScriptAnalyzer on 'C:\Users\Jaykul\Projects\Modules\Configuration\1.4.5' with 'C:\Users\Jaykul\Projects\Modules\Configuration\PSScriptAnalyzerSettings.psd1'
When we run ScriptAnalyzer on 'C:\Users\Jaykul\Projects\Modules\Configuration\1.5.5' with 'C:\Users\Jaykul\Projects\Modules\Configuration\PSScriptAnalyzerSettings.psd1'

Then it passes the ScriptAnalyzer rule PSAlignAssignmentStatement
Then it passes the ScriptAnalyzer rule PSAvoidUsingCmdletAliases
Expand Down Expand Up @@ -58,6 +58,7 @@ Feature: Passes Script Analyzer
Then it passes the ScriptAnalyzer rule PSUsePSCredentialType
Then it passes the ScriptAnalyzer rule PSShouldProcess
Then it passes the ScriptAnalyzer rule PSUseShouldProcessForStateChangingFunctions
Then it passes the ScriptAnalyzer rule PSUseSingularNouns
Then it passes the ScriptAnalyzer rule PSUseSupportsShouldProcess
Then it passes the ScriptAnalyzer rule PSUseToExportFieldsInManifest
Then it passes the ScriptAnalyzer rule PSUseUsingScopeModifierInNewRunspaces
Expand Down

0 comments on commit 786ab69

Please sign in to comment.