Repository: PowerShell/PowerShell
File: test/powershell/engine/Basic/ValidateAttributes.Tests.ps1 (PowerShell)

Code before:
                    InnerErrorId            = "ValidateLengthMaxLengthFailure"
                }
                @{
                    ScriptBlock             = { function foo { param([ValidateLength(2, 5)] $bar) }; foo 123 }
                    FullyQualifiedErrorId   = "ParameterArgumentValidationError,foo"
                    InnerErrorId            = "ValidateLengthNotString"
                }
            )

            $validTestCases = @(
                @{
                    ScriptBlock  = { function foo { param([ValidateLength(2, 5)] [string] $bar) }; foo "abc" }
                }
                @{
                    ScriptBlock  = { function foo { param([ValidateLength(2, 5)] [string] $bar) }; foo "ab" }
                }
                @{
                    ScriptBlock  = { function foo { param([ValidateLength(2, 5)] [string] $bar) }; foo "abcde" }
                }
            )
        }

        It 'Exception: <FullyQualifiedErrorId>:<InnerErrorId>' -TestCases $testCases {
            param($ScriptBlock, $FullyQualifiedErrorId, $InnerErrorId)

            $ScriptBlock | Should -Throw -ErrorId $FullyQualifiedErrorId
            if ($InnerErrorId) {
                $error[0].exception.innerexception.errorrecord.FullyQualifiedErrorId | Should -Be $InnerErrorId
            }
        }

        It 'No Exception: valid string length' -TestCases $validTestCases {
            param($ScriptBlock)
            $ScriptBlock | Should -Not -Throw
        }

        It 'ValidateLength error message should be properly formatted' {
            function Test-ValidateLengthMax { param([ValidateLength(0,2)] [string] $Value) $Value }
            function Test-ValidateLengthMin { param([ValidateLength(5,10)] [string] $Value) $Value }

            $TestStringTooLong = "11111"
            $TestStringTooShort = "123"
            $ExpectedMaxLength = 2
            $ExpectedMinLength = 5

            { Test-ValidateLengthMax $TestStringTooLong } | Should -Throw -ErrorId "ParameterArgumentValidationError,Test-ValidateLengthMax"
            $error[0].Exception.InnerException.Message | Should -Match ".+\($($TestStringTooLong.Length)\).+\`"$ExpectedMaxLength\`""
            $error[0].Exception.Message | Should -Match 'Value'

            { Test-ValidateLengthMin $TestStringTooShort } | Should -Throw -ErrorId "ParameterArgumentValidationError,Test-ValidateLengthMin"
            $error[0].Exception.InnerException.Message | Should -Match ".+\($($TestStringTooShort.Length)\).+\`"$ExpectedMinLength\`""

Review comment (suggestion):
Using `$error[0]` is not reliable. We can use:
```powershell
            $err = $ScriptBlock | Should -Throw -ErrorId $FullyQualifiedErrorId -PassThru
```

Code after:
                    InnerErrorId            = "ValidateLengthMaxLengthFailure"
                }
                @{
                    ScriptBlock             = { function Test-StringLength { param([ValidateLength(2, 5)] $InputString) }; Test-StringLength 123 }
                    FullyQualifiedErrorId   = "ParameterArgumentValidationError,Test-StringLength"
                    InnerErrorId            = "ValidateLengthNotString"
                }
            )

            $validTestCases = @(
                @{
                    ScriptBlock  = { function Test-StringLength { param([ValidateLength(2, 5)] [string] $InputString) }; Test-StringLength "abc" }
                }
                @{
                    ScriptBlock  = { function Test-StringLength { param([ValidateLength(2, 5)] [string] $InputString) }; Test-StringLength "ab" }
                }
                @{
                    ScriptBlock  = { function Test-StringLength { param([ValidateLength(2, 5)] [string] $InputString) }; Test-StringLength "abcde" }
                }
            )
        }

        It 'Exception: <FullyQualifiedErrorId>:<InnerErrorId>' -TestCases $testCases {
            param($ScriptBlock, $FullyQualifiedErrorId, $InnerErrorId)

            $err = $ScriptBlock | Should -Throw -ErrorId $FullyQualifiedErrorId -PassThru
            if ($InnerErrorId) {
                $err.exception.innerexception.errorrecord.FullyQualifiedErrorId | Should -Be $InnerErrorId
            }
        }

        It 'No Exception: valid string length' -TestCases $validTestCases {
            param($ScriptBlock)
            $ScriptBlock | Should -Not -Throw
        }

        It 'ValidateLength error message should be properly formatted' {
            function Test-ValidateLengthMax { param([ValidateLength(0,2)] [string] $Value) $Value }
            function Test-ValidateLengthMin { param([ValidateLength(5,10)] [string] $Value) $Value }

            $TestStringTooLong = "11111"
            $TestStringTooShort = "123"
            $ExpectedMaxLength = 2
            $ExpectedMinLength = 5

            $err = { Test-ValidateLengthMax $TestStringTooLong } | Should -Throw -ErrorId "ParameterArgumentValidationError,Test-ValidateLengthMax" -PassThru
            $err.Exception.InnerException.Message | Should -Match ".+\($($TestStringTooLong.Length)\).+\`"$ExpectedMaxLength\`""

            $err = { Test-ValidateLengthMin $TestStringTooShort } | Should -Throw -ErrorId "ParameterArgumentValidationError,Test-ValidateLengthMin" -PassThru
            $err.Exception.InnerException.Message | Should -Match ".+\($($TestStringTooShort.Length)\).+\`"$ExpectedMinLength\`""
        }