@@ -140,6 +140,49 @@ describe( 'SymlinkManager', () => {
140140 ( symlinkManager as unknown as SymlinkManagerPrivateProperties ) . mountedTargets . size
141141 ) . toBe ( 1 ) ;
142142 } ) ;
143+
144+ it ( 'should handle broken symlinks' , async ( ) => {
145+ const mockSymlink = '/mock/project/path/broken/symlink' ;
146+ const relativeSymlinkPath = 'broken/symlink' ;
147+
148+ mockPHP . fileExists . mockImplementation ( ( path ) => ! path . includes ( 'vfspath' ) ) ;
149+ mockPHP . readlink . mockImplementation ( ( path ) => '/mock/document/root/vfspath/' + path ) ;
150+
151+ // Mock fs.readdir to return our mock symlinks
152+ ( fs . readdir as jest . Mock ) . mockResolvedValue ( path . basename ( mockSymlink ) ) ;
153+
154+ // Mock fs.lstat to indicate these are symlinks
155+ ( fs . lstat as jest . Mock ) . mockResolvedValue ( { isSymbolicLink : ( ) => true } as Stats ) ;
156+
157+ // Mock fs.realpath to throw ENOENT error, simulating a broken symlink
158+ const notFoundError = new Error ( 'ENOENT' ) as NodeJS . ErrnoException ;
159+ notFoundError . code = 'ENOENT' ;
160+ ( fs . realpath as jest . Mock ) . mockRejectedValue ( notFoundError ) ;
161+
162+ // Spy on console.error
163+ const consoleErrorSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ) ;
164+
165+ await symlinkManager . scanAndCreateSymlinks ( ) ;
166+
167+ // Verify that the broken symlink was not added to the internal map
168+ expect (
169+ ( symlinkManager as unknown as SymlinkManagerPrivateProperties ) . symlinks . has (
170+ relativeSymlinkPath
171+ )
172+ ) . toBe ( false ) ;
173+
174+ // Verify that no mount was attempted for the broken symlink
175+ expect ( mockPHP . mkdir ) . not . toHaveBeenCalled ( ) ;
176+ expect ( mockPHP . mount ) . not . toHaveBeenCalled ( ) ;
177+
178+ // Verify that an error was logged
179+ expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
180+ expect . stringContaining ( 'Symlink target does not exist:' )
181+ ) ;
182+
183+ // Clean up the spy
184+ consoleErrorSpy . mockRestore ( ) ;
185+ } ) ;
143186 } ) ;
144187
145188 describe ( 'startWatching and stopWatching' , ( ) => {
0 commit comments