diff --git a/CHANGELOG.md b/CHANGELOG.md index bf5aa7061..da14dd293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CO - Cucumber Expressions now support a wider array of parameter types (see [documentation](https://github.com/cucumber/cucumber-expressions#parameter-types)) - Improved styling and usability on report from `html` formatter +### Fixed +- Warn users who are on an unsupported node version ([#1922](https://github.com/cucumber/cucumber-js/pull/1922)) + ### Changed - Switch from `colors` to `chalk` for terminal coloring ([#1895](https://github.com/cucumber/cucumber-js/pull/1895)) diff --git a/package-lock.json b/package-lock.json index c910567ae..925b32293 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "progress": "^2.0.3", "resolve": "^1.19.0", "resolve-pkg": "^2.0.0", + "semver": "7.3.5", "stack-chain": "^2.0.0", "string-argv": "^0.3.1", "tmp": "^0.2.1", @@ -85,7 +86,6 @@ "nyc": "15.1.0", "prettier": "2.5.1", "reindent-template-literals": "1.1.0", - "semver": "7.3.5", "shx": "0.3.4", "sinon": "13.0.1", "sinon-chai": "3.7.0", @@ -4501,7 +4501,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -6132,7 +6131,6 @@ "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -7124,8 +7122,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "16.2.0", @@ -10633,7 +10630,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -11823,7 +11819,6 @@ "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -12592,8 +12587,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "16.2.0", diff --git a/package.json b/package.json index e1dd4ee58..0508d2672 100644 --- a/package.json +++ b/package.json @@ -209,6 +209,7 @@ "progress": "^2.0.3", "resolve": "^1.19.0", "resolve-pkg": "^2.0.0", + "semver": "7.3.5", "stack-chain": "^2.0.0", "string-argv": "^0.3.1", "tmp": "^0.2.1", @@ -258,7 +259,6 @@ "nyc": "15.1.0", "prettier": "2.5.1", "reindent-template-literals": "1.1.0", - "semver": "7.3.5", "shx": "0.3.4", "sinon": "13.0.1", "sinon-chai": "3.7.0", diff --git a/src/cli/assert_node_engine_version.ts b/src/cli/assert_node_engine_version.ts new file mode 100644 index 000000000..e2a72f4ab --- /dev/null +++ b/src/cli/assert_node_engine_version.ts @@ -0,0 +1,25 @@ +import fs from 'fs' +import path from 'path' +import semver from 'semver' + +type PackageJSON = { + engines: { node: string } +} + +const readActualPackageJSON: () => PackageJSON = () => + JSON.parse( + fs + .readFileSync(path.resolve(__dirname, '..', '..', 'package.json')) + .toString() + ) + +export function assertNodeEngineVersion( + currentVersion: string, + readPackageJSON: () => PackageJSON = readActualPackageJSON +): void { + const requiredVersion = readPackageJSON().engines.node + if (!semver.satisfies(currentVersion, requiredVersion)) { + const message = `Cucumber can only run on Node.js versions ${requiredVersion}. This Node.js version is ${currentVersion}` + throw new Error(message) + } +} diff --git a/src/cli/assert_node_engine_version_spec.ts b/src/cli/assert_node_engine_version_spec.ts new file mode 100644 index 000000000..01133411a --- /dev/null +++ b/src/cli/assert_node_engine_version_spec.ts @@ -0,0 +1,18 @@ +import assert from 'assert' +import { assertNodeEngineVersion } from './assert_node_engine_version' + +describe(assertNodeEngineVersion.name, () => { + it('fails when the version is lower than specified in package.json', () => { + assert.throws(() => + assertNodeEngineVersion('v11.0.0', () => ({ + engines: { + node: '>=12', + }, + })) + ) + }) + + it('passes when the version is greater than specified in package.json', () => { + assertNodeEngineVersion('v17.0.0') + }) +}) diff --git a/src/cli/run.ts b/src/cli/run.ts index 508b71666..f7dec91e1 100644 --- a/src/cli/run.ts +++ b/src/cli/run.ts @@ -1,6 +1,7 @@ import Cli, { ICliRunResult } from './' import VError from 'verror' import publishBanner from './publish_banner' +import { assertNodeEngineVersion } from './assert_node_engine_version' function exitWithError(error: Error): void { console.error(VError.fullStack(error)) // eslint-disable-line no-console @@ -12,6 +13,13 @@ function displayPublishAdvertisementBanner(): void { } export default async function run(): Promise { + try { + assertNodeEngineVersion(process.version) + } catch (error) { + console.error(error.message) // eslint-disable-line no-console + process.exit(1) + } + const cli = new Cli({ argv: process.argv, cwd: process.cwd(),