Skip to content

Commit

Permalink
Add pnpm integration test (#17882)
Browse files Browse the repository at this point in the history
  • Loading branch information
elliottsj committed Jan 11, 2021
1 parent 1c75bf7 commit 16ff439
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 99 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"npm-run-all": "4.1.5",
"nprogress": "0.2.0",
"pixrem": "5.0.0",
"pnpm": "5.8.0",
"pnpm": "5.14.3",
"postcss-nested": "4.2.1",
"postcss-pseudoelements": "5.0.0",
"postcss-short-size": "4.0.0",
Expand Down
3 changes: 0 additions & 3 deletions test/package-managers-tests/basic-pnpm/pages/about.js

This file was deleted.

3 changes: 0 additions & 3 deletions test/package-managers-tests/basic-pnpm/pages/about2.js

This file was deleted.

3 changes: 0 additions & 3 deletions test/package-managers-tests/basic-pnpm/pages/day/index.js

This file was deleted.

11 changes: 0 additions & 11 deletions test/package-managers-tests/basic-pnpm/pages/index.js

This file was deleted.

74 changes: 0 additions & 74 deletions test/package-managers-tests/basic-pnpm/test/index.test.js

This file was deleted.

14 changes: 14 additions & 0 deletions test/package-managers/pnpm/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "pnpm-app",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0"
}
}
1 change: 1 addition & 0 deletions test/package-managers/pnpm/app/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default () => <h1>Hello World</h1>
127 changes: 127 additions & 0 deletions test/package-managers/pnpm/test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* eslint-env jest */
import execa from 'execa'
import fs from 'fs-extra'
import os from 'os'
import path from 'path'

const pnpmExecutable = path.join(
__dirname,
'..',
'..',
'..',
'..',
'node_modules',
'.bin',
'pnpm'
)
const packagesDir = path.join(__dirname, '..', '..', '..', '..', 'packages')
const appDir = path.join(__dirname, '..', 'app')

jest.setTimeout(1000 * 60 * 5)

const runNpm = (cwd, ...args) => execa('npm', [...args], { cwd })
const runPnpm = (cwd, ...args) => execa(pnpmExecutable, [...args], { cwd })

async function usingTempDir(fn) {
const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2))
await fs.mkdirp(folder)
try {
return await fn(folder)
} finally {
await fs.remove(folder)
}
}

/**
* Using 'npm pack', create a tarball of the given package in
* directory `pkg` and write it to `cwd`.
*
* `pkg` is relative to the monorepo 'packages/' directory.
*
* Return the absolute path to the tarball.
*/
async function pack(cwd, pkg) {
const pkgDir = path.join(packagesDir, pkg)
const { stdout } = await runNpm(
cwd,
'pack',
'--ignore-scripts', // Skip the prepublish script
path.join(packagesDir, pkg)
)
const tarballFilename = stdout.match(/.*\.tgz/)[0]

if (!tarballFilename) {
throw new Error(
`pnpm failed to pack "next" package tarball in directory ${pkgDir}.`
)
}

return path.join(cwd, tarballFilename)
}

describe('pnpm support', () => {
it('should build with dependencies installed via pnpm', async () => {
// Create a Next.js app in a temporary directory, and install dependencies with pnpm.
//
// "next" and its monorepo dependencies are installed by `npm pack`-ing tarballs from
// 'next.js/packages/*', because installing "next" directly via
// `pnpm add path/to/next.js/packages/next` results in a symlink:
// 'app/node_modules/next' -> 'path/to/next.js/packages/next'.
// This is undesired since modules inside "next" would be resolved to the
// next.js monorepo 'node_modules' and lead to false test results;
// installing from a tarball avoids this issue.
//
// The "next" package's monorepo dependencies (e.g. "@next/env", "@next/polyfill-module")
// are not bundled with `npm pack next.js/packages/next`,
// so they need to be packed individually.
// To ensure that they are installed upon installing "next", a package.json "pnpm.overrides"
// field is used to override these dependency paths at install time.
await usingTempDir(async (tempDir) => {
const nextTarballPath = await pack(tempDir, 'next')
const dependencyTarballPaths = {
'@next/env': await pack(tempDir, 'next-env'),
'@next/polyfill-module': await pack(tempDir, 'next-polyfill-module'),
'@next/react-dev-overlay': await pack(tempDir, 'react-dev-overlay'),
'@next/react-refresh-utils': await pack(tempDir, 'react-refresh-utils'),
}

const tempAppDir = path.join(tempDir, 'app')
await fs.copy(appDir, tempAppDir)

// Inject dependency tarball paths into a "pnpm.overrides" field in package.json,
// so that they are installed from packed tarballs rather than from the npm registry.
const packageJsonPath = path.join(tempAppDir, 'package.json')
const overrides = {}
for (const [dependency, tarballPath] of Object.entries(
dependencyTarballPaths
)) {
overrides[dependency] = `file:${tarballPath}`
}
const packageJsonWithOverrides = {
...(await fs.readJson(packageJsonPath)),
pnpm: { overrides },
}
await fs.writeFile(
packageJsonPath,
JSON.stringify(packageJsonWithOverrides, null, 2)
)

await runPnpm(tempAppDir, 'install')
await runPnpm(tempAppDir, 'add', nextTarballPath)

expect(
await fs.pathExists(path.join(tempAppDir, 'pnpm-lock.yaml'))
).toBeTruthy()

const packageJson = await fs.readJson(packageJsonPath)
expect(packageJson.dependencies['next']).toMatch(/^file:/)
for (const dependency of Object.keys(dependencyTarballPaths)) {
expect(packageJson.pnpm.overrides[dependency]).toMatch(/^file:/)
}

const { stdout, stderr } = await runPnpm(tempAppDir, 'run', 'build')
console.log(stdout, stderr)
expect(stdout).toMatch(/Compiled successfully/)
})
})
})
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11945,10 +11945,10 @@ pnp-webpack-plugin@1.6.4:
dependencies:
ts-pnp "^1.1.6"

pnpm@5.8.0:
version "5.8.0"
resolved "https://registry.yarnpkg.com/pnpm/-/pnpm-5.8.0.tgz#a933d6c756efe8795b12004bbff1b82c622e771b"
integrity sha512-J2rAxEXnohwcDkR4KNI6UsYhDs9hJ/tje/BahHpXawi406pmxd6caJUXfRxZPbKvKdyVqfBRKhlX1vyhYbM8lQ==
pnpm@5.14.3:
version "5.14.3"
resolved "https://registry.yarnpkg.com/pnpm/-/pnpm-5.14.3.tgz#88e53906652c85ba2e6f69294042d95aad018cbe"
integrity sha512-PFjHFWCsHgaNCpOwOAgN6H71PA8td8PnwSE1ArXz//OyfdfIwws1s23XLmokhHcnE3JsBSiIR3NOW8JZ5QcxlQ==

posix-character-classes@^0.1.0:
version "0.1.1"
Expand Down

0 comments on commit 16ff439

Please sign in to comment.