Skip to content

Commit

Permalink
esm: rename bin script file to avoid loader issues (#1993)
Browse files Browse the repository at this point in the history
* rename bin script, update tests

* update documentation

* update CHANGELOG.md

* fix program name in cli

* Update CHANGELOG.md
  • Loading branch information
davidjgoss committed Apr 12, 2022
1 parent 024911b commit 9e9ebd2
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 32 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CONTRIBUTING.md) on how to contribute to Cucumber.

## [Unreleased]
### Changed
- Rename the `cucumber-js` binary's underlying file to be `cucumber.js`, so it doesn't fall foul of Node.js module conventions and plays nicely with ESM loaders (see [documentation](./docs/esm.md#transpiling)) ([#1993](https://github.com/cucumber/cucumber-js/pull/1993))

### Fixed
- Correctly escape backslashes in generated expressions for snippets ([#1324](https://github.com/cucumber/cucumber-js/issues/1324) [#1995](https://github.com/cucumber/cucumber-js/pull/1995))

Expand Down
File renamed without changes.
6 changes: 5 additions & 1 deletion docs/esm.md
Expand Up @@ -58,4 +58,8 @@ export const ci = {

## Transpiling

When using a transpiler for e.g. TypeScript, ESM isn't supported - you'll need to configure your transpiler to output modules in CommonJS syntax (for now). See [this GitHub issue](https://github.com/cucumber/cucumber-js/issues/1844) for the latest on support for ESM loaders.
You can use [ESM loaders](https://nodejs.org/api/esm.html#loaders) to transpile your support code on the fly. The `requireModule` configuration option only works with CommonJS (i.e. `require` hooks) and is not applicable here. Cucumber doesn't have an equivalent option for ESM loaders because they currently can't be registered in-process, so you'll need to declare the loader externally, like this:

```shell
$ NODE_OPTIONS="--loader <loader>" npx cucumber-js
```
43 changes: 19 additions & 24 deletions docs/transpiling.md
Expand Up @@ -20,10 +20,6 @@ Your `tsconfig.json` should have these `compilerOptions` on:

Other than that, a pretty standard TypeScript setup should work as expected.

> ⚠️ Some TypeScript setups use `esnext` modules by default,
> which doesn't marry well with Node. You may consider using commonjs instead.
> See how to add [extra configuration](#extra-configuration) below.
You'll also need to specify where your support code is, since `.ts` files won't be picked up by default.

### With ts-node
Expand All @@ -33,32 +29,31 @@ If you are using [ts-node](https://github.com/TypeStrong/ts-node):
- In a configuration file `{ requireModule: ['ts-node/register'], require: ['step-definitions/**/*.ts'] }`
- On the CLI `$ cucumber-js --require-module ts-node/register --require 'step-definitions/**/*.ts'`

### With Babel
#### ESM

If you are using babel with [@babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript):
For ESM projects, you can use `ts-node`'s ESM loader and then `import` your TypeScript files:

- In a configuration file `{ requireModule: ['@babel/register'], require: ['step-definitions/**/*.ts'] }`
- On the CLI `$ cucumber-js --require-module @babel/register --require 'step-definitions/**/*.ts'`

## Extra Configuration
```shell
$ NODE_OPTIONS"--loader ts-node/esm" cucumber-js --import 'step-definitions/**/*.ts'
```

Sometimes the required module (say `ts-node/register`) needs extra configuration. For example, you might want to configure it such that it prevents the compiled JS being written out to files, and pass some compiler options. In such cases, create a script (say, `tests.setup.js`):
Don't forget to set your `tsconfig.json` to emit JavaScript with `import` and `export` statements:

```js
require('ts-node').register({
transpileOnly: true,
compilerOptions: {
"module": "commonjs",
"resolveJsonModule": true,
},
});
```json
{
"compilerOptions": {
"module": "esnext"
}
}
```

And then require it using the `require` option:
### With Babel

If you are using babel with [@babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript):

- In a configuration file `{ require: ['tests.setup.js', 'features/**/*.ts'] }`
- On the CLI `$ cucumber-js --require tests.setup.js --require 'features/**/*.ts'`
- In a configuration file `{ requireModule: ['@babel/register'], require: ['step-definitions/**/*.ts'] }`
- On the CLI `$ cucumber-js --require-module @babel/register --require 'step-definitions/**/*.ts'`

## ESM
### ESM

Cucumber doesn't yet support native ESM loader hooks ([see GitHub issue](https://github.com/cucumber/cucumber-js/issues/1844)).
See [ESM](./esm.md) for general advice on using loaders for transpilation in ESM projects.
4 changes: 2 additions & 2 deletions features/support/hooks.ts
Expand Up @@ -45,7 +45,7 @@ Before(function (
} catch (error) {
warnUserAboutEnablingDeveloperMode(error)
}
this.localExecutablePath = path.join(projectPath, 'bin', 'cucumber-js')
this.localExecutablePath = path.join(projectPath, 'bin', 'cucumber.js')
})

Before('@esm', function (this: World) {
Expand Down Expand Up @@ -102,7 +102,7 @@ Before('@global-install', function (this: World) {
this.globalExecutablePath = path.join(
globalInstallCucumberPath,
'bin',
'cucumber-js'
'cucumber.js'
)
})

Expand Down
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -291,7 +291,7 @@
"cck-test": "mocha 'compatibility/**/*_spec.ts'",
"docs:ci": "api-extractor run --verbose",
"docs:local": "api-extractor run --verbose --local && api-documenter markdown --input-folder ./tmp/api-extractor --output-folder ./docs/api",
"feature-test": "node ./bin/cucumber-js",
"feature-test": "node bin/cucumber.js",
"lint-autofix": "eslint --fix \"{compatibility,example,features,scripts,src,test}/**/*.ts\"",
"lint-code": "eslint \"{compatibility,example,features,scripts,src,test}/**/*.ts\"",
"lint-dependencies": "dependency-lint",
Expand All @@ -303,14 +303,14 @@
"prepublishOnly": "rm -rf lib && npm run build-local",
"pretest-coverage": "npm run build-local",
"pretypes-test": "npm run build-local",
"test-coverage": "nyc --silent mocha 'src/**/*_spec.ts' 'compatibility/**/*_spec.ts' && nyc --silent --no-clean node ./bin/cucumber-js && nyc report --reporter=lcov",
"test-coverage": "nyc --silent mocha 'src/**/*_spec.ts' 'compatibility/**/*_spec.ts' && nyc --silent --no-clean node bin/cucumber.js && nyc report --reporter=lcov",
"test": "npm run lint && npm run types-test && npm run unit-test && npm run cck-test && npm run feature-test",
"types-test": "tsd",
"unit-test": "mocha 'src/**/*_spec.ts'",
"update-dependencies": "npx npm-check-updates --upgrade"
},
"bin": {
"cucumber-js": "./bin/cucumber-js"
"cucumber-js": "bin/cucumber.js"
},
"license": "MIT",
"files": [
Expand Down
3 changes: 1 addition & 2 deletions src/configuration/argv_parser.ts
@@ -1,6 +1,5 @@
import { Command } from 'commander'
import merge from 'lodash.merge'
import path from 'path'
import { dialects } from '@cucumber/gherkin'
import Formatters from '../formatter/helpers/formatters'
import { version } from '../version'
Expand Down Expand Up @@ -65,7 +64,7 @@ const ArgvParser = {
},

parse(argv: string[]): IParsedArgv {
const program = new Command(path.basename(argv[1]))
const program = new Command('cucumber-js')

program
.storeOptionsAsProperties(false)
Expand Down

0 comments on commit 9e9ebd2

Please sign in to comment.