Skip to content

Add prototype to author Microsoft DSC configuration document(s)#4

Open
Gijsreyn wants to merge 7 commits into
mainfrom
gh-3/main/prototype-authoring-experience
Open

Add prototype to author Microsoft DSC configuration document(s)#4
Gijsreyn wants to merge 7 commits into
mainfrom
gh-3/main/prototype-authoring-experience

Conversation

@Gijsreyn
Copy link
Copy Markdown
Collaborator

@Gijsreyn Gijsreyn commented May 29, 2026

Built a first prototype for authoring Microsoft DSC configuration documents from PowerShell.

This branch adds a schema-aware authoring flow that can discover DSC resources through dsc.exe. It generates resource-specific .NET property types and PowerShell functions. After values are set, it can be exported to a valid Microsoft DSC configuration document. The generated types also honor JSON schema defaults, expose enum values for validation and IntelliSense.

It also adds support for adapted resource discovery, configuration variables, and more.

Fixes #3.


This change is Reviewable

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

Warning

Review limit reached

@Gijsreyn, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 50 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc579be6-49ed-4b9c-af22-2586cf70e93f

📥 Commits

Reviewing files that changed from the base of the PR and between 24ceeb7 and 0a96ce1.

📒 Files selected for processing (2)
  • source/Private/ConvertTo-Hashtable.ps1
  • tests/Unit/Private/ConvertTo-Hashtable.Tests.ps1

Walkthrough

Adds end-to-end DSC configuration authoring: embedded Microsoft.DSC types, resource discovery (dsc.exe/manifests/adapter cache), schema-driven C# type generation, dynamic resource functions, expression transpilation, configuration construction/export, helpers, docs, and broad test coverage.

Changes

DSC Configuration Authoring Implementation

Layer / File(s) Summary
Core DSC authoring types
source/Classes/005.MicrosoftDscAuthoringTypes.ps1
Embedded C# types for Microsoft.DSC.Expression, Directives, ResourceDirectives, Resource, Configuration, and AuthoringData.Normalize() used for serialization.
Expression transpilation
source/Private/ConvertTo-DscExpressionText.ps1
Transpiles constrained PowerShell AST nodes into DSC expression text, with validation and error reporting for unsupported forms.
dsc.exe discovery and parsing
source/Classes/006.DscExecutableResourceDiscovery.ps1, source/Private/Invoke-DscResourceDiscovery.ps1
Invoke and parse external DSC executable output, normalize varied JSON shapes, and produce standard resource metadata objects.
Manifest and schema resolution
source/Private/Resolve-DscResourceAuthoringSchemaCommand.ps1, source/Private/ConvertTo-DscResourceAuthoringMetadata.ps1, source/Public/Import-DscResourceAuthoringMetadata.ps1
Read manifests/manifest lists, run schema commands (optional), ingest adapter cache entries, and normalize metadata into PSCustomObject shapes.
C# authoring type generation
source/Private/New-DscResourceAuthoringTypeSource.ps1
Generate C# sealed classes from JSON Schema including enums, nullable wrappers, default initialization, and ShouldSerialize methods.
Resource function registration
source/Private/Register-DscResourceFunction.ps1, source/Public/Register-DscResourceAuthoringType.ps1
Dynamically generate/register PowerShell functions that instantiate Microsoft.DSC.Resource objects from schema-backed parameters with enum validation and adapter directives.
Import and user workflows
source/Public/Import-DscAuthoringResource.ps1, source/Public/Import-DscResourceAuthoringMetadata.ps1
High-level cmdlets to discover/import resource metadata from multiple sources and register generated types/functions.
Configuration building and export
source/Public/New-DscConfigurationDocument.ps1, source/Public/New-DscExpression.ps1, source/Public/Export-DscConfigurationDocument.ps1, source/Private/ConvertTo-DscAuthoringHashtable.ps1
Build Microsoft.DSC.Configuration objects, create DSC expressions from scriptblocks, convert graphs to JSON-serializable hashtables, and export JSON with $schema preserved as first property.
Helpers and conversions
source/Private/Get-DscAdapterCachePath.ps1, source/Private/Get-DscResourceAuthoringTypeName.ps1, source/Private/ConvertTo-Hashtable.ps1, source/Private/ConvertTo-JsonSchemaType.ps1, source/Private/New-EmbeddedJsonSchema.ps1
Utility functions for adapter cache path discovery, type-name sanitization, null-safe hashtable conversion, JSON-schema type mapping, and embedded schema helpers.
Documentation
source/WikiSource/Configuration-Authoring.md, source/WikiSource/Home.md, source/WikiSource/Command-Reference.md, source/WikiSource/Getting-Started.md
New and expanded docs describing authoring workflows, discovery, schema resolution, examples, and command references.
Tests & fixtures
tests/Unit/**/*, tests/Unit/Fixtures/*
Comprehensive Pester tests and fixtures covering discovery, schema resolution, conversion, type generation, function registration, configuration creation, export, and edge cases.
Changelog
CHANGELOG.md
Documented added features and fixes related to configuration authoring and schema handling.

🎯 4 (Complex) | ⏱️ ~60 minutes

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.

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

🟠 Major comments (37)
source/Private/New-DscResourceAuthoringTypeSource.ps1-145-147 (1)

145-147: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Preserve the original schema property names when serializing generated objects.

Sanitizing property names into C# identifiers changes the emitted JSON key. For example, a schema property named foo-bar is generated as foo_bar, and AuthoringData.Normalize() will serialize that sanitized CLR name back out. The generated document no longer matches the schema.

A generated ToHashtable() that writes the original schema keys would avoid that drift.

Also applies to: 229-229

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/New-DscResourceAuthoringTypeSource.ps1` around lines 145 -
147, The code currently converts schema property names into C# identifiers (via
ConvertTo-CSharpIdentifier) and uses those sanitized names (e.g., $identifier)
when generating properties and later serializing, which changes emitted JSON
keys (foo-bar -> foo_bar); update the generation and serialization path so that
ToHashtable() / AuthoringData.Normalize() use the original schema key names from
$Schema['properties'].Keys (store the original property name alongside the
sanitized identifier when creating properties) and emit the original key when
building hashtables or serializing, while continuing to use the sanitized
identifier only for CLR member names (refer to ConvertTo-CSharpIdentifier,
$identifier, $Schema['properties'], ToHashtable(), and AuthoringData.Normalize).
source/Private/Resolve-DscResourceAuthoringSchemaCommand.ps1-41-123 (1)

41-123: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Localize the debug and warning messages in this helper.

This file hardcodes every Write-Debug/Write-Warning message. Those need to move to localized string keys and be emitted through $script:localizedData instead of inline literals.

As per coding guidelines, "Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/Resolve-DscResourceAuthoringSchemaCommand.ps1` around lines 41
- 123, Replace all hard-coded Write-Debug/Write-Warning strings in
Resolve-DscResourceAuthoringSchemaCommand.ps1 with localized entries served from
$script:localizedData: find the messages emitted around the schema checks (when
$Manifest, $schema, $schemaCommand are missing or invalid), the debug that logs
"$executable" and $arguments.Count, the "Running schema command from manifest
directory" debug before Push-Location, the warnings that include $commandText,
$exitCode, $errorText and the "returned no output" message, the debug before
parsing and the catch warning that references $_.Exception.Message; add
corresponding keys to the script localization table and call the localization
accessor (using formatting/placeholders for variables like $Manifest['type'],
$executable, $arguments.Count, $sourceDirectory, $commandText, $exitCode,
$errorText) so each Write-Debug/Write-Warning invokes the localized string
rather than an inline literal while leaving logic around $errorPath, $output,
$exitCode and ConvertTo-Hashtable intact.
source/Private/New-DscResourceAuthoringTypeSource.ps1-145-149 (1)

145-149: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Map JSON schema types to concrete C# property types instead of defaulting everything to object.

Right now only enum-backed properties become strongly typed. Plain schema types still emit object, so boolean, integer, number, string, and array properties never gain the type safety or IntelliSense this feature is meant to generate.

Also applies to: 203-229

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/New-DscResourceAuthoringTypeSource.ps1` around lines 145 -
149, The loop currently defaults $propertyType to 'object' for every schema
property; update the logic in New-DscResourceAuthoringTypeSource.ps1 (inside the
foreach over $Schema['properties'] using $propertyName, $propertySchema,
$identifier) to map JSON Schema primitive types to concrete C# types (e.g.
"boolean" => "bool", "integer" => "int" (or pick width based on "format"),
"number" => "double", "string" => "string") and map "array" to a generic
collection type (e.g. "List<...>" or element type plus "[]") while preserving
existing enum handling; apply the same type resolution changes to the duplicate
block noted around lines 203-229 so plain schema types produce strong C# types
instead of always 'object'.
source/Private/Get-DscAdapterCachePath.ps1-37-45 (1)

37-45: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t assume LOCALAPPDATA exists just because the session is on Windows.

Line 39 enters the branch for any Windows session, but Line 41 still uses $env:LOCALAPPDATA unconditionally. If that variable is missing, Join-Path throws instead of returning zero paths.

Suggested fix
-    if ($Adapter -in @('PowerShell', 'All'))
+    if ($Adapter -in @('PowerShell', 'All'))
     {
-        if ($IsWindows -or $env:LOCALAPPDATA)
+        if ($env:LOCALAPPDATA)
         {
             $paths.Add((Join-Path -Path $env:LOCALAPPDATA -ChildPath 'dsc\PSAdapterCache.json'))
         }
         elseif ($env:HOME)
         {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/Get-DscAdapterCachePath.ps1` around lines 37 - 45, The Windows
branch assumes $env:LOCALAPPDATA exists; change the condition so you only call
Join-Path and $paths.Add when $env:LOCALAPPDATA is non-empty (e.g. use if
($IsWindows -and $env:LOCALAPPDATA) or add an inner if ($env:LOCALAPPDATA)
before calling Join-Path), otherwise fall back to the $env:HOME branch or skip
adding a path; update the code paths that reference $env:LOCALAPPDATA, Join-Path
and $paths.Add inside Get-DscAdapterCachePath to guard against a missing
LOCALAPPDATA.
source/Private/ConvertTo-DscResourceAuthoringMetadata.ps1-136-146 (1)

136-146: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Check array types before scalar type-name matches.

Line 138 can classify array-typed adapter properties incorrectly. For example, System.String[] matches String before it ever reaches \[\]|Array, so the generated schema says string instead of array.

Suggested fix
-        $jsonType = switch -Regex ([System.String]$property.PropertyType)
+        $jsonType = switch -Regex ([System.String]$property.PropertyType)
         {
+            '\[\]|Array' { 'array'; break }
             'Boolean|bool' { 'boolean'; break }
             'Byte|Int16|Int32|Int64|UInt16|UInt32|UInt64|SInt|UInt' { 'integer'; break }
             'Single|Double|Decimal' { 'number'; break }
             'String' { 'string'; break }
             'Hashtable|Dictionary|Object' { 'object'; break }
-            '\[\]|Array' { 'array'; break }
             default { 'string' }
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/ConvertTo-DscResourceAuthoringMetadata.ps1` around lines 136 -
146, The switch -Regex on ([System.String]$property.PropertyType) in the foreach
over $resourceInfo.Properties currently matches scalar types before array types
(e.g., "System.String[]" hits the 'String' case), so move the array detection
case '\[\]|Array' to appear before the scalar type cases (especially before
'String' and other scalar patterns) in the switch to ensure array-typed
properties are classified as 'array'; keep the existing mapping logic and other
cases intact, only reorder the '\[\]|Array' branch within the switch expression.
source/Private/ConvertTo-DscResourceAuthoringMetadata.ps1-124-160 (1)

124-160: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard resources that have no property metadata.

If DscResourceInfo.Properties is $null, the loop still runs once with $property = $null, and Line 138 then dereferences $property.PropertyType. That turns a parameterless resource into a hard failure during import.

Suggested fix
-    foreach ($property in @($resourceInfo.Properties))
+    foreach ($property in @($resourceInfo.Properties | Where-Object -FilterScript { $null -ne $_ }))
     {
         $jsonType = switch -Regex ([System.String]$property.PropertyType)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/ConvertTo-DscResourceAuthoringMetadata.ps1` around lines 124 -
160, The foreach over @($resourceInfo.Properties) can iterate once with
$property = $null when DscResourceInfo.Properties is $null, causing
dereferencing errors; before the foreach add a guard like: if ($null -eq
$resourceInfo.Properties -or $resourceInfo.Properties.Count -eq 0) { Write-Debug
"No properties for '$($AdapterCacheEntry.Type)'; skipping." ; return } so the
code only normalizes properties when $resourceInfo.Properties contains valid
entries (references: DscResourceInfo.Properties, the foreach loop,
property.PropertyType, property.IsMandatory, $properties and $required).
source/Public/Register-DscResourceAuthoringType.ps1-31-41 (1)

31-41: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

This state-changing command should support -WhatIf/-Confirm.

Add-Type and Register-DscResourceFunction both mutate the current session, so this
public command should opt into SupportsShouldProcess and guard those operations with
$PSCmdlet.ShouldProcess(...).

As per coding guidelines, "For state-changing functions, use SupportsShouldProcess" and "Place ShouldProcess check immediately before each state-change".

Also applies to: 82-90

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Register-DscResourceAuthoringType.ps1` around lines 31 - 41,
Update the public command to support ShouldProcess: add SupportsShouldProcess =
$true to the CmdletBinding for Register-DscResourceAuthoringType and,
immediately before each state-changing call (specifically the Add-Type
invocation and any Register-DscResourceFunction call), wrap them with a
$PSCmdlet.ShouldProcess(...) check so the operations only execute when confirmed
(and respect -WhatIf/-Confirm); apply the same pattern to the other
state-changing block referenced (the Register-DscResourceFunction usage later in
the file).
source/Public/Import-DscResourceAuthoringMetadata.ps1-109-109 (1)

109-109: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Localize the diagnostic messages in this command.

These Write-Debug/Write-Verbose calls are hardcoded. In source/**/*.ps1, those
messages need to come from $script:localizedData so the command stays compliant with
the module’s localization contract.

As per coding guidelines, "Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages" and "Use localized string keys, not hardcoded strings".

Also applies to: 117-117, 122-122, 128-128, 152-156, 164-164, 172-172, 176-176, 184-184, 188-188, 194-194, 203-203, 212-212, 220-220, 224-224, 237-237

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Import-DscResourceAuthoringMetadata.ps1` at line 109, Replace
hardcoded diagnostic strings in the Import-DscResourceAuthoringMetadata
command's Write-Debug/Write-Verbose (and any Write-Error/Write-Warning) calls
with localized entries from $script:localizedData; e.g., instead of the literal
"Importing DSC resource metadata..." build the message using a localized key in
$script:localizedData and format it with the existing variables
($UseDscExecutable, $ResourceType, $Adapter), and do the same for the other
listed diagnostic calls in this file so all messages use $script:localizedData
keys rather than hardcoded strings.
source/Public/Register-DscResourceAuthoringType.ps1-50-50 (1)

50-50: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Localize these debug messages too.

The command is still emitting hardcoded Write-Debug text instead of localized string
keys.

As per coding guidelines, "Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages" and "Use localized string keys, not hardcoded strings".

Also applies to: 53-53, 59-59, 80-80, 89-94

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Register-DscResourceAuthoringType.ps1` at line 50, Replace
hardcoded Write-Debug messages in Register-DscResourceAuthoringType.ps1 (the
Write-Debug calls shown and the other occurrences flagged) with localized string
keys: call your localization helper (e.g., Get-LocalizedString or the module's
localization lookup) to fetch a key like "ProcessingDscAuthoringMetadata" and
format it with $resourceType, then pass that localized string to Write-Debug; do
the same for the other Write-Debug/Write-Verbose/Write-Warning/Write-Error
occurrences (use unique keys per message, include interpolation/placeholders for
variables, and update each Write-* invocation to use the localized text).
source/Public/Import-DscAuthoringResource.ps1-110-110 (1)

110-110: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Localize the debug messages here as well.

These diagnostics are still hardcoded, so this public command does not meet the
localization requirement for source/**/*.ps1.

As per coding guidelines, "Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages" and "Use localized string keys, not hardcoded strings".

Also applies to: 117-117, 125-125, 128-128, 134-134, 153-153, 161-163

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Import-DscAuthoringResource.ps1` at line 110, Replace the
hardcoded diagnostics in the public command (e.g., the Write-Debug call
"Starting DSC authoring resource import." and the other
Write-Debug/Write-Verbose/Write-Error/Write-Warning/ThrowTerminatingError usages
referenced) with localized resource lookups: use a localized string key (for
example ImportDscAuthoringResource_Start) obtained from your module localization
helper (e.g., $PSCmdlet.GetLocalizedString('ImportDscAuthoringResource_Start')
or a $LocalizedStrings['ImportDscAuthoringResource_Start'] lookup), and pass
that localized string into Write-Debug/Write-Verbose/etc.; for terminating
errors construct the ErrorRecord/Exception message from a localized string key
as well and ensure you add the corresponding keys to the module resource file
(.psd1/.resx) so the new keys exist for all supported locales.
source/Public/Register-DscResourceAuthoringType.ps1-57-84 (1)

57-84: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Loaded-type reuse can leave the session on a stale schema.

Once a type name has been loaded, later imports of the same resource type skip
regeneration entirely, even if the incoming schema changed. That means updated
defaults/properties/enums never make it into the generated type or function during the
same session.

Please either version the generated type name with schema identity or detect schema
mismatches and fail fast instead of silently reusing the old type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Register-DscResourceAuthoringType.ps1` around lines 57 - 84,
The current flow reuses an already-loaded type ($typeName from
Get-DscResourceAuthoringTypeName) even if the incoming $schema changed; update
the logic so type identity includes schema identity or detect mismatches and
fail fast: have Get-DscResourceAuthoringTypeName incorporate a short
deterministic schema fingerprint (e.g. hash of ConvertTo-Json $schema) into the
returned $typeName, or modify New-DscResourceAuthoringTypeSource to embed a
schema hash/marker in the generated type (e.g. static field or attribute) and,
after resolving $type = $typeName -as [System.Type], compare the embedded hash
to the current schema and either regenerate (use hashed name) or throw a
terminating error before returning; ensure Add-Type is called only when the
schema-hashed name/type does not already exist.
source/Public/Import-DscResourceAuthoringMetadata.ps1-147-158 (1)

147-158: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate explicit file inputs before parsing them as manifests.

Directory input is filtered to *.dsc.resource.json, *.dsc.adaptedResource.json, and
*.dsc.manifests.json, but a direct -Path file bypasses that filter and is parsed
unconditionally. That makes pipeline scenarios like Get-ChildItem | Import-DscResourceAuthoringMetadata
fail on unrelated files instead of skipping or rejecting them early.

Suggested guard
                 else
                 {
-                    $item
+                    if (
+                        $item.Name -notlike '*.dsc.resource.json' -and
+                        $item.Name -notlike '*.dsc.adaptedResource.json' -and
+                        $item.Name -notlike '*.dsc.manifests.json'
+                    )
+                    {
+                        Write-Verbose -Message ($script:localizedData.Import_DscResourceAuthoringMetadata_UnsupportedManifestPath -f $item.FullName)
+                        continue
+                    }
+
+                    $item
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Import-DscResourceAuthoringMetadata.ps1` around lines 147 -
158, The code parses any file passed via $item as a DSC manifest without
validating its filename; update the logic in Import-DscResourceAuthoringMetadata
so that when $item is a file (PSIsContainer -eq $false) you first check its
name/extension against the allowed patterns (*.dsc.resource.json,
*.dsc.adaptedResource.json, *.dsc.manifests.json) and if it does not match, skip
it (Write-Debug/Write-Verbose a message and continue) instead of adding it to
$manifestFiles and calling ConvertFrom-Json/ConvertTo-Hashtable; keep the
existing behavior for directories (filtering into $manifestFiles) but ensure
$item, $manifestFiles, Write-Debug, and the ConvertFrom-Json/ConvertTo-Hashtable
call are only reached for validated manifest files.
source/Private/ConvertTo-DscExpressionText.ps1-42-43 (1)

42-43: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Localize these terminating error messages.

These ThrowTerminatingError() calls hardcode user-facing text, so they won't follow the module's localization contract.

As per coding guidelines, "Localize all Write-Debug, Write-Verbose, Write-Error, Write-Warning and $PSCmdlet.ThrowTerminatingError() messages".

Also applies to: 53-54, 74-75, 130-131, 173-174, 180-181

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Private/ConvertTo-DscExpressionText.ps1` around lines 42 - 43, The
ThrowTerminatingError calls create ErrorRecord objects with hardcoded
user-facing messages (see the [System.NotSupportedException]::new(...) and
subsequent ErrorRecord instantiation and the error IDs like
'DscExpressionStatementCount'); replace those literal strings with localized
strings retrieved from the module's localization helper (e.g., call the existing
Get-LocalizedString/Get-LocalizedResource function or equivalent used by the
module) and add corresponding resource keys for each message (handle the
occurrences referenced by the comment: the blocks around the
NotSupportedException/ErrorRecord at the DscExpressionStatementCount ID and the
other listed occurrences). Ensure you pass the localized text into the
NotSupportedException constructor and ErrorRecord creation so
ThrowTerminatingError logs localized messages.
source/Private/ConvertTo-DscExpressionText.ps1-80-96 (1)

80-96: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Flatten concat() operands from the AST, not by splitting rendered text.

This breaks valid expressions whenever an operand contains a comma, e.g. ('a,b' + 'c') + 'd', because Line 85 treats commas inside string literals or nested function calls as operand separators.

💡 Proposed fix
-        foreach ($side in @($Ast.Left, $Ast.Right))
-        {
-            $text = ConvertTo-DscExpressionText -Ast $side
-            if ($text -match '^concat\((?<inner>.*)\)$')
-            {
-                foreach ($item in $Matches['inner'] -split ',\s*')
-                {
-                    $items.Add($item)
-                }
-            }
-            else
-            {
-                $items.Add($text)
-            }
-        }
+        $pending = [System.Collections.Generic.Stack[System.Management.Automation.Language.Ast]]::new()
+        $pending.Push($Ast.Right)
+        $pending.Push($Ast.Left)
+
+        while ($pending.Count -gt 0)
+        {
+            $side = $pending.Pop()
+
+            if (
+                $side -is [System.Management.Automation.Language.BinaryExpressionAst] -and
+                $side.Operator -eq [System.Management.Automation.Language.TokenKind]::Plus
+            )
+            {
+                $pending.Push($side.Right)
+                $pending.Push($side.Left)
+                continue
+            }
+
+            $items.Add((ConvertTo-DscExpressionText -Ast $side))
+        }
source/Public/Export-DscConfigurationDocument.ps1-79-88 (1)

79-88: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use the required localized ShouldProcess pattern for the export path.

This branch performs file-system writes, but the current call skips the required description/confirmation/caption messages and hardcodes the action text.

💡 Proposed fix
-        if ($PSCmdlet.ShouldProcess($Path, 'Export DSC configuration document'))
+        $descriptionMessage = $script:localizedData.Export_DscConfigurationDocument_Export_ShouldProcessDescription -f $Path
+        $confirmationMessage = $script:localizedData.Export_DscConfigurationDocument_Export_ShouldProcessConfirmation -f $Path
+        $captionMessage = $script:localizedData.Export_DscConfigurationDocument_Export_ShouldProcessCaption
+
+        if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage))
         {
             $parentPath = Split-Path -Path $Path -Parent
             if (-not [System.String]::IsNullOrWhiteSpace($parentPath) -and -not (Test-Path -LiteralPath $parentPath))
             {
                 New-Item -Path $parentPath -ItemType Directory -Force | Out-Null
As per coding guidelines, "$PSCmdlet.ShouldProcess must use required pattern".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Export-DscConfigurationDocument.ps1` around lines 79 - 88, The
current $PSCmdlet.ShouldProcess($Path, 'Export DSC configuration document') call
must be replaced with the required localized ShouldProcess pattern in
Export-DscConfigurationDocument: call $PSCmdlet.ShouldProcess with the target
($Path), an action/caption and a localized description that includes the path
(e.g. an action like 'Export DSC configuration document' and a description like
"Create or overwrite file: $Path"), using your module's localization helper (or
resource strings) rather than hardcoded text; update the ShouldProcess
invocation and any message strings so the check follows the official
three-argument/localized pattern and retains the existing directory creation and
Set-Content behavior when it returns true.
tests/Unit/Private/ConvertTo-DscResourceAuthoringMetadata.Tests.ps1-4-13 (1)

4-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align this suite with the required Unit Pester harness template.

Please add the mandated BeforeDiscovery bootstrap and Pester module default parameter setup instead of per-call module scoping literals.

As per coding guidelines, “Use this exact setup block before Describe” and “Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName.”

Also applies to: 16-121

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/ConvertTo-DscResourceAuthoringMetadata.Tests.ps1` around
lines 4 - 13, Replace the current BeforeAll/AfterAll bootstrap with the required
Pester harness: add a BeforeDiscovery block that sets $script:dscModuleName =
'DscResource.Authoring', imports the module once, and sets
$PSDefaultParameterValues to map
"Mock:ModuleName","Should:ModuleName","InModuleScope:ModuleName" to
$script:dscModuleName (so tests use the default module scoping), and keep
AfterAll to remove the module; update any per-call literals to rely on these
defaults (references: BeforeAll, AfterAll, BeforeDiscovery,
$PSDefaultParameterValues, Mock:ModuleName, Should:ModuleName,
InModuleScope:ModuleName, $script:dscModuleName).
tests/Unit/Private/ConvertTo-DscExpressionText.Tests.ps1-4-13 (1)

4-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the standard unit-test scaffold and Pester module defaults in this file.

The file currently bypasses the required BeforeDiscovery block and direct $PSDefaultParameterValues setup, so it diverges from the repository’s required test harness pattern.

As per coding guidelines, “Use this exact setup block before Describe” and “Omit -ModuleName parameter on Pester commands” by setting module defaults.

Also applies to: 16-123

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/ConvertTo-DscExpressionText.Tests.ps1` around lines 4 -
13, Replace the custom BeforeAll/AfterAll scaffold with the repository-standard
BeforeDiscovery block and set Pester module defaults via
$PSDefaultParameterValues instead of using -ModuleName on Pester commands: move
the Import-Module and module-name assignment into a BeforeDiscovery {
$script:dscModuleName='DscResource.Authoring'; Import-Module -Name
$script:dscModuleName -Force } and mirror cleanup in an AfterDiscovery/AfterAll
as appropriate, and set $PSDefaultParameterValues to configure Pester defaults
(omitting -ModuleName on Describe/It calls) so the test uses the standard
harness and module defaults rather than direct BeforeAll manipulation.
tests/Unit/Private/ConvertTo-DscPropertyOverrideFromConfig.Tests.ps1-4-13 (1)

4-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Adopt the required unit-test initialization block.

This file needs the repository’s standard BeforeDiscovery/BeforeAll/AfterAll template for dependency initialization and Pester defaults.

As per coding guidelines, “Use this exact setup block before Describe.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/ConvertTo-DscPropertyOverrideFromConfig.Tests.ps1` around
lines 4 - 13, Replace the existing standalone BeforeAll/AfterAll block with the
repository's standard Pester initialization template by adding the required
BeforeDiscovery block and the canonical BeforeAll/AfterAll pattern before the
Describe block; ensure you include the standard Pester defaults and dependency
initialization (use the exact symbols BeforeDiscovery, BeforeAll, AfterAll and
the existing Describe) and move the Import-Module/Remove-Module calls into that
template so the module ($script:dscModuleName = 'DscResource.Authoring',
Import-Module -Name $script:dscModuleName -Force, and Get-Module ... |
Remove-Module -Force) run inside the approved setup/teardown flow.
tests/Unit/Private/ConvertTo-DscAuthoringHashtable.Tests.ps1-4-13 (1)

4-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required Unit test bootstrap and Pester default parameter setup.

This test file skips the mandated BeforeDiscovery dependency bootstrap and does not set $PSDefaultParameterValues for InModuleScope, Mock, and Should, which your test guidelines require for unit tests.

As per coding guidelines, “Use this exact setup block before Describe” and “Set $PSDefaultParameterValues for Mock:ModuleName, Should:ModuleName, InModuleScope:ModuleName.”

Also applies to: 14-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/ConvertTo-DscAuthoringHashtable.Tests.ps1` around lines 4
- 13, The test file is missing the required Pester unit-test bootstrap and
default parameter settings; add the mandated BeforeDiscovery bootstrap block
prior to Describe and initialize $PSDefaultParameterValues for the module under
test (use $script:dscModuleName) setting entries for "Mock:ModuleName",
"Should:ModuleName", and "InModuleScope:ModuleName" so Pester calls route to the
current module; keep the existing BeforeAll/AfterAll but ensure the bootstrap
and $PSDefaultParameterValues are present before any Describe blocks (refer to
the existing BeforeAll, AfterAll, and the $script:dscModuleName symbol to locate
where to insert these settings).
tests/Unit/Private/Register-DscResourceFunction.Tests.ps1-4-56 (1)

4-56: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix private test harness in tests/Unit/Private/Register-DscResourceFunction.Tests.ps1

  • Add the required unit-test setup template (SuppressMessageAttribute/param()/BeforeDiscovery importing DscResource.Test) before Describe (currently only BeforeAll/AfterAll at lines 4-13).
  • Add Set-StrictMode -Version 1.0 immediately before the Register-DscResourceFunction call inside InModuleScope 'DscResource.Authoring' (call at line 46).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/Register-DscResourceFunction.Tests.ps1` around lines 4 -
56, The private test harness is missing the unit-test setup template and strict
mode: insert the standard unit-test setup boilerplate (SuppressMessageAttribute
block, param() and a BeforeDiscovery block that imports DscResource.Test)
immediately before the Describe 'Register-DscResourceFunction' block so the
BeforeAll/AfterAll run in the proper test harness context; and inside the
InModuleScope 'DscResource.Authoring' scope, add Set-StrictMode -Version 1.0
immediately before the call to Register-DscResourceFunction to enforce strict
mode during the resource registration step.
tests/Unit/Private/Get-DscAdapterCachePath.Tests.ps1-4-39 (1)

4-39: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Fix unit-test harness + strict mode in Get-DscAdapterCachePath private tests (tests/Unit/Private/Get-DscAdapterCachePath.Tests.ps1)

  • Replace the ad-hoc BeforeAll/AfterAll module import/removal with the required unit-test harness scaffold (including param () and BeforeDiscovery) immediately before Describe.
  • Add Set-StrictMode -Version 1.0 immediately before each Get-DscAdapterCachePath call inside every InModuleScope It block.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/Get-DscAdapterCachePath.Tests.ps1` around lines 4 - 39,
Replace the ad-hoc BeforeAll/AfterAll module import/removal scaffold with the
standard unit-test harness: add a top-level "param ()" and a "BeforeDiscovery {
Import-Module -Name 'DscResource.Authoring' -Force }" block immediately before
the Describe 'Get-DscAdapterCachePath' declaration, and remove the existing
BeforeAll/AfterAll blocks; then, inside every It block that uses InModuleScope
and calls Get-DscAdapterCachePath, add a Set-StrictMode -Version 1.0 line
immediately before the Get-DscAdapterCachePath invocation to enforce strict mode
for those private tests.
tests/Unit/Private/Resolve-DscResourceAuthoringSchemaCommand.Tests.ps1-4-147 (1)

4-147: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align Resolve-DscResourceAuthoringSchemaCommand unit tests with the required private-function Pester pattern

  • tests/Unit/Private/Resolve-DscResourceAuthoringSchemaCommand.Tests.ps1 omits the required unit-test setup block (param () + BeforeDiscovery module import pattern) before Describe.
  • Each InModuleScope 'DscResource.Authoring' case invokes Resolve-DscResourceAuthoringSchemaCommand without Set-StrictMode -Version 1.0 immediately before the call (e.g., around lines 28, 39, 55, 84, 110, 129, 145).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/Resolve-DscResourceAuthoringSchemaCommand.Tests.ps1`
around lines 4 - 147, Add the required Pester private-function pattern and
ensure strict mode is set before invoking the tested private function: add a
leading "param ()" and a BeforeDiscovery block that imports the
DscResource.Authoring module (matching the existing Import-Module usage) before
the Describe block, and insert Set-StrictMode -Version 1.0 immediately before
each Resolve-DscResourceAuthoringSchemaCommand invocation inside each
InModuleScope (so each It block calls Set-StrictMode -Version 1.0 then
Resolve-DscResourceAuthoringSchemaCommand) to align with the private-function
test conventions.
tests/Unit/Private/Get-DscResourceAuthoringTypeName.Tests.ps1-4-29 (1)

4-29: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix tests/Unit/Private/Get-DscResourceAuthoringTypeName.Tests.ps1 to use the required private-function Pester scaffold

  • Add the exact unit-test scaffold block (“param ()” SuppressMessageAttribute + BeforeDiscovery for DscResource.Test + BeforeAll/AfterAll PSDefaultParameterValues for InModuleScope/Mock/Should) before Describe.
  • In each InModuleScope 'DscResource.Authoring' test, add Set-StrictMode -Version 1.0 immediately before calling Get-DscResourceAuthoringTypeName.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/Get-DscResourceAuthoringTypeName.Tests.ps1` around lines 4
- 29, Add the required Pester private-function scaffold block before the
Describe block: insert the exact "param ()" with the SuppressMessageAttribute
plus a BeforeDiscovery for DscResource.Test and a BeforeAll/AfterAll that sets
PSDefaultParameterValues for InModuleScope/Mock/Should so the private-function
testing harness is available; then inside each InModuleScope
'DscResource.Authoring' example (where Get-DscResourceAuthoringTypeName is
invoked) add Set-StrictMode -Version 1.0 immediately before calling
Get-DscResourceAuthoringTypeName to enforce strict mode during the test.
tests/Unit/Private/New-DscResourceAuthoringTypeSource.Tests.ps1-4-80 (1)

4-80: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix required Pester unit-test harness + add strict mode for InModuleScope calls

  • tests/Unit/Private/New-DscResourceAuthoringTypeSource.Tests.ps1 is missing the required unit-test setup scaffold (SuppressMessageAttribute/param ()/BeforeDiscovery/BeforeAll/AfterAll) exactly as specified before Describe.
  • Each InModuleScope test invokes New-DscResourceAuthoringTypeSource without Set-StrictMode -Version 1.0 immediately before the invocation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/New-DscResourceAuthoringTypeSource.Tests.ps1` around lines
4 - 80, Add the required Pester harness scaffold (the SuppressMessageAttribute
block, a top-level "param ()", and the BeforeDiscovery/BeforeAll/AfterAll stubs)
immediately before the Describe block so the test file matches the expected
template, and ensure each InModuleScope block sets strict mode by calling
Set-StrictMode -Version 1.0 immediately before invoking
New-DscResourceAuthoringTypeSource (i.e., inside each InModuleScope where
New-DscResourceAuthoringTypeSource is called) so tests run under strict mode.
tests/Unit/Private/Invoke-DscResourceDiscovery.Tests.ps1-4-169 (1)

4-169: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Fix Invoke-DscResourceDiscovery unit-test scaffold and strict-mode usage

  • tests/Unit/Private/Invoke-DscResourceDiscovery.Tests.ps1 uses bespoke top-level BeforeAll/AfterAll and is missing the required standard unit-test setup block (the param() + BeforeDiscovery + BeforeAll $script:moduleName/$PSDefaultParameterValues scaffold) before Describe.
  • Each InModuleScope It that invokes Invoke-DscResourceDiscovery (calls at lines ~127, ~141, ~153, ~165) is missing Set-StrictMode -Version 1.0 immediately before the invocation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/Invoke-DscResourceDiscovery.Tests.ps1` around lines 4 -
169, The test file's Describe block is missing the required unit-test scaffold
(the top-level param(), BeforeDiscovery, and a BeforeAll that sets
$script:moduleName and $PSDefaultParameterValues) and several It blocks calling
Invoke-DscResourceDiscovery do not set strict mode; add the standard scaffold
before Describe (ensure the param() declaration and a BeforeDiscovery function
plus a BeforeAll that initializes $script:moduleName and
$PSDefaultParameterValues) and inside each InModuleScope It that calls
Invoke-DscResourceDiscovery (the tests that call Invoke-DscResourceDiscovery
within InModuleScope) insert Set-StrictMode -Version 1.0 immediately before
invoking Invoke-DscResourceDiscovery to enforce strict-mode for those calls.
tests/Unit/Private/Resolve-ModuleInfo.Tests.ps1-64-79 (1)

64-79: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enable strict mode before calling Resolve-ModuleInfo.

This new InModuleScope scenario invokes the private function without Set-StrictMode -Version 1.0, so it misses the required strict-scope coverage for private tests.

As per coding guidelines, "In InModuleScope tests, add Set-StrictMode -Version 1.0 immediately before invoking the tested function".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Private/Resolve-ModuleInfo.Tests.ps1` around lines 64 - 79, In the
InModuleScope block that tests the private Resolve-ModuleInfo function, enable
strict mode immediately before invoking Resolve-ModuleInfo by adding
Set-StrictMode -Version 1.0 just prior to the call; this ensures the private
test runs under required strict-scope coverage for Resolve-ModuleInfo and
related assertions (e.g., checking $result.Version, $result.Author,
$result.Description, and $result.ScriptPath).
tests/Unit/Public/New-DscConfigurationDocument.Tests.ps1-12-19 (1)

12-19: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Create the configuration inside each It.

These contexts run New-DscConfigurationDocument in BeforeAll and assert on the cached result later. That shares state across examples and violates the required test layout.

As per coding guidelines, "Tested entity must be called from within the It blocks" and "Keep results and assertions in same It block".

Also applies to: 38-48, 59-73

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/New-DscConfigurationDocument.Tests.ps1` around lines 12 -
19, The tests call New-DscConfigurationDocument in a BeforeAll which shares
state across examples; move the creation and assertions into each It block
instead: remove the New-DscConfigurationDocument call from the BeforeAll and for
each It create a fresh $resource (using [Microsoft.DSC.Resource]::new(), setting
Name/Type/Properties) and call New-DscConfigurationDocument inside that It, then
perform assertions against the local $configuration there; apply the same change
for the other contexts mentioned (lines ~38-48 and ~59-73) to ensure each It
constructs its own $resource and calls New-DscConfigurationDocument locally.
tests/Unit/Public/New-DscConfigurationDocument.Tests.ps1-4-91 (1)

4-91: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required unit-test scaffold and parameter-set assertions.

This public-command test file skips the standard BeforeDiscovery/BeforeAll/AfterAll bootstrap and doesn't validate the command's parameter sets, so it doesn't match the repo's required unit-test template.

As per coding guidelines, "Use this exact setup block before Describe:" and "All public commands require parameter set validation tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/New-DscConfigurationDocument.Tests.ps1` around lines 4 -
91, The test file for the public command New-DscConfigurationDocument is missing
the required unit-test scaffold and parameter-set validation; update the
Describe block to include the standard BeforeDiscovery, BeforeAll and AfterAll
bootstrap setup used across the repo and add tests that assert the cmdlet's
parameter sets for New-DscConfigurationDocument (e.g., validate mutually
exclusive parameter sets for -Resource vs pipeline input and presence of
optional parameters like -Parameter, -Variable, -Directive, -Metadata); ensure
you reference the cmdlet name New-DscConfigurationDocument and the parameter
names (-Resource, -Parameter, -Variable, -Directive, -Metadata) when adding the
parameter-set validation tests so they match the repo template.
tests/Unit/Public/New-DscExpression.Tests.ps1-4-22 (1)

4-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required unit-test scaffold and parameter-set assertions.

This public-command test file skips the standard BeforeDiscovery/BeforeAll/AfterAll bootstrap and doesn't validate the command's parameter sets, so it doesn't match the repo's required unit-test template.

As per coding guidelines, "Use this exact setup block before Describe:" and "All public commands require parameter set validation tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/New-DscExpression.Tests.ps1` around lines 4 - 22, The test
file for New-DscExpression is missing the standard unit-test scaffold and
parameter-set validation; update tests/Unit/Public/New-DscExpression.Tests.ps1
to include the required BeforeDiscovery/BeforeAll/AfterAll bootstrap block
(using the repo's exact setup block) before the Describe block, and add the
mandatory parameter-set assertions for the public command New-DscExpression
(validate all parameter sets and required parameters using the repository's
standard parameter-set tests) so the file follows the project's public-command
test template.
tests/Unit/Public/Import-DscAuthoringResource.Tests.ps1-69-71 (1)

69-71: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Invoke Import-DscAuthoringResource inside each It.

These contexts execute the command under test in BeforeAll and assert on shared state later. That makes the examples order-dependent and breaks the repo's required Pester structure.

As per coding guidelines, "Tested entity must be called from within the It blocks" and "Keep results and assertions in same It block".

Also applies to: 96-100, 110-112

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Import-DscAuthoringResource.Tests.ps1` around lines 69 -
71, The tests currently call Import-DscAuthoringResource inside a BeforeAll
block (variable $registration set in BeforeAll) which makes examples
order-dependent; move the invocation of Import-DscAuthoringResource -Path
$commandResourcePath -PassThru out of BeforeAll and into each It block that
asserts on its result (replace uses of the shared $registration with a locally
scoped variable inside each It), and do the same refactor for the other contexts
that call the command in BeforeAll (the blocks referenced near the other
occurrences), so each It both invokes Import-DscAuthoringResource and performs
its assertions in the same block.
tests/Unit/Public/Import-DscAuthoringResource.Tests.ps1-4-132 (1)

4-132: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required unit-test scaffold and parameter-set assertions.

This public-command test file skips the standard BeforeDiscovery/BeforeAll/AfterAll bootstrap and doesn't validate the command's parameter sets, so it doesn't match the repo's required unit-test template.

As per coding guidelines, "Use this exact setup block before Describe:" and "All public commands require parameter set validation tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Import-DscAuthoringResource.Tests.ps1` around lines 4 -
132, This test file is missing the required unit-test scaffold and parameter-set
assertions for the public command Import-DscAuthoringResource; add the standard
BeforeDiscovery/BeforeAll/AfterAll bootstrap block (the exact shared setup block
used across other public-command tests) immediately before the Describe
'Import-DscAuthoringResource' block and ensure the teardown in AfterAll cleans
up any created functions, then add explicit tests that validate
Import-DscAuthoringResource's parameter sets (e.g., verify -Path/-PassThru,
-UseDscExecutable/-DscExecutablePath, and pipeline input variations) using
Should assertions against (Get-Command Import-DscAuthoringResource).Parameters
and ParameterSets so the command's declared parameter sets are asserted;
reference the Import-DscAuthoringResource and
Import-DscResourceAuthoringMetadata symbols to locate where to add these checks.
tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1-86-88 (1)

86-88: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move Import-DscResourceAuthoringMetadata calls into the It blocks.

These contexts execute the command under test in BeforeAll and reuse the result across assertions. That shares state between examples and violates the required test structure.

As per coding guidelines, "Tested entity must be called from within the It blocks" and "Keep results and assertions in same It block".

Also applies to: 177-179, 193-195, 210-212, 225-227

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1` around lines
86 - 88, The tests currently call Import-DscResourceAuthoringMetadata in
BeforeAll and store its result in $metadata, which shares state across examples;
move each Import-DscResourceAuthoringMetadata -Path $commandResourcePath
invocation into the corresponding It block so the tested entity is executed
inside the assertion, replace the shared $metadata usage with a local $metadata
variable inside each It, remove or empty the BeforeAll calls that only performed
the import, and repeat this change for the other contexts that currently call
Import-DscResourceAuthoringMetadata in BeforeAll so each It executes
Import-DscResourceAuthoringMetadata and performs its assertions on its own local
result.
tests/Unit/Public/Export-DscConfigurationDocument.Tests.ps1-4-70 (1)

4-70: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required unit-test scaffold and parameter-set assertions.

This public-command test file skips the standard BeforeDiscovery/BeforeAll/AfterAll bootstrap and doesn't validate the command's parameter sets, so it doesn't match the repo's required unit-test template.

As per coding guidelines, "Use this exact setup block before Describe:" and "All public commands require parameter set validation tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Export-DscConfigurationDocument.Tests.ps1` around lines 4 -
70, The test file Export-DscConfigurationDocument.Tests.ps1 is missing the
required unit-test bootstrap and parameter-set validation for the public command
Export-DscConfigurationDocument; add the standard "BeforeDiscovery" bootstrap
block (import test helpers, call Initialize-PSResourceTests or repo's template)
and the matching BeforeAll/AfterAll scaffolding used across other public command
tests, then add parameter-set assertions that validate all parameter sets of the
Export-DscConfigurationDocument command (e.g., verify -Path vs pipeline usage vs
-WhatIf interactions) by calling the command metadata via
Test-CommandParameterSets or equivalent helper and include explicit It blocks
that assert the expected parameter sets and mandatory parameters for
Export-DscConfigurationDocument and New-DscConfigurationDocument where
applicable so the file follows the repository's public-command test template.
tests/Unit/Public/Register-DscResourceAuthoringType.Tests.ps1-6-13 (1)

6-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Register the type inside each It that validates it.

The file performs Register-DscResourceAuthoringType in BeforeAll and then asserts on the shared registration later. That makes the examples depend on shared setup instead of exercising the command inside each test.

As per coding guidelines, "Tested entity must be called from within the It blocks" and "Keep results and assertions in same It block".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Register-DscResourceAuthoringType.Tests.ps1` around lines 6
- 13, The tests currently call Register-DscResourceAuthoringType in the
BeforeAll block (using $metadata from Import-DscResourceAuthoringMetadata) which
creates shared state; change each It block that asserts on the registration to
call Register-DscResourceAuthoringType inside the It and perform the assertions
there (use Import-DscResourceAuthoringMetadata to produce $metadata inside the
It or reuse the fixture path there), ensuring $registration is created and
asserted in the same It rather than relying on the BeforeAll $registration.
tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1-4-250 (1)

4-250: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore the standard unit-test bootstrap and add parameter-set coverage.

This file adds custom discovery setup, but it still skips the required unit-test scaffold and the mandatory parameter-set validation for a public command.

As per coding guidelines, "Use this exact setup block before Describe:" and "All public commands require parameter set validation tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1` around lines
4 - 250, Restore the standard unit-test bootstrap block exactly as required and
place it before the Describe block, replacing the custom discovery setup; then
add parameter-set validation tests for the public function
Import-DscResourceAuthoringMetadata that exercise each declared parameter set
(e.g., calls using -Path, -AdapterCachePath, and
-UseDscExecutable/-DscExecutablePath combinations) and assert correct parameter
binding and required-parameter failures (ParameterBindingException) where
applicable, ensuring the test names and BeforeAll/BeforeDiscovery scaffold
follow the project's standard pattern.
tests/Unit/Public/Register-DscResourceAuthoringType.Tests.ps1-4-189 (1)

4-189: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required unit-test scaffold and parameter-set assertions.

This public-command test file skips the standard BeforeDiscovery/BeforeAll/AfterAll bootstrap and doesn't validate the command's parameter sets, so it doesn't match the repo's required unit-test template.

As per coding guidelines, "Use this exact setup block before Describe:" and "All public commands require parameter set validation tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Register-DscResourceAuthoringType.Tests.ps1` around lines 4
- 189, The test is missing the required test scaffold and parameter-set
validation: insert the standard BeforeDiscovery/BeforeAll/AfterAll bootstrap
block (matching the repo template) before the Describe block and update the
public-command tests to assert parameter sets for generated functions (use the
registered functions/commands produced by Register-DscResourceAuthoringType such
as Test.Company.Tool, Test.Company.CompletionTool, Test.Company.SanitizedTool,
Test.Company.EmptyTool, Test.Company.DefaultTool, Test.Company.UnsetEnumTool);
specifically, after creating the command (via $registration = $metadata |
Register-DscResourceAuthoringType and Get-Command), add assertions that the
command's Parameters have the expected ParameterSetNames and that required
parameter-set combinations are enforced (use (Get-Command -Name
'Test.Company.Tool').Parameters and inspect .ParameterSets/.Attributes or call
the function with parameter combinations to Verify throws).
tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1-132-133 (1)

132-133: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Drop Should -Not -Throw here.

Invoke the command directly and assign the unused result to $null; that's the required non-throwing pattern in this repo.

Proposed fix
-            { Import-DscResourceAuthoringMetadata -Path $manifestPath } |
-                Should -Not -Throw
+            $null = Import-DscResourceAuthoringMetadata -Path $manifestPath

As per coding guidelines, "No Should -Not -Throw - invoke commands directly" and "Inside It blocks, assign unused return objects to $null (unless part of pipeline)".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1` around lines
132 - 133, Drop the Should -Not -Throw assertion and invoke
Import-DscResourceAuthoringMetadata directly, assigning its unused return value
to $null; specifically replace the pipeline "{
Import-DscResourceAuthoringMetadata -Path $manifestPath } | Should -Not -Throw"
with a direct call like "$null = Import-DscResourceAuthoringMetadata -Path
$manifestPath" so the test follows the repo pattern of invoking commands
directly inside It blocks.
🧹 Nitpick comments (1)
source/Public/Import-DscAuthoringResource.ps1 (1)

164-166: ⚡ Quick win

Return the registrations directly instead of using Write-Output.

This is the only output path, so return $registrations is simpler and matches the
module guideline for functions.

Minimal change
         if ($PassThru.IsPresent)
         {
-            Write-Output $registrations
+            return $registrations
         }

As per coding guidelines, "Avoid Write-Output (use return instead)".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/Public/Import-DscAuthoringResource.ps1` around lines 164 - 166, The
current output path in Import-DscAuthoringResource.ps1 uses Write-Output inside
the PassThru branch (if ($PassThru.IsPresent) { Write-Output $registrations });
replace that call with a direct return of the value (return $registrations) so
the function returns the registrations object instead of using Write-Output,
keeping the behavior consistent with the module guideline and ensuring
$registrations is returned when $PassThru is present.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/Private/ConvertTo-Hashtable.ps1`:
- Line 68: The return statement in the ConvertTo-Hashtable function uses a unary
comma which wraps the result as a single-element nested array; change the return
from "return ,$items.ToArray()" to return the array directly (e.g. "return
$items.ToArray()") so $items (and List/IList inputs) are returned with the
correct flat array shape; ensure you update the return in the function handling
$items.ToArray().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f6b387ec-b377-49e0-8fac-e8f41c825048

📥 Commits

Reviewing files that changed from the base of the PR and between cb5870b and 24ceeb7.

📒 Files selected for processing (5)
  • source/Classes/006.DscExecutableResourceDiscovery.ps1
  • source/Private/ConvertTo-Hashtable.ps1
  • tests/Unit/Public/Export-DscConfigurationDocument.Tests.ps1
  • tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1
  • tests/Unit/Public/Register-DscResourceAuthoringType.Tests.ps1
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/Unit/Public/Export-DscConfigurationDocument.Tests.ps1
  • tests/Unit/Public/Register-DscResourceAuthoringType.Tests.ps1
  • source/Classes/006.DscExecutableResourceDiscovery.ps1
  • tests/Unit/Public/Import-DscResourceAuthoringMetadata.Tests.ps1

Comment thread source/Private/ConvertTo-Hashtable.ps1
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.

Author Microsoft DSC configuration documents from discovered resource schema

1 participant