Skip to content

Assert-BoundParameter: Move IfEqualParameterList into IfParameterPresent#165

Merged
johlju merged 11 commits intodsccommunity:mainfrom
johlju:fix/parameter-assert-boundparameter
Aug 27, 2025
Merged

Assert-BoundParameter: Move IfEqualParameterList into IfParameterPresent#165
johlju merged 11 commits intodsccommunity:mainfrom
johlju:fix/parameter-assert-boundparameter

Conversation

@johlju
Copy link
Copy Markdown
Member

@johlju johlju commented Aug 27, 2025

Pull Request (PR) description

  • Assert-BoundParameter
    • Enhanced parameter IfParameterPresent to support both string arrays and
      hashtables for conditional assertion logic.
    • Added alias IfEqualParameterList to parameter IfParameterPresent for
      backward compatibility.

This Pull Request (PR) fixes the following issues

None.

Task list

  • Added an entry to the change log under the Unreleased section of the
    file CHANGELOG.md. Entry should say what was changed and how that
    affects users (if applicable), and reference the issue being resolved
    (if applicable).
  • Documentation added/updated in README.md.
  • Comment-based help added/updated for all new/changed functions.
  • Localization strings added/updated in all localization files as appropriate.
  • Examples appropriately added/updated.
  • Unit tests added/updated. See DSC Community Testing Guidelines.
  • Integration tests added/updated (where possible). See
    DSC Community Testing Guidelines.
  • New/changed code adheres to DSC Community Style Guidelines.

This change is Reviewable

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 27, 2025

Walkthrough

Unifies Assert-BoundParameter gating into a single untyped parameter IfParameterPresent (accepts a hashtable or string[]), keeps alias IfEqualParameterList, adds AtLeastOne parameter set with AtLeastOneList, updates tests and examples, and removes one integration test. CHANGELOG updated accordingly. (≤50 words)

Changes

Cohort / File(s) Summary
Public function: Assert-BoundParameter
source/Public/Assert-BoundParameter.ps1
Replaces separate IfEqualParameterList with a single untyped IfParameterPresent (accepts hashtable or string[]), exposes it across parameter sets (MutuallyExclusiveParameters, RequiredParameter, AtLeastOne), adds alias IfEqualParameterList, adds AtLeastOne set with AtLeastOneList, and generalizes early-return/validation logic.
Private helper: Assert-RequiredCommandParameter (docs/example/formatting)
source/Private/Assert-RequiredCommandParameter.ps1
Example usage changed to RequiredBehavior 'Any' and minor formatting cleanups; no signature or logic changes.
Unit tests: Assert-BoundParameter expectations
tests/Unit/Public/Assert-BoundParameter.Tests.ps1
Updates parameter-set expectation strings and test contexts to reflect -IfParameterPresent <object> and alias-based naming; adds tests exercising IfParameterPresent as both string and string[] usages.
Integration tests: Assert-BoundParameter
tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1
Renames module variable and removes one integration test covering combined multi-condition/value-matching scenario with IfParameterPresent.
Unit tests: import-module robustness & moduleName variable
tests/Unit/Private/Assert-RequiredCommandParameter.Tests.ps1
tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1
tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
Strengthens Import-Module in BeforeAll to -Force -ErrorAction 'Stop', replaces $script:dscModuleName with $script:moduleName in several tests, updates PSDefaultParameterValues teardown, and adjusts assertions where IfParameterPresent behavior changed.
Integration tests: moduleName variable rename
tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1
tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1
tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1
Renames script-scoped variable to $script:moduleName and updates Import-Module calls; no logic changes.
Changelog
CHANGELOG.md
Documents Assert-BoundParameter changes (IfParameterPresent, alias, AtLeastOne), plus unrelated entries: Format-Path (ExpandEnvironmentVariable), Compare-DscParameterState (large hashtable support), and Get-ComputerName cross-platform/FQDN changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant Assert as Assert-BoundParameter
  participant Logic as ValidationLogic

  Caller->>Assert: Invoke with BoundParameterList\nand -IfParameterPresent (hashtable or string[])
  Assert->>Assert: Inspect type of IfParameterPresent

  alt IfParameterPresent is hashtable (param -> expectedValue)
    Assert->>Logic: Verify each key exists and value equals expected
    alt Any mismatch
      Logic-->>Assert: Gate not satisfied
      Assert-->>Caller: Return early (no assertion)
    else All match
      Logic-->>Assert: Gate satisfied
      Assert->>Logic: Run parameter-set checks (MutuallyExclusive/Required/AtLeastOne)
      Logic-->>Caller: Assertion result
    end
  else IfParameterPresent is string[]
    Assert->>Logic: Check intersection with BoundParameterList
    alt None present
      Logic-->>Assert: Gate not satisfied
      Assert-->>Caller: Return early (no assertion)
    else Any present
      Logic-->>Assert: Gate satisfied
      Assert->>Logic: Run parameter-set checks
      Logic-->>Caller: Assertion result
    end
  end

  note right of Assert: `IfEqualParameterList` is an alias to `IfParameterPresent` (backcompat)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

johlju and others added 2 commits August 27, 2025 06:45
…ng arrays and hashtables; add alias `IfEqualParameterList` for backward compatibility.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (7)
CHANGELOG.md (2)

29-31: Normalize issue link style to match guidelines

Use the “#” form without the “issue ” prefix for consistency with the rest of the file.

-- `Format-Path`
-  - Added parameter `ExpandEnvironmentVariable` (issue [#147](https://github.com/dsccommunity/DscResource.Common/issues/147)).
+- `Format-Path`
+  - Added parameter `ExpandEnvironmentVariable` [#147](https://github.com/dsccommunity/DscResource.Common/issues/147).

36-41: Minor grammar: “fall back” (verb), not “fallback” (noun)

Also remove “cross-platform implementation” redundancy.

-  - Replaced platform-specific logic with cross-platform implementation using
+  - Replaced platform-specific logic with a cross-platform approach using
     `[System.Environment]::MachineName` for consistent short name behavior.
   - Enhanced FQDN functionality to use `[System.Net.Dns]::GetHostEntry()` for
     proper domain name resolution on Windows, Linux, and macOS.
-  - Improved error handling to gracefully fallback to short name when DNS
+  - Improved error handling to gracefully fall back to the short name when DNS
     resolution fails.
source/Public/Assert-BoundParameter.ps1 (4)

55-57: Clarify hashtable gating semantics in help

Tighten wording and fix agreement (“has” vs “have”). Mention exact-match requirement.

-       This parameter can also accept a hashtable of parameter names and their expected
-       values. The assertion will only be performed if all the specified parameters in
-       the BoundParameterList have the exact values specified in this hashtable.
+       This parameter also accepts a hashtable mapping parameter names to expected values.
+       The assertion is performed only when all specified parameters exist in
+       BoundParameterList and their values exactly match those in the hashtable.

122-133: Add example for string[] gating usage

Show the legacy string[] form explicitly to reduce ambiguity and to test single‑value behavior.

Proposed addition (outside diff scope, for an extra .EXAMPLE block):

    .EXAMPLE
        Assert-BoundParameter -BoundParameterList $PSBoundParameters `
            -AtLeastOneList @('Severity', 'MessageId') `
            -IfParameterPresent @('Ensure')

        Performs the assertion only when the parameter 'Ensure' is present.

163-165: Declare explicit parameter type for IfParameterPresent

Guidelines require explicit types. Use [System.Object] since the parameter accepts either hashtable or string[].

-        [Alias('IfEqualParameterList')]
-        $IfParameterPresent,
+        [Alias('IfEqualParameterList')]
+        [System.Object]
+        $IfParameterPresent,

224-233: Avoid mutating $PSBoundParameters; pass a cloned hashtable

Mutation is safe here but cloning prevents side effects if future changes reuse $PSBoundParameters. Also ensures type consistency when converting keys.

-            if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
+            if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
             {
                 # Convert hashtable to string array if needed for Assert-RequiredCommandParameter
                 if ($IfParameterPresent -is [System.Collections.Hashtable])
                 {
                     # For hashtable case, we already handled the early return above
                     # Pass the keys as IfParameterPresent to Assert-RequiredCommandParameter
-                    $PSBoundParameters.IfParameterPresent = $IfParameterPresent.Keys
+                    $localParams = [System.Collections.Hashtable]::new($PSBoundParameters)
+                    $localParams.IfParameterPresent = [string[]] $IfParameterPresent.Keys
+                    $PSBoundParameters = $localParams
                 }
             }
tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (1)

317-579: Add coverage for string[] gating and single-string input

Current tests validate hashtable alias via IfEqualParameterList. Add cases for:

  • -IfParameterPresent @('Ensure') with MutuallyExclusiveParameters and AtLeastOne.
  • Single string input -IfParameterPresent 'Ensure' to guard against char-array pitfalls (fixed in code).

Additional test snippet (outside diff scope):

Context 'When using IfParameterPresent (string[])' {
    It 'Should gate MutuallyExclusiveParameters when Ensure is present' {
        {
            $params = @{
                BoundParameterList     = @{ Severity = 'High'; MessageId = '12345'; Ensure = 'Present' }
                MutuallyExclusiveList1 = @('Severity')
                MutuallyExclusiveList2 = @('MessageId')
                IfParameterPresent     = @('Ensure')
            }
            Assert-BoundParameter @params
        } | Should -Throw
    }

    It 'Should return early when Ensure is absent (AtLeastOne)' {
        {
            $params = @{
                BoundParameterList = @{ OtherParam = 'value' }
                AtLeastOneList     = @('Severity', 'MessageId')
                IfParameterPresent = @('Ensure')
            }
            Assert-BoundParameter @params
        } | Should -Not -Throw
    }
}

Context 'When using IfParameterPresent (single string)' {
    It 'Should treat single string as list' {
        {
            $params = @{
                BoundParameterList = @{ Ensure = 'Present' }
                AtLeastOneList     = @('Severity', 'MessageId')
                IfParameterPresent = 'Ensure'
            }
            Assert-BoundParameter @params
        } | Should -Throw
    }
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ff86007 and a44da65.

📒 Files selected for processing (4)
  • CHANGELOG.md (2 hunks)
  • source/Public/Assert-BoundParameter.ps1 (5 hunks)
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1 (0 hunks)
  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (1 hunks)
💤 Files with no reviewable changes (1)
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1
🧰 Additional context used
📓 Path-based instructions (6)
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow

  • Run project scripts in PowerShell from repository root
  • Build after source changes: .\build.ps1 -Tasks build
  • Test workflow: Build → Invoke-Pester -Path @('<test paths>') -Output Detailed
  • New session required after class changes

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow guidelines over existing code patterns
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1
  • CHANGELOG.md
  • source/Public/Assert-BoundParameter.ps1
**/*.ps?(m|d)1

⚙️ CodeRabbit configuration file

**/*.ps?(m|d)1: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Multi-line: each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description.
  • ...

Files:

  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1
  • source/Public/Assert-BoundParameter.ps1
**/*.[Tt]ests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • One Describe block per file matching the tested entity name
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'
  • Prefer -BeTrue/-BeFalse over -Be $true/-Be $false
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands

File Organization

  • Class resources: tests/Unit/Classes/{Name}.Tests.ps1
  • Public commands: tests/Unit/Public/{Name}.Tests.ps1
  • Private functions: tests/Unit/Private/{Name}.Tests.ps1

Data-Driven Tests

  • Define variables in separate BeforeDiscovery for -ForEach (close to usage)
  • -ForEach allowed on Context and It blocks
  • Keep scope close to usage context

Best Practices

  • Inside It blocks, assign unused return objects to $null (unless part of ...

Files:

  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: # Markdown Style Guidelines

  • Wrap lines at word boundaries when over 80 characters (except tables/code blocks)
  • Use 2 spaces for indentation
  • Use '1.' for all items in ordered lists (1/1/1 numbering style)
  • Disable MD013 rule by adding a comment for tables/code blocks exceeding 80 characters
  • Empty lines required before/after code blocks and headings (except before line 1)
  • Escape backslashes in file paths only (not in code blocks)
  • Code blocks must specify language identifiers

Text Formatting

  • Parameters: bold
  • Values/literals: inline code
  • Resource/module/product names: italic
  • Commands/files/paths: inline code

Files:

  • CHANGELOG.md
CHANGELOG.md

⚙️ CodeRabbit configuration file

CHANGELOG.md: # Changelog Guidelines

  • Always update the Unreleased section in CHANGELOG.md
  • Use Keep a Changelog format
  • Describe notable changes briefly, ≤2 items per change type
  • Reference issues using format #<issue_number>
  • No empty lines between list items in same section
  • Do not add item if there are already an existing item for the same change

Files:

  • CHANGELOG.md
source/**/*.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/SqlServerDsc.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_SqlDscDatabase_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Assert-BoundParameter.ps1
🪛 LanguageTool
CHANGELOG.md

[grammar] ~14-~14: There might be a mistake here.
Context: ...htables for conditional assertion logic. - Added alias IfEqualParameterList to pa...

(QB_NEW_EN)


[grammar] ~39-~39: There might be a mistake here.
Context: ...resolution on Windows, Linux, and macOS. - Improved error handling to gracefully fa...

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: dsccommunity.DscResource.Common (Test HQRM)
  • GitHub Check: dsccommunity.DscResource.Common (Test macOS)
  • GitHub Check: dsccommunity.DscResource.Common (Test Windows (PowerShell Core))
  • GitHub Check: dsccommunity.DscResource.Common (Test Windows (Windows PowerShell))
  • GitHub Check: dsccommunity.DscResource.Common (Test Linux)
  • GitHub Check: dsccommunity.DscResource.Common (Build Package Module)
🔇 Additional comments (3)
tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (3)

58-58: Same verification for RequiredParameter set

Ensure the expected string matches actual output on CI images.

Use the same script as above and compare the RequiredParameter set line.


63-63: Same verification for AtLeastOne set

Confirm consistency on all target PS versions.

Use the same script as above and check the AtLeastOne set line.


53-53: Confirm ParameterSetMetadata.ToString() Casing Consistency Across PowerShell Versions

ParameterSetMetadata.ToString() can emit different casing for the <object> placeholder depending on the PowerShell edition and version. To ensure our test’s MockExpectedParameters string is correct on all supported PS versions, please verify the actual output on each:

• File needing attention:
• tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (around line 53)

• Steps to verify:
• On Windows PowerShell 5.1
powershell powershell -NoLogo -NoProfile -Command "Get-Command Assert-BoundParameter | % ParameterSets | % ToString"
• On PowerShell 7+ (Core)
powershell pwsh -NoLogo -NoProfile -Command "Get-Command Assert-BoundParameter | % ParameterSets | % ToString"

• What to look for:
Ensure each invocation prints the parameter list including [-IfParameterPresent <object>] (lowercase “object”). If any version returns [-IfParameterPresent <Object>] (or differs in casing), update the string on line 53 accordingly:

-    MockExpectedParameters = '-BoundParameterList <hashtable> -MutuallyExclusiveList1 <string[]> -MutuallyExclusiveList2 <string[]> [-IfParameterPresent <object>] [<CommonParameters>]'
+    # adjust <object> casing here if necessary to match PS output

Comment thread CHANGELOG.md Outdated
Comment thread source/Public/Assert-BoundParameter.ps1
johlju added 5 commits August 27, 2025 07:12
…quiredBehavior; remove unnecessary line breaks in error messages.
…ent; pass parameters to Assert-RequiredCommandParameter for enhanced error messaging.
…ct expected behavior; change error assertions to indicate no errors should be thrown.
…ing; add -Force and -ErrorAction 'Stop' parameters for improved reliability.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/Private/Assert-RequiredCommandParameter.ps1 (1)

23-36: Fix example parameter name: use -BoundParameterList (not -BoundParameter).

Examples currently reference a non-existent parameter name, which can mislead users. Keep the updated RequiredBehavior 'Any' example, but correct the parameter name.

Apply this diff:

-        Assert-RequiredCommandParameter -BoundParameter $PSBoundParameters -RequiredParameter @('PBStartPortRange', 'PBEndPortRange')
+        Assert-RequiredCommandParameter -BoundParameterList $PSBoundParameters -RequiredParameter @('PBStartPortRange', 'PBEndPortRange')

-        Assert-RequiredCommandParameter -BoundParameter $PSBoundParameters -RequiredParameter @('Property2', 'Property3') -IfParameterPresent @('Property1')
+        Assert-RequiredCommandParameter -BoundParameterList $PSBoundParameters -RequiredParameter @('Property2', 'Property3') -IfParameterPresent @('Property1')
♻️ Duplicate comments (1)
source/Public/Assert-BoundParameter.ps1 (1)

171-195: Fix single-string being treated as char array and empty-match check.

Single string input causes -in to compare against characters; and boolean check on an empty array is unreliable. Normalize to string[] and use Count.

     if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
     {
         if ($IfParameterPresent -is [System.Collections.Hashtable])
         {
             # Handle hashtable case (original IfEqualParameterList behavior)
             foreach ($parameterName in $IfParameterPresent.Keys)
             {
-                if (-not $BoundParameterList.ContainsKey($parameterName) -or $BoundParameterList[$parameterName] -ne $IfParameterPresent[$parameterName])
+                if (-not $BoundParameterList.ContainsKey($parameterName) -or $BoundParameterList[$parameterName] -ne $IfParameterPresent[$parameterName])
                 {
                     return
                 }
             }
         }
         else
         {
-            # Handle string array case (original IfParameterPresent behavior)
-            $hasIfParameterPresent = $BoundParameterList.Keys.Where( { $_ -in $IfParameterPresent } )
-
-            if (-not $hasIfParameterPresent)
+            # Normalize single string to array and handle original IfParameterPresent behavior
+            if ($IfParameterPresent -is [string]) { $IfParameterPresent = @($IfParameterPresent) }
+            $hasIfParameterPresent = $BoundParameterList.Keys.Where({ $_ -in $IfParameterPresent })
+
+            if ($hasIfParameterPresent.Count -eq 0)
             {
                 return
             }
         }
     }

Optional: If you intended case-sensitive value matching for hashtables, change -ne above to -cne (and update docs accordingly).

To confirm test coverage for the single-string case across parameter sets, run:

#!/bin/bash
# Find usages of IfParameterPresent in tests: hashtable vs single string vs string[]
rg -n -C2 -g 'tests/**' -P "Assert-BoundParameter.*-IfParameterPresent\s*@\{" \
  && echo "--- hashtable cases above ---" \
  && rg -n -C2 -g 'tests/**' -P "Assert-BoundParameter.*-IfParameterPresent\s*'[^']+'" \
  && echo "--- single string cases above ---" \
  && rg -n -C2 -g 'tests/**' -P 'Assert-BoundParameter.*-IfParameterPresent\s*@\([^\)]*\)'
🧹 Nitpick comments (4)
CHANGELOG.md (2)

12-16: Tighten wording and apply code formatting for types/alias line.

Minor clarity/style improvement.

Apply this diff:

-  - Enhanced parameter `IfParameterPresent` to support both string arrays and
-    hashtables for conditional assertion logic.
-  - Added alias `IfEqualParameterList` to parameter `IfParameterPresent` for
-    backward compatibility.
+  - Enhanced parameter `IfParameterPresent` to support both `string[]` and
+    `hashtable` inputs for conditional assertion logic.
+  - Added alias `IfEqualParameterList` to `IfParameterPresent` for backward compatibility.

40-41: Grammar: “fall back” (verb) instead of “fallback.”

Small grammar fix.

Apply this diff:

-  - Improved error handling to gracefully fallback to short name when DNS
+  - Improved error handling to gracefully fall back to short name when DNS
source/Public/Assert-BoundParameter.ps1 (2)

55-57: Doc says “exact values” but implementation is case-insensitive (-ne). Align wording or code.

Currently comparisons use case-insensitive operators. Either update help text or switch to case-sensitive compare.

Apply one of:

Option A (docs): clarify case-insensitive match.

-       values. The assertion will only be performed if all the specified parameters in
-       the BoundParameterList have the exact values specified in this hashtable.
+       values. The assertion will only be performed if all the specified parameters in
+       the BoundParameterList have values equal (case-insensitive) to those specified in this hashtable.

Option B (code): enforce case-sensitive equality (see lines 177–181).


163-165: Consider explicit typing for IfParameterPresent to satisfy style guide.

Keep dual-form flexibility but declare a full type for consistency.

         [Parameter(ParameterSetName = 'AtLeastOne')]
         [Alias('IfEqualParameterList')]
-        $IfParameterPresent,
+        [System.Object]
+        $IfParameterPresent,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a44da65 and 54783f5.

📒 Files selected for processing (6)
  • CHANGELOG.md (2 hunks)
  • source/Private/Assert-RequiredCommandParameter.ps1 (1 hunks)
  • source/Public/Assert-BoundParameter.ps1 (5 hunks)
  • tests/Unit/Private/Assert-RequiredCommandParameter.Tests.ps1 (3 hunks)
  • tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1 (1 hunks)
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1 (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow

  • Run project scripts in PowerShell from repository root
  • Build after source changes: .\build.ps1 -Tasks build
  • Test workflow: Build → Invoke-Pester -Path @('<test paths>') -Output Detailed
  • New session required after class changes

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow guidelines over existing code patterns
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
  • source/Private/Assert-RequiredCommandParameter.ps1
  • tests/Unit/Private/Assert-RequiredCommandParameter.Tests.ps1
  • source/Public/Assert-BoundParameter.ps1
  • CHANGELOG.md
**/*.ps?(m|d)1

⚙️ CodeRabbit configuration file

**/*.ps?(m|d)1: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Multi-line: each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description.
  • ...

Files:

  • tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
  • source/Private/Assert-RequiredCommandParameter.ps1
  • tests/Unit/Private/Assert-RequiredCommandParameter.Tests.ps1
  • source/Public/Assert-BoundParameter.ps1
**/*.[Tt]ests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • One Describe block per file matching the tested entity name
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'
  • Prefer -BeTrue/-BeFalse over -Be $true/-Be $false
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands

File Organization

  • Class resources: tests/Unit/Classes/{Name}.Tests.ps1
  • Public commands: tests/Unit/Public/{Name}.Tests.ps1
  • Private functions: tests/Unit/Private/{Name}.Tests.ps1

Data-Driven Tests

  • Define variables in separate BeforeDiscovery for -ForEach (close to usage)
  • -ForEach allowed on Context and It blocks
  • Keep scope close to usage context

Best Practices

  • Inside It blocks, assign unused return objects to $null (unless part of ...

Files:

  • tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
  • tests/Unit/Private/Assert-RequiredCommandParameter.Tests.ps1
source/**/*.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/SqlServerDsc.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_SqlDscDatabase_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Private/Assert-RequiredCommandParameter.ps1
  • source/Public/Assert-BoundParameter.ps1
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: # Markdown Style Guidelines

  • Wrap lines at word boundaries when over 80 characters (except tables/code blocks)
  • Use 2 spaces for indentation
  • Use '1.' for all items in ordered lists (1/1/1 numbering style)
  • Disable MD013 rule by adding a comment for tables/code blocks exceeding 80 characters
  • Empty lines required before/after code blocks and headings (except before line 1)
  • Escape backslashes in file paths only (not in code blocks)
  • Code blocks must specify language identifiers

Text Formatting

  • Parameters: bold
  • Values/literals: inline code
  • Resource/module/product names: italic
  • Commands/files/paths: inline code

Files:

  • CHANGELOG.md
CHANGELOG.md

⚙️ CodeRabbit configuration file

CHANGELOG.md: # Changelog Guidelines

  • Always update the Unreleased section in CHANGELOG.md
  • Use Keep a Changelog format
  • Describe notable changes briefly, ≤2 items per change type
  • Reference issues using format #<issue_number>
  • No empty lines between list items in same section
  • Do not add item if there are already an existing item for the same change

Files:

  • CHANGELOG.md
🪛 LanguageTool
CHANGELOG.md

[grammar] ~14-~14: There might be a mistake here.
Context: ...htables for conditional assertion logic. - Added alias IfEqualParameterList to pa...

(QB_NEW_EN)


[grammar] ~39-~39: There might be a mistake here.
Context: ...resolution on Windows, Linux, and macOS. - Improved error handling to gracefully fa...

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: dsccommunity.DscResource.Common (Build Package Module)
🔇 Additional comments (8)
tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1 (1)

32-32: LGTM: deterministic module import.

Using -Force and -ErrorAction 'Stop' improves test reliability.

tests/Unit/Private/Assert-RequiredCommandParameter.Tests.ps1 (3)

32-32: LGTM: deterministic module import.

Force reload and fail-fast behavior is correct.


146-162: LGTM: behavior aligns with IfParameterPresent + All.

No exception when both gate and required parameters are present is correct.


242-258: LGTM: behavior aligns with IfParameterPresent + Any.

No exception when gate parameters are present and at least one required parameter is present is correct.

source/Public/Assert-BoundParameter.ps1 (4)

112-116: Example for hashtable gating looks good.


123-127: Example for RequiredParameter + hashtable gating looks good.


129-133: Example for AtLeastOne + hashtable gating looks good.


219-241: Passing IfParameterPresent through to Assert-RequiredCommandParameter is a good improvement.

Keeps gating semantics while improving error messages. Ensure tests cover both hashtable and string-array flows.

Comment thread tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
johlju added 3 commits August 27, 2025 07:31
…stency; update import statements to enhance error handling with -Force and -ErrorAction 'Stop'.
…usage; add new tests for IfParameterPresent conditions with string and array inputs.
Copy link
Copy Markdown
Member Author

@johlju johlju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@johlju reviewed 4 of 6 files at r3, 7 of 7 files at r4, all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @johlju)

@johlju
Copy link
Copy Markdown
Member Author

johlju commented Aug 27, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 27, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/Public/Assert-BoundParameter.ps1 (1)

172-196: Bug: single string for IfParameterPresent is treated as char array; empty-match check is fragile.

Normalize single strings to string[] and use .Count for emptiness to avoid false early returns.

Apply this diff:

-    # Early return if IfParameterPresent conditions are not met
+    # Early return if IfParameterPresent conditions are not met
     if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
     {
         if ($IfParameterPresent -is [System.Collections.Hashtable])
         {
             # Handle hashtable case (original IfEqualParameterList behavior)
             foreach ($parameterName in $IfParameterPresent.Keys)
             {
                 if (-not $BoundParameterList.ContainsKey($parameterName) -or $BoundParameterList[$parameterName] -ne $IfParameterPresent[$parameterName])
                 {
                     return
                 }
             }
         }
         else
         {
-            # Handle string array case (original IfParameterPresent behavior)
-            $hasIfParameterPresent = $BoundParameterList.Keys.Where( { $_ -in $IfParameterPresent } )
-
-            if (-not $hasIfParameterPresent)
+            # Handle string / string[] case (original IfParameterPresent behavior)
+            if ($IfParameterPresent -is [string]) { $IfParameterPresent = @($IfParameterPresent) }
+            $hasIfParameterPresent = $BoundParameterList.Keys.Where({ $_ -in $IfParameterPresent })
+
+            if ($hasIfParameterPresent.Count -eq 0)
             {
                 return
             }
         }
     }
♻️ Duplicate comments (1)
tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1 (1)

27-33: Resolved: wrong Import-Module variable from earlier review

Switched to defining and using $script:moduleName everywhere (Import-Module, PSDefaultParameterValues, teardown). This addresses the prior mismatch noted in earlier comments.

Also applies to: 42-42

🧹 Nitpick comments (4)
tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1 (1)

228-288: Add coverage for the new hashtable form of IfParameterPresent

You test hashtable via the alias IfEqualParameterList; add one direct IfParameterPresent hashtable case to exercise the new input type explicitly.

Example to add under the existing “When using IfParameterPresent condition” context:

It 'Should honor hashtable form of IfParameterPresent' {
    {
        $assertBoundParameterParameters = @{
            BoundParameterList   = @{
                ConfigType = 'Advanced'
                Param1     = 'Value1'
                Param2     = 'Value2'
            }
            MutuallyExclusiveList1 = @('Param1')
            MutuallyExclusiveList2 = @('Param2')
            IfParameterPresent     = @{ ConfigType = 'Advanced' } # hashtable form
            ErrorAction            = 'Stop'
        }

        Assert-BoundParameter @assertBoundParameterParameters
    } | Should -Throw
}
tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (2)

53-64: Parameter set strings look correct; consider brittleness across PS versions.

Exact string equality on ParameterListAsString can be version‑sensitive. If flakiness appears, switch to a regex/contains-based assert around the new [-IfParameterPresent <object>] token.


595-670: Optional: add direct IfParameterPresent tests for AtLeastOne/MutuallyExclusive.

You have alias (hashtable) coverage; mirror with direct IfParameterPresent string/string[] for AtLeastOne (and optionally MutuallyExclusive) to fully exercise the new input forms.

source/Public/Assert-BoundParameter.ps1 (1)

226-239: Optional: normalize before splatting to Assert-RequiredCommandParameter.

Be explicit to pass string[] for consistency (even when caller passed a single string).

Apply this diff:

             if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
             {
                 if ($IfParameterPresent -is [System.Collections.Hashtable])
                 {
                     # For hashtable case, pass the keys as IfParameterPresent
                     $assertRequiredCommandParameterParams.IfParameterPresent = $IfParameterPresent.Keys
                 }
                 else
                 {
-                    # For string array case, pass as-is
-                    $assertRequiredCommandParameterParams.IfParameterPresent = $IfParameterPresent
+                    # For string / string[] case, pass as string[]
+                    if ($IfParameterPresent -is [string]) { $IfParameterPresent = @($IfParameterPresent) }
+                    $assertRequiredCommandParameterParams.IfParameterPresent = [string[]] $IfParameterPresent
                 }
             }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 54783f5 and fdaa88a.

📒 Files selected for processing (7)
  • source/Public/Assert-BoundParameter.ps1 (5 hunks)
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1 (1 hunks)
  • tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1 (1 hunks)
  • tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1 (1 hunks)
  • tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1 (1 hunks)
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1 (2 hunks)
  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (8 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**

⚙️ CodeRabbit configuration file

**: # DSC Community Guidelines

Terminology

  • Command: Public command
  • Function: Private function
  • Resource: DSC class-based resource

Build & Test Workflow

  • Run project scripts in PowerShell from repository root
  • Build after source changes: .\build.ps1 -Tasks build
  • Test workflow: Build → Invoke-Pester -Path @('<test paths>') -Output Detailed
  • New session required after class changes

File Organization

  • Public commands: source/Public/{CommandName}.ps1
  • Private functions: source/Private/{FunctionName}.ps1
  • Unit tests: tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1
  • Integration tests: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1

Requirements

  • Follow guidelines over existing code patterns
  • Always update CHANGELOG.md Unreleased section
  • Localize all strings using string keys; remove any orphaned string keys
  • Check DscResource.Common before creating private functions
  • Separate reusable logic into private functions
  • Add unit tests for all commands/functions/resources
  • Add integration tests for all public commands and resources

Files:

  • tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1
  • tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1
  • tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1
  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
  • source/Public/Assert-BoundParameter.ps1
**/*.ps?(m|d)1

⚙️ CodeRabbit configuration file

**/*.ps?(m|d)1: # PowerShell Guidelines

Naming

  • Use descriptive names (3+ characters, no abbreviations)
  • Functions: PascalCase with Verb-Noun format using approved verbs
  • Parameters: PascalCase
  • Variables: camelCase
  • Keywords: lower-case
  • Classes: PascalCase
  • Include scope for script/global/environment variables: $script:, $global:, $env:

File naming

  • Class files: ###.ClassName.ps1 format (e.g. 001.SqlReason.ps1, 004.StartupParameters.ps1)

Formatting

Indentation & Spacing

  • Use 4 spaces (no tabs)
  • One space around operators: $a = 1 + 2
  • One space between type and variable: [String] $name
  • One space between keyword and parenthesis: if ($condition)
  • No spaces on empty lines
  • Try to limit lines to 120 characters

Braces

  • Newline before opening brace (except variable assignments)
  • One newline after opening brace
  • Two newlines after closing brace (one if followed by another brace or continuation)

Quotes

  • Use single quotes unless variable expansion is needed: 'text' vs "text $variable"

Arrays

  • Single line: @('one', 'two', 'three')
  • Multi-line: each element on separate line with proper indentation
  • Do not use the unary comma operator (,) in return statements to force
    an array

Hashtables

  • Empty: @{}
  • Multi-line: each property on separate line with proper indentation
  • Properties: Use PascalCase

Comments

  • Single line: # Comment (capitalized, on own line)
  • Multi-line: <# Comment #> format (opening and closing brackets on own line), and indent text
  • No commented-out code

Comment-based help

  • Always add comment-based help to all functions and scripts
  • Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
  • Comment-based help indentation: keywords 4 spaces, text 8 spaces
  • Include examples for all parameter sets and combinations
  • INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description.
  • ...

Files:

  • tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1
  • tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1
  • tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1
  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
  • source/Public/Assert-BoundParameter.ps1
**/*.[Tt]ests.ps1

⚙️ CodeRabbit configuration file

**/*.[Tt]ests.ps1: # Tests Guidelines

Core Requirements

  • All public commands, private functions and classes must have unit tests
  • All public commands and class-based resources must have integration tests
  • Use Pester v5 syntax only
  • One Describe block per file matching the tested entity name
  • Test code only inside Describe blocks
  • Assertions only in It blocks
  • Never test verbose messages, debug messages or parameter binding behavior
  • Pass all mandatory parameters to avoid prompts

Structure & Scope

  • Public commands: Never use InModuleScope (unless retrieving localized strings)
  • Private functions/class resources: Always use InModuleScope
  • Each scenario = separate Context block
  • Use nested Context blocks for complex scenarios
  • Mocking in BeforeAll (BeforeEach only when required)
  • Setup/teardown in BeforeAll,BeforeEach/AfterAll,AfterEach close to usage

Syntax Rules

  • PascalCase: Describe, Context, It, Should, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Context descriptions start with 'When'
  • It descriptions start with 'Should', must not contain 'when'
  • Mock variables prefix: 'mock'
  • Prefer -BeTrue/-BeFalse over -Be $true/-Be $false
  • No Should -Not -Throw - invoke commands directly
  • Never add an empty -MockWith block
  • Omit -MockWith when returning $null
  • Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName
  • Omit -ModuleName parameter on Pester commands

File Organization

  • Class resources: tests/Unit/Classes/{Name}.Tests.ps1
  • Public commands: tests/Unit/Public/{Name}.Tests.ps1
  • Private functions: tests/Unit/Private/{Name}.Tests.ps1

Data-Driven Tests

  • Define variables in separate BeforeDiscovery for -ForEach (close to usage)
  • -ForEach allowed on Context and It blocks
  • Keep scope close to usage context

Best Practices

  • Inside It blocks, assign unused return objects to $null (unless part of ...

Files:

  • tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1
  • tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1
  • tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1
  • tests/Unit/Public/Assert-BoundParameter.Tests.ps1
  • tests/Unit/Private/Test-DscPropertyIsAssigned.Tests.ps1
tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1

⚙️ CodeRabbit configuration file

tests/[iI]ntegration/**/*.[iI]ntegration.[tT]ests.ps1: # Integration Tests Guidelines

Requirements

  • Location Commands: tests/Integration/Commands/{CommandName}.Integration.Tests.ps1
  • Location Resources: tests/Integration/Resources/{ResourceName}.Integration.Tests.ps1
  • No mocking - real environment only
  • Cover all scenarios and code paths
  • Use Get-ComputerName for computer names in CI
  • Avoid ExpectedMessage for Should -Throw assertions
  • Only run integration tests in CI unless explicitly instructed.
  • Call commands with -Force parameter where applicable (avoids prompting).
  • Use -ErrorAction Stop on commands so failures surface immediately

Required Setup Block

[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
param ()

BeforeDiscovery {
    try
    {
        if (-not (Get-Module -Name 'DscResource.Test'))
        {
            # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
            if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
            {
                # Redirect all streams to $null, except the error stream (stream 2)
                & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
            }

            # If the dependencies have not been resolved, this will throw an error.
            Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
        }
    }
    catch [System.IO.FileNotFoundException]
    {
        throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.'
    }
}

BeforeAll {
    $script:dscModuleName = 'SqlServerDsc'

    Import-Module -Name $script:dscModuleName -Force -ErrorAction 'Stop'
}

Files:

  • tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1
  • tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1
  • tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1
  • tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1
source/**/*.ps1

⚙️ CodeRabbit configuration file

source/**/*.ps1: # Localization Guidelines

Requirements

  • Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages
  • Use localized string keys, not hardcoded strings
  • Assume $script:localizedData is available

String Files

  • Commands/functions: source/en-US/SqlServerDsc.strings.psd1
  • Class resources: source/en-US/{ResourceClassName}.strings.psd1

Key Naming Patterns

  • Format: Verb_FunctionName_Action (underscore separators), e.g. Get_SqlDscDatabase_ConnectingToDatabase

String Format

ConvertFrom-StringData @'
    KeyName = Message with {0} placeholder. (PREFIX0001)
'@

String IDs

  • Format: (PREFIX####)
  • PREFIX: First letter of each word in class or function name (SqlSetup → SS, Get-SqlDscDatabase → GSDD)
  • Number: Sequential from 0001

Usage

Write-Verbose -Message ($script:localizedData.KeyName -f $value1)

Files:

  • source/Public/Assert-BoundParameter.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: dsccommunity.DscResource.Common (Test Publish Code Coverage)
  • GitHub Check: dsccommunity.DscResource.Common (Test Linux)
  • GitHub Check: dsccommunity.DscResource.Common (Test Windows (Windows PowerShell))
  • GitHub Check: dsccommunity.DscResource.Common (Test macOS)
  • GitHub Check: dsccommunity.DscResource.Common (Test Windows (PowerShell Core))
  • GitHub Check: dsccommunity.DscResource.Common (Test HQRM)
  • GitHub Check: dsccommunity.DscResource.Common (Build Package Module)
🔇 Additional comments (10)
tests/Integration/Commands/Set-PSModulePath.Integration.Tests.ps1 (1)

39-41: LGTM: module variable rename is consistent and safe

Consistent use of $script:moduleName and matching Import-Module looks good.

tests/Integration/Commands/Set-DscMachineRebootRequired.Integration.Tests.ps1 (1)

27-29: LGTM: standardized module variable

Rename to $script:moduleName with Import-Module updated correctly.

tests/Integration/Commands/Get-ComputerName.Integration.Tests.ps1 (1)

27-29: LGTM: consistent import pattern

$script:moduleName assignment and Import-Module align with other tests.

tests/Integration/Commands/Assert-BoundParameter.Integration.Tests.ps1 (1)

27-29: LGTM: import rename

Adopts $script:moduleName consistently; import flags are correct.

tests/Unit/Public/Assert-BoundParameter.Tests.ps1 (1)

317-452: Alias coverage LGTM.

Good backward‑compatibility coverage for IfEqualParameterList across all parameter sets.

Also applies to: 459-499, 595-670

source/Public/Assert-BoundParameter.ps1 (5)

55-57: Docs: hashtable form explanation reads well.

Clear statement that all key/value pairs must match to trigger evaluation.


112-121: Examples LGTM.

Good demonstrations for hashtable gating across parameter sets.

Also applies to: 123-123, 129-133


163-166: Alias strategy LGTM.

Keeping IfEqualParameterList as an alias preserves compatibility while unifying the API.


220-224: Delegation object assembly is clean.

Parameter pass‑through for required checks is straightforward.


241-242: Call site LGTM.

Once normalization is in, error messaging from the callee should remain intact.

Comment thread tests/Unit/Public/Assert-BoundParameter.Tests.ps1
@johlju johlju merged commit 5340c7a into dsccommunity:main Aug 27, 2025
10 checks passed
@johlju johlju deleted the fix/parameter-assert-boundparameter branch August 27, 2025 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant