@@ -148,7 +148,7 @@ describe("syncShellEnvironment", () => {
148148 expect ( env . PATH ) . toBe ( "/opt/homebrew/bin:/usr/bin" ) ;
149149 } ) ;
150150
151- it ( "does nothing outside macOS and linux " , ( ) => {
151+ it ( "does nothing on unsupported platforms " , ( ) => {
152152 const env : NodeJS . ProcessEnv = {
153153 SHELL : "C:/Program Files/Git/bin/bash.exe" ,
154154 PATH : "C:\\Windows\\System32" ,
@@ -160,12 +160,130 @@ describe("syncShellEnvironment", () => {
160160 } ) ) ;
161161
162162 syncShellEnvironment ( env , {
163- platform : "win32 " ,
163+ platform : "freebsd " ,
164164 readEnvironment,
165165 } ) ;
166166
167167 expect ( readEnvironment ) . not . toHaveBeenCalled ( ) ;
168168 expect ( env . PATH ) . toBe ( "C:\\Windows\\System32" ) ;
169169 expect ( env . SSH_AUTH_SOCK ) . toBe ( "/tmp/inherited.sock" ) ;
170170 } ) ;
171+
172+ it ( "hydrates PATH on Windows by merging PowerShell PATH with inherited PATH" , ( ) => {
173+ const env : NodeJS . ProcessEnv = {
174+ PATH : "C:\\Windows\\System32" ,
175+ APPDATA : "C:\\Users\\testuser\\AppData\\Roaming" ,
176+ LOCALAPPDATA : "C:\\Users\\testuser\\AppData\\Local" ,
177+ USERPROFILE : "C:\\Users\\testuser" ,
178+ } ;
179+ const readWindowsEnvironment = vi . fn ( ( ) => ( {
180+ PATH : "C:\\Custom\\Bin;C:\\Windows\\System32" ,
181+ } ) ) ;
182+ const isWindowsCommandAvailable = vi . fn ( ( ) => true ) ;
183+
184+ syncShellEnvironment ( env , {
185+ platform : "win32" ,
186+ readWindowsEnvironment,
187+ isWindowsCommandAvailable,
188+ } ) ;
189+
190+ expect ( readWindowsEnvironment ) . toHaveBeenCalledWith ( [ "PATH" ] , { loadProfile : false } ) ;
191+ expect ( env . PATH ) . toBe (
192+ [
193+ "C:\\Users\\testuser\\AppData\\Roaming\\npm" ,
194+ "C:\\Users\\testuser\\AppData\\Local\\Programs\\nodejs" ,
195+ "C:\\Users\\testuser\\AppData\\Local\\Volta\\bin" ,
196+ "C:\\Users\\testuser\\AppData\\Local\\pnpm" ,
197+ "C:\\Users\\testuser\\.bun\\bin" ,
198+ "C:\\Users\\testuser\\scoop\\shims" ,
199+ "C:\\Custom\\Bin" ,
200+ "C:\\Windows\\System32" ,
201+ ] . join ( ";" ) ,
202+ ) ;
203+ expect ( isWindowsCommandAvailable ) . toHaveBeenCalledTimes ( 1 ) ;
204+ } ) ;
205+
206+ it ( "loads the PowerShell profile on Windows when node is not available" , ( ) => {
207+ const env : NodeJS . ProcessEnv = {
208+ PATH : "C:\\Windows\\System32" ,
209+ APPDATA : "C:\\Users\\testuser\\AppData\\Roaming" ,
210+ LOCALAPPDATA : "C:\\Users\\testuser\\AppData\\Local" ,
211+ USERPROFILE : "C:\\Users\\testuser" ,
212+ } ;
213+ const readWindowsEnvironment = vi . fn (
214+ ( _names : ReadonlyArray < string > , options ?: { loadProfile ?: boolean } ) =>
215+ options ?. loadProfile
216+ ? {
217+ PATH : "C:\\Profile\\Node;C:\\Windows\\System32" ,
218+ FNM_DIR : "C:\\Users\\testuser\\AppData\\Roaming\\fnm" ,
219+ FNM_MULTISHELL_PATH : "C:\\Users\\testuser\\AppData\\Local\\fnm_multishells\\123" ,
220+ }
221+ : { PATH : "C:\\Custom\\Bin;C:\\Windows\\System32" } ,
222+ ) ;
223+ const isWindowsCommandAvailable = vi . fn ( ) . mockReturnValueOnce ( false ) . mockReturnValueOnce ( true ) ;
224+
225+ syncShellEnvironment ( env , {
226+ platform : "win32" ,
227+ readWindowsEnvironment,
228+ isWindowsCommandAvailable,
229+ } ) ;
230+
231+ expect ( env . PATH ) . toBe (
232+ [
233+ "C:\\Profile\\Node" ,
234+ "C:\\Windows\\System32" ,
235+ "C:\\Users\\testuser\\AppData\\Roaming\\npm" ,
236+ "C:\\Users\\testuser\\AppData\\Local\\Programs\\nodejs" ,
237+ "C:\\Users\\testuser\\AppData\\Local\\Volta\\bin" ,
238+ "C:\\Users\\testuser\\AppData\\Local\\pnpm" ,
239+ "C:\\Users\\testuser\\.bun\\bin" ,
240+ "C:\\Users\\testuser\\scoop\\shims" ,
241+ "C:\\Custom\\Bin" ,
242+ ] . join ( ";" ) ,
243+ ) ;
244+ expect ( env . FNM_DIR ) . toBe ( "C:\\Users\\testuser\\AppData\\Roaming\\fnm" ) ;
245+ expect ( env . FNM_MULTISHELL_PATH ) . toBe (
246+ "C:\\Users\\testuser\\AppData\\Local\\fnm_multishells\\123" ,
247+ ) ;
248+ expect ( readWindowsEnvironment ) . toHaveBeenNthCalledWith ( 1 , [ "PATH" ] , { loadProfile : false } ) ;
249+ expect ( readWindowsEnvironment ) . toHaveBeenNthCalledWith (
250+ 2 ,
251+ [ "PATH" , "FNM_DIR" , "FNM_MULTISHELL_PATH" ] ,
252+ { loadProfile : true } ,
253+ ) ;
254+ } ) ;
255+
256+ it ( "preserves baseline Windows env when the profile probe fails" , ( ) => {
257+ const env : NodeJS . ProcessEnv = {
258+ PATH : "C:\\Windows\\System32" ,
259+ APPDATA : "C:\\Users\\testuser\\AppData\\Roaming" ,
260+ USERPROFILE : "C:\\Users\\testuser" ,
261+ } ;
262+ const readWindowsEnvironment = vi . fn (
263+ ( _names : ReadonlyArray < string > , options ?: { loadProfile ?: boolean } ) => {
264+ if ( options ?. loadProfile ) {
265+ throw new Error ( "profile load failed" ) ;
266+ }
267+ return { PATH : "C:\\Custom\\Bin;C:\\Windows\\System32" } ;
268+ } ,
269+ ) ;
270+ const isWindowsCommandAvailable = vi . fn ( ( ) => false ) ;
271+
272+ syncShellEnvironment ( env , {
273+ platform : "win32" ,
274+ readWindowsEnvironment,
275+ isWindowsCommandAvailable,
276+ } ) ;
277+
278+ expect ( env . PATH ) . toBe (
279+ [
280+ "C:\\Users\\testuser\\AppData\\Roaming\\npm" ,
281+ "C:\\Users\\testuser\\.bun\\bin" ,
282+ "C:\\Users\\testuser\\scoop\\shims" ,
283+ "C:\\Custom\\Bin" ,
284+ "C:\\Windows\\System32" ,
285+ ] . join ( ";" ) ,
286+ ) ;
287+ expect ( env . SSH_AUTH_SOCK ) . toBeUndefined ( ) ;
288+ } ) ;
171289} ) ;
0 commit comments