|
| 1 | +#Requires -Modules @{ ModuleName='Pester'; ModuleVersion='5.0.0' } |
| 2 | +# PR #488: a profile can pin the command palette (delegate) agent to an exact |
| 3 | +# execution source, so `wta delegate` always gets an explicit `--delegate-source |
| 4 | +# host|wsl` and never re-routes itself. Both assertions are deterministic once a |
| 5 | +# runnable WSL distro is present. |
| 6 | +# |
| 7 | +# The C++ half (TerminalPage.cpp turning a profile's `commandPaletteAgent` into |
| 8 | +# those flags) is only reachable via non-injectable UI — Alt+Shift+B, the |
| 9 | +# Alt+Shift+/ palette, `?<prompt>` — so, exactly like Feature.Delegate, these |
| 10 | +# cases drive the delegate ENGINE directly with the flags it now always passes. |
| 11 | +# The oracle is the rendered pane, not wta-delegate.log: `Invoke-Wta` runs an |
| 12 | +# unpackaged copy of wta.exe, which logs to the bare fallback dir rather than the |
| 13 | +# packaged one `Assert-Log` reads. |
| 14 | + |
| 15 | +BeforeDiscovery { |
| 16 | + $script:Ready = [bool]( |
| 17 | + (Get-AppxPackage | Where-Object { $_.Name -like '*IntelligentTerminal*' }) -and |
| 18 | + (Get-Command winapp -ErrorAction SilentlyContinue) -and |
| 19 | + (Get-Command wsl.exe -ErrorAction SilentlyContinue) |
| 20 | + ) |
| 21 | +} |
| 22 | + |
| 23 | +Describe 'Feature profile-scoped delegate source' -Tag 'Feature' -Skip:(-not $script:Ready) { |
| 24 | + BeforeAll { |
| 25 | + Import-Module (Join-Path $PSScriptRoot '..\ItE2E\ItE2E.psd1') -Force |
| 26 | + |
| 27 | + $script:app = $null |
| 28 | + $script:skipReason = $null |
| 29 | + |
| 30 | + $distroProbe = Invoke-Native -FilePath 'wsl.exe' -Arguments @( |
| 31 | + '-e', 'sh', '-lc', 'printf "%s" "${WSL_DISTRO_NAME:-}"' |
| 32 | + ) -TimeoutSec 45 |
| 33 | + $script:distro = $distroProbe.StdOut.Trim() |
| 34 | + if ($distroProbe.ExitCode -ne 0 -or -not $script:distro) { |
| 35 | + $script:skipReason = 'no runnable default WSL distro is available' |
| 36 | + } |
| 37 | + elseif ($script:distro -match '["\r\n]') { |
| 38 | + $script:skipReason = 'the default WSL distro name cannot be represented safely in a test command line' |
| 39 | + } |
| 40 | + |
| 41 | + $script:app = Start-Terminal -Package (Get-ItTestPackage) -PassFre $true ` |
| 42 | + -Settings @{ acpAgent = 'copilot'; delegateAgent = 'copilot' } |
| 43 | + |
| 44 | + # A random, never-installed name is absent from BOTH the Windows PATH and every |
| 45 | + # distro's PATH, so the "agent unavailable" branch fires deterministically. |
| 46 | + $script:bogusAgent = "ite2e-bogus-delegate-$(Get-Random -Maximum 999999)" |
| 47 | + |
| 48 | + # Launch a delegate and return the NEW tab created in this window. |
| 49 | + $script:RunDelegate = { |
| 50 | + param([string[]]$ExtraArgs = @()) |
| 51 | + $wid = [string]$script:app.WindowId |
| 52 | + $before = @((Get-WtTabs -App $script:app -WindowId $wid).tab_id) |
| 53 | + Invoke-Wta -App $script:app -TimeoutSec 40 -Raw -Arguments (@( |
| 54 | + 'delegate', 'hi', '--agent', 'copilot --acp --stdio', |
| 55 | + '--delegate-agent', $script:bogusAgent) + $ExtraArgs) | Out-Null |
| 56 | + $newTab = $null |
| 57 | + for ($i = 0; $i -lt 30 -and -not $newTab; $i++) { |
| 58 | + $newTab = @(Get-WtTabs -App $script:app -WindowId $wid) | Where-Object { $_.tab_id -notin $before } | Select-Object -First 1 |
| 59 | + if (-not $newTab) { Start-Sleep -Milliseconds 500 } |
| 60 | + } |
| 61 | + $panes = if ($newTab) { @(Get-WtPanes -App $script:app -WindowId $wid -TabId ([string]$newTab.tab_id)) } else { @() } |
| 62 | + @{ Tab = $newTab; Panes = $panes } |
| 63 | + } |
| 64 | + } |
| 65 | + AfterAll { if ($script:app) { Stop-Terminal -App $script:app } } |
| 66 | + |
| 67 | + It 'An explicit WSL delegate source never falls back to the Windows host' { |
| 68 | + if ($script:skipReason) { Set-ItResult -Skipped -Because $script:skipReason; return } |
| 69 | + |
| 70 | + $d = & $script:RunDelegate -ExtraArgs @('--delegate-source', 'wsl', '--delegate-wsl-distro', $script:distro) |
| 71 | + $d.Tab | Should -Not -BeNullOrEmpty -Because 'even a doomed WSL launch must open a tab so the real error stays visible' |
| 72 | + |
| 73 | + # bash's own "not found" (the launch wraps the command in `exec`) proves it really |
| 74 | + # ran in the distro; Windows would say "cannot find the file specified". |
| 75 | + $sid = $d.Panes[0].session_id |
| 76 | + (Test-Until -TimeoutSec 20 -IntervalSec 1 -Condition { |
| 77 | + (Get-WtCapture -App $script:app -SessionId $sid -MaxLines 40) -match '(?i)bash:.*not found' |
| 78 | + }) | Should -BeTrue -Because 'a missing WSL delegate agent must surface the real in-distro error, not silently switch to the host' |
| 79 | + } |
| 80 | + |
| 81 | + It 'The default delegate source is never diverted to WSL' { |
| 82 | + if ($script:skipReason) { Set-ItResult -Skipped -Because $script:skipReason; return } |
| 83 | + |
| 84 | + # No --delegate-source => host. A runnable distro on this machine (proven by the |
| 85 | + # probe above) must not tempt the CLI into routing there. |
| 86 | + $d = & $script:RunDelegate |
| 87 | + $d.Tab | Should -Not -BeNullOrEmpty -Because 'the host delegate launch must still open a tab' |
| 88 | + |
| 89 | + $sid = $d.Panes[0].session_id |
| 90 | + (Test-Until -TimeoutSec 20 -IntervalSec 1 -Condition { |
| 91 | + (Get-WtCapture -App $script:app -SessionId $sid -MaxLines 40) -match '(?i)cannot find the file specified|is not recognized' |
| 92 | + }) | Should -BeTrue -Because 'the default launch must fail with the real Windows error, proving it never ran inside WSL bash' |
| 93 | + } |
| 94 | +} |
0 commit comments