Skip to content

Commit 8bb3fd2

Browse files
mrstorkserhalp
andauthored
fix: pnpx context awareness + e2e tests (#7324)
* fix: make unlink command highlighting consistent with other command output * fix: accurately capture command for pnpx vs pnpm exec * test: split standard package manager calls from npx/pnpx * chore: update test description Co-authored-by: Philippe Serhal <[email protected]> --------- Co-authored-by: Philippe Serhal <[email protected]>
1 parent 03fd72d commit 8bb3fd2

File tree

3 files changed

+95
-47
lines changed

3 files changed

+95
-47
lines changed

e2e/install.e2e.ts

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ type Test = { packageName: string }
157157
type InstallTest = Test & { install: [cmd: string, args: string[]]; lockfile: string }
158158
type RunTest = Test & { run: [cmd: string, args: string[]] }
159159

160-
const tests: [packageManager: string, config: InstallTest | RunTest][] = [
160+
const installTests: [packageManager: string, config: InstallTest][] = [
161161
[
162162
'npm',
163163
{
@@ -182,62 +182,104 @@ const tests: [packageManager: string, config: InstallTest | RunTest][] = [
182182
lockfile: 'yarn.lock',
183183
},
184184
],
185+
]
186+
187+
describe.each(installTests)('%s → installs the cli and runs commands without errors', (_, config) => {
188+
// TODO: Figure out why this flow is failing on Windows.
189+
const npxOnWindows = platform() === 'win32' && 'run' in config
190+
191+
itWithMockNpmRegistry.skipIf(npxOnWindows)('runs the commands without errors', async ({ registry }) => {
192+
// Install
193+
194+
const cwd = registry.cwd
195+
await execa(...config.install, {
196+
cwd,
197+
env: { npm_config_registry: registry.address },
198+
stdio: debug.enabled ? 'inherit' : 'ignore',
199+
})
200+
201+
expect(
202+
existsSync(path.join(cwd, config.lockfile)),
203+
`Generated lock file ${config.lockfile} does not exist in ${cwd}`,
204+
).toBe(true)
205+
206+
const binary = path.resolve(path.join(cwd, `./node_modules/.bin/netlify${platform() === 'win32' ? '.cmd' : ''}`))
207+
208+
// Help
209+
210+
const helpOutput = (await execa(binary, ['help'], { cwd })).stdout
211+
212+
expect(helpOutput.trim(), `Help command does not start with '⬥ Netlify CLI'\\n\\nVERSION: ${helpOutput}`).toMatch(
213+
/^ Netlify CLI\n\nVERSION/,
214+
)
215+
expect(
216+
helpOutput,
217+
`Help command does not include '${config.packageName}/${pkg.version}':\n\n${helpOutput}`,
218+
).toContain(`${config.packageName}/${pkg.version}`)
219+
expect(helpOutput, `Help command does not include '$ netlify [COMMAND]':\n\n${helpOutput}`).toMatch(
220+
'$ netlify [COMMAND]',
221+
)
222+
223+
// Unlink
224+
225+
const unlinkOutput = (await execa(binary, ['unlink'], { cwd })).stdout
226+
expect(unlinkOutput, `Unlink command includes command context':\n\n${unlinkOutput}`).toContain(
227+
`Run netlify link to link it`,
228+
)
229+
})
230+
})
231+
232+
const runTests: [packageManager: string, config: RunTest][] = [
185233
[
186234
'npx',
187235
{
188236
packageName: 'netlify',
189237
run: ['npx', ['-y', 'netlify@testing']],
190238
},
191239
],
240+
[
241+
'pnpx',
242+
{
243+
packageName: 'netlify',
244+
run: ['pnpx', ['netlify@testing']],
245+
},
246+
],
192247
]
193248

194-
describe.each(tests)('%s → installs the cli and runs the help command without error', (_, config) => {
249+
describe.each(runTests)('%s → runs cli commands without errors', (_, config) => {
195250
// TODO: Figure out why this flow is failing on Windows.
196251
const npxOnWindows = platform() === 'win32' && 'run' in config
197252

198-
itWithMockNpmRegistry.skipIf(npxOnWindows)(
199-
'installs the cli and runs the help command without error',
200-
async ({ registry }) => {
201-
const cwd = registry.cwd
202-
203-
let stdout: string
204-
205-
if ('install' in config) {
206-
await execa(...config.install, {
207-
cwd,
208-
env: { npm_config_registry: registry.address },
209-
stdio: debug.enabled ? 'inherit' : 'ignore',
210-
})
211-
212-
expect(
213-
existsSync(path.join(cwd, config.lockfile)),
214-
`Generated lock file ${config.lockfile} does not exist in ${cwd}`,
215-
).toBe(true)
216-
217-
const binary = path.resolve(
218-
path.join(cwd, `./node_modules/.bin/netlify${platform() === 'win32' ? '.cmd' : ''}`),
219-
)
220-
const result = await execa(binary, ['help'], { cwd })
221-
222-
stdout = result.stdout
223-
} else {
224-
const [cmd, args] = config.run
225-
const result = await execa(cmd, args, {
226-
env: {
227-
npm_config_registry: registry.address,
228-
},
229-
})
253+
itWithMockNpmRegistry.skipIf(npxOnWindows)('runs commands without errors', async ({ registry }) => {
254+
const [cmd, args] = config.run
255+
const env = {
256+
npm_config_registry: registry.address,
257+
}
230258

231-
stdout = result.stdout
232-
}
259+
// Install
233260

234-
expect(stdout.trim(), `Help command does not start with '⬥ Netlify CLI'\\n\\nVERSION: ${stdout}`).toMatch(
235-
/^ Netlify CLI\n\nVERSION/,
236-
)
237-
expect(stdout, `Help command does not include '${config.packageName}/${pkg.version}':\n\n${stdout}`).toContain(
238-
`${config.packageName}/${pkg.version}`,
239-
)
240-
expect(stdout, `Help command does not include '$ netlify [COMMAND]':\n\n${stdout}`).toMatch('$ netlify [COMMAND]')
241-
},
242-
)
261+
await execa(cmd, [...args], { env })
262+
263+
// Help
264+
265+
const helpOutput = (await execa(cmd, [...args, 'help'], { env })).stdout
266+
267+
expect(helpOutput.trim(), `Help command does not start with '⬥ Netlify CLI'\\n\\nVERSION: ${helpOutput}`).toMatch(
268+
/^ Netlify CLI\n\nVERSION/,
269+
)
270+
expect(
271+
helpOutput,
272+
`Help command does not include '${config.packageName}/${pkg.version}':\n\n${helpOutput}`,
273+
).toContain(`${config.packageName}/${pkg.version}`)
274+
expect(helpOutput, `Help command does not include '$ netlify [COMMAND]':\n\n${helpOutput}`).toMatch(
275+
'$ netlify [COMMAND]',
276+
)
277+
278+
// Unlink
279+
280+
const unlinkOutput = (await execa(cmd, [...args, 'unlink'], { env })).stdout
281+
expect(unlinkOutput, `Unlink command includes command context':\n\n${unlinkOutput}`).toContain(
282+
`Run ${cmd} netlify link to link it`,
283+
)
284+
})
243285
})

src/commands/unlink/unlink.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { OptionValues } from 'commander'
33
import { exit, log } from '../../utils/command-helpers.js'
44
import { track } from '../../utils/telemetry/index.js'
55
import BaseCommand from '../base-command.js'
6+
import { chalk, netlifyCommand } from '../../utils/command-helpers.js'
67

78
export const unlink = async (_options: OptionValues, command: BaseCommand) => {
89
const { site, siteInfo, state } = command.netlify
910
const siteId = site.id
1011

1112
if (!siteId) {
12-
log(`Folder is not linked to a Netlify project. Run 'netlify link' to link it`)
13+
log(`Folder is not linked to a Netlify project. Run ${chalk.cyanBright(`${netlifyCommand()} link`)} to link it`)
1314
return exit()
1415
}
1516

src/utils/command-helpers.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,13 @@ export const netlifyCommand = () => {
364364
return `npx netlify`
365365
}
366366

367-
// Captures both `pnpx netlify ...` and `pnpm exec netlify ...`
367+
// Captures `pnpm exec netlify ...`
368368
if (pkgFromUserAgent(npm_config_user_agent) === 'pnpm' && npm_command === 'exec') {
369+
return `pnpm exec netlify`
370+
}
371+
372+
// Captures `pnpx netlify ...`
373+
if (pkgFromUserAgent(npm_config_user_agent) === 'pnpm' && npm_command === 'run-script') {
369374
return `pnpx netlify`
370375
}
371376

0 commit comments

Comments
 (0)