@@ -615,30 +615,64 @@ describe("Rules directory reading", () => {
615615 } as any )
616616
617617 // Simulate listing files including a symlink
618- readdirMock . mockResolvedValueOnce ( [
619- {
620- name : "regular.txt" ,
621- isFile : ( ) => true ,
622- isSymbolicLink : ( ) => false ,
623- parentPath : "/fake/path/.roo/rules" ,
624- } ,
625- { name : "link.txt" , isFile : ( ) => false , isSymbolicLink : ( ) => true , parentPath : "/fake/path/.roo/rules" } ,
626- ] as any )
618+ readdirMock
619+ . mockResolvedValueOnce ( [
620+ {
621+ name : "regular.txt" ,
622+ isFile : ( ) => true ,
623+ isSymbolicLink : ( ) => false ,
624+ parentPath : "/fake/path/.roo/rules" ,
625+ } ,
626+ {
627+ name : "link.txt" ,
628+ isFile : ( ) => false ,
629+ isSymbolicLink : ( ) => true ,
630+ parentPath : "/fake/path/.roo/rules" ,
631+ } ,
632+ {
633+ name : "link_dir" ,
634+ isFile : ( ) => false ,
635+ isSymbolicLink : ( ) => true ,
636+ parentPath : "/fake/path/.roo/rules" ,
637+ } ,
638+ {
639+ name : "nested_link.txt" ,
640+ isFile : ( ) => false ,
641+ isSymbolicLink : ( ) => true ,
642+ parentPath : "/fake/path/.roo/rules" ,
643+ } ,
644+ ] as any )
645+ . mockResolvedValueOnce ( [
646+ { name : "subdir_link.txt" , isFile : ( ) => true , parentPath : "/fake/path/.roo/rules/symlink-target-dir" } ,
647+ ] as any )
627648
628649 // Simulate readlink response
629- readlinkMock . mockResolvedValueOnce ( "../symlink-target.txt" )
650+ readlinkMock
651+ . mockResolvedValueOnce ( "../symlink-target.txt" )
652+ . mockResolvedValueOnce ( "../symlink-target-dir" )
653+ . mockResolvedValueOnce ( "../nested-symlink" )
654+ . mockResolvedValueOnce ( "nested-symlink-target.txt" )
630655
631656 // Reset and set up the stat mock with more granular control
632657 statMock . mockReset ( )
633658 statMock . mockImplementation ( ( path : string ) => {
634659 // For directory check
635- if ( path === "/fake/path/.roo/rules" ) {
660+ if ( path === "/fake/path/.roo/rules" || path . endsWith ( "dir" ) ) {
636661 return Promise . resolve ( {
637662 isDirectory : jest . fn ( ) . mockReturnValue ( true ) ,
638663 isFile : jest . fn ( ) . mockReturnValue ( false ) ,
639664 } as any )
640665 }
641666
667+ // For symlink check
668+ if ( path . endsWith ( "symlink" ) ) {
669+ return Promise . resolve ( {
670+ isDirectory : jest . fn ( ) . mockReturnValue ( false ) ,
671+ isFile : jest . fn ( ) . mockReturnValue ( false ) ,
672+ isSymbolicLink : jest . fn ( ) . mockReturnValue ( true ) ,
673+ } as any )
674+ }
675+
642676 // For all files
643677 return Promise . resolve ( {
644678 isFile : jest . fn ( ) . mockReturnValue ( true ) ,
@@ -654,6 +688,12 @@ describe("Rules directory reading", () => {
654688 if ( filePath . toString ( ) === "/fake/path/.roo/rules/../symlink-target.txt" ) {
655689 return Promise . resolve ( "symlink target content" )
656690 }
691+ if ( filePath . toString ( ) === "/fake/path/.roo/rules/symlink-target-dir/subdir_link.txt" ) {
692+ return Promise . resolve ( "regular file content under symlink target dir" )
693+ }
694+ if ( filePath . toString ( ) === "/fake/path/.roo/rules/../nested-symlink-target.txt" ) {
695+ return Promise . resolve ( "nested symlink target content" )
696+ }
657697 return Promise . reject ( { code : "ENOENT" } )
658698 } )
659699
@@ -664,13 +704,20 @@ describe("Rules directory reading", () => {
664704 expect ( result ) . toContain ( "regular file content" )
665705 expect ( result ) . toContain ( "# Rules from /fake/path/.roo/rules/../symlink-target.txt:" )
666706 expect ( result ) . toContain ( "symlink target content" )
707+ expect ( result ) . toContain ( "# Rules from /fake/path/.roo/rules/symlink-target-dir/subdir_link.txt:" )
708+ expect ( result ) . toContain ( "regular file content under symlink target dir" )
709+ expect ( result ) . toContain ( "# Rules from /fake/path/.roo/rules/../nested-symlink-target.txt:" )
710+ expect ( result ) . toContain ( "nested symlink target content" )
667711
668712 // Verify readlink was called with the symlink path
669713 expect ( readlinkMock ) . toHaveBeenCalledWith ( "/fake/path/.roo/rules/link.txt" )
714+ expect ( readlinkMock ) . toHaveBeenCalledWith ( "/fake/path/.roo/rules/link_dir" )
670715
671716 // Verify both files were read
672717 expect ( readFileMock ) . toHaveBeenCalledWith ( "/fake/path/.roo/rules/regular.txt" , "utf-8" )
673718 expect ( readFileMock ) . toHaveBeenCalledWith ( "/fake/path/.roo/rules/../symlink-target.txt" , "utf-8" )
719+ expect ( readFileMock ) . toHaveBeenCalledWith ( "/fake/path/.roo/rules/symlink-target-dir/subdir_link.txt" , "utf-8" )
720+ expect ( readFileMock ) . toHaveBeenCalledWith ( "/fake/path/.roo/rules/../nested-symlink-target.txt" , "utf-8" )
674721 } )
675722 beforeEach ( ( ) => {
676723 jest . clearAllMocks ( )
0 commit comments