diff --git a/src/Format2.ps1 b/src/Format2.ps1 index 38348fb0d..67c1759c9 100644 --- a/src/Format2.ps1 +++ b/src/Format2.ps1 @@ -1,4 +1,8 @@ -function Format-Collection2 ($Value, [switch]$Pretty) { + +# 0x1B is escape, the control code "`e" was introduces in Powershell 7, and so we write it directly as the number here. +[char[]] $script:specialChars = foreach ($ch in ("`0", "`a", "`b", "`t", "`f", "`r", "`n", 0x1B)) { [char]$ch } + +function Format-Collection2 ($Value, [switch]$Pretty) { $length = 0 $o = foreach ($v in $Value) { $formatted = Format-Nicely2 -Value $v -Pretty:$Pretty @@ -45,11 +49,35 @@ function Format-Object2 ($Value, $Property, [switch]$Pretty) { $o } +function Replace-SpecialCharactersInString ($Value) { + +} function Format-String2 ($Value) { if ('' -eq $Value) { return '' } + + # Special characters like `n or `e should be rendered as their visible versions. + # Especially `e which is used in ANSI codes and can entirely break our output. + # + # We convert each of these using the unicode printable version, + # which is obtained by adding 0x2400 + [int]$unicodeControlPictures = 0x2400 + + if (0 -lt $Value.IndexOfAny($script:specialChars)) { + $chars = [char[]]$Value + $charCount = $chars.Length + for ($j = 0; $j -lt $charCount; $j++) { + $char = $chars[$j] + if ($char -in $script:specialChars) { + $chars[$j] = [char]([int]$char + $unicodeControlPictures) + } + } + + $Value = $chars -join '' + } + "'$Value'" } diff --git a/src/functions/TestResults.NUnit3.ps1 b/src/functions/TestResults.NUnit3.ps1 index a4b08a70f..b0989aa2e 100644 --- a/src/functions/TestResults.NUnit3.ps1 +++ b/src/functions/TestResults.NUnit3.ps1 @@ -1,6 +1,6 @@ # NUnit3 schema docs: https://docs.nunit.org/articles/nunit/technical-notes/usage/Test-Result-XML-Format.html -[char[]] $script:invalidCDataChars = foreach ($ch in (0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)) { [char]$ch } +[char[]] $script:invalidCDataChars = foreach ($ch in (0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)) { [char]$ch } function Write-NUnit3Report([Pester.Run] $Result, [System.Xml.XmlWriter] $XmlWriter) { # Write the XML Declaration diff --git a/tst/Format2.Tests.ps1 b/tst/Format2.Tests.ps1 index ecb4b9ee2..ee2d3f8b6 100644 --- a/tst/Format2.Tests.ps1 +++ b/tst/Format2.Tests.ps1 @@ -209,8 +209,41 @@ InPesterModuleScope { Format-String2 -Value "" | Verify-Equal '' } - It "Formats string to be sorrounded by quotes" { + It "Formats string to be surrounded by quotes" { Format-String2 -Value "abc" | Verify-Equal "'abc'" } + + + It "Replaces ansi escapes with their showable equivalent" -ForEach @( + @{ Value = "`0"; Expected = '␀'; PowerShellVersion = 5 } + @{ Value = "`a"; Expected = '␇'; PowerShellVersion = 5 } + @{ Value = "`b"; Expected = '␈'; PowerShellVersion = 5 } + @{ Value = "`t"; Expected = '␉'; PowerShellVersion = 5 } + @{ Value = "`f"; Expected = '␌'; PowerShellVersion = 5 } + @{ Value = "`r"; Expected = '␍'; PowerShellVersion = 5 } + @{ Value = "`n"; Expected = '␊'; PowerShellVersion = 5 } + # Escape for escape was introduced in PowerShell 7 + @{ Value = "`e"; Expected = '␛'; PowerShellVersion = 7 } + ) { + if ($PSVersionTable.PSVersion.Major -lt $PowerShellVersion) { + continue + } + + Format-String2 -Value "-$value-" | Verify-Equal "'-$expected-'" + } + + It "Does not replace non escaped values with escapes" -ForEach @( + @{ Value = "0"; Expected = '0' } + @{ Value = "a"; Expected = 'a' } + @{ Value = "b"; Expected = 'b' } + @{ Value = "t"; Expected = 't' } + @{ Value = "f"; Expected = 'f' } + @{ Value = "r"; Expected = 'r' } + @{ Value = "n"; Expected = 'n' } + @{ Value = "e"; Expected = 'e' } + ) { + Format-String2 -Value "-$value-" | Verify-Equal "'-$expected-'" + } + } } diff --git a/tst/functions/assert/String/Should-BeString.Tests.ps1 b/tst/functions/assert/String/Should-BeString.Tests.ps1 index db9e702fe..e12626965 100644 --- a/tst/functions/assert/String/Should-BeString.Tests.ps1 +++ b/tst/functions/assert/String/Should-BeString.Tests.ps1 @@ -120,4 +120,9 @@ Describe "Should-BeString" { $err = { Should-BeString -Expected "abc" -Actual "bde" } | Verify-AssertionFailed $err.Exception.Message | Verify-Equal "Expected [string] 'abc', but got [string] 'bde'." } + + It "Handles escape character in the error message" { + $err = { Should-BeString -Expected "ee `e ee" -Actual "mmmmm" } | Verify-AssertionFailed + $err.Exception.Message | Verify-Equal "Expected [string] 'ee ␛ ee', but got [string] 'mmmmm'." + } }