@@ -4135,3 +4135,258 @@ t.test('engine checking respects omit flags', async t => {
41354135 t . pass ( 'should succeed when omitting peer dependencies with engine mismatches' )
41364136 } )
41374137} )
4138+
4139+ t . test ( 'installLinks behavior with project-internal file dependencies' , async t => {
4140+ t . test ( 'project-internal file dependencies are always symlinked regardless of installLinks' , async t => {
4141+ const path = t . testdir ( {
4142+ 'package.json' : JSON . stringify ( {
4143+ name : 'test-root' ,
4144+ version : '1.0.0' ,
4145+ dependencies : {
4146+ 'local-pkg' : 'file:./packages/local-pkg' ,
4147+ } ,
4148+ } ) ,
4149+ packages : {
4150+ 'local-pkg' : {
4151+ 'package.json' : JSON . stringify ( {
4152+ name : 'local-pkg' ,
4153+ version : '1.0.0' ,
4154+ dependencies : {
4155+ 'local-shared' : 'file:../local-shared' , // Project-internal dependency
4156+ } ,
4157+ } ) ,
4158+ 'index.js' : 'module.exports = "local-pkg"' ,
4159+ } ,
4160+ 'local-shared' : {
4161+ 'package.json' : JSON . stringify ( {
4162+ name : 'local-shared' ,
4163+ version : '1.0.0' ,
4164+ } ) ,
4165+ 'index.js' : 'module.exports = "local-shared"' ,
4166+ } ,
4167+ } ,
4168+ } )
4169+
4170+ createRegistry ( t , false )
4171+
4172+ // Test with installLinks=true (this used to fail before our fix)
4173+ const arb = newArb ( path , { installLinks : true } )
4174+ const tree = await arb . buildIdealTree ( )
4175+
4176+ // Both packages should be present in the tree
4177+ t . ok ( tree . children . has ( 'local-pkg' ) , 'local-pkg should be in the tree' )
4178+ t . ok ( tree . children . has ( 'local-shared' ) , 'local-shared should be in the tree' )
4179+
4180+ // Both should be Links (symlinked) because they are project-internal
4181+ const localPkg = tree . children . get ( 'local-pkg' )
4182+ const localShared = tree . children . get ( 'local-shared' )
4183+
4184+ t . ok ( localPkg . isLink , 'local-pkg should be a link' )
4185+ t . ok ( localShared . isLink , 'local-shared should be a link (hoisted from local-pkg)' )
4186+
4187+ // Verify the paths are correct
4188+ t . ok ( localPkg . realpath . endsWith ( join ( 'packages' , 'local-pkg' ) ) , 'local-pkg should link to correct path' )
4189+ t . ok ( localShared . realpath . endsWith ( join ( 'packages' , 'local-shared' ) ) , 'local-shared should link to correct path' )
4190+ } )
4191+
4192+ t . test ( 'external file dependencies respect installLinks setting' , async t => {
4193+ // Create test structure with both project and external dependency in same testdir
4194+ const testRoot = t . testdir ( {
4195+ project : {
4196+ 'package.json' : JSON . stringify ( {
4197+ name : 'test-project' ,
4198+ version : '1.0.0' ,
4199+ dependencies : {
4200+ 'external-lib' : 'file:../external-lib' , // External dependency (outside project)
4201+ } ,
4202+ } ) ,
4203+ } ,
4204+ 'external-lib' : {
4205+ 'package.json' : JSON . stringify ( {
4206+ name : 'external-lib' ,
4207+ version : '1.0.0' ,
4208+ } ) ,
4209+ 'index.js' : 'module.exports = "external-lib"' ,
4210+ } ,
4211+ } )
4212+
4213+ const projectPath = join ( testRoot , 'project' )
4214+ createRegistry ( t , false )
4215+
4216+ // Test with installLinks=true - external dependency should be copied (not linked)
4217+ const arbWithLinks = newArb ( projectPath , { installLinks : true } )
4218+ const treeWithLinks = await arbWithLinks . buildIdealTree ( )
4219+
4220+ t . ok ( treeWithLinks . children . has ( 'external-lib' ) , 'external-lib should be in the tree' )
4221+ const externalWithLinks = treeWithLinks . children . get ( 'external-lib' )
4222+ t . notOk ( externalWithLinks . isLink , 'external-lib should not be a link when installLinks=true' )
4223+
4224+ // Test with installLinks=false - external dependency should be linked
4225+ const arbNoLinks = newArb ( projectPath , { installLinks : false } )
4226+ const treeNoLinks = await arbNoLinks . buildIdealTree ( )
4227+
4228+ t . ok ( treeNoLinks . children . has ( 'external-lib' ) , 'external-lib should be in the tree' )
4229+ const externalNoLinks = treeNoLinks . children . get ( 'external-lib' )
4230+ t . ok ( externalNoLinks . isLink , 'external-lib should be a link when installLinks=false' )
4231+ } )
4232+
4233+ t . test ( 'mixed internal and external file dependencies' , async t => {
4234+ const testRoot = t . testdir ( {
4235+ project : {
4236+ 'package.json' : JSON . stringify ( {
4237+ name : 'mixed-test' ,
4238+ version : '1.0.0' ,
4239+ dependencies : {
4240+ 'internal-pkg' : 'file:./lib/internal-pkg' ,
4241+ 'external-dep' : 'file:../external-dep' , // External dependency
4242+ } ,
4243+ } ) ,
4244+ lib : {
4245+ 'internal-pkg' : {
4246+ 'package.json' : JSON . stringify ( {
4247+ name : 'internal-pkg' ,
4248+ version : '1.0.0' ,
4249+ dependencies : {
4250+ 'internal-shared' : 'file:../internal-shared' , // Project-internal
4251+ } ,
4252+ } ) ,
4253+ 'index.js' : 'module.exports = "internal-pkg"' ,
4254+ } ,
4255+ 'internal-shared' : {
4256+ 'package.json' : JSON . stringify ( {
4257+ name : 'internal-shared' ,
4258+ version : '1.0.0' ,
4259+ } ) ,
4260+ 'index.js' : 'module.exports = "internal-shared"' ,
4261+ } ,
4262+ } ,
4263+ } ,
4264+ 'external-dep' : {
4265+ 'package.json' : JSON . stringify ( {
4266+ name : 'external-dep' ,
4267+ version : '1.0.0' ,
4268+ } ) ,
4269+ 'index.js' : 'module.exports = "external-dep"' ,
4270+ } ,
4271+ } )
4272+
4273+ const projectPath = join ( testRoot , 'project' )
4274+ createRegistry ( t , false )
4275+
4276+ const arb = newArb ( projectPath , { installLinks : true } )
4277+ const tree = await arb . buildIdealTree ( )
4278+
4279+ // All dependencies should be present
4280+ t . ok ( tree . children . has ( 'internal-pkg' ) , 'internal-pkg should be in tree' )
4281+ t . ok ( tree . children . has ( 'internal-shared' ) , 'internal-shared should be in tree' )
4282+ t . ok ( tree . children . has ( 'external-dep' ) , 'external-dep should be in tree' )
4283+
4284+ // Internal dependencies should be links (project-internal rule)
4285+ const internalPkg = tree . children . get ( 'internal-pkg' )
4286+ const internalShared = tree . children . get ( 'internal-shared' )
4287+ t . ok ( internalPkg . isLink , 'internal-pkg should be a link (project-internal)' )
4288+ t . ok ( internalShared . isLink , 'internal-shared should be a link (project-internal)' )
4289+
4290+ // External dependency should not be a link (respects installLinks=true)
4291+ const externalDep = tree . children . get ( 'external-dep' )
4292+ t . notOk ( externalDep . isLink , 'external-dep should not be a link (respects installLinks=true)' )
4293+ } )
4294+
4295+ t . test ( 'code coverage for project-internal file dependency edge cases' , async t => {
4296+ const testRoot = t . testdir ( {
4297+ 'parent-dir-external' : {
4298+ 'package.json' : JSON . stringify ( {
4299+ name : 'parent-dir-external' ,
4300+ version : '1.0.0' ,
4301+ } ) ,
4302+ 'index.js' : 'module.exports = "parent-dir-external"' ,
4303+ } ,
4304+ project : {
4305+ 'package.json' : JSON . stringify ( {
4306+ name : 'coverage-test' ,
4307+ version : '1.0.0' ,
4308+ dependencies : {
4309+ 'current-dir-dep' : 'file:./current-dir-dep' , // file:./ case
4310+ 'parent-dir-external' : 'file:../parent-dir-external' , // file:../ case outside project
4311+ } ,
4312+ } ) ,
4313+ 'current-dir-dep' : {
4314+ 'package.json' : JSON . stringify ( {
4315+ name : 'current-dir-dep' ,
4316+ version : '1.0.0' ,
4317+ } ) ,
4318+ 'index.js' : 'module.exports = "current-dir-dep"' ,
4319+ } ,
4320+ } ,
4321+ } )
4322+
4323+ const projectPath = join ( testRoot , 'project' )
4324+ createRegistry ( t , false )
4325+
4326+ // Test with installLinks=false to verify external dependencies respect setting
4327+ const arb = newArb ( projectPath , { installLinks : false } )
4328+ const tree = await arb . buildIdealTree ( )
4329+
4330+ t . ok ( tree . children . has ( 'current-dir-dep' ) , 'current-dir-dep should be in tree' )
4331+ t . ok ( tree . children . has ( 'parent-dir-external' ) , 'parent-dir-external should be in tree' )
4332+
4333+ const currentDirDep = tree . children . get ( 'current-dir-dep' )
4334+ const parentDirExternal = tree . children . get ( 'parent-dir-external' )
4335+
4336+ // current-dir-dep should be a link (project-internal always links)
4337+ t . ok ( currentDirDep . isLink , 'current-dir-dep should be a link (file:./ within project)' )
4338+
4339+ // parent-dir-external should ALSO be a link (external, but installLinks=false means link everything)
4340+ t . ok ( parentDirExternal . isLink , 'parent-dir-external should be a link (file:../ outside project, installLinks=false means link)' )
4341+
4342+ // Verify the logic branches - current-dir should resolve within project, parent-dir should not
4343+ t . match ( currentDirDep . realpath , new RegExp ( join ( testRoot , 'project' ) . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ) ,
4344+ 'current-dir-dep realpath should be within project root' )
4345+ } )
4346+
4347+ t . test ( 'installLinks=true with nested project-internal file dependencies' , async t => {
4348+ // Test a more complex scenario with nested dependencies to ensure comprehensive coverage
4349+ const testRoot = t . testdir ( {
4350+ project : {
4351+ 'package.json' : JSON . stringify ( {
4352+ name : 'nested-test' ,
4353+ version : '1.0.0' ,
4354+ dependencies : {
4355+ 'wrapper-pkg' : 'file:./packages/wrapper-pkg' ,
4356+ } ,
4357+ } ) ,
4358+ packages : {
4359+ 'wrapper-pkg' : {
4360+ 'package.json' : JSON . stringify ( {
4361+ name : 'wrapper-pkg' ,
4362+ version : '1.0.0' ,
4363+ dependencies : {
4364+ 'nested-dep' : 'file:../nested-dep' ,
4365+ } ,
4366+ } ) ,
4367+ } ,
4368+ 'nested-dep' : {
4369+ 'package.json' : JSON . stringify ( {
4370+ name : 'nested-dep' ,
4371+ version : '1.0.0' ,
4372+ } ) ,
4373+ } ,
4374+ } ,
4375+ } ,
4376+ } )
4377+
4378+ const projectPath = join ( testRoot , 'project' )
4379+ createRegistry ( t , false )
4380+
4381+ const arb = newArb ( projectPath , { installLinks : true } )
4382+ const tree = await arb . buildIdealTree ( )
4383+
4384+ const wrapperPkg = tree . children . get ( 'wrapper-pkg' )
4385+ const nestedDep = tree . children . get ( 'nested-dep' )
4386+
4387+ t . ok ( wrapperPkg , 'wrapper-pkg should be found' )
4388+ t . ok ( wrapperPkg . isLink , 'wrapper-pkg should be a link (project-internal)' )
4389+ t . ok ( nestedDep , 'nested-dep should be found' )
4390+ t . ok ( nestedDep . isLink , 'nested-dep should be a link (project-internal)' )
4391+ } )
4392+ } )
0 commit comments