Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Pester Test to find Troublesome Characters
Describe 'Troublesome characters' {
Context 'Computer says no' {
BeforeAll {
$charsHyphen = [char[]](8211, 8212, 8213)
$charsQuoteSingle = [char[]](8216,8217,8218,8219)
$charsQuoteDouble = [char[]](8220,8221,8222)
$allowedScriptsHyphen = @(
'Write-Host First {0} Second'
'Write-Host "Text {0}"'
'"Double {0} quoted"'
"'Single {0} quote'"
('@"', 'Here{0}String', '"@' -join "`n")
"@'`nHere{0}String`n'@"
)
$allowedCasesHyphen = foreach ($char in $charsHyphen) {
foreach ($script in $allowedScriptsHyphen) {
@{ Char = $char; Code = [Int]$Char; Script = $script -f $char }
}
}
$allowedScriptsQuoteSingle = @(
'"Double `{0} quoted"'
)
$allowedScriptsQuoteDouble = @(
"'Single ``{0} quote'"
)
$allowedCasesQuoteSingle = foreach ($char in $charsQuoteSingle) {
foreach ($script in $allowedScriptsQuoteSingle) {
@{ Char = $char; Code = [Int]$Char; Script = $script -f $char }
}
}
$allowedCasesQuoteDouble = foreach ($char in $charsQuoteDouble) {
foreach ($script in $allowedScriptsQuoteDouble) {
@{ Char = $char; Code = [Int]$Char; Script = $script -f $char }
}
}
$allowedCases = $allowedCasesHyphen + $allowedCasesQuoteSingle + $allowedCasesQuoteDouble
$disallowedScriptsHyphen = @(
'1 {0} 2' # Warn
'Get-Command Get-Command {0}Syntax' # Error
'Get{0}Command' # Error
'1 {0}and 2' # Error
'5 {0}= 1' # Error
)
$disallowedCasesHyphen = foreach ($char in $charsHyphen) {
foreach ($script in $disallowedScriptsHyphen) {
@{ Char = $char; Code = [Int]$Char; Script = $script -f $char }
}
}
$disallowedScriptsQuoteSingle = @(
"{0}two singles{0}"
"{0}front single'"
"'back single{0}"
)
$disallowedScriptsQuoteDouble = @(
"{0}two doubles{0}"
"{0}front double`""
"`"back double{0}"
)
$disallowedCasesQuoteSingle = foreach ($char in $charsQuoteSingle) {
foreach ($script in $disallowedScriptsQuoteSingle) {
@{ Char = $char; Code = [Int]$Char; Script = $script -f $char }
}
}
$disallowedCasesQuoteDouble = foreach ($char in $charsQuoteDouble) {
foreach ($script in $disallowedScriptsQuoteDouble) {
@{ Char = $char; Code = [Int]$Char; Script = $script -f $char }
}
}
$disallowedCases = $disallowedCasesHyphen + $disallowedCasesQuoteSingle + $disallowedCasesQuoteDouble
$predicate = {
param ( $ast )
if ($ast -is [System.Management.Automation.Language.BinaryExpressionAst] -or
$ast -is [System.Management.Automation.Language.CommandParameterAst] -or
$ast -is [System.Management.Automation.Language.AssignmentStatementAst]) {
if ($ast.ErrorPosition.Text[0] -in 0x2013, 0x2014, 0x2015) {
return $true
}
}
if ($ast -is [System.Management.Automation.Language.CommandAst] -and
$ast.GetCommandName() -match '\u2013|\u2014|\u2015') {
return $true
}
if (($ast -is [System.Management.Automation.Language.StringConstantExpressionAst] -or
$ast -is [System.Management.Automation.Language.ExpandableStringExpressionAst]) -and
$ast.Parent -is [System.Management.Automation.Language.CommandExpressionAst]) {
if ($ast.Parent -match '^[\u2018-\u201e]|[\u2018-\u201e]$') {return $true}
}
}
}
It 'Allows <Char> (<Code>) in a quoted string in script "<Script>"' -TestCases $allowedCases {
param (
[Char]$Char,
[String]$Script
)
$tokens = $errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput($Script, [Ref]$tokens, [Ref]$errors)
$elements = $ast.FindAll($predicate, $true)
$elements | Should -BeNullOrEmpty
}
It 'Does not allow <Char> (<Code>) outside a quoted string in script "<Script>"' -TestCases $disallowedCases {
param (
[Char]$Char,
[String]$Script
)
$tokens = $errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput($Script, [Ref]$tokens, [Ref]$errors)
$elements = $ast.FindAll($predicate, $true)
$elements | Should -Not -BeNullOrEmpty
@($elements).Count | Should -Be 1
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment