11import { describe , expect , it , vi } from "vitest" ;
22
3- import { extractPathFromShellOutput , readPathFromLoginShell } from "./shell" ;
3+ import {
4+ extractPathFromShellOutput ,
5+ readEnvironmentFromLoginShell ,
6+ readPathFromLoginShell ,
7+ } from "./shell" ;
48
59describe ( "extractPathFromShellOutput" , ( ) => {
610 it ( "extracts the path between capture markers" , ( ) => {
@@ -32,7 +36,7 @@ describe("readPathFromLoginShell", () => {
3236 args : ReadonlyArray < string > ,
3337 options : { encoding : "utf8" ; timeout : number } ,
3438 ) => string
35- > ( ( ) => "__T3CODE_PATH_START__ \n/a:/b\n__T3CODE_PATH_END__ \n" ) ;
39+ > ( ( ) => "__T3CODE_ENV_PATH_START__ \n/a:/b\n__T3CODE_ENV_PATH_END__ \n" ) ;
3640
3741 expect ( readPathFromLoginShell ( "/opt/homebrew/bin/fish" , execFile ) ) . toBe ( "/a:/b" ) ;
3842 expect ( execFile ) . toHaveBeenCalledTimes ( 1 ) ;
@@ -49,9 +53,76 @@ describe("readPathFromLoginShell", () => {
4953 expect ( shell ) . toBe ( "/opt/homebrew/bin/fish" ) ;
5054 expect ( args ) . toHaveLength ( 2 ) ;
5155 expect ( args ?. [ 0 ] ) . toBe ( "-ilc" ) ;
52- expect ( args ?. [ 1 ] ) . toContain ( "printenv PATH" ) ;
53- expect ( args ?. [ 1 ] ) . toContain ( "__T3CODE_PATH_START__ " ) ;
54- expect ( args ?. [ 1 ] ) . toContain ( "__T3CODE_PATH_END__ " ) ;
56+ expect ( args ?. [ 1 ] ) . toContain ( "printenv PATH || true " ) ;
57+ expect ( args ?. [ 1 ] ) . toContain ( "__T3CODE_ENV_PATH_START__ " ) ;
58+ expect ( args ?. [ 1 ] ) . toContain ( "__T3CODE_ENV_PATH_END__ " ) ;
5559 expect ( options ) . toEqual ( { encoding : "utf8" , timeout : 5000 } ) ;
5660 } ) ;
5761} ) ;
62+
63+ describe ( "readEnvironmentFromLoginShell" , ( ) => {
64+ it ( "extracts multiple environment variables from a login shell command" , ( ) => {
65+ const execFile = vi . fn <
66+ (
67+ file : string ,
68+ args : ReadonlyArray < string > ,
69+ options : { encoding : "utf8" ; timeout : number } ,
70+ ) => string
71+ > ( ( ) =>
72+ [
73+ "__T3CODE_ENV_PATH_START__" ,
74+ "/a:/b" ,
75+ "__T3CODE_ENV_PATH_END__" ,
76+ "__T3CODE_ENV_SSH_AUTH_SOCK_START__" ,
77+ "/tmp/secretive.sock" ,
78+ "__T3CODE_ENV_SSH_AUTH_SOCK_END__" ,
79+ ] . join ( "\n" ) ,
80+ ) ;
81+
82+ expect ( readEnvironmentFromLoginShell ( "/bin/zsh" , [ "PATH" , "SSH_AUTH_SOCK" ] , execFile ) ) . toEqual ( {
83+ PATH : "/a:/b" ,
84+ SSH_AUTH_SOCK : "/tmp/secretive.sock" ,
85+ } ) ;
86+ expect ( execFile ) . toHaveBeenCalledTimes ( 1 ) ;
87+ } ) ;
88+
89+ it ( "omits environment variables that are missing or empty" , ( ) => {
90+ const execFile = vi . fn <
91+ (
92+ file : string ,
93+ args : ReadonlyArray < string > ,
94+ options : { encoding : "utf8" ; timeout : number } ,
95+ ) => string
96+ > ( ( ) =>
97+ [
98+ "__T3CODE_ENV_PATH_START__" ,
99+ "/a:/b" ,
100+ "__T3CODE_ENV_PATH_END__" ,
101+ "__T3CODE_ENV_SSH_AUTH_SOCK_START__" ,
102+ "__T3CODE_ENV_SSH_AUTH_SOCK_END__" ,
103+ ] . join ( "\n" ) ,
104+ ) ;
105+
106+ expect ( readEnvironmentFromLoginShell ( "/bin/zsh" , [ "PATH" , "SSH_AUTH_SOCK" ] , execFile ) ) . toEqual ( {
107+ PATH : "/a:/b" ,
108+ } ) ;
109+ } ) ;
110+
111+ it ( "preserves surrounding whitespace in captured values" , ( ) => {
112+ const execFile = vi . fn <
113+ (
114+ file : string ,
115+ args : ReadonlyArray < string > ,
116+ options : { encoding : "utf8" ; timeout : number } ,
117+ ) => string
118+ > ( ( ) =>
119+ [ "__T3CODE_ENV_CUSTOM_VAR_START__" , " padded value " , "__T3CODE_ENV_CUSTOM_VAR_END__" ] . join (
120+ "\n" ,
121+ ) ,
122+ ) ;
123+
124+ expect ( readEnvironmentFromLoginShell ( "/bin/zsh" , [ "CUSTOM_VAR" ] , execFile ) ) . toEqual ( {
125+ CUSTOM_VAR : " padded value " ,
126+ } ) ;
127+ } ) ;
128+ } ) ;
0 commit comments