Tests/Get-JevRanking.Tests.ps1
|
BeforeAll { Import-Module (Join-Path $PSScriptRoot '..' 'Jev.psd1') -Force } AfterAll { Remove-Module Jev -Force -ErrorAction SilentlyContinue } Describe 'Get-JevRanking semantic ranking' { BeforeEach { Mock -ModuleName Jev Invoke-JevDecision { param($State, $Questions) $Questions.Count | Should -Be 1 $Questions.ranking.type | Should -Be 'noul' $Questions.ranking.instructions | Should -Be 'Does this need urgent attention?' $probability = if ($State -is [version]) { $State.Minor / 10 } elseif ($State -is [string]) { switch ($State) { 'Low' { 0.05 } 'Middle' { 0.6 } 'High' { 0.95 } 'Tie A' { 0.6 } 'Tie B' { 0.6 } 'Zero' { 0.0 } 'One' { 1.0 } default { throw "Unexpected state: $State" } } } else { $State.Probability } [pscustomobject]@{ answers = [ordered]@{ ranking = [pscustomobject]@{ type = 'noul'; noul = $probability } } } } } It 'returns all original strings in descending order with stable ties' { $results = @(@('Low', 'Middle', 'High', 'Tie A', 'Tie B') | Get-JevRanking 'Does this need urgent attention?') $results | Should -Be @('High', 'Middle', 'Tie A', 'Tie B', 'Low') $results[0] | Should -BeOfType [string] Should -Invoke Invoke-JevDecision -ModuleName Jev -Exactly 5 -Scope It } It 'limits output with Top while evaluating every input and keeping the earlier boundary tie' { $results = @(@('Low', 'Tie A', 'High', 'Tie B') | Get-JevRanking 'Does this need urgent attention?' -Top 2) $results | Should -Be @('High', 'Tie A') Should -Invoke Invoke-JevDecision -ModuleName Jev -Exactly 4 -Scope It } It 'preserves original objects, types, and properties without using input ranking fields' { $ticket = [pscustomobject]@{ Id = 1; Probability = 0.7; ranking = 0.01 } $dictionary = [ordered]@{ Id = 2; Probability = 0.3; ranking = 0.99 } $version = [version] '2.9' $results = @(@($ticket, $dictionary, $version) | Get-JevRanking 'Does this need urgent attention?') $results.Count | Should -Be 3 [object]::ReferenceEquals($results[0], $version) | Should -BeTrue [object]::ReferenceEquals($results[1], $ticket) | Should -BeTrue [object]::ReferenceEquals($results[2], $dictionary) | Should -BeTrue $results[0] | Should -BeOfType [version] $ticket.ranking | Should -Be 0.01 $dictionary.ranking | Should -Be 0.99 @($ticket.PSObject.Properties.Name) | Should -Not -Contain 'answers' } It 'accepts named input and preserves a complete array as one record' { Mock -ModuleName Jev Invoke-JevDecision { [pscustomobject]@{ answers = [pscustomobject]@{ ranking = [pscustomobject]@{ type = 'noul'; noul = 0.9 } } } } $state = @('First part.', 'Second part.') $results = @(Get-JevRanking -State $state -Question 'Does this need urgent attention?' -Top 10) $results.Count | Should -Be 1 [object]::ReferenceEquals($results[0], $state) | Should -BeTrue Should -Invoke Invoke-JevDecision -ModuleName Jev -Exactly 1 -Scope It } It 'includes valid zero and one probabilities' { $results = @(@('Zero', 'One') | Get-JevRanking 'Does this need urgent attention?') $results | Should -Be @('One', 'Zero') } It 'makes no requests and emits nothing for an empty pipeline' { $results = @(@() | Get-JevRanking 'Does this need urgent attention?') $results.Count | Should -Be 0 Should -Invoke Invoke-JevDecision -ModuleName Jev -Exactly 0 -Scope It } It 'rejects Top <Top> before making a request' -TestCases @( @{ Top = 0 } @{ Top = -1 } ) { param($Top) { 'High' | Get-JevRanking 'Does this need urgent attention?' -Top $Top } | Should -Throw Should -Invoke Invoke-JevDecision -ModuleName Jev -Exactly 0 -Scope It } It 'rejects a missing Noul answer instead of ranking it as zero' { Mock -ModuleName Jev Invoke-JevDecision { [pscustomobject]@{ answers = [pscustomobject]@{} } } { 'High' | Get-JevRanking 'Does this need urgent attention?' } | Should -Throw '*did not return a Noul answer*' } It 'rejects an invalid probability: <Probability>' -TestCases @( @{ Probability = -0.1 } @{ Probability = 1.1 } @{ Probability = [double]::NaN } @{ Probability = [double]::PositiveInfinity } ) { param($Probability) Mock -ModuleName Jev Invoke-JevDecision { [pscustomobject]@{ answers = [pscustomobject]@{ ranking = [pscustomobject]@{ type = 'noul'; noul = $Probability } } } } { 'High' | Get-JevRanking 'Does this need urgent attention?' } | Should -Throw '*invalid probability*' } It 'propagates a failed request without emitting a partial ranking' { Mock -ModuleName Jev Invoke-JevDecision { param($State) if ($State -eq 'Middle') { throw 'Ranking backend unavailable.' } [pscustomobject]@{ answers = [pscustomobject]@{ ranking = [pscustomobject]@{ type = 'noul'; noul = 0.9 } } } } $received = [System.Collections.Generic.List[object]]::new() { @('High', 'Middle', 'Low') | Get-JevRanking 'Does this need urgent attention?' | ForEach-Object { $received.Add($_) } } | Should -Throw '*Ranking backend unavailable*' $received.Count | Should -Be 0 } } |