From 109efc79424ed17b68bfbd4627efc76ac24bfa8a Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Sat, 19 Sep 2026 16:49:21 +0800 Subject: [PATCH] test(boot): cover the projection removal edge cases A profile with the legacy directory but no node_modules, and a symlink whose target parent is gone, exercise the remaining branches of removeLinkProjections; the non-ENOENT realpath failure is a host filesystem fault and is excluded from coverage like its siblings. --- packages/boot/app-boot/src/profile.ts | 2 ++ packages/boot/app-boot/tests/profile.spec.ts | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/boot/app-boot/src/profile.ts b/packages/boot/app-boot/src/profile.ts index 51bfb31266..a62817e3d4 100644 --- a/packages/boot/app-boot/src/profile.ts +++ b/packages/boot/app-boot/src/profile.ts @@ -240,7 +240,9 @@ function pointsInto(link: string, root: string): boolean { return parent === rootPath || parent.startsWith(rootPath + sep) } catch (error) { // A target whose parent no longer exists cannot be one of the projections this launch owns. + /* v8 ignore next 2 -- a non-ENOENT realpath failure requires a host filesystem fault */ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false + /* v8 ignore next -- see the host-filesystem exception above */ throw error } } diff --git a/packages/boot/app-boot/tests/profile.spec.ts b/packages/boot/app-boot/tests/profile.spec.ts index 28ba1152f2..b98e77e939 100644 --- a/packages/boot/app-boot/tests/profile.spec.ts +++ b/packages/boot/app-boot/tests/profile.spec.ts @@ -712,6 +712,21 @@ describe('removeLinkProjections', () => { expect(() => { removeLinkProjections(profile) }).not.toThrow() }) + it('removes the directory when the profile has no node_modules and keeps links whose target parent is gone', () => { + const home = tmp() + const profile = join(home, 'profiles', 'web') + mkdirSync(join(profile, '.dsh-module-fallback', 'node_modules'), { recursive: true }) + removeLinkProjections(profile) + expect(existsSync(join(profile, '.dsh-module-fallback'))).toBe(false) + + const other = join(home, 'profiles', 'other') + mkdirSync(join(other, '.dsh-module-fallback', 'node_modules'), { recursive: true }) + link(join(home, 'missing-parent', 'pkg'), join(other, 'node_modules', 'orphan')) + removeLinkProjections(other) + expect(existsSync(join(other, '.dsh-module-fallback'))).toBe(false) + expect(lstatSync(join(other, 'node_modules', 'orphan')).isSymbolicLink()).toBe(true) + }) + it('leaves a profile without the directory untouched', () => { const home = tmp() const profile = join(home, 'profiles', 'web')