mirror of
https://github.com/pnpm/pnpm.git
synced 2026-03-27 11:31:45 -04:00
Update all packages from zkochan/packages to their latest major versions and exclude them from minimumReleaseAge requirement. This includes updating catalog entries, adapting to breaking API changes (default exports replaced with named exports, sync functions renamed with Sync suffix), and updating type declarations.
759 lines
20 KiB
TypeScript
759 lines
20 KiB
TypeScript
/// <reference path="../../../__typings__/index.d.ts" />
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import type { PnpmError } from '@pnpm/error'
|
|
import { filterPackagesFromDir } from '@pnpm/workspace.filter-packages-from-dir'
|
|
import {
|
|
restart,
|
|
run,
|
|
} from '@pnpm/plugin-commands-script-runners'
|
|
import { prepare, preparePackages } from '@pnpm/prepare'
|
|
import { createTestIpcServer } from '@pnpm/test-ipc-server'
|
|
import { safeExeca as execa } from 'execa'
|
|
import isWindows from 'is-windows'
|
|
import { writeYamlFileSync } from 'write-yaml-file'
|
|
import { DEFAULT_OPTS, REGISTRY_URL } from './utils/index.js'
|
|
|
|
const pnpmBin = path.join(import.meta.dirname, '../../../pnpm/bin/pnpm.mjs')
|
|
|
|
const skipOnWindows = isWindows() ? test.skip : test
|
|
const onlyOnWindows = !isWindows() ? test.skip : test
|
|
|
|
test('pnpm run: returns correct exit code', async () => {
|
|
prepare({
|
|
scripts: {
|
|
exit0: 'exit 0',
|
|
exit1: 'exit 1',
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['exit0'])
|
|
|
|
let err!: Error & { errno: number }
|
|
try {
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bail: true,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['exit1'])
|
|
} catch (_err: any) { // eslint-disable-line
|
|
err = _err
|
|
}
|
|
expect(err.errno).toBe(1)
|
|
})
|
|
|
|
test('pnpm run --no-bail never fails', async () => {
|
|
prepare({
|
|
scripts: {
|
|
exit1: 'node recordArgs && exit 1',
|
|
},
|
|
})
|
|
fs.writeFileSync('args.json', '[]', 'utf8')
|
|
fs.writeFileSync('recordArgs.js', RECORD_ARGS_FILE, 'utf8')
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
bail: false,
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['exit1'])
|
|
|
|
const { default: args } = await import(path.resolve('args.json'))
|
|
expect(args).toStrictEqual([[]])
|
|
})
|
|
|
|
const RECORD_ARGS_FILE = 'require(\'fs\').writeFileSync(\'args.json\', JSON.stringify(require(\'./args.json\').concat([process.argv.slice(2)])), \'utf8\')'
|
|
|
|
test('run: pass the args to the command that is specified in the build script', async () => {
|
|
prepare({
|
|
scripts: {
|
|
foo: 'node recordArgs',
|
|
postfoo: 'node recordArgs',
|
|
prefoo: 'node recordArgs',
|
|
},
|
|
})
|
|
fs.writeFileSync('args.json', '[]', 'utf8')
|
|
fs.writeFileSync('recordArgs.js', RECORD_ARGS_FILE, 'utf8')
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['foo', 'arg', '--flag=true', '--help', '-h'])
|
|
|
|
const { default: args } = await import(path.resolve('args.json'))
|
|
expect(args).toStrictEqual([['arg', '--flag=true', '--help', '-h']])
|
|
})
|
|
|
|
test('run: pass the args to the command that is specified in the build script of a package.yaml manifest', async () => {
|
|
prepare({
|
|
scripts: {
|
|
foo: 'node recordArgs',
|
|
postfoo: 'node recordArgs',
|
|
prefoo: 'node recordArgs',
|
|
},
|
|
}, { manifestFormat: 'YAML' })
|
|
fs.writeFileSync('args.json', '[]', 'utf8')
|
|
fs.writeFileSync('recordArgs.js', RECORD_ARGS_FILE, 'utf8')
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['foo', 'arg', '--flag=true', '--help', '-h'])
|
|
|
|
const { default: args } = await import(path.resolve('args.json'))
|
|
expect(args).toStrictEqual([['arg', '--flag=true', '--help', '-h']])
|
|
})
|
|
|
|
test('test: pass the args to the command that is specified in the build script of a package.yaml manifest', async () => {
|
|
prepare({
|
|
scripts: {
|
|
posttest: 'node recordArgs',
|
|
pretest: 'node recordArgs',
|
|
test: 'node recordArgs',
|
|
},
|
|
}, { manifestFormat: 'YAML' })
|
|
fs.writeFileSync('args.json', '[]', 'utf8')
|
|
fs.writeFileSync('recordArgs.js', RECORD_ARGS_FILE, 'utf8')
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['test', 'arg', '--flag=true', '--help', '-h'])
|
|
|
|
const { default: args } = await import(path.resolve('args.json'))
|
|
expect(args).toStrictEqual([['arg', '--flag=true', '--help', '-h']])
|
|
})
|
|
|
|
test('run start: pass the args to the command that is specified in the build script of a package.yaml manifest', async () => {
|
|
prepare({
|
|
scripts: {
|
|
poststart: 'node recordArgs',
|
|
prestart: 'node recordArgs',
|
|
start: 'node recordArgs',
|
|
},
|
|
}, { manifestFormat: 'YAML' })
|
|
fs.writeFileSync('args.json', '[]', 'utf8')
|
|
fs.writeFileSync('recordArgs.js', RECORD_ARGS_FILE, 'utf8')
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['start', 'arg', '--flag=true', '--help', '-h'])
|
|
|
|
const { default: args } = await import(path.resolve('args.json'))
|
|
expect(args).toStrictEqual([['arg', '--flag=true', '--help', '-h']])
|
|
})
|
|
|
|
test('run stop: pass the args to the command that is specified in the build script of a package.yaml manifest', async () => {
|
|
prepare({
|
|
scripts: {
|
|
poststop: 'node recordArgs',
|
|
prestop: 'node recordArgs',
|
|
stop: 'node recordArgs',
|
|
},
|
|
}, { manifestFormat: 'YAML' })
|
|
fs.writeFileSync('args.json', '[]', 'utf8')
|
|
fs.writeFileSync('recordArgs.js', RECORD_ARGS_FILE, 'utf8')
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['stop', 'arg', '--flag=true', '--help', '-h'])
|
|
|
|
const { default: args } = await import(path.resolve('args.json'))
|
|
expect(args).toStrictEqual([['arg', '--flag=true', '--help', '-h']])
|
|
})
|
|
|
|
test('restart: run stop, restart and start', async () => {
|
|
await using server = await createTestIpcServer()
|
|
|
|
prepare({
|
|
scripts: {
|
|
poststop: server.sendLineScript('poststop'),
|
|
prestop: server.sendLineScript('prestop'),
|
|
stop: server.sendLineScript('stop'),
|
|
|
|
postrestart: server.sendLineScript('postrestart'),
|
|
prerestart: server.sendLineScript('prerestart'),
|
|
restart: server.sendLineScript('restart'),
|
|
|
|
poststart: server.sendLineScript('poststart'),
|
|
prestart: server.sendLineScript('prestart'),
|
|
start: server.sendLineScript('start'),
|
|
},
|
|
})
|
|
|
|
await restart.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, [])
|
|
|
|
expect(server.getLines()).toStrictEqual([
|
|
'stop',
|
|
'restart',
|
|
'start',
|
|
])
|
|
})
|
|
|
|
test('restart: run stop, restart and start and all the pre/post scripts', async () => {
|
|
await using server = await createTestIpcServer()
|
|
|
|
prepare({
|
|
scripts: {
|
|
poststop: server.sendLineScript('poststop'),
|
|
prestop: server.sendLineScript('prestop'),
|
|
stop: `${server.sendLineScript('stop')} && pnpm poststop`,
|
|
|
|
postrestart: server.sendLineScript('postrestart'),
|
|
prerestart: server.sendLineScript('prerestart'),
|
|
restart: server.sendLineScript('restart'),
|
|
|
|
poststart: server.sendLineScript('poststart'),
|
|
prestart: server.sendLineScript('prestart'),
|
|
start: server.sendLineScript('start'),
|
|
},
|
|
})
|
|
|
|
await restart.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
enablePrePostScripts: true,
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, [])
|
|
|
|
expect(server.getLines()).toStrictEqual([
|
|
'prestop',
|
|
'stop',
|
|
'poststop',
|
|
'prerestart',
|
|
'restart',
|
|
'postrestart',
|
|
'prestart',
|
|
'start',
|
|
'poststart',
|
|
])
|
|
})
|
|
|
|
test('"pnpm run" prints the list of available commands', async () => {
|
|
prepare({
|
|
scripts: {
|
|
foo: 'echo hi',
|
|
test: 'ts-node test',
|
|
},
|
|
})
|
|
|
|
const output = await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, [])
|
|
|
|
expect(output).toBe(`\
|
|
Lifecycle scripts:
|
|
test
|
|
ts-node test
|
|
|
|
Commands available via "pnpm run":
|
|
foo
|
|
echo hi`)
|
|
})
|
|
|
|
test('"pnpm run" prints the list of available commands, including commands of the root workspace project', async () => {
|
|
preparePackages([
|
|
{
|
|
location: '.',
|
|
package: {
|
|
scripts: {
|
|
build: 'echo root',
|
|
test: 'test-all',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'foo',
|
|
version: '1.0.0',
|
|
|
|
scripts: {
|
|
foo: 'echo hi',
|
|
test: 'ts-node test',
|
|
},
|
|
},
|
|
])
|
|
writeYamlFileSync('pnpm-workspace.yaml', {})
|
|
const workspaceDir = process.cwd()
|
|
|
|
const { allProjects, selectedProjectsGraph } = await filterPackagesFromDir(process.cwd(), [])
|
|
|
|
{
|
|
process.chdir('foo')
|
|
const output = await run.handler({
|
|
...DEFAULT_OPTS,
|
|
allProjects,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
selectedProjectsGraph,
|
|
workspaceDir,
|
|
}, [])
|
|
|
|
expect(output).toBe(`\
|
|
Lifecycle scripts:
|
|
test
|
|
ts-node test
|
|
|
|
Commands available via "pnpm run":
|
|
foo
|
|
echo hi
|
|
|
|
Commands of the root workspace project (to run them, use "pnpm -w run"):
|
|
build
|
|
echo root
|
|
test
|
|
test-all`)
|
|
}
|
|
{
|
|
process.chdir('..')
|
|
const output = await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
allProjects,
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
selectedProjectsGraph,
|
|
workspaceDir,
|
|
}, [])
|
|
|
|
expect(output).toBe(`\
|
|
Lifecycle scripts:
|
|
test
|
|
test-all
|
|
|
|
Commands available via "pnpm run":
|
|
build
|
|
echo root`)
|
|
}
|
|
})
|
|
|
|
test('pnpm run does not fail with --if-present even if the wanted script is not present', async () => {
|
|
prepare({})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
ifPresent: true,
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['build'])
|
|
})
|
|
|
|
test('if a script is not found but is present in the root, print an info message about it in the error message', async () => {
|
|
preparePackages([
|
|
{
|
|
location: '.',
|
|
package: {
|
|
scripts: {
|
|
build: 'node -e "process.stdout.write(\'root\')"',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'foo',
|
|
version: '1.0.0',
|
|
},
|
|
])
|
|
writeYamlFileSync('pnpm-workspace.yaml', {})
|
|
|
|
await execa(pnpmBin, [
|
|
'install',
|
|
'-r',
|
|
'--registry',
|
|
REGISTRY_URL,
|
|
'--store-dir',
|
|
path.resolve(DEFAULT_OPTS.storeDir),
|
|
])
|
|
const { allProjects, selectedProjectsGraph } = await filterPackagesFromDir(process.cwd(), [])
|
|
|
|
let err!: PnpmError
|
|
try {
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
allProjects,
|
|
dir: path.resolve('foo'),
|
|
selectedProjectsGraph,
|
|
workspaceDir: process.cwd(),
|
|
}, ['build'])
|
|
} catch (_err: any) { // eslint-disable-line
|
|
err = _err
|
|
}
|
|
|
|
expect(err).toBeTruthy()
|
|
expect(err.hint).toMatch(/But script matched with build is present in the root/)
|
|
})
|
|
|
|
test('scripts work with PnP', async () => {
|
|
prepare({
|
|
scripts: {
|
|
foo: 'hello-world-js-bin > ./output.txt',
|
|
},
|
|
})
|
|
|
|
await execa(pnpmBin, ['add', '@pnpm.e2e/hello-world-js-bin@1.0.0'], {
|
|
env: {
|
|
NPM_CONFIG_REGISTRY: REGISTRY_URL,
|
|
NPM_CONFIG_NODE_LINKER: 'pnp',
|
|
NPM_CONFIG_SYMLINK: 'false',
|
|
},
|
|
})
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['foo'])
|
|
|
|
// https://github.com/pnpm/registry-mock/blob/ac2e129eb262009d2e7cd43ed869c31097793073/packages/hello-world-js-bin%401.0.0/index.js#L2
|
|
const helloWorldJsBinOutput = 'Hello world!\n'
|
|
|
|
const fooOutput = fs.readFileSync(path.resolve('output.txt')).toString()
|
|
expect(fooOutput).toStrictEqual(helloWorldJsBinOutput)
|
|
})
|
|
|
|
// A .exe file to configure as the scriptShell option would be necessary to test
|
|
// this behavior on Windows. Skip this test for now since compiling a custom
|
|
// .exe would be quite involved and hard to maintain.
|
|
skipOnWindows('pnpm run with custom shell', async () => {
|
|
prepare({
|
|
scripts: {
|
|
build: 'foo bar',
|
|
},
|
|
dependencies: {
|
|
'@pnpm.e2e/shell-mock': '0.0.0',
|
|
},
|
|
})
|
|
|
|
await execa(pnpmBin, [
|
|
'install',
|
|
`--registry=${REGISTRY_URL}`,
|
|
'--store-dir',
|
|
path.resolve(DEFAULT_OPTS.storeDir),
|
|
])
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
scriptShell: path.resolve('node_modules/.bin/shell-mock'),
|
|
}, ['build'])
|
|
|
|
expect((await import(path.resolve('shell-input.json'))).default).toStrictEqual(['-c', 'foo bar'])
|
|
})
|
|
|
|
onlyOnWindows('pnpm shows error if script-shell is .cmd', async () => {
|
|
prepare({
|
|
scripts: {
|
|
build: 'foo bar',
|
|
},
|
|
dependencies: {
|
|
'@pnpm.e2e/shell-mock': '0.0.0',
|
|
},
|
|
})
|
|
|
|
await execa(pnpmBin, [
|
|
'install',
|
|
`--registry=${REGISTRY_URL}`,
|
|
'--store-dir',
|
|
path.resolve(DEFAULT_OPTS.storeDir),
|
|
])
|
|
|
|
async function runScript () {
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bail: true,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
scriptShell: path.resolve('node_modules/.bin/shell-mock.cmd'),
|
|
}, ['build'])
|
|
}
|
|
|
|
await expect(runScript).rejects.toMatchObject({
|
|
code: 'ERR_PNPM_INVALID_SCRIPT_SHELL_WINDOWS',
|
|
})
|
|
})
|
|
|
|
test('pnpm run with RegExp script selector should work', async () => {
|
|
prepare({
|
|
scripts: {
|
|
'build:a': 'node -e "require(\'fs\').writeFileSync(\'./output-build-a.txt\', \'a\', \'utf8\')"',
|
|
'build:b': 'node -e "require(\'fs\').writeFileSync(\'./output-build-b.txt\', \'b\', \'utf8\')"',
|
|
'build:c': 'node -e "require(\'fs\').writeFileSync(\'./output-build-c.txt\', \'c\', \'utf8\')"',
|
|
build: 'node -e "require(\'fs\').writeFileSync(\'./output-build-a.txt\', \'should not run\', \'utf8\')"',
|
|
'lint:a': 'node -e "require(\'fs\').writeFileSync(\'./output-lint-a.txt\', \'a\', \'utf8\')"',
|
|
'lint:b': 'node -e "require(\'fs\').writeFileSync(\'./output-lint-b.txt\', \'b\', \'utf8\')"',
|
|
'lint:c': 'node -e "require(\'fs\').writeFileSync(\'./output-lint-c.txt\', \'c\', \'utf8\')"',
|
|
lint: 'node -e "require(\'fs\').writeFileSync(\'./output-lint-a.txt\', \'should not run\', \'utf8\')"',
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['/^(lint|build):.*/'])
|
|
|
|
expect(fs.readFileSync('output-build-a.txt', { encoding: 'utf-8' })).toBe('a')
|
|
expect(fs.readFileSync('output-build-b.txt', { encoding: 'utf-8' })).toBe('b')
|
|
expect(fs.readFileSync('output-build-c.txt', { encoding: 'utf-8' })).toBe('c')
|
|
|
|
expect(fs.readFileSync('output-lint-a.txt', { encoding: 'utf-8' })).toBe('a')
|
|
expect(fs.readFileSync('output-lint-b.txt', { encoding: 'utf-8' })).toBe('b')
|
|
expect(fs.readFileSync('output-lint-c.txt', { encoding: 'utf-8' })).toBe('c')
|
|
})
|
|
|
|
test('pnpm run with RegExp script selector should work also for pre/post script', async () => {
|
|
prepare({
|
|
scripts: {
|
|
'build:a': 'node -e "require(\'fs\').writeFileSync(\'./output-a.txt\', \'a\', \'utf8\')"',
|
|
'prebuild:a': 'node -e "require(\'fs\').writeFileSync(\'./output-pre-a.txt\', \'pre-a\', \'utf8\')"',
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
enablePrePostScripts: true,
|
|
}, ['/build:.*/'])
|
|
|
|
expect(fs.readFileSync('output-a.txt', { encoding: 'utf-8' })).toBe('a')
|
|
expect(fs.readFileSync('output-pre-a.txt', { encoding: 'utf-8' })).toBe('pre-a')
|
|
})
|
|
|
|
test('pnpm run with RegExp script selector should work parallel as a default behavior (parallel execution limits number is four)', async () => {
|
|
await using serverA = await createTestIpcServer()
|
|
await using serverB = await createTestIpcServer()
|
|
|
|
prepare({
|
|
scripts: {
|
|
'build:a': `node -e "let i = 20;setInterval(() => {if (!--i) process.exit(0); console.log(Date.now());},50)" | ${serverA.generateSendStdinScript()}`,
|
|
'build:b': `node -e "let i = 40;setInterval(() => {if (!--i) process.exit(0); console.log(Date.now());},25)" | ${serverB.generateSendStdinScript()}`,
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
}, ['/build:.*/'])
|
|
|
|
const outputsA = serverA.getLines().map(x => Number.parseInt(x))
|
|
const outputsB = serverB.getLines().map(x => Number.parseInt(x))
|
|
|
|
expect(Math.max(outputsA[0], outputsB[0]) < Math.min(outputsA[outputsA.length - 1], outputsB[outputsB.length - 1])).toBeTruthy()
|
|
})
|
|
|
|
test('pnpm run with RegExp script selector should work sequentially with --workspace-concurrency=1', async () => {
|
|
await using serverA = await createTestIpcServer()
|
|
await using serverB = await createTestIpcServer()
|
|
|
|
prepare({
|
|
scripts: {
|
|
'build:a': `node -e "let i = 2;setInterval(() => {if (!i--) process.exit(0); console.log(Date.now()); },16)" | ${serverA.generateSendStdinScript()}`,
|
|
'build:b': `node -e "let i = 2;setInterval(() => {if (!i--) process.exit(0); console.log(Date.now()); },16)" | ${serverB.generateSendStdinScript()}`,
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
workspaceConcurrency: 1,
|
|
}, ['/build:.*/'])
|
|
|
|
const outputsA = serverA.getLines().map(x => Number.parseInt(x))
|
|
const outputsB = serverB.getLines().map(x => Number.parseInt(x))
|
|
|
|
expect(outputsA[0] < outputsB[0] && outputsA[1] < outputsB[1]).toBeTruthy()
|
|
})
|
|
|
|
test.each(['d', 'g', 'i', 'm', 'u', 'v', 'y', 's'])('pnpm run with RegExp script selector with flag %s should throw error', async (flag) => {
|
|
await using serverA = await createTestIpcServer()
|
|
await using serverB = await createTestIpcServer()
|
|
|
|
prepare({
|
|
scripts: {
|
|
'build:a': `node -e "let i = 2;setInterval(() => {if (!i--) process.exit(0); console.log(Date.now()); },16)" | ${serverA.generateSendStdinScript()}`,
|
|
'build:b': `node -e "let i = 2;setInterval(() => {if (!i--) process.exit(0); console.log(Date.now()); },16)" | ${serverB.generateSendStdinScript()}`,
|
|
},
|
|
})
|
|
|
|
let err!: Error
|
|
try {
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
workspaceConcurrency: 1,
|
|
}, [`/build:.*/${flag}`])
|
|
} catch (_err: any) { // eslint-disable-line
|
|
err = _err
|
|
}
|
|
expect(err.message).toBe('RegExp flags are not supported in script command selector')
|
|
})
|
|
|
|
test('pnpm run with slightly incorrect command suggests correct one', async () => {
|
|
prepare({
|
|
scripts: {
|
|
build: 'echo 0',
|
|
},
|
|
})
|
|
|
|
// cspell:ignore buil
|
|
await expect(run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
workspaceConcurrency: 1,
|
|
}, ['buil'])).rejects.toMatchObject({
|
|
code: 'ERR_PNPM_NO_SCRIPT',
|
|
hint: 'Command "buil" not found. Did you mean "pnpm run build"?',
|
|
})
|
|
})
|
|
|
|
test('pnpm run with custom node-options', async () => {
|
|
prepare({
|
|
scripts: {
|
|
build: 'node -e "if (process.env.NODE_OPTIONS !== \'--max-old-space-size=1200\') { process.exit(1) }"',
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: '',
|
|
rawConfig: {},
|
|
nodeOptions: '--max-old-space-size=1200',
|
|
workspaceConcurrency: 1,
|
|
}, ['build'])
|
|
})
|
|
|
|
test('pnpm run without node version', async () => {
|
|
prepare({
|
|
scripts: {
|
|
'assert-node-version': `node -e "assert.equal(process.version, '${process.version}')"`,
|
|
},
|
|
})
|
|
|
|
await run.handler({
|
|
...DEFAULT_OPTS,
|
|
bin: 'node_modules/.bin',
|
|
dir: process.cwd(),
|
|
extraBinPaths: [],
|
|
extraEnv: {},
|
|
pnpmHomeDir: process.cwd(),
|
|
rawConfig: {},
|
|
workspaceConcurrency: 1,
|
|
}, ['assert-node-version'])
|
|
})
|