Skip to content

Commit 90e8fb2

Browse files
Jaromir Obrclaude
andcommitted
fix: use bunx instead of npx to read Playwright versions under Bun
`getPlaywrightBrowsers()` hardcoded `npx playwright install --dry-run`. A Bun-only environment has no `npx` on PATH, so `execSync` throws and the catch reports `Playwright not installed` on a working install. That is a false negative rather than a visible error, so it reads as a real misconfiguration. Pick the package runner from the runtime that is actually executing, via `process.versions.bun`, the same detection already used by `getRuntimeInfo()`. `bunx playwright install --dry-run` resolves the local `node_modules/.bin/playwright` and emits output identical to the `npx` form, so `parsePlaywrightBrowsers()` is unaffected and Node behaviour is unchanged. This is the only place CodeceptJS shells out to `npx`; every other occurrence under `lib/` is documentation text. It removes the need to symlink `npx` to `bun` in Bun images. Closes #5713 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent b9a7366 commit 90e8fb2

2 files changed

Lines changed: 36 additions & 3 deletions

File tree

lib/command/info.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,16 @@ function parsePlaywrightBrowsers(output) {
2121
return versions.join(', ')
2222
}
2323

24+
// Bun has its own package runner and a Bun-only install has no `npx` on PATH at all, so the
25+
// runner has to follow the runtime that is actually executing rather than what PATH happens to hold.
26+
function getPackageRunner() {
27+
if (process.versions.bun) return 'bunx'
28+
return 'npx'
29+
}
30+
2431
async function getPlaywrightBrowsers() {
2532
try {
26-
const info = execSync('npx playwright install --dry-run').toString().trim()
33+
const info = execSync(`${getPackageRunner()} playwright install --dry-run`).toString().trim()
2734
return parsePlaywrightBrowsers(info)
2835
} catch (err) {
2936
return 'Playwright not installed'
@@ -85,7 +92,7 @@ export default async function (path) {
8592
output.print('***************************************')
8693
}
8794

88-
export { parsePlaywrightBrowsers, getRuntimeInfo }
95+
export { parsePlaywrightBrowsers, getRuntimeInfo, getPackageRunner }
8996

9097
export const getMachineInfo = async () => {
9198
const info = {

test/unit/command/info_test.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from 'chai'
2-
import { parsePlaywrightBrowsers, getRuntimeInfo } from '../../../lib/command/info.js'
2+
import { parsePlaywrightBrowsers, getRuntimeInfo, getPackageRunner } from '../../../lib/command/info.js'
33

44
describe('info command', () => {
55
describe('getRuntimeInfo', () => {
@@ -42,6 +42,32 @@ describe('info command', () => {
4242
})
4343
})
4444

45+
describe('getPackageRunner', () => {
46+
let originalBunVersion
47+
48+
beforeEach(() => {
49+
originalBunVersion = process.versions.bun
50+
})
51+
52+
afterEach(() => {
53+
if (originalBunVersion === undefined) {
54+
delete process.versions.bun
55+
} else {
56+
process.versions.bun = originalBunVersion
57+
}
58+
})
59+
60+
it('should use bunx when running under Bun', () => {
61+
process.versions.bun = '1.4.2'
62+
expect(getPackageRunner()).to.equal('bunx')
63+
})
64+
65+
it('should use npx when not running under Bun', () => {
66+
delete process.versions.bun
67+
expect(getPackageRunner()).to.equal('npx')
68+
})
69+
})
70+
4571
describe('parsePlaywrightBrowsers', () => {
4672
describe('old format (Playwright < 1.58)', () => {
4773
const oldFormatOutput = `browser: chromium version 140.0.7339.186

0 commit comments

Comments
 (0)