#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0.0' } <# Pins the V-5a observation about Test-Json -SchemaFile. OTD-005 chose a cmdlet whose failure reporting is version-dependent, and validation layer 2 is written against the behaviour observed on PowerShell 7.6.5 (specs/001-persona-engine/verification/V-5a.md). If a future build changes any row of that table, the wrapper's assumptions change with it - and the failure mode is silent: configurations start passing validation that should not. These tests fail loudly at that moment instead. #> BeforeAll { $repoRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent $script:schemaFile = Join-Path ([System.IO.Path]::GetTempPath()) ("pe-pin-{0}.json" -f [guid]::NewGuid().ToString('N')) Set-Content -LiteralPath $script:schemaFile -Encoding utf8NoBOM -Value @' { "type": "object", "required": ["a"], "properties": { "a": { "type": "string" } } } '@ $script:brokenSchemaFile = Join-Path ([System.IO.Path]::GetTempPath()) ("pe-pin-broken-{0}.json" -f [guid]::NewGuid().ToString('N')) Set-Content -LiteralPath $script:brokenSchemaFile -Encoding utf8NoBOM -Value '{ not json' } AfterAll { Remove-Item -LiteralPath $script:schemaFile, $script:brokenSchemaFile -Force -ErrorAction SilentlyContinue } Describe 'Test-Json -SchemaFile failure behaviour (V-5a)' { It 'returns $true and writes nothing for a valid document' { $errors = $null $result = '{ "a": "ok" }' | Test-Json -SchemaFile $script:schemaFile -ErrorAction SilentlyContinue -ErrorVariable errors $result | Should -BeTrue @($errors).Count | Should -Be 0 } It 'returns $false and writes one error for a type mismatch' { $errors = $null $result = '{ "a": 123 }' | Test-Json -SchemaFile $script:schemaFile -ErrorAction SilentlyContinue -ErrorVariable errors $result | Should -BeFalse @($errors).Count | Should -Be 1 } It 'returns $false and writes one error for a missing required property' { $errors = $null $result = '{}' | Test-Json -SchemaFile $script:schemaFile -ErrorAction SilentlyContinue -ErrorVariable errors $result | Should -BeFalse @($errors).Count | Should -Be 1 } It 'reports failure without throwing, so -ErrorVariable is sufficient' { # If a future build made this terminating, layer 2 would abort the run instead # of returning findings, and the editor would report an exception rather than # a PE-SCH finding. { '{ "a": 123 }' | Test-Json -SchemaFile $script:schemaFile -ErrorAction SilentlyContinue } | Should -Not -Throw } It 'returns $TRUE when the schema itself cannot be parsed - the trap layer 2 is built around' { # The load-bearing observation. A wrapper trusting the return value alone # would report every configuration as schema-valid against a schema that # never ran. $errors = $null $result = '{}' | Test-Json -SchemaFile $script:brokenSchemaFile -ErrorAction SilentlyContinue -ErrorVariable errors $result | Should -BeTrue @($errors).Count | Should -Be 1 $errors[0].Exception.Message | Should -Match 'Cannot parse the JSON schema' } It 'embeds a JSON pointer in the failure message, which VR-004 needs for Location' { $errors = $null $null = '{ "a": 123 }' | Test-Json -SchemaFile $script:schemaFile -ErrorAction SilentlyContinue -ErrorVariable errors $errors[0].Exception.Message | Should -Match "at '/a'" } It 'reports one error per violating location when several properties fail' { # Not exhaustive across nested subschemas, but not first-failure-only either. # Layer 2 therefore emits one finding per collected error rather than assuming # a single one. $multiSchema = Join-Path ([System.IO.Path]::GetTempPath()) ("pe-pin-multi-{0}.json" -f [guid]::NewGuid().ToString('N')) Set-Content -LiteralPath $multiSchema -Encoding utf8NoBOM -Value @' { "type": "object", "required": ["a", "b"], "properties": { "a": { "type": "string" }, "b": { "type": "string" } } } '@ try { $errors = $null $null = '{ "a": 1, "b": 2 }' | Test-Json -SchemaFile $multiSchema -ErrorAction SilentlyContinue -ErrorVariable errors @($errors).Count | Should -Be 2 ($errors | ForEach-Object { $_.Exception.Message }) -join ' ' | Should -Match "at '/a'" ($errors | ForEach-Object { $_.Exception.Message }) -join ' ' | Should -Match "at '/b'" } finally { Remove-Item -LiteralPath $multiSchema -Force -ErrorAction SilentlyContinue } } }