@@ -6,6 +6,7 @@ import * as vscode from "vscode"
66
77import { Terminal } from "../Terminal"
88import { TerminalRegistry } from "../TerminalRegistry"
9+ import { ShellIntegrationManager } from "../ShellIntegrationManager"
910
1011vi . mock ( "execa" , ( ) => ( {
1112 execa : vi . fn ( ) ,
@@ -127,6 +128,102 @@ describe("Terminal VS Code terminal profile (#277)", () => {
127128
128129 expect ( Terminal . getAvailableProfileNames ( "linux" ) ) . toEqual ( [ "bash" , "zsh" ] )
129130 } )
131+
132+ it ( "excludes cmd.exe profiles on Windows (shell integration unsupported)" , ( ) => {
133+ stubProfiles ( {
134+ windows : {
135+ "Command Prompt" : { path : "C:\\Windows\\System32\\cmd.exe" } ,
136+ PowerShell : { path : "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" } ,
137+ } ,
138+ } )
139+
140+ expect ( Terminal . getAvailableProfileNames ( "win32" ) ) . toEqual ( [ "PowerShell" ] )
141+ } )
142+
143+ describe ( "isCmdExe" , ( ) => {
144+ it . each ( [
145+ [ "C:\\Windows\\System32\\cmd.exe" , true ] ,
146+ [ "C:\\WINDOWS\\SYSTEM32\\CMD.EXE" , true ] ,
147+ [ "/mnt/c/Windows/System32/cmd.exe" , true ] ,
148+ [ "/bin/bash" , false ] ,
149+ [ "pwsh.exe" , false ] ,
150+ [ "cmd" , false ] ,
151+ ] ) ( "isCmdExe(%s) === %s" , ( input , expected ) => {
152+ expect ( Terminal . isCmdExe ( input ) ) . toBe ( expected )
153+ } )
154+ } )
155+
156+ describe ( "isActiveShellCmdExe" , ( ) => {
157+ it ( "returns false on non-Windows platforms" , ( ) => {
158+ expect ( Terminal . isActiveShellCmdExe ( "linux" ) ) . toBe ( false )
159+ expect ( Terminal . isActiveShellCmdExe ( "darwin" ) ) . toBe ( false )
160+ } )
161+
162+ it ( "returns true when profile override resolves to cmd.exe" , ( ) => {
163+ stubProfiles ( { windows : { "Command Prompt" : { path : "C:\\Windows\\System32\\cmd.exe" } } } )
164+ Terminal . setTerminalProfile ( "Command Prompt" )
165+ expect ( Terminal . isActiveShellCmdExe ( "win32" ) ) . toBe ( true )
166+ } )
167+
168+ it ( "returns false when profile override resolves to a non-cmd shell" , ( ) => {
169+ stubProfiles ( { windows : { PowerShell : { path : "C:\\Program Files\\PowerShell\\pwsh.exe" } } } )
170+ Terminal . setTerminalProfile ( "PowerShell" )
171+ expect ( Terminal . isActiveShellCmdExe ( "win32" ) ) . toBe ( false )
172+ } )
173+
174+ it ( "returns true when no override and default profile is cmd.exe" , ( ) => {
175+ Terminal . setTerminalProfile ( undefined )
176+ stubProfiles ( { windows : { "Command Prompt" : { path : "C:\\Windows\\System32\\cmd.exe" } } } )
177+ getConfigurationSpy = vi
178+ . spyOn ( vscode . workspace , "getConfiguration" )
179+ . mockImplementation ( ( section ?: string ) => {
180+ if ( section === "terminal.integrated.profiles" ) {
181+ return {
182+ inspect : ( _key : string ) => ( {
183+ defaultValue : { "Command Prompt" : { path : "C:\\Windows\\System32\\cmd.exe" } } ,
184+ globalValue : undefined ,
185+ } ) ,
186+ } as any
187+ }
188+ if ( section === "terminal.integrated" ) {
189+ return {
190+ get : ( key : string ) => ( key === "defaultProfile.windows" ? "Command Prompt" : undefined ) ,
191+ } as any
192+ }
193+ return { get : ( _key : string , defaultValue ?: unknown ) => defaultValue } as any
194+ } )
195+ expect ( Terminal . isActiveShellCmdExe ( "win32" ) ) . toBe ( true )
196+ } )
197+
198+ it ( "returns false when no override and default profile is PowerShell" , ( ) => {
199+ Terminal . setTerminalProfile ( undefined )
200+ getConfigurationSpy = vi
201+ . spyOn ( vscode . workspace , "getConfiguration" )
202+ . mockImplementation ( ( section ?: string ) => {
203+ if ( section === "terminal.integrated.profiles" ) {
204+ return {
205+ inspect : ( _key : string ) => ( {
206+ defaultValue : { PowerShell : { path : "C:\\Program Files\\PowerShell\\pwsh.exe" } } ,
207+ globalValue : undefined ,
208+ } ) ,
209+ } as any
210+ }
211+ if ( section === "terminal.integrated" ) {
212+ return {
213+ get : ( key : string ) => ( key === "defaultProfile.windows" ? "PowerShell" : undefined ) ,
214+ } as any
215+ }
216+ return { get : ( _key : string , defaultValue ?: unknown ) => defaultValue } as any
217+ } )
218+ expect ( Terminal . isActiveShellCmdExe ( "win32" ) ) . toBe ( false )
219+ } )
220+
221+ it ( "returns false when no override and no default profile configured" , ( ) => {
222+ Terminal . setTerminalProfile ( undefined )
223+ stubProfiles ( { } )
224+ expect ( Terminal . isActiveShellCmdExe ( "win32" ) ) . toBe ( false )
225+ } )
226+ } )
130227 } )
131228
132229 describe ( "getProfileShell" , ( ) => {
@@ -328,4 +425,41 @@ describe("Terminal VS Code terminal profile (#277)", () => {
328425 expect ( options . shellArgs ) . toBeUndefined ( )
329426 } )
330427 } )
428+
429+ describe ( "ZDOTDIR injection guard" , ( ) => {
430+ let zshInitTmpDirSpy : any
431+
432+ beforeEach ( ( ) => {
433+ zshInitTmpDirSpy = vi
434+ . spyOn ( ShellIntegrationManager , "zshInitTmpDir" )
435+ . mockReturnValue ( "/tmp/roo-zdotdir-test" )
436+ Terminal . setTerminalZdotdir ( true )
437+ } )
438+
439+ afterEach ( ( ) => {
440+ Terminal . setTerminalZdotdir ( false )
441+ Terminal . setTerminalProfile ( undefined )
442+ TerminalRegistry [ "terminals" ] = [ ]
443+ vi . restoreAllMocks ( )
444+ } )
445+
446+ it ( "sets ZDOTDIR when zdotdir is enabled and no profile is configured" , ( ) => {
447+ stubProfiles ( { } )
448+ const env = Terminal . getEnv ( )
449+ expect ( zshInitTmpDirSpy ) . toHaveBeenCalledTimes ( 1 )
450+ expect ( env . ZDOTDIR ) . toBe ( "/tmp/roo-zdotdir-test" )
451+ } )
452+
453+ it ( "skips ZDOTDIR when zdotdir is enabled but a profile is configured" , ( ) => {
454+ stubProfiles ( {
455+ [ Terminal . getPlatformProfileKey ( process . platform ) ] : {
456+ zsh : { path : "/bin/zsh" } ,
457+ } ,
458+ } )
459+ Terminal . setTerminalProfile ( "zsh" )
460+ const env = Terminal . getEnv ( )
461+ expect ( zshInitTmpDirSpy ) . not . toHaveBeenCalled ( )
462+ expect ( env . ZDOTDIR ) . toBeUndefined ( )
463+ } )
464+ } )
331465} )
0 commit comments