@@ -105,6 +105,9 @@ vi.mock("vscode", () => {
105105 openTextDocument,
106106 getConfiguration : vi . fn ( ( ) => ( { get : vi . fn ( ) } ) ) ,
107107 } ,
108+ commands : {
109+ executeCommand : vi . fn ( ) . mockResolvedValue ( undefined ) ,
110+ } ,
108111 }
109112} )
110113
@@ -897,17 +900,48 @@ describe("webviewMessageHandler - terminalProfile", () => {
897900describe ( "webviewMessageHandler - requestTerminalProfiles" , ( ) => {
898901 beforeEach ( ( ) => {
899902 vi . clearAllMocks ( )
903+ vi . spyOn ( Terminal , "resolveProfilePath" ) . mockImplementation ( ( profilePath ) => {
904+ const candidates = Array . isArray ( profilePath ) ? profilePath : [ profilePath ]
905+ const value = candidates . find (
906+ ( candidate ) =>
907+ typeof candidate === "string" && candidate . trim ( ) . length > 0 && ! candidate . includes ( "missing" ) ,
908+ )
909+ return typeof value === "string" ? value . trim ( ) : undefined
910+ } )
911+ } )
912+
913+ afterEach ( ( ) => {
914+ vi . restoreAllMocks ( )
900915 } )
901916
902- it ( "posts sorted profile names for the active platform" , async ( ) => {
903- const mockGet = vi . fn ( ) . mockReturnValue ( { "Git Bash" : { } , PowerShell : { } , "Command Prompt" : { } } )
917+ it ( "posts sorted path-resolvable profile names for the active platform" , async ( ) => {
918+ const mockGet = vi . fn ( ) . mockReturnValue ( {
919+ "Git Bash" : { path : "C:\\Git\\bin\\bash.exe" } ,
920+ bash : { path : "/bin/bash" } ,
921+ PowerShell : { source : "PowerShell" } , // source-only — must be excluded
922+ } )
904923 vi . mocked ( vscode . workspace . getConfiguration ) . mockReturnValue ( { get : mockGet } as any )
905924
906925 await webviewMessageHandler ( mockClineProvider , { type : "requestTerminalProfiles" } )
907926
908927 expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
909928 type : "terminalProfiles" ,
910- profiles : [ "Command Prompt" , "Git Bash" , "PowerShell" ] ,
929+ profiles : [ "Git Bash" , "bash" ] ,
930+ } )
931+ } )
932+
933+ it ( "excludes source-only profiles that have no path field" , async ( ) => {
934+ const mockGet = vi . fn ( ) . mockReturnValue ( {
935+ PowerShell : { source : "PowerShell" } ,
936+ "Windows PowerShell" : { source : "PowerShell" } ,
937+ } )
938+ vi . mocked ( vscode . workspace . getConfiguration ) . mockReturnValue ( { get : mockGet } as any )
939+
940+ await webviewMessageHandler ( mockClineProvider , { type : "requestTerminalProfiles" } )
941+
942+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
943+ type : "terminalProfiles" ,
944+ profiles : [ ] ,
911945 } )
912946 } )
913947
@@ -935,6 +969,64 @@ describe("webviewMessageHandler - requestTerminalProfiles", () => {
935969 profiles : [ ] ,
936970 } )
937971 } )
972+
973+ it ( "excludes profiles with empty or whitespace-only path strings" , async ( ) => {
974+ const mockGet = vi . fn ( ) . mockReturnValue ( {
975+ empty : { path : "" } ,
976+ whitespace : { path : " " } ,
977+ valid : { path : "/bin/bash" } ,
978+ } )
979+ vi . mocked ( vscode . workspace . getConfiguration ) . mockReturnValue ( { get : mockGet } as any )
980+
981+ await webviewMessageHandler ( mockClineProvider , { type : "requestTerminalProfiles" } )
982+
983+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
984+ type : "terminalProfiles" ,
985+ profiles : [ "valid" ] ,
986+ } )
987+ } )
988+
989+ it ( "excludes profiles with path arrays containing only empty or whitespace strings" , async ( ) => {
990+ const mockGet = vi . fn ( ) . mockReturnValue ( {
991+ emptyArray : { path : [ ] } ,
992+ whitespaceArray : { path : [ "" , " " ] } ,
993+ valid : { path : [ "/bin/bash" , "/usr/bin/bash" ] } ,
994+ } )
995+ vi . mocked ( vscode . workspace . getConfiguration ) . mockReturnValue ( { get : mockGet } as any )
996+
997+ await webviewMessageHandler ( mockClineProvider , { type : "requestTerminalProfiles" } )
998+
999+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
1000+ type : "terminalProfiles" ,
1001+ profiles : [ "valid" ] ,
1002+ } )
1003+ } )
1004+
1005+ it ( "excludes profiles whose executable cannot be resolved" , async ( ) => {
1006+ const mockGet = vi . fn ( ) . mockReturnValue ( {
1007+ missing : { path : "/missing/bash" } ,
1008+ valid : { path : "/bin/bash" } ,
1009+ } )
1010+ vi . mocked ( vscode . workspace . getConfiguration ) . mockReturnValue ( { get : mockGet } as any )
1011+
1012+ await webviewMessageHandler ( mockClineProvider , { type : "requestTerminalProfiles" } )
1013+
1014+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
1015+ type : "terminalProfiles" ,
1016+ profiles : [ "valid" ] ,
1017+ } )
1018+ } )
1019+ } )
1020+
1021+ describe ( "webviewMessageHandler - openTerminalProfilePicker" , ( ) => {
1022+ beforeEach ( ( ) => {
1023+ vi . clearAllMocks ( )
1024+ } )
1025+
1026+ it ( "executes the VS Code selectDefaultShell command" , async ( ) => {
1027+ await webviewMessageHandler ( mockClineProvider , { type : "openTerminalProfilePicker" } )
1028+ expect ( vscode . commands . executeCommand ) . toHaveBeenCalledWith ( "workbench.action.terminal.selectDefaultShell" )
1029+ } )
9381030} )
9391031
9401032describe ( "webviewMessageHandler - requestCommands" , ( ) => {
0 commit comments