forked from pnpm/pnpm
/
cli.ts
198 lines (140 loc) · 5.76 KB
/
cli.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import { createReadStream, promises as fs, mkdirSync } from 'fs'
import path from 'path'
import PATH_NAME from 'path-name'
import prepare, { prepareEmpty } from '@pnpm/prepare'
import rimraf from '@zkochan/rimraf'
import execa from 'execa'
import loadJsonFile from 'load-json-file'
import {
execPnpm,
execPnpmSync,
execPnpxSync,
} from './utils'
const fixtures = path.join(__dirname, '../../../fixtures')
const hasOutdatedDepsFixture = path.join(fixtures, 'has-outdated-deps')
test('some commands pass through to npm', () => {
const result = execPnpmSync(['dist-tag', 'ls', 'is-positive'])
expect(result.status).toBe(0)
expect(result.stdout.toString()).not.toMatch(/Usage: pnpm [command] [flags]/)
})
test('installs in the folder where the package.json file is', async () => {
const project = prepare()
await fs.mkdir('subdir')
process.chdir('subdir')
await execPnpm(['install', 'rimraf@2.5.1'])
const m = project.requireModule('rimraf')
expect(typeof m).toBe('function')
await project.isExecutable('.bin/rimraf')
})
test('pnpm import does not move modules created by npm', async () => {
prepare()
await execa('npm', ['install', 'is-positive@1.0.0', '--save'])
await execa('npm', ['shrinkwrap'])
const packageManifestInodeBefore = (await fs.stat('node_modules/is-positive/package.json')).ino
await execPnpm(['import'])
const packageManifestInodeAfter = (await fs.stat('node_modules/is-positive/package.json')).ino
expect(packageManifestInodeBefore).toBe(packageManifestInodeAfter)
})
test('pass through to npm CLI for commands that are not supported by npm', () => {
const result = execPnpmSync(['config', 'get', 'user-agent'])
expect(result.status).toBe(0)
expect(result.stdout.toString()).toMatch(/npm\//) // command returned correct result
})
test('pass through to npm with all the args', async () => {
prepare()
await rimraf('package.json')
const result = execPnpmSync(['dist-tag', 'ls', 'pnpm'])
expect(result.status).toBe(0)
})
test('pnpm fails when an unsupported command is used', async () => {
prepare()
const { status } = execPnpmSync(['unsupported-command'])
expect(status).toBe(1)
})
test('pnpm fails when no command is specified', async () => {
prepare()
const { status, stdout } = execPnpmSync([])
expect(status).toBe(1)
expect(stdout.toString()).toMatch(/Usage:/)
})
test('command fails when an unsupported flag is used', async () => {
prepare()
const { status, stdout } = execPnpmSync(['update', '--save-dev'])
expect(status).toBe(1)
expect(stdout.toString()).toMatch(/Unknown option: 'save-dev'/)
})
test('command does not fail when a deprecated option is used', async () => {
prepare()
const { status, stdout } = execPnpmSync(['install', '--no-lock'])
expect(status).toBe(0)
expect(stdout.toString()).toMatch(/Deprecated option: 'lock'/)
})
test('command does not fail when deprecated options are used', async () => {
prepare()
const { status, stdout } = execPnpmSync(['install', '--no-lock', '--independent-leaves'])
expect(status).toBe(0)
expect(stdout.toString()).toMatch(/Deprecated options: 'lock', 'independent-leaves'/)
})
test('adding new dep does not fail if node_modules was created with --public-hoist-pattern=eslint-*', async () => {
const project = prepare()
await execPnpm(['add', 'is-positive', '--public-hoist-pattern=eslint-*'])
expect(execPnpmSync(['add', 'is-negative', '--no-hoist']).status).toBe(1)
expect(execPnpmSync(['add', 'is-negative', '--no-shamefully-hoist']).status).toBe(1)
expect(execPnpmSync(['add', 'is-negative']).status).toBe(0)
await project.has('is-negative')
})
test('pnpx works', () => {
prepareEmpty()
const global = path.resolve('..', 'global')
const pnpmHome = path.join(global, 'pnpm')
mkdirSync(global)
const env = {
[PATH_NAME]: `${pnpmHome}${path.delimiter}${process.env[PATH_NAME]}`, // eslint-disable-line
PNPM_HOME: pnpmHome,
XDG_DATA_HOME: global,
}
const result = execPnpxSync(['hello-world-js-bin'], { env })
expect(result.stdout.toString()).toEqual('Hello world!\n')
expect(result.status).toBe(0)
})
test('exit code from plugin is used to end the process', () => {
process.chdir(hasOutdatedDepsFixture)
const result = execPnpmSync(['outdated'])
expect(result.status).toBe(1)
expect(result.stdout.toString()).toMatch(/is-positive/)
})
const PNPM_CLI = path.join(__dirname, '../dist/pnpm.cjs')
test('the bundled CLI is independent', async () => {
const project = prepare()
await fs.copyFile(PNPM_CLI, 'pnpm.cjs')
await execa('node', ['./pnpm.cjs', 'add', 'is-positive'])
await project.has('is-positive')
})
test('the bundled CLI can be executed from stdin', async () => {
const project = prepare()
const nodeProcess = execa('node', ['-', 'add', 'is-positive'])
createReadStream(PNPM_CLI).pipe(nodeProcess.stdin!)
await nodeProcess
await project.has('is-positive')
})
test('the bundled CLI prints the correct version, when executed from stdin', async () => {
const nodeProcess = execa('node', ['-', '--version'])
createReadStream(PNPM_CLI).pipe(nodeProcess.stdin!)
const { version } = await loadJsonFile<{ version: string }>(path.join(__dirname, '../package.json'))
expect((await nodeProcess).stdout).toBe(version)
})
test('use the specified Node.js version for running scripts', async () => {
prepare({
scripts: {
test: "node -e \"require('fs').writeFileSync('version',process.version,'utf8')\"",
},
})
await fs.writeFile('.npmrc', 'use-node-version=14.0.0', 'utf8')
await execPnpm(['run', 'test'])
expect(await fs.readFile('version', 'utf8')).toBe('v14.0.0')
})
test('if an unknown command is executed, run it', async () => {
prepare({})
await execPnpm(['node', '-e', "require('fs').writeFileSync('foo','','utf8')"])
expect(await fs.readFile('foo', 'utf8')).toBe('')
})