Background
VTest.PowerShell has two paths for invoking cmdlets:
- Direct path (
VisioPSSession.Cmd_* helpers): instantiates a cmdlet object in C# and calls cmd.Invoke() directly. Bypasses PowerShell's parameter binder.
- Runspace path (
VisioPSSession.InvokeScript<T>): goes through PowerShell's actual binder via _powershell.AddScript(...).Invoke(). Required for binding tests (the whole point of #173).
Each path operates with its own VisioScripting.Client instance. When a single test mixes the two paths, those Clients disagree on which Visio app / document is "active." Cmdlets that call TargetShapes.ResolveToSelection (which routes through Client.GetCommandTarget) trip the application does not match doc.application consistency check and throw.
End users in a real PowerShell session never hit this: there's only one Client per session. It's a test-infrastructure-only quirk.
Concrete evidence
VTest.PowerShell/CmdletBindingTests.cs's ExportVisioShape_TargetExists_WithOverwrite_ReplacesFile is currently [Ignore]'d for exactly this reason. It hits CommandTarget: application does not match doc.application because:
- Test setup creates a doc and shape via
Cmd_* helpers (direct path → Client A).
- Test action calls
Export-VisioShape ... -Overwrite via InvokeScript (runspace path → Client B).
- Export-VisioShape's success path reaches
TargetShapes.ResolveToSelection, which makes the mismatched Client B see Client A's doc and reject the call.
The companion test ExportVisioShape_TargetExists_NoOverwrite_Throws in the same file works fine because the cmdlet throws at the file-existence check before reaching ResolveToSelection. So the issue specifically affects success-path tests for cmdlets that touch the active selection.
This is the same constraint that blocked #163 and led to filing #164.
Options
Option 1: All-runspace setup pattern
The mismatch goes away if setup + action all happen inside one InvokeScript call (or successive calls that share the runspace's SessionState). One Client, one consistent view. Concretely the [Ignore]'d test would change setup from Cmd_New_VisioDocument / Cmd_New_VisioShape_rectangle to in-script New-VisioDocument / New-VisioShape -Rectangle ....
If it works: we re-enable the test AND establish "all-runspace" as the canonical pattern for future binding tests, without touching VisioCmdlet / VisioPSSession infrastructure. Effort: S.
If it doesn't: the issue is deeper than test-method-level mixing (it's at the session level), and the proper fix really does need #164.
Option 2: Make VisioPSSession share a single Client across paths
Re-architect the test session so the Cmd_* helpers and the runspace cmdlets resolve to the same VisioScripting.Client instance. Likely requires touching VisioCmdlet base class to accept an externally-injected Client, or having VisioPSSession configure the runspace's Client to match the direct-path Client.
This is the structural fix. May overlap significantly with whatever #164 ends up doing.
Effort: M.
Option 3: Defer entirely to #164
Treat the mismatch as a known limitation; track it on #164; accept that some binding tests stay [Ignore]'d until #164 lands. Effort: zero (just close this issue as "duplicate of #164").
Suggested approach when picked up
Try Option 1 first since it's small. If the all-runspace pattern works:
- Re-enable the
[Ignore]'d test.
- Add a paragraph to
docs/TESTING.md on the all-runspace pattern for cmdlet-binding tests.
- File a sibling issue (or a comment on #173) noting that future cmdlet-binding tests should use the all-runspace pattern by default.
If Option 1 doesn't work (the mismatch is deeper than method-level mixing), escalate to Option 2 or #164.
Cross-refs
- #164 - Investigate switching
VisioCmdlet base from Cmdlet to PSCmdlet (related architectural question).
- #163 - The original bug report that surfaced this mismatch.
- #173 - Cmdlet-binding test coverage; the
[Ignore]'d test came out of the first slice.
- memory: feedback_pscmdlet_avoid - The constraint that motivated keeping
VisioCmdlet : Cmdlet rather than PSCmdlet.
Effort
S to investigate Option 1. M if Option 2 is needed.
Background
VTest.PowerShellhas two paths for invoking cmdlets:VisioPSSession.Cmd_*helpers): instantiates a cmdlet object in C# and callscmd.Invoke()directly. Bypasses PowerShell's parameter binder.VisioPSSession.InvokeScript<T>): goes through PowerShell's actual binder via_powershell.AddScript(...).Invoke(). Required for binding tests (the whole point of #173).Each path operates with its own
VisioScripting.Clientinstance. When a single test mixes the two paths, those Clients disagree on which Visio app / document is "active." Cmdlets that callTargetShapes.ResolveToSelection(which routes throughClient.GetCommandTarget) trip theapplication does not match doc.applicationconsistency check and throw.End users in a real PowerShell session never hit this: there's only one Client per session. It's a test-infrastructure-only quirk.
Concrete evidence
VTest.PowerShell/CmdletBindingTests.cs'sExportVisioShape_TargetExists_WithOverwrite_ReplacesFileis currently[Ignore]'d for exactly this reason. It hitsCommandTarget: application does not match doc.applicationbecause:Cmd_*helpers (direct path → Client A).Export-VisioShape ... -OverwriteviaInvokeScript(runspace path → Client B).TargetShapes.ResolveToSelection, which makes the mismatched Client B see Client A's doc and reject the call.The companion test
ExportVisioShape_TargetExists_NoOverwrite_Throwsin the same file works fine because the cmdlet throws at the file-existence check before reachingResolveToSelection. So the issue specifically affects success-path tests for cmdlets that touch the active selection.This is the same constraint that blocked #163 and led to filing #164.
Options
Option 1: All-runspace setup pattern
The mismatch goes away if setup + action all happen inside one
InvokeScriptcall (or successive calls that share the runspace's SessionState). One Client, one consistent view. Concretely the[Ignore]'d test would change setup fromCmd_New_VisioDocument/Cmd_New_VisioShape_rectangleto in-scriptNew-VisioDocument/New-VisioShape -Rectangle ....If it works: we re-enable the test AND establish "all-runspace" as the canonical pattern for future binding tests, without touching
VisioCmdlet/VisioPSSessioninfrastructure. Effort: S.If it doesn't: the issue is deeper than test-method-level mixing (it's at the session level), and the proper fix really does need #164.
Option 2: Make
VisioPSSessionshare a single Client across pathsRe-architect the test session so the Cmd_* helpers and the runspace cmdlets resolve to the same
VisioScripting.Clientinstance. Likely requires touchingVisioCmdletbase class to accept an externally-injected Client, or havingVisioPSSessionconfigure the runspace's Client to match the direct-path Client.This is the structural fix. May overlap significantly with whatever #164 ends up doing.
Effort: M.
Option 3: Defer entirely to #164
Treat the mismatch as a known limitation; track it on #164; accept that some binding tests stay
[Ignore]'d until #164 lands. Effort: zero (just close this issue as "duplicate of #164").Suggested approach when picked up
Try Option 1 first since it's small. If the all-runspace pattern works:
[Ignore]'d test.docs/TESTING.mdon the all-runspace pattern for cmdlet-binding tests.If Option 1 doesn't work (the mismatch is deeper than method-level mixing), escalate to Option 2 or #164.
Cross-refs
VisioCmdletbase fromCmdlettoPSCmdlet(related architectural question).[Ignore]'d test came out of the first slice.VisioCmdlet : Cmdletrather thanPSCmdlet.Effort
S to investigate Option 1. M if Option 2 is needed.