@@ -41,11 +41,10 @@ import { COutlineItem } from '../tree-structure/solution-outline-item';
4141import * as child_process from 'child_process' ;
4242import * as os from 'os' ;
4343import * as path from 'path' ;
44- import * as fsUtilsModule from '../../../utils/fs-utils' ;
44+ import * as fsUtils from '../../../utils/fs-utils' ;
4545
4646jest . mock ( 'child_process' ) ;
4747jest . mock ( 'os' ) ;
48- jest . mock ( '../../../utils/fs-utils' ) ;
4948
5049describe ( 'MergeCommand' , ( ) => {
5150 let commandsProvider : MockCommandsProvider ;
@@ -57,11 +56,9 @@ describe('MergeCommand', () => {
5756 let componentNode : COutlineItem ;
5857 let fileNode : COutlineItem ;
5958
60- const mockedFsUtils = fsUtilsModule as jest . Mocked < typeof fsUtilsModule > ;
6159 const mockedExec = child_process . exec as jest . MockedFunction < typeof child_process . exec > ;
6260 const mockedExecSync = child_process . execSync as jest . MockedFunction < typeof child_process . execSync > ;
6361 const mockedPath = path as jest . Mocked < typeof path > ;
64- const fsUtils = jest . requireActual ( '../../../utils/fs-utils' ) as typeof import ( '../../../utils/fs-utils' ) ;
6562
6663 beforeAll ( ( ) => {
6764 tmpDir = testDataHandler . tmpDir ;
@@ -72,6 +69,7 @@ describe('MergeCommand', () => {
7269 } ) ;
7370
7471 beforeEach ( async ( ) => {
72+ jest . restoreAllMocks ( ) ;
7573 jest . resetAllMocks ( ) ;
7674 mockedPath . isAbsolute . mockImplementation ( ( filePath : string ) => actualPath . isAbsolute ( filePath ) ) ;
7775 testDataHandler . rmTmpDir ( ) ;
@@ -81,8 +79,6 @@ describe('MergeCommand', () => {
8179 fsUtils . writeTextFile ( path . join ( tmpDir , 'component.c.update@1.0.0' ) , '// update\n' ) ;
8280 fsUtils . writeTextFile ( path . join ( tmpDir , 'component.c.base@1.0.0' ) , '// base\n' ) ;
8381
84- mockedFsUtils . readDirectory . mockImplementation ( ( dir : string ) => fsUtils . readDirectory ( dir ) ) ;
85-
8682 commandsProvider = commandsProviderFactory ( ) ;
8783 activeSolutionTracker = activeSolutionTrackerFactory ( ) ;
8884 command = new MergeCommand ( commandsProvider , activeSolutionTracker ) ;
@@ -128,7 +124,7 @@ describe('MergeCommand', () => {
128124 fsUtils . writeTextFile ( path . join ( tmpDir , 'component.c.update@invalid' ) , '// ignored update\n' ) ;
129125 fsUtils . writeTextFile ( path . join ( tmpDir , 'component.c.base@invalid' ) , '// ignored base\n' ) ;
130126
131- const result = command [ 'findMergeFiles ' ] ( path . join ( tmpDir , 'component.c' ) ) ;
127+ const result = command [ 'findNewestMergeFiles ' ] ( path . join ( tmpDir , 'component.c' ) ) ;
132128
133129 expect ( result ) . toEqual ( {
134130 update : path . join ( tmpDir , 'component.c.update@1.2.0' ) ,
@@ -137,19 +133,19 @@ describe('MergeCommand', () => {
137133 } ) ;
138134
139135 it ( 'returns undefined siblings when reading the local directory fails' , ( ) => {
140- mockedFsUtils . readDirectory . mockImplementation ( ( ) => {
136+ jest . spyOn ( fsUtils , ' readDirectory' ) . mockImplementation ( ( ) => {
141137 throw new Error ( 'directory unavailable' ) ;
142138 } ) ;
143139
144- const result = command [ 'findMergeFiles ' ] ( path . join ( tmpDir , 'component.c' ) ) ;
140+ const result = command [ 'findNewestMergeFiles ' ] ( path . join ( tmpDir , 'component.c' ) ) ;
145141
146142 expect ( result ) . toEqual ( { update : undefined , base : undefined } ) ;
147143 } ) ;
148144 } ) ;
149145
150146 describe ( 'merge sibling resolution' , ( ) => {
151- it ( 'resolveMergeSibling filters by prefix and returns the highest valid semver file' , ( ) => {
152- const result = command [ 'resolveMergeSibling ' ] ( [
147+ it ( 'resolveNewestMergeSibling filters by prefix and returns the highest valid semver file' , ( ) => {
148+ const result = command [ 'resolveNewestMergeSibling ' ] ( [
153149 'component.c.base@1.0.0' ,
154150 'component.c.update@1.0.0' ,
155151 'component.c.update@2.0.0' ,
@@ -160,31 +156,31 @@ describe('MergeCommand', () => {
160156 expect ( result ) . toBe ( 'component.c.update@2.0.0' ) ;
161157 } ) ;
162158
163- it ( 'resolveMergeSibling returns undefined when no file matches the prefix' , ( ) => {
164- const result = command [ 'resolveMergeSibling ' ] ( [
159+ it ( 'resolveNewestMergeSibling returns undefined when no file matches the prefix' , ( ) => {
160+ const result = command [ 'resolveNewestMergeSibling ' ] ( [
165161 'component.c.base@1.0.0' ,
166162 'other.c.update@2.0.0' ,
167163 ] , 'component.c.update@' ) ;
168164
169165 expect ( result ) . toBeUndefined ( ) ;
170166 } ) ;
171167
172- it ( 'selectMergeSibling ignores non-semver suffixes and picks the latest version' , ( ) => {
173- const result = command [ 'selectMergeSibling ' ] ( [
168+ it ( 'selectNewestMergeSibling ignores non-semver suffixes and picks the latest version' , ( ) => {
169+ const result = command [ 'selectNewestMergeSibling ' ] ( [
174170 'component.c.update@1.9.0' ,
175171 'component.c.update@invalid' ,
176172 'component.c.update@2.0.0-beta.1' ,
177173 'component.c.update@2.0.0' ,
178- ] , 'component.c.update@' ) ;
174+ ] ) ;
179175
180176 expect ( result ) . toBe ( 'component.c.update@2.0.0' ) ;
181177 } ) ;
182178
183- it ( 'selectMergeSibling returns undefined when there are no valid semver candidates' , ( ) => {
184- const result = command [ 'selectMergeSibling ' ] ( [
179+ it ( 'selectNewestMergeSibling returns undefined when there are no valid semver candidates' , ( ) => {
180+ const result = command [ 'selectNewestMergeSibling ' ] ( [
185181 'component.c.update@draft' ,
186182 'component.c.update@next' ,
187- ] , 'component.c.update@' ) ;
183+ ] ) ;
188184
189185 expect ( result ) . toBeUndefined ( ) ;
190186 } ) ;
@@ -266,7 +262,7 @@ describe('MergeCommand', () => {
266262 it ( 'returns Windows VS Code CLI path when found in standard locations' , ( ) => {
267263 const expectedCodePath = path . join ( 'C:' , 'Program Files' , 'Microsoft VS Code' , 'bin' , 'code.cmd' ) ;
268264 jest . spyOn ( os , 'platform' ) . mockReturnValue ( 'win32' ) ;
269- mockedFsUtils . fileExists . mockImplementation ( ( filePath ?: string ) : filePath is string => filePath === expectedCodePath ) ;
265+ jest . spyOn ( fsUtils , ' fileExists' ) . mockImplementation ( ( filePath ?: string ) : filePath is string => filePath === expectedCodePath ) ;
270266
271267 const result = command [ 'getVSCodeExecutablePath' ] ( ) ;
272268
@@ -292,28 +288,30 @@ describe('MergeCommand', () => {
292288 getVSCodeExecutablePath : ( ) => string | undefined ;
293289 doOpen3WayMerge : ( cmd : string ) => Promise < number > ;
294290 } ;
291+ const deleteFileIfExistsSpy = jest . spyOn ( fsUtils , 'deleteFileIfExists' ) ;
292+ const renameFileSpy = jest . spyOn ( fsUtils , 'renameFile' ) ;
293+ jest . spyOn ( fsUtils , 'copyFile' ) . mockImplementation ( ( ) => { } ) ;
294+ jest . spyOn ( fsUtils , 'getFileModificationTime' ) . mockReturnValue ( 1000 ) ;
295295 jest . spyOn ( commandPrivate , 'getVSCodeExecutablePath' ) . mockReturnValue ( '/usr/bin/code' ) ;
296296 jest . spyOn ( commandPrivate , 'doOpen3WayMerge' ) . mockResolvedValue ( 1 ) ;
297- mockedFsUtils . copyFile . mockImplementation ( ( ) => { } ) ;
298- mockedFsUtils . getFileModificationTime . mockReturnValue ( 1000 ) ;
299297
300298 const warningSpy = jest . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
301299
302300 await command [ 'runVSCodeMerge' ] ( fileNode ) ;
303301
304302 expect ( warningSpy ) . toHaveBeenCalledWith ( 'Merge exited with code 1. Conflicts may exist.' ) ;
305- expect ( mockedFsUtils . deleteFileIfExists ) . not . toHaveBeenCalled ( ) ;
306- expect ( mockedFsUtils . renameFile ) . not . toHaveBeenCalled ( ) ;
303+ expect ( deleteFileIfExistsSpy ) . not . toHaveBeenCalled ( ) ;
304+ expect ( renameFileSpy ) . not . toHaveBeenCalled ( ) ;
307305 expect ( activeSolutionTracker . triggerReload ) . not . toHaveBeenCalled ( ) ;
308306 } ) ;
309307
310308 it ( 'handles merge errors gracefully' , async ( ) => {
311309 const codePath = '/usr/bin/code' ;
312310 jest . spyOn ( os , 'platform' ) . mockReturnValue ( 'linux' ) ;
313311 mockedExecSync . mockReturnValue ( codePath ) ;
314- mockedFsUtils . copyFile . mockImplementation ( ( ) => { } ) ;
315- mockedFsUtils . fileExists . mockReturnValue ( true ) ;
316- mockedFsUtils . getFileModificationTime . mockReturnValue ( 1000 ) ;
312+ jest . spyOn ( fsUtils , ' copyFile' ) . mockImplementation ( ( ) => { } ) ;
313+ jest . spyOn ( fsUtils , ' fileExists' ) . mockReturnValue ( true ) ;
314+ jest . spyOn ( fsUtils , ' getFileModificationTime' ) . mockReturnValue ( 1000 ) ;
317315 mockedExec . mockImplementation ( ( _cmd , _cb ) => { throw new Error ( 'unexpected' ) ; } ) ;
318316
319317 const errorSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
@@ -330,15 +328,15 @@ describe('MergeCommand', () => {
330328
331329 const commandPrivate = command as unknown as {
332330 getVSCodeExecutablePath : ( ) => string | undefined ;
333- findMergeFiles : ( localPath : string ) => { update : string | undefined ; base : string | undefined } ;
331+ findNewestMergeFiles : ( localPath : string ) => { update : string | undefined ; base : string | undefined } ;
334332 } ;
335333 jest . spyOn ( commandPrivate , 'getVSCodeExecutablePath' ) . mockReturnValue ( '/usr/bin/code' ) ;
336- jest . spyOn ( commandPrivate , 'findMergeFiles ' ) . mockReturnValue ( {
334+ jest . spyOn ( commandPrivate , 'findNewestMergeFiles ' ) . mockReturnValue ( {
337335 update : `${ local } .update@1.0.0&unsafe` ,
338336 base : `${ local } .base@1.0.0` ,
339337 } ) ;
340- mockedFsUtils . copyFile . mockImplementation ( ( ) => { } ) ;
341- mockedFsUtils . getFileModificationTime . mockReturnValue ( 1000 ) ;
338+ jest . spyOn ( fsUtils , ' copyFile' ) . mockImplementation ( ( ) => { } ) ;
339+ jest . spyOn ( fsUtils , ' getFileModificationTime' ) . mockReturnValue ( 1000 ) ;
342340
343341 const showErrorMessageSpy = jest . spyOn ( vscode . window , 'showErrorMessage' ) ;
344342
@@ -362,21 +360,24 @@ describe('MergeCommand', () => {
362360 getVSCodeExecutablePath : ( ) => string | undefined ;
363361 doOpen3WayMerge : ( cmd : string ) => Promise < number > ;
364362 } ;
365- jest . spyOn ( commandPrivate , 'getVSCodeExecutablePath' ) . mockReturnValue ( '/usr/bin/code' ) ;
366- jest . spyOn ( commandPrivate , 'doOpen3WayMerge' ) . mockResolvedValue ( 0 ) ;
367- mockedFsUtils . copyFile . mockImplementation ( ( ) => { } ) ;
368- mockedFsUtils . getFileModificationTime
363+ const copyFileSpy = jest . spyOn ( fsUtils , 'copyFile' ) . mockImplementation ( ( ) => { } ) ;
364+ const getFileModificationTimeSpy = jest . spyOn ( fsUtils , 'getFileModificationTime' )
369365 . mockReturnValueOnce ( 1000 )
370366 . mockReturnValueOnce ( 2000 ) ;
367+ const deleteFileIfExistsSpy = jest . spyOn ( fsUtils , 'deleteFileIfExists' ) . mockImplementation ( ( ) => { } ) ;
368+ const renameFileSpy = jest . spyOn ( fsUtils , 'renameFile' ) . mockImplementation ( ( ) => { } ) ;
369+ jest . spyOn ( commandPrivate , 'getVSCodeExecutablePath' ) . mockReturnValue ( '/usr/bin/code' ) ;
370+ jest . spyOn ( commandPrivate , 'doOpen3WayMerge' ) . mockResolvedValue ( 0 ) ;
371371
372372 await command [ 'runVSCodeMerge' ] ( node ) ;
373373
374- expect ( mockedFsUtils . copyFile ) . toHaveBeenCalledWith ( local , merged ) ;
375- expect ( mockedFsUtils . copyFile ) . toHaveBeenCalledWith ( local , `${ local } .bak` ) ;
376- expect ( mockedFsUtils . deleteFileIfExists ) . toHaveBeenCalledWith ( local ) ;
377- expect ( mockedFsUtils . deleteFileIfExists ) . toHaveBeenCalledWith ( base ) ;
378- expect ( mockedFsUtils . renameFile ) . toHaveBeenCalledWith ( update , expectedBase ) ;
379- expect ( mockedFsUtils . renameFile ) . toHaveBeenCalledWith ( merged , local ) ;
374+ expect ( copyFileSpy ) . toHaveBeenCalledWith ( local , merged ) ;
375+ expect ( copyFileSpy ) . toHaveBeenCalledWith ( local , `${ local } .bak` ) ;
376+ expect ( getFileModificationTimeSpy ) . toHaveBeenCalledTimes ( 2 ) ;
377+ expect ( deleteFileIfExistsSpy ) . toHaveBeenCalledWith ( local ) ;
378+ expect ( deleteFileIfExistsSpy ) . toHaveBeenCalledWith ( base ) ;
379+ expect ( renameFileSpy ) . toHaveBeenCalledWith ( update , expectedBase ) ;
380+ expect ( renameFileSpy ) . toHaveBeenCalledWith ( merged , local ) ;
380381 expect ( activeSolutionTracker . triggerReload ) . toHaveBeenCalledTimes ( 1 ) ;
381382 } ) ;
382383 } ) ;
0 commit comments