diff --git a/module/Entra/Microsoft.Entra/Applications/Add-EntraInheritablePermissionsToAgentIdentityBlueprint.ps1 b/module/Entra/Microsoft.Entra/Applications/Add-EntraInheritablePermissionsToAgentIdentityBlueprint.ps1 index e1ccbb5ae..7b2b3b667 100644 --- a/module/Entra/Microsoft.Entra/Applications/Add-EntraInheritablePermissionsToAgentIdentityBlueprint.ps1 +++ b/module/Entra/Microsoft.Entra/Applications/Add-EntraInheritablePermissionsToAgentIdentityBlueprint.ps1 @@ -146,7 +146,7 @@ function Add-EntraInheritablePermissionsToAgentIdentityBlueprint { if ($existingEntry) { # Overwrite the existing entry for this resourceAppId - Write-Verbose "Existing inheritable permissions found for resource '$resourceName' — overwriting..." + Write-Verbose "Existing inheritable permissions found for resource '$resourceName' - overwriting..." $patchUrl = "$apiUrl/$($currentResourceAppId.ToString())" Write-Debug "PATCH URL: $patchUrl" @@ -169,8 +169,8 @@ function Add-EntraInheritablePermissionsToAgentIdentityBlueprint { } } else { - # No existing entry for this resourceAppId — add it (preserves other resources' permissions) - Write-Verbose "No existing inheritable permissions for resource '$resourceName' — adding..." + # No existing entry for this resourceAppId - add it (preserves other resources' permissions) + Write-Verbose "No existing inheritable permissions for resource '$resourceName' - adding..." Write-Debug "POST URL: $apiUrl" while ($retryCount -lt $maxRetries -and -not $success) { diff --git a/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprint.ps1 b/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprint.ps1 index 0a74f40cb..bcd8eb03a 100644 --- a/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprint.ps1 +++ b/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprint.ps1 @@ -19,7 +19,7 @@ function Get-EntraAgentIdentityBlueprint { return } - # Resolve BlueprintId: explicit param → stored → prompt → error + # Resolve BlueprintId: explicit param -> stored -> prompt -> error if (-not $BlueprintId) { if ((Test-Path variable:script:CurrentAgentBlueprintId) -and $script:CurrentAgentBlueprintId) { $BlueprintId = $script:CurrentAgentBlueprintId diff --git a/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprintPrincipal.ps1 b/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprintPrincipal.ps1 index aa70417b1..0e5456d70 100644 --- a/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprintPrincipal.ps1 +++ b/module/Entra/Microsoft.Entra/Applications/Get-EntraAgentIdentityBlueprintPrincipal.ps1 @@ -19,7 +19,7 @@ function Get-EntraAgentIdentityBlueprintPrincipal { return } - # Resolve ServicePrincipalId: explicit param → stored → prompt → error + # Resolve ServicePrincipalId: explicit param -> stored -> prompt -> error if (-not $ServicePrincipalId) { if ((Test-Path variable:script:CurrentAgentBlueprintServicePrincipalId) -and $script:CurrentAgentBlueprintServicePrincipalId) { $ServicePrincipalId = $script:CurrentAgentBlueprintServicePrincipalId diff --git a/module/Entra/Microsoft.Entra/Applications/Invoke-EntraAgentIdInteractive.ps1 b/module/Entra/Microsoft.Entra/Applications/Invoke-EntraAgentIdInteractive.ps1 index 096d030e5..3c3b87ec7 100644 --- a/module/Entra/Microsoft.Entra/Applications/Invoke-EntraAgentIdInteractive.ps1 +++ b/module/Entra/Microsoft.Entra/Applications/Invoke-EntraAgentIdInteractive.ps1 @@ -609,44 +609,44 @@ function Invoke-EntraAgentIdInteractive { # =================================================================== Write-Host "=== Complete Workflow Summary ===" -ForegroundColor Green - Write-Host "✓ 1. Agent Identity Blueprint created and configured" -ForegroundColor Green - Write-Host "✓ 2. Client secret added for API authentication" -ForegroundColor Green + Write-Host "[OK] 1. Agent Identity Blueprint created and configured" -ForegroundColor Green + Write-Host "[OK] 2. Client secret added for API authentication" -ForegroundColor Green if ($hasInteractiveAgents) { - Write-Host "✓ 3. Interactive agent scopes configured with user prompts" -ForegroundColor Green + Write-Host "[OK] 3. Interactive agent scopes configured with user prompts" -ForegroundColor Green } else { Write-Host "- 3. Interactive agent scopes (skipped by user choice)" -ForegroundColor Gray } if ($blueprintWillCreateAgentUsers) { - Write-Host "✓ 4. Blueprint configured to create Agent ID users" -ForegroundColor Green + Write-Host "[OK] 4. Blueprint configured to create Agent ID users" -ForegroundColor Green } else { Write-Host "- 4. Blueprint configured to create Agent ID users (skipped by user choice)" -ForegroundColor Gray } if ($hasInheritablePermissions) { - Write-Host "✓ 5. Inheritable permissions configured for agent users" -ForegroundColor Green + Write-Host "[OK] 5. Inheritable permissions configured for agent users" -ForegroundColor Green } else { Write-Host "- 5. Inheritable permissions (skipped by user choice)" -ForegroundColor Gray } if ($hasInheritablePermissions -and $useStaticPermissions) { - Write-Host "✓ 6. Static permissions configured via required resource access" -ForegroundColor Green + Write-Host "[OK] 6. Static permissions configured via required resource access" -ForegroundColor Green } elseif ($hasInheritablePermissions -and -not $useStaticPermissions) { - Write-Host "✓ 6. Dynamic permissions selected (resolved at runtime)" -ForegroundColor Green + Write-Host "[OK] 6. Dynamic permissions selected (resolved at runtime)" -ForegroundColor Green } else { Write-Host "- 6. Permission model selection (skipped - no inheritable permissions)" -ForegroundColor Gray } - Write-Host "✓ 7. Consent obtained for the blueprint in this tenant" -ForegroundColor Green + Write-Host "[OK] 7. Consent obtained for the blueprint in this tenant" -ForegroundColor Green if ($allAgentIdentities.Count -gt 0) { - Write-Host "✓ 8. Agent Identity and User Creation completed" -ForegroundColor Green + Write-Host "[OK] 8. Agent Identity and User Creation completed" -ForegroundColor Green Write-Host " - Created $($allAgentIdentities.Count) Agent $(if ($allAgentIdentities.Count -eq 1) { 'Identity' } else { 'Identities' })" -ForegroundColor Green if ($blueprintWillCreateAgentUsers) { Write-Host " - Created $($allAgentUsers.Count) Agent $(if ($allAgentUsers.Count -eq 1) { 'User' } else { 'Users' })" -ForegroundColor Green diff --git a/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIDForAgentIdentityBlueprint.ps1 b/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIDForAgentIdentityBlueprint.ps1 index 49d7c6f81..79ed70188 100644 --- a/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIDForAgentIdentityBlueprint.ps1 +++ b/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIDForAgentIdentityBlueprint.ps1 @@ -77,7 +77,7 @@ function New-EntraAgentIDForAgentIdentityBlueprint { Write-Verbose "Could not retrieve current user details: $_" } - # Sponsors are always required — prompt until at least one is provided + # Sponsors are always required - prompt until at least one is provided $hasSponsors = (($SponsorUserIds -and $SponsorUserIds.Count -gt 0) -or ($SponsorGroupIds -and $SponsorGroupIds.Count -gt 0)) diff --git a/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIdentityBlueprint.ps1 b/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIdentityBlueprint.ps1 index ec76b7e72..ab4304956 100644 --- a/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIdentityBlueprint.ps1 +++ b/module/Entra/Microsoft.Entra/Applications/New-EntraAgentIdentityBlueprint.ps1 @@ -58,7 +58,7 @@ function New-EntraAgentIdentityBlueprint { $customHeaders = $null } - # Sponsors are always required — prompt until at least one is provided + # Sponsors are always required - prompt until at least one is provided $hasSponsors = (($SponsorUserIds -and $SponsorUserIds.Count -gt 0) -or ($SponsorGroupIds -and $SponsorGroupIds.Count -gt 0)) diff --git a/module/Entra/Microsoft.Entra/Users/New-EntraUser.ps1 b/module/Entra/Microsoft.Entra/Users/New-EntraUser.ps1 index 5152aa351..05e1bedd7 100644 --- a/module/Entra/Microsoft.Entra/Users/New-EntraUser.ps1 +++ b/module/Entra/Microsoft.Entra/Users/New-EntraUser.ps1 @@ -83,7 +83,7 @@ function New-EntraUser { [Parameter(ParameterSetName = "CreateUser", HelpMessage = "The user's surname (last name). Maximum length: 64 characters.")] [System.String] $Surname, - [Parameter(ParameterSetName = "CreateUser", HelpMessage = "A list of the user’s additional email addresses (e.g., ['bob@contoso.com', 'Robert@fabrikam.com']). Supports up to 250 entries, each up to 250 characters.")] + [Parameter(ParameterSetName = "CreateUser", HelpMessage = "A list of the user's additional email addresses (e.g., ['bob@contoso.com', 'Robert@fabrikam.com']). Supports up to 250 entries, each up to 250 characters.")] [System.Collections.Generic.List`1[System.String]] $OtherMails, [Parameter(ParameterSetName = "CreateUser", HelpMessage = "The user's sign-in name (UPN) in the format alias@domain. It should match the user's email and use a verified domain in the tenant.")] diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Add-EntraBetaInheritablePermissionsToAgentIdentityBlueprint.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Add-EntraBetaInheritablePermissionsToAgentIdentityBlueprint.ps1 index 68aabdb1e..25cd52041 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Add-EntraBetaInheritablePermissionsToAgentIdentityBlueprint.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Add-EntraBetaInheritablePermissionsToAgentIdentityBlueprint.ps1 @@ -129,7 +129,7 @@ function Add-EntraBetaInheritablePermissionsToAgentIdentityBlueprint { if ($existingEntry) { # Overwrite the existing entry for this resourceAppId - Write-Verbose "Existing inheritable permissions found for resource '$resourceName' — overwriting..." + Write-Verbose "Existing inheritable permissions found for resource '$resourceName' - overwriting..." $patchUrl = "$apiUrl/$($currentResourceAppId.ToString())" Write-Debug "PATCH URL: $patchUrl" @@ -152,8 +152,8 @@ function Add-EntraBetaInheritablePermissionsToAgentIdentityBlueprint { } } else { - # No existing entry for this resourceAppId — add it (preserves other resources' permissions) - Write-Verbose "No existing inheritable permissions for resource '$resourceName' — adding..." + # No existing entry for this resourceAppId - add it (preserves other resources' permissions) + Write-Verbose "No existing inheritable permissions for resource '$resourceName' - adding..." Write-Debug "POST URL: $apiUrl" while ($retryCount -lt $maxRetries -and -not $success) { diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprint.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprint.ps1 index eb2edc66c..9a8e82796 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprint.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprint.ps1 @@ -19,7 +19,7 @@ function Get-EntraBetaAgentIdentityBlueprint { return } - # Resolve BlueprintId: explicit param → stored → prompt → error + # Resolve BlueprintId: explicit param -> stored -> prompt -> error if (-not $BlueprintId) { if ((Test-Path variable:script:CurrentAgentBlueprintId) -and $script:CurrentAgentBlueprintId) { $BlueprintId = $script:CurrentAgentBlueprintId diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprintPrincipal.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprintPrincipal.ps1 index 889310db5..d36b21444 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprintPrincipal.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Get-EntraBetaAgentIdentityBlueprintPrincipal.ps1 @@ -19,7 +19,7 @@ function Get-EntraBetaAgentIdentityBlueprintPrincipal { return } - # Resolve ServicePrincipalId: explicit param → stored → prompt → error + # Resolve ServicePrincipalId: explicit param -> stored -> prompt -> error if (-not $ServicePrincipalId) { if ((Test-Path variable:script:CurrentAgentBlueprintServicePrincipalId) -and $script:CurrentAgentBlueprintServicePrincipalId) { $ServicePrincipalId = $script:CurrentAgentBlueprintServicePrincipalId diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Grant-EntraBetaMCPServerPermission.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Grant-EntraBetaMCPServerPermission.ps1 index 138864aa5..55f023d13 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Grant-EntraBetaMCPServerPermission.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Grant-EntraBetaMCPServerPermission.ps1 @@ -98,7 +98,7 @@ function Grant-EntraBetaMcpServerPermission { $incomingScopes = $targetScopes | Where-Object { $_ } | Sort-Object -Unique if (-not $grant) { - # No existing grant – create with provided scopes (already additive by definition) + # No existing grant - create with provided scopes (already additive by definition) $targetString = ($incomingScopes) -join ' ' Write-Verbose "Creating new permission grant with scopes: $targetString" $body = @{ diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Invoke-EntraBetaAgentIdInteractive.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Invoke-EntraBetaAgentIdInteractive.ps1 index a77c9decb..fc2ca3cb9 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Invoke-EntraBetaAgentIdInteractive.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Invoke-EntraBetaAgentIdInteractive.ps1 @@ -609,44 +609,44 @@ function Invoke-EntraBetaAgentIdInteractive { # =================================================================== Write-Host "=== Complete Workflow Summary ===" -ForegroundColor Green - Write-Host "✓ 1. Agent Identity Blueprint created and configured" -ForegroundColor Green - Write-Host "✓ 2. Client secret added for API authentication" -ForegroundColor Green + Write-Host "[OK] 1. Agent Identity Blueprint created and configured" -ForegroundColor Green + Write-Host "[OK] 2. Client secret added for API authentication" -ForegroundColor Green if ($hasInteractiveAgents) { - Write-Host "✓ 3. Interactive agent scopes configured with user prompts" -ForegroundColor Green + Write-Host "[OK] 3. Interactive agent scopes configured with user prompts" -ForegroundColor Green } else { Write-Host "- 3. Interactive agent scopes (skipped by user choice)" -ForegroundColor Gray } if ($blueprintWillCreateAgentUsers) { - Write-Host "✓ 4. Blueprint configured to create Agent ID users" -ForegroundColor Green + Write-Host "[OK] 4. Blueprint configured to create Agent ID users" -ForegroundColor Green } else { Write-Host "- 4. Blueprint configured to create Agent ID users (skipped by user choice)" -ForegroundColor Gray } if ($hasInheritablePermissions) { - Write-Host "✓ 5. Inheritable permissions configured for agent users" -ForegroundColor Green + Write-Host "[OK] 5. Inheritable permissions configured for agent users" -ForegroundColor Green } else { Write-Host "- 5. Inheritable permissions (skipped by user choice)" -ForegroundColor Gray } if ($hasInheritablePermissions -and $useStaticPermissions) { - Write-Host "✓ 6. Static permissions configured via required resource access" -ForegroundColor Green + Write-Host "[OK] 6. Static permissions configured via required resource access" -ForegroundColor Green } elseif ($hasInheritablePermissions -and -not $useStaticPermissions) { - Write-Host "✓ 6. Dynamic permissions selected (resolved at runtime)" -ForegroundColor Green + Write-Host "[OK] 6. Dynamic permissions selected (resolved at runtime)" -ForegroundColor Green } else { Write-Host "- 6. Permission model selection (skipped - no inheritable permissions)" -ForegroundColor Gray } - Write-Host "✓ 7. Consent obtained for the blueprint in this tenant" -ForegroundColor Green + Write-Host "[OK] 7. Consent obtained for the blueprint in this tenant" -ForegroundColor Green if ($allAgentIdentities.Count -gt 0) { - Write-Host "✓ 8. Agent Identity and User Creation completed" -ForegroundColor Green + Write-Host "[OK] 8. Agent Identity and User Creation completed" -ForegroundColor Green Write-Host " - Created $($allAgentIdentities.Count) Agent $(if ($allAgentIdentities.Count -eq 1) { 'Identity' } else { 'Identities' })" -ForegroundColor Green if ($blueprintWillCreateAgentUsers) { Write-Host " - Created $($allAgentUsers.Count) Agent $(if ($allAgentUsers.Count -eq 1) { 'User' } else { 'Users' })" -ForegroundColor Green diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIDForAgentIdentityBlueprint.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIDForAgentIdentityBlueprint.ps1 index 50eae311d..1b4534196 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIDForAgentIdentityBlueprint.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIDForAgentIdentityBlueprint.ps1 @@ -77,7 +77,7 @@ function New-EntraBetaAgentIDForAgentIdentityBlueprint { Write-Verbose "Could not retrieve current user details: $_" } - # Sponsors are always required — prompt until at least one is provided + # Sponsors are always required - prompt until at least one is provided $hasSponsors = (($SponsorUserIds -and $SponsorUserIds.Count -gt 0) -or ($SponsorGroupIds -and $SponsorGroupIds.Count -gt 0)) diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIdentityBlueprint.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIdentityBlueprint.ps1 index 63af49452..29d463661 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIdentityBlueprint.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/New-EntraBetaAgentIdentityBlueprint.ps1 @@ -58,7 +58,7 @@ function New-EntraBetaAgentIdentityBlueprint { $customHeaders = $null } - # Sponsors are always required — prompt until at least one is provided + # Sponsors are always required - prompt until at least one is provided $hasSponsors = (($SponsorUserIds -and $SponsorUserIds.Count -gt 0) -or ($SponsorGroupIds -and $SponsorGroupIds.Count -gt 0)) diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Revoke-EntraBetaMCPServerPermission.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Revoke-EntraBetaMCPServerPermission.ps1 index 8f1a124af..72c0730ef 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Applications/Revoke-EntraBetaMCPServerPermission.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Applications/Revoke-EntraBetaMCPServerPermission.ps1 @@ -191,10 +191,10 @@ function Revoke-EntraBetaMcpServerPermission { $updatedGrant = Update-GrantScopes -clientSpId $clientSp.Id -resourceSpId $resourceSp.Id -targetScopes $remainingScopes if (@($remainingScopes).Count -eq 0) { - Write-Host "✓ All permissions revoked from $($resolvedClient.Name)" -ForegroundColor Green + Write-Host "[OK] All permissions revoked from $($resolvedClient.Name)" -ForegroundColor Green return $null } else { - Write-Host "✓ Permissions partially revoked from $($resolvedClient.Name)" -ForegroundColor Green + Write-Host "[OK] Permissions partially revoked from $($resolvedClient.Name)" -ForegroundColor Green Write-Verbose " Revoked scopes:" $validScopesToRevoke | ForEach-Object { Write-Verbose " - $_"} Write-Verbose " Remaining scopes:" diff --git a/module/EntraBeta/Microsoft.Entra.Beta/Users/New-EntraBetaUser.ps1 b/module/EntraBeta/Microsoft.Entra.Beta/Users/New-EntraBetaUser.ps1 index 3f6571450..e0c4e3100 100644 --- a/module/EntraBeta/Microsoft.Entra.Beta/Users/New-EntraBetaUser.ps1 +++ b/module/EntraBeta/Microsoft.Entra.Beta/Users/New-EntraBetaUser.ps1 @@ -83,7 +83,7 @@ function New-EntraBetaUser { [Parameter(ParameterSetName = "CreateUser", HelpMessage = "The user's surname (last name). Maximum length: 64 characters.")] [System.String] $Surname, - [Parameter(ParameterSetName = "CreateUser", HelpMessage = "A list of the user’s additional email addresses (e.g., ['bob@contoso.com', 'Robert@fabrikam.com']). Supports up to 250 entries, each up to 250 characters.")] + [Parameter(ParameterSetName = "CreateUser", HelpMessage = "A list of the user's additional email addresses (e.g., ['bob@contoso.com', 'Robert@fabrikam.com']). Supports up to 250 entries, each up to 250 characters.")] [System.Collections.Generic.List`1[System.String]] $OtherMails, [Parameter(ParameterSetName = "CreateUser", HelpMessage = "The user's sign-in name (UPN) in the format alias@domain. It should match the user's email and use a verified domain in the tenant.")] diff --git a/test/Entra/SourceFileEncoding.Tests.ps1 b/test/Entra/SourceFileEncoding.Tests.ps1 new file mode 100644 index 000000000..f6da8113e --- /dev/null +++ b/test/Entra/SourceFileEncoding.Tests.ps1 @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +# ------------------------------------------------------------------------------ + +# Regression guard for issue #1603. +# +# The module .psm1 files are assembled by concatenating the per-cmdlet .ps1 source +# files under module/. When a source file contains non-ASCII characters (for example +# the arrow "->", an em dash, or a check mark) and is saved without a UTF-8 BOM, +# Windows PowerShell 5.1 decodes the bytes using the system ANSI code page instead of +# UTF-8. The mis-decoded multi-byte characters turn into stray quote characters that +# unbalance the surrounding strings, so Import-Module fails with parser errors such as +# "Missing closing ')' in expression" and "The string is missing the terminator". +# +# PowerShell 7 (Core) reads BOM-less files as UTF-8, which is why the CI test runs and +# every day-to-day PowerShell 7 user import the module without error while the module +# is broken on Windows PowerShell 5.1. Keeping the shipped source ASCII-only makes the +# generated .psm1 parse identically under every encoding. + +Describe "Module source file encoding (Windows PowerShell 5.1 import safety)" { + BeforeDiscovery { + $moduleRoot = Join-Path $PSScriptRoot '..' '..' 'module' + $script:SourceFileCases = @() + if (Test-Path -Path $moduleRoot) { + $script:SourceFileCases = Get-ChildItem -Path $moduleRoot -Recurse -Filter '*.ps1' -File | + ForEach-Object { @{ FullName = $_.FullName; Name = $_.Name } } + } + } + + It "Should resolve the module source directory" { + (Join-Path $PSScriptRoot '..' '..' 'module') | Should -Exist + } + + It "Should discover module source files to validate" { + $moduleRoot = Join-Path $PSScriptRoot '..' '..' 'module' + @(Get-ChildItem -Path $moduleRoot -Recurse -Filter '*.ps1' -File).Count | Should -BeGreaterThan 0 + } + + It "'' should not contain non-ASCII characters" -ForEach $script:SourceFileCases { + $bytes = [System.IO.File]::ReadAllBytes($FullName) + $nonAsciiCount = @($bytes | Where-Object { $_ -gt 0x7F }).Count + $nonAsciiCount | Should -Be 0 -Because "$Name must be ASCII-only so Windows PowerShell 5.1 imports the module regardless of a BOM (issue #1603)" + } +}