|
| 1 | +#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.2.0' } |
| 2 | + |
| 3 | +<# |
| 4 | + The table IslPowerShell7Syntax reports from, held against the two hosts themselves: each entry |
| 5 | + must be missing from Windows PowerShell 5.1 and present in PowerShell 7. Both hosts are asked |
| 6 | + as child processes, so the test gives the same answer whichever one runs it; it is skipped |
| 7 | + where either host is missing. |
| 8 | +#> |
| 9 | + |
| 10 | +BeforeDiscovery { |
| 11 | + $script:BothHosts = [bool](Get-Command powershell.exe -ErrorAction SilentlyContinue) -and |
| 12 | + [bool](Get-Command pwsh.exe -ErrorAction SilentlyContinue) |
| 13 | +} |
| 14 | + |
| 15 | +BeforeAll { |
| 16 | + $script:ModuleRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) |
| 17 | + Import-Module (Join-Path $script:ModuleRoot 'IntuneScriptLab.psd1') -Force |
| 18 | + $script:Table = InModuleScope IntuneScriptLab { Get-IslCoreOnlyFeature } |
| 19 | + |
| 20 | + # What each host says about the table: for every command whether it exists, for every parameter |
| 21 | + # whether its command has it, and for every value whether the parameter's ValidateSet takes it |
| 22 | + # (no ValidateSet means the value is not refused there) |
| 23 | + $probe = { |
| 24 | + param($Json) |
| 25 | + $table = $Json | ConvertFrom-Json |
| 26 | + $result = @{ Commands = @{}; Parameters = @{}; Values = @{} } |
| 27 | + foreach ($name in $table.Commands) { |
| 28 | + $result.Commands[$name] = [bool](Get-Command -Name $name -ErrorAction SilentlyContinue) |
| 29 | + } |
| 30 | + foreach ($entry in $table.Parameters) { |
| 31 | + $command = Get-Command -Name $entry.Command -ErrorAction SilentlyContinue |
| 32 | + foreach ($parameter in $entry.Parameters) { |
| 33 | + $result.Parameters["$($entry.Command) -$parameter"] = |
| 34 | + [bool]($command -and $command.Parameters.ContainsKey($parameter)) |
| 35 | + } |
| 36 | + } |
| 37 | + foreach ($entry in $table.Values) { |
| 38 | + $command = Get-Command -Name $entry.Command -ErrorAction SilentlyContinue |
| 39 | + $set = @() |
| 40 | + if ($command -and $command.Parameters.ContainsKey($entry.Parameter)) { |
| 41 | + $set = @($command.Parameters[$entry.Parameter].Attributes | |
| 42 | + Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } | |
| 43 | + ForEach-Object { $_.ValidValues }) |
| 44 | + } |
| 45 | + foreach ($value in $entry.Values) { |
| 46 | + $result.Values["$($entry.Command) -$($entry.Parameter) $value"] = |
| 47 | + if ($set.Count) { [bool]($set -contains $value) } else { [bool]$command } |
| 48 | + } |
| 49 | + } |
| 50 | + $result | ConvertTo-Json -Depth 4 -Compress |
| 51 | + } |
| 52 | + $flat = [pscustomobject]@{ |
| 53 | + Commands = @($script:Table.Commands) |
| 54 | + Parameters = @(foreach ($command in $script:Table.Parameters.Keys) { |
| 55 | + @{ Command = $command; Parameters = @($script:Table.Parameters[$command]) } |
| 56 | + }) + @(@{ Command = 'ForEach-Object'; Parameters = @('Parallel') }) |
| 57 | + Values = @(foreach ($command in $script:Table.Values.Keys) { |
| 58 | + foreach ($parameter in $script:Table.Values[$command].Keys) { |
| 59 | + $values = @($script:Table.Values[$command][$parameter]) |
| 60 | + @{ Command = $command; Parameter = $parameter; Values = $values } |
| 61 | + } |
| 62 | + }) |
| 63 | + } |
| 64 | + $json = $flat | ConvertTo-Json -Depth 5 -Compress |
| 65 | + $command = "& { $($probe.ToString()) } '$($json.Replace("'", "''"))'" |
| 66 | + $encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($command)) |
| 67 | + function script:Get-HostAnswer { |
| 68 | + param([string]$Exe, [string]$Command) |
| 69 | + $raw = & $Exe -NoProfile -NonInteractive -EncodedCommand $Command 2>&1 |
| 70 | + ($raw | Where-Object { "$_".StartsWith('{') } | Select-Object -Last 1) | ConvertFrom-Json |
| 71 | + } |
| 72 | + # Discovery-time variables do not reach the run, so the lookup is repeated here |
| 73 | + $script:BothHosts = [bool](Get-Command powershell.exe -ErrorAction SilentlyContinue) -and |
| 74 | + [bool](Get-Command pwsh.exe -ErrorAction SilentlyContinue) |
| 75 | + if ($script:BothHosts) { |
| 76 | + $script:Desktop = Get-HostAnswer 'powershell.exe' $encoded |
| 77 | + $script:Core = Get-HostAnswer 'pwsh.exe' $encoded |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +AfterAll { |
| 82 | + Remove-Module IntuneScriptLab -Force -ErrorAction SilentlyContinue |
| 83 | +} |
| 84 | + |
| 85 | +Describe 'Get-IslCoreOnlyFeature' -Tag 'Unit', 'Private' { |
| 86 | + |
| 87 | + It 'returns the three tables' { |
| 88 | + $script:Table.PSObject.TypeNames | Should-ContainCollection 'IntuneScriptLab.CoreOnlyFeature' |
| 89 | + $script:Table.Commands.Count | Should-BeGreaterThan 5 |
| 90 | + $script:Table.Parameters.Keys.Count | Should-BeGreaterThan 5 |
| 91 | + $script:Table.Values['Out-File'].Encoding | Should-ContainCollection 'utf8NoBOM' |
| 92 | + } |
| 93 | + |
| 94 | + Context 'Against both hosts' -Skip:(-not $script:BothHosts) { |
| 95 | + It 'every listed command is missing from Windows PowerShell 5.1 and present in PowerShell 7' { |
| 96 | + $wrong = @(foreach ($name in $script:Table.Commands) { |
| 97 | + if ($script:Desktop.Commands.$name) { "$name exists in 5.1" } |
| 98 | + if (-not $script:Core.Commands.$name) { "$name is missing from 7" } |
| 99 | + }) |
| 100 | + $wrong | Should-BeCollection @() |
| 101 | + } |
| 102 | + |
| 103 | + It 'every listed parameter is missing from the 5.1 command and present on the 7 one' { |
| 104 | + $keys = @($script:Core.Parameters.PSObject.Properties.Name) |
| 105 | + $keys.Count | Should-BeGreaterThan 30 |
| 106 | + $wrong = @(foreach ($key in $keys) { |
| 107 | + if ($script:Desktop.Parameters.$key) { "$key exists in 5.1" } |
| 108 | + if (-not $script:Core.Parameters.$key) { "$key is missing from 7" } |
| 109 | + }) |
| 110 | + $wrong | Should-BeCollection @() |
| 111 | + } |
| 112 | + |
| 113 | + It 'every listed value is refused by the 5.1 parameter and taken by the 7 one' { |
| 114 | + $keys = @($script:Core.Values.PSObject.Properties.Name) |
| 115 | + $keys.Count | Should-BeGreaterThan 0 |
| 116 | + $wrong = @(foreach ($key in $keys) { |
| 117 | + if ($script:Desktop.Values.$key) { "$key is accepted by 5.1" } |
| 118 | + if (-not $script:Core.Values.$key) { "$key is refused by 7" } |
| 119 | + }) |
| 120 | + $wrong | Should-BeCollection @() |
| 121 | + } |
| 122 | + } |
| 123 | +} |
0 commit comments