From a3e3139178110ddd3229665eff7e9e3e4d7f210a Mon Sep 17 00:00:00 2001 From: Jaromir Obr Date: Mon, 7 Sep 2026 15:05:54 +0200 Subject: [PATCH] fix: report Bun runtime in environment info `codecept info` and the machine-info block printed by `run --verbose`, `run-workers --verbose` and `check` hardcoded `envinfo.helpers.getNodeInfo()`, which probes PATH rather than the running process. Under Bun that is wrong in two ways: - `nodeInfo: Not Found` on a working install, either because the image has no Node at all, or because `bunx --bun` prepends a shim dir whose `node` re-execs Bun and rejects `--version`. - A real but irrelevant Node version when some Node happens to be on PATH, which is worse because it looks correct. Pick the helper by the runtime that is actually executing, via `process.versions.bun`, and report Bun through `envinfo.helpers.getbunInfo()` so both runtimes are resolved the same way. Node output is unchanged. The returned array keeps the shape of `getNodeInfo()`, so the existing `Array.isArray` printer shows the version at index 1 with no printer change. Closes #5698 Co-Authored-By: Claude Opus 5 --- lib/command/info.js | 14 +++++++++--- test/unit/command/info_test.js | 42 +++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/lib/command/info.js b/lib/command/info.js index 184c5f329..073c0c98e 100644 --- a/lib/command/info.js +++ b/lib/command/info.js @@ -44,6 +44,14 @@ async function getOsBrowsers() { ].join(', ') } +// Which runtime executes CodeceptJS can only be told from `process.versions`; envinfo probes +// PATH, where under `bunx --bun` the first `node` is a Bun shim with no --version, so +// getNodeInfo() returns "Not Found" on a working install. +async function getRuntimeInfo() { + if (process.versions.bun) return { bunInfo: await envinfo.helpers.getbunInfo() } + return { nodeInfo: await envinfo.helpers.getNodeInfo() } +} + export default async function (path) { const testsPath = getTestRoot(path) const config = await getConfig(testsPath) @@ -53,7 +61,7 @@ export default async function (path) { output.print('\n Environment information: \n') const info = {} info.codeceptVersion = Codecept.version() - info.nodeInfo = await envinfo.helpers.getNodeInfo() + Object.assign(info, await getRuntimeInfo()) info.osInfo = await envinfo.helpers.getOSInfo() info.cpuInfo = await envinfo.helpers.getCPUInfo() info.osBrowsers = await getOsBrowsers() @@ -77,11 +85,11 @@ export default async function (path) { output.print('***************************************') } -export { parsePlaywrightBrowsers } +export { parsePlaywrightBrowsers, getRuntimeInfo } export const getMachineInfo = async () => { const info = { - nodeInfo: await envinfo.helpers.getNodeInfo(), + ...(await getRuntimeInfo()), osInfo: await envinfo.helpers.getOSInfo(), cpuInfo: await envinfo.helpers.getCPUInfo(), chromeInfo: await envinfo.helpers.getChromeInfo(), diff --git a/test/unit/command/info_test.js b/test/unit/command/info_test.js index f6c378dac..a6780881a 100644 --- a/test/unit/command/info_test.js +++ b/test/unit/command/info_test.js @@ -1,7 +1,47 @@ import { expect } from 'chai' -import { parsePlaywrightBrowsers } from '../../../lib/command/info.js' +import { parsePlaywrightBrowsers, getRuntimeInfo } from '../../../lib/command/info.js' describe('info command', () => { + describe('getRuntimeInfo', () => { + let originalBunVersion + + beforeEach(() => { + originalBunVersion = process.versions.bun + }) + + afterEach(() => { + if (originalBunVersion === undefined) { + delete process.versions.bun + } else { + process.versions.bun = originalBunVersion + } + }) + + it('should report bunInfo when running under Bun', async () => { + process.versions.bun = '1.4.2' + const info = await getRuntimeInfo() + expect(info).to.have.property('bunInfo') + expect(info).to.not.have.property('nodeInfo') + expect(info.bunInfo[0]).to.equal('bun') + }) + + it('should report nodeInfo when not running under Bun', async () => { + delete process.versions.bun + const info = await getRuntimeInfo() + expect(info).to.have.property('nodeInfo') + expect(info).to.not.have.property('bunInfo') + expect(info.nodeInfo[0]).to.equal('Node') + }) + + it('should return an array so the printer shows the version at index 1', async () => { + delete process.versions.bun + const { nodeInfo } = await getRuntimeInfo() + expect(nodeInfo).to.be.an('array') + expect(nodeInfo.length).to.be.at.least(2) + expect(nodeInfo[1]).to.be.a('string') + }) + }) + describe('parsePlaywrightBrowsers', () => { describe('old format (Playwright < 1.58)', () => { const oldFormatOutput = `browser: chromium version 140.0.7339.186