@@ -2,7 +2,10 @@ import { describe, expect, it, vi } from "vitest";
22
33import {
44 extractPathFromShellOutput ,
5+ listLoginShellCandidates ,
6+ mergePathEntries ,
57 readEnvironmentFromLoginShell ,
8+ readPathFromLaunchctl ,
69 readPathFromLoginShell ,
710} from "./shell" ;
811
@@ -60,6 +63,38 @@ describe("readPathFromLoginShell", () => {
6063 } ) ;
6164} ) ;
6265
66+ describe ( "readPathFromLaunchctl" , ( ) => {
67+ it ( "returns a trimmed PATH value from launchctl" , ( ) => {
68+ const execFile = vi . fn <
69+ (
70+ file : string ,
71+ args : ReadonlyArray < string > ,
72+ options : { encoding : "utf8" ; timeout : number } ,
73+ ) => string
74+ > ( ( ) => " /opt/homebrew/bin:/usr/bin \n" ) ;
75+
76+ expect ( readPathFromLaunchctl ( execFile ) ) . toBe ( "/opt/homebrew/bin:/usr/bin" ) ;
77+ expect ( execFile ) . toHaveBeenCalledWith ( "/bin/launchctl" , [ "getenv" , "PATH" ] , {
78+ encoding : "utf8" ,
79+ timeout : 2000 ,
80+ } ) ;
81+ } ) ;
82+
83+ it ( "returns undefined when launchctl is unavailable" , ( ) => {
84+ const execFile = vi . fn <
85+ (
86+ file : string ,
87+ args : ReadonlyArray < string > ,
88+ options : { encoding : "utf8" ; timeout : number } ,
89+ ) => string
90+ > ( ( ) => {
91+ throw new Error ( "spawn /bin/launchctl ENOENT" ) ;
92+ } ) ;
93+
94+ expect ( readPathFromLaunchctl ( execFile ) ) . toBeUndefined ( ) ;
95+ } ) ;
96+ } ) ;
97+
6398describe ( "readEnvironmentFromLoginShell" , ( ) => {
6499 it ( "extracts multiple environment variables from a login shell command" , ( ) => {
65100 const execFile = vi . fn <
@@ -126,3 +161,30 @@ describe("readEnvironmentFromLoginShell", () => {
126161 } ) ;
127162 } ) ;
128163} ) ;
164+
165+ describe ( "listLoginShellCandidates" , ( ) => {
166+ it ( "returns env shell, user shell, then the platform fallback without duplicates" , ( ) => {
167+ expect ( listLoginShellCandidates ( "darwin" , " /opt/homebrew/bin/nu " , "/bin/zsh" ) ) . toEqual ( [
168+ "/opt/homebrew/bin/nu" ,
169+ "/bin/zsh" ,
170+ ] ) ;
171+ } ) ;
172+
173+ it ( "falls back to the platform default when no shells are available" , ( ) => {
174+ expect ( listLoginShellCandidates ( "linux" , undefined , "" ) ) . toEqual ( [ "/bin/bash" ] ) ;
175+ } ) ;
176+ } ) ;
177+
178+ describe ( "mergePathEntries" , ( ) => {
179+ it ( "prefers login-shell PATH entries and keeps inherited extras" , ( ) => {
180+ expect (
181+ mergePathEntries ( "/opt/homebrew/bin:/usr/bin" , "/Users/test/.local/bin:/usr/bin" , "darwin" ) ,
182+ ) . toBe ( "/opt/homebrew/bin:/usr/bin:/Users/test/.local/bin" ) ;
183+ } ) ;
184+
185+ it ( "uses the platform-specific delimiter" , ( ) => {
186+ expect ( mergePathEntries ( "C:\\Tools;C:\\Windows" , "C:\\Windows;C:\\Git" , "win32" ) ) . toBe (
187+ "C:\\Tools;C:\\Windows;C:\\Git" ,
188+ ) ;
189+ } ) ;
190+ } ) ;
0 commit comments