From 51c1de44e18590de131d18254faf31316a9b7717 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Sat, 5 Mar 2022 02:10:46 +0200 Subject: [PATCH] test: injected deps --- .../core/test/install/injectLocalPackages.ts | 198 ++++++++++++++++++ packages/local-resolver/src/parsePref.ts | 1 + packages/local-resolver/test/index.ts | 2 +- .../package-requester/src/packageRequester.ts | 2 +- 4 files changed, 201 insertions(+), 2 deletions(-) diff --git a/packages/core/test/install/injectLocalPackages.ts b/packages/core/test/install/injectLocalPackages.ts index 14bf2583837..8e8c28ab2ca 100644 --- a/packages/core/test/install/injectLocalPackages.ts +++ b/packages/core/test/install/injectLocalPackages.ts @@ -443,6 +443,204 @@ test('inject local packages declared via file protocol', async () => { } }) +test('inject local packages when the file protocol is used', async () => { + const project1Manifest = { + name: 'project-1', + version: '1.0.0', + dependencies: { + 'is-negative': '1.0.0', + }, + devDependencies: { + 'dep-of-pkg-with-1-dep': '100.0.0', + }, + peerDependencies: { + 'is-positive': '>=1.0.0', + }, + } + const project2Manifest = { + name: 'project-2', + version: '1.0.0', + dependencies: { + 'project-1': 'file:../project-1', + }, + devDependencies: { + 'is-positive': '1.0.0', + }, + } + const project3Manifest = { + name: 'project-3', + version: '1.0.0', + dependencies: { + 'project-2': 'file:../project-2', + }, + devDependencies: { + 'is-positive': '2.0.0', + }, + } + const projects = preparePackages([ + { + location: 'project-1', + package: project1Manifest, + }, + { + location: 'project-2', + package: project2Manifest, + }, + { + location: 'project-3', + package: project3Manifest, + }, + ]) + + const importers: MutatedProject[] = [ + { + buildIndex: 0, + manifest: project1Manifest, + mutation: 'install', + rootDir: path.resolve('project-1'), + }, + { + buildIndex: 0, + manifest: project2Manifest, + mutation: 'install', + rootDir: path.resolve('project-2'), + }, + { + buildIndex: 0, + manifest: project3Manifest, + mutation: 'install', + rootDir: path.resolve('project-3'), + }, + ] + const workspacePackages = { + 'project-1': { + '1.0.0': { + dir: path.resolve('project-1'), + manifest: project1Manifest, + }, + }, + 'project-2': { + '1.0.0': { + dir: path.resolve('project-2'), + manifest: project2Manifest, + }, + }, + 'project-3': { + '1.0.0': { + dir: path.resolve('project-3'), + manifest: project2Manifest, + }, + }, + } + await mutateModules(importers, await testDefaults({ + workspacePackages, + })) + + await projects['project-1'].has('is-negative') + await projects['project-1'].has('dep-of-pkg-with-1-dep') + await projects['project-1'].hasNot('is-positive') + + await projects['project-2'].has('is-positive') + await projects['project-2'].has('project-1') + + await projects['project-3'].has('is-positive') + await projects['project-3'].has('project-2') + + expect(fs.readdirSync('node_modules/.pnpm').length).toBe(8) + + const rootModules = assertProject(process.cwd()) + { + const lockfile = await rootModules.readLockfile() + expect(lockfile.packages['file:project-1_is-positive@1.0.0']).toEqual({ + resolution: { + directory: 'project-1', + type: 'directory', + }, + id: 'file:project-1', + name: 'project-1', + version: '1.0.0', + peerDependencies: { + 'is-positive': '>=1.0.0', + }, + dependencies: { + 'is-negative': '1.0.0', + 'is-positive': '1.0.0', + }, + dev: false, + }) + expect(lockfile.packages['file:project-2_is-positive@2.0.0']).toEqual({ + resolution: { + directory: 'project-2', + type: 'directory', + }, + id: 'file:project-2', + name: 'project-2', + version: '1.0.0', + dependencies: { + 'project-1': 'file:project-1_is-positive@2.0.0', + }, + transitivePeerDependencies: ['is-positive'], + dev: false, + }) + + const modulesState = await rootModules.readModulesManifest() + expect(modulesState?.injectedDeps?.['project-1'].length).toEqual(2) + expect(modulesState?.injectedDeps?.['project-1'][0]).toContain(`node_modules${path.sep}.pnpm`) + expect(modulesState?.injectedDeps?.['project-1'][1]).toContain(`node_modules${path.sep}.pnpm`) + } + + await rimraf('node_modules') + await rimraf('project-1/node_modules') + await rimraf('project-2/node_modules') + await rimraf('project-3/node_modules') + + await mutateModules(importers, await testDefaults({ + frozenLockfile: true, + workspacePackages, + })) + + await projects['project-1'].has('is-negative') + await projects['project-1'].has('dep-of-pkg-with-1-dep') + await projects['project-1'].hasNot('is-positive') + + await projects['project-2'].has('is-positive') + await projects['project-2'].has('project-1') + + await projects['project-3'].has('is-positive') + await projects['project-3'].has('project-2') + + expect(fs.readdirSync('node_modules/.pnpm').length).toBe(8) + + // The injected project is updated when one of its dependencies needs to be updated + importers[0].manifest.dependencies!['is-negative'] = '2.0.0' + writeJsonFile('project-1/package.json', importers[0].manifest) + await mutateModules(importers, await testDefaults({ workspacePackages })) + { + const lockfile = await rootModules.readLockfile() + expect(lockfile.packages['file:project-1_is-positive@1.0.0']).toEqual({ + resolution: { + directory: 'project-1', + type: 'directory', + }, + id: 'file:project-1', + name: 'project-1', + version: '1.0.0', + peerDependencies: { + 'is-positive': '>=1.0.0', + }, + dependencies: { + 'is-negative': '2.0.0', + 'is-positive': '1.0.0', + }, + dev: false, + }) + const modulesState = await rootModules.readModulesManifest() + expect(modulesState?.injectedDeps?.['project-1'].length).toEqual(2) + expect(modulesState?.injectedDeps?.['project-1'][0]).toContain(`node_modules${path.sep}.pnpm`) + expect(modulesState?.injectedDeps?.['project-1'][1]).toContain(`node_modules${path.sep}.pnpm`) + } +}) + test('inject local packages and relink them after build', async () => { const project1Manifest = { name: 'project-1', diff --git a/packages/local-resolver/src/parsePref.ts b/packages/local-resolver/src/parsePref.ts index 9a05ba4554c..3e9bb4ca2eb 100644 --- a/packages/local-resolver/src/parsePref.ts +++ b/packages/local-resolver/src/parsePref.ts @@ -85,6 +85,7 @@ function fromLocal ( } } + injected = protocol === 'file:' const dependencyPath = injected ? normalize(path.relative(lockfileDir, fetchSpec)) : normalize(path.resolve(fetchSpec)) diff --git a/packages/local-resolver/test/index.ts b/packages/local-resolver/test/index.ts index adb63ac151d..e9b2ffaf620 100644 --- a/packages/local-resolver/test/index.ts +++ b/packages/local-resolver/test/index.ts @@ -26,7 +26,7 @@ test('resolve directory specified using the file: protocol', async () => { expect(resolveResult!.id).toEqual('file:..') expect(resolveResult!.normalizedPref).toEqual('file:..') expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver') - expect(resolveResult!.resolution['directory']).toEqual(normalize(path.join(__dirname, '..'))) + expect(resolveResult!.resolution['directory']).toEqual('..') expect(resolveResult!.resolution['type']).toEqual('directory') }) diff --git a/packages/package-requester/src/packageRequester.ts b/packages/package-requester/src/packageRequester.ts index 40d3ba78b18..95c2a5fa3a4 100644 --- a/packages/package-requester/src/packageRequester.ts +++ b/packages/package-requester/src/packageRequester.ts @@ -195,7 +195,7 @@ async function resolveAndFetch ( const id = pkgId as string - if (resolution.type === 'directory' && !wantedDependency.injected) { + if (resolution.type === 'directory' && !id.startsWith('file:')) { if (manifest == null) { throw new Error(`Couldn't read package.json of local dependency ${wantedDependency.alias ? wantedDependency.alias + '@' : ''}${wantedDependency.pref ?? ''}`) }