diff --git a/src/functions/assert/String/Should-BeString.ps1 b/src/functions/assert/String/Should-BeString.ps1 index 3059fa12c..fedc3e097 100644 --- a/src/functions/assert/String/Should-BeString.ps1 +++ b/src/functions/assert/String/Should-BeString.ps1 @@ -96,8 +96,75 @@ function Should-BeString { $stringsAreEqual = Test-StringEqual -Expected $Expected -Actual $Actual -CaseSensitive:$CaseSensitive -IgnoreWhitespace:$IgnoreWhiteSpace -TrimWhitespace:$TrimWhitespace if (-not ($stringsAreEqual)) { - $Message = Get-AssertionMessage -Expected $Expected -Actual $Actual -Because $Because -DefaultMessage "Expected , but got ." + if ($Actual -is [string]) { + $Message = Get-StringDifferenceMessage -Expected $Expected -Actual $Actual -CaseSensitive:$CaseSensitive -Because $Because + } + else { + $Message = Get-AssertionMessage -Expected $Expected -Actual $Actual -Because $Because -DefaultMessage "Expected , but got ." + } Invoke-AssertionFailed -Message $Message -CallerCmdlet $PSCmdlet } Set-AssertionPassResult } + +function Get-StringDifferenceMessage { + param ( + [Parameter(Mandatory)] + [AllowEmptyString()] + [string] $Expected, + [Parameter(Mandatory)] + [AllowEmptyString()] + [string] $Actual, + [switch] $CaseSensitive, + [string] $Because + ) + + $maxLength = [Math]::Max($Expected.Length, $Actual.Length) + + $differenceIndex = $null + for ($i = 0; $i -lt $maxLength -and ($null -eq $differenceIndex); ++$i) { + if ($CaseSensitive) { + if ($Expected[$i] -cne $Actual[$i]) { $differenceIndex = $i } + } + else { + if ($Expected[$i] -ne $Actual[$i]) { $differenceIndex = $i } + } + } + + $because = if ($Because) { " because $Because," } else { "" } + + $lines = @( + "Expected strings to be the same,$because but they were different." + ) + + if ($Expected.Length -ne $Actual.Length) { + $lines += "Expected length: $($Expected.Length)" + $lines += "Actual length: $($Actual.Length)" + } + else { + $lines += "String lengths are both $($Expected.Length)." + } + $lines += "Strings differ at index $differenceIndex." + + $expectedExpanded = Expand-SpecialCharacters -InputObject $Expected + $actualExpanded = Expand-SpecialCharacters -InputObject $Actual + + # Recompute difference index on expanded strings + $maxLength = [Math]::Max($expectedExpanded.Length, $actualExpanded.Length) + $expandedDiffIndex = $null + for ($i = 0; $i -lt $maxLength -and ($null -eq $expandedDiffIndex); ++$i) { + if ($CaseSensitive) { + if ($expectedExpanded[$i] -cne $actualExpanded[$i]) { $expandedDiffIndex = $i } + } + else { + if ($expectedExpanded[$i] -ne $actualExpanded[$i]) { $expandedDiffIndex = $i } + } + } + + $prefix = "Expected: '" + $lines += "$prefix$expectedExpanded'" + $lines += "But was: '$actualExpanded'" + $lines += (' ' * ($prefix.Length - 1)) + ('-' * $expandedDiffIndex) + '^' + + $lines -join "`n" +} diff --git a/tst/functions/assert/String/Should-BeString.Tests.ps1 b/tst/functions/assert/String/Should-BeString.Tests.ps1 index db9e702fe..4786c5b78 100644 --- a/tst/functions/assert/String/Should-BeString.Tests.ps1 +++ b/tst/functions/assert/String/Should-BeString.Tests.ps1 @@ -118,6 +118,51 @@ Describe "Should-BeString" { It "Throws with default message when test fails" { $err = { Should-BeString -Expected "abc" -Actual "bde" } | Verify-AssertionFailed - $err.Exception.Message | Verify-Equal "Expected [string] 'abc', but got [string] 'bde'." + $err.Exception.Message | Verify-Equal (@' +Expected strings to be the same, but they were different. +String lengths are both 3. +Strings differ at index 0. +Expected: 'abc' +But was: 'bde' + ^ +'@ -replace "`r`n", "`n") + } + + It "Shows arrow at correct position for case-sensitive difference" { + $err = { "hello world" | Should-BeString "Hello World" -CaseSensitive } | Verify-AssertionFailed + $err.Exception.Message | Verify-Equal (@' +Expected strings to be the same, but they were different. +String lengths are both 11. +Strings differ at index 0. +Expected: 'Hello World' +But was: 'hello world' + ^ +'@ -replace "`r`n", "`n") + } + + It "Shows arrow with dashes for mid-string difference" { + $err = { "abc" | Should-BeString "abcdef" } | Verify-AssertionFailed + $err.Exception.Message | Verify-Equal (@' +Expected strings to be the same, but they were different. +Expected length: 6 +Actual length: 3 +Strings differ at index 3. +Expected: 'abcdef' +But was: 'abc' + ---^ +'@ -replace "`r`n", "`n") + } + + It "Shows expanded whitespace characters in diff" { + $err = { "abc`ndef" | Should-BeString "abc`r`ndef" } | Verify-AssertionFailed + $err.Exception.Message | Verify-Equal (@' +Expected strings to be the same, but they were different. +Expected length: 8 +Actual length: 7 +Strings differ at index 3. +Expected: 'abc\r\ndef' +But was: 'abc\ndef' + ----^ +'@ -replace "`r`n", "`n") } }