@@ -216,16 +216,38 @@ describe('MergeCommand', () => {
216216 mockedExec . mockImplementation ( ( _cmd , _cb ) => { throw new Error ( 'unexpected' ) ; } ) ;
217217
218218 const errorSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
219+ const showErrorMessageSpy = jest . spyOn ( vscode . window , 'showErrorMessage' ) ;
219220 await command [ 'runVSCodeMerge' ] ( fileNode ) ;
220221 expect ( errorSpy ) . toHaveBeenCalledWith ( 'Merge operations failed:' , expect . any ( Error ) ) ;
222+ expect ( showErrorMessageSpy ) . toHaveBeenCalledWith ( 'Merge operation failed: unexpected' ) ;
223+ } ) ;
224+
225+ it ( 'shows a merge failure message when merge command validation throws' , async ( ) => {
226+ const node = new COutlineItem ( 'file' ) ;
227+ node . setAttribute ( 'local' , '/tmp/safe-local.c' ) ;
228+ node . setAttribute ( 'update' , '/tmp/update&unsafe.c' ) ;
229+ node . setAttribute ( 'base' , '/tmp/base.c' ) ;
230+
231+ const commandPrivate = command as unknown as {
232+ getVSCodeExecutablePath : ( ) => string | undefined ;
233+ } ;
234+ jest . spyOn ( commandPrivate , 'getVSCodeExecutablePath' ) . mockReturnValue ( '/usr/bin/code' ) ;
235+ mockedFs . copyFileSync . mockImplementation ( ( ) => { } ) ;
236+ mockedFs . existsSync . mockReturnValue ( true ) ;
237+ mockedFs . statSync . mockReturnValue ( { mtimeMs : 1000 } as fs . Stats ) ;
238+
239+ const showErrorMessageSpy = jest . spyOn ( vscode . window , 'showErrorMessage' ) ;
240+
241+ await command [ 'runVSCodeMerge' ] ( node ) ;
242+
243+ expect ( showErrorMessageSpy ) . toHaveBeenCalledWith ( 'Merge operation failed: Invalid update file: contains unsupported shell-sensitive characters.' ) ;
221244 } ) ;
222245
223246 it ( 'performs post-merge file operations and triggers reload when merged file changes' , async ( ) => {
224247 const local = path . resolve ( 'tmp' , 'component.c' ) ;
225248 const update = path . resolve ( 'tmp' , 'component.update.c' ) ;
226249 const base = path . resolve ( 'tmp' , 'component.base.c' ) ;
227250 const merged = `${ local } .merged` ;
228- const backup = `${ local } .bak` ;
229251 const expectedBase = path . join ( path . dirname ( update ) , path . basename ( update ) . replaceAll ( 'update' , 'base' ) ) ;
230252 const node = new COutlineItem ( 'file' ) ;
231253 node . setTag ( 'file' ) ;
@@ -249,7 +271,7 @@ describe('MergeCommand', () => {
249271 await command [ 'runVSCodeMerge' ] ( node ) ;
250272
251273 expect ( mockedFs . copyFileSync ) . toHaveBeenCalledWith ( local , merged ) ;
252- expect ( mockedFs . copyFileSync ) . toHaveBeenCalledWith ( local , backup ) ;
274+ expect ( mockedFs . copyFileSync ) . toHaveBeenCalledWith ( local , ` ${ local } .bak` ) ;
253275 expect ( mockedFs . unlinkSync ) . toHaveBeenCalledWith ( local ) ;
254276 expect ( mockedFs . unlinkSync ) . toHaveBeenCalledWith ( base ) ;
255277 expect ( mockedFs . renameSync ) . toHaveBeenCalledWith ( update , expectedBase ) ;
@@ -277,7 +299,6 @@ describe('MergeCommand', () => {
277299 const update = 'C:\\workspace\\component.update.c' ;
278300 const base = 'C:\\workspace\\component.base.c' ;
279301 const merged = `${ local } .merged` ;
280- const backup = `${ local } .bak` ;
281302 const expectedBase = 'C:\\workspace\\component.base.c' ;
282303 const node = new COutlineItem ( 'file' ) ;
283304 node . setTag ( 'file' ) ;
@@ -312,7 +333,7 @@ describe('MergeCommand', () => {
312333 expect ( mockedPath . dirname ) . toHaveBeenCalledWith ( update ) ;
313334 expect ( mockedPath . join ) . toHaveBeenCalledWith ( 'C:\\workspace' , 'component.base.c' ) ;
314335 expect ( mockedFs . copyFileSync ) . toHaveBeenCalledWith ( local , merged ) ;
315- expect ( mockedFs . copyFileSync ) . toHaveBeenCalledWith ( local , backup ) ;
336+ expect ( mockedFs . copyFileSync ) . toHaveBeenCalledWith ( local , ` ${ local } .bak` ) ;
316337 expect ( mockedFs . renameSync ) . toHaveBeenCalledWith ( update , expectedBase ) ;
317338 expect ( mockedFs . renameSync ) . toHaveBeenCalledWith ( merged , local ) ;
318339 expect ( activeSolutionTracker . triggerReload ) . toHaveBeenCalledTimes ( 1 ) ;
0 commit comments