Last active
January 30, 2019 08:22
-
-
Save ritalin/88e8cabd0fd84724760918870f49a46a to your computer and use it in GitHub Desktop.
Pester operator for object properties matching.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Import-Module Pester -MinimumVersion 4.0.5 -Force -Scope Local | |
Import-Module (Get-Module Pester | % NestedModules | ? Name -eq "Format" | % Path) -Scope Local | |
function BeSame([object[]]$ActualValue, [object[]]$ExpectedValue, [switch]$Negate, [string[]]$Property = $null, [switch]$Loose) { | |
_AssertSameObject $ActualValue $ExpectedValue $Property $Negate $Loose $false | |
} | |
function BeSameExactly([object[]]$ActualValue, [object[]]$ExpectedValue, [switch]$Negate, [string[]]$Property = $null, [switch]$Loose) { | |
_AssertSameObject $ActualValue $ExpectedValue $Property $Negate $Loose $true | |
} | |
function _AssertSameObject([object[]]$ActualValues, [object[]]$ExpectedValues, [string[]]$Property, [bool]$Negate, [bool]$Loose, [bool]$StrictType) { | |
if ($ExpectedValues.Length -eq 0) { | |
return _MakeFalure "Expected value(s) is not specified." | |
} | |
if ($ActualValues.Length -ne $ExpectedValues.Length) { | |
return _MakeFalure "Element Count is not matched (actuals:$($ActualValues.Length) != epects:$($ExpectedValues.Length)" | |
} | |
if ($Property -eq $null) { | |
$Property = $ExpectedValues[0] | Get-Member -MemberType Properties | % Name | |
} | |
for ($i = 0; $i -lt $ActualValues.Length; ++$i) { | |
$a = $ActualValues[$i] | |
$e = $ExpectedValues[$i] | |
if ($StrictType) { | |
$actualType = $a.GetType() | |
$expectType = $e.GetType() | |
if ($actualType -ne $expectType) { | |
return _MakeFalure "At $($i)-th element, type is mismatched. (Expect: $actualType, but Actual: $expectType)" | |
} | |
} | |
$actualProps = $a | Get-Member -MemberType Properties | % Name | |
if (-not $Loose) { | |
[string[]]$unmatched = $Property | ?{ $_ -notin $actualProps } | |
if ($unmatched.Length -gt 0) { | |
return _MakeFalure "At $($i)-th element, property is not found $($unmatched -join ",")" | |
} | |
} | |
$falureProps = @() | |
foreach ($p in $Property) { | |
if ($p -in $actualProps) { | |
if ($Negate) { | |
if ($a."$p" -eq $e."$p") { $falureProps += $p } | |
} | |
else { | |
if ($a."$p" -ne $e."$p") { $falureProps += $p } | |
} | |
} | |
} | |
$success = | |
if ($Negate) { | |
$falureProps.Count -ne $Property.Length | |
} | |
else { | |
$falureProps.Count -eq 0 | |
} | |
if (-not $success) { | |
$expectSubset = _SubsetValues $e $falureProps | |
$actualSubset = _SubsetValues $a $falureProps | |
$m = if ($Negate) { "matched property is found" } else { "property is not matched" } | |
return _MakeFalure "At $($i)-th element, $m. (Expected: $(Format-Nicely $expectSubset), Actual: $(Format-Nicely $actualSubset))" | |
} | |
} | |
[PSCustomObject]@{ | |
Succeeded = $true; FailureMessage = '' | |
} | |
} | |
function _MakeFalure([string]$Message) { | |
[PSCustomObject]@{ | |
Succeeded = $false | |
FailureMessage = $Message | |
} | |
} | |
function _SubsetValues([object]$v, [string[]]$props) { | |
foreach ($p in $props) { $v."$p" } | |
} | |
Add-AssertionOperator -Name BeSame -Test $function:BeSame -SupportsArrayInput | |
Add-AssertionOperator -Name BeSameExactly -Test $function:BeSameExactly -SupportsArrayInput |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment