Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 2105 more detailed error #2264

Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
Please see [CONTRIBUTING.md](./CONTRIBUTING.md) on how to contribute to Cucumber.

## [Unreleased]

### Added
- Formatters create sub-directory automatically instead of failing ([#2266](https://github.com/cucumber/cucumber-js/pull/2266))
- Include a less cryptic error message when trying to `require` an ES module ([#2264](https://github.com/cucumber/cucumber-js/pull/2264))

### Changed
- Change hashes type from `any` to `Record<string, string>` in `DataTable` ([#2270](https://github.com/cucumber/cucumber-js/pull/2270))
Expand Down
20 changes: 20 additions & 0 deletions features/esm.feature
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,23 @@ Feature: ES modules support
When I run cucumber-js
Then it runs 2 scenarios
And it passes

Scenario: ES module invoked with --require
Given a file named "features/a.feature" with:
"""
Feature:
Scenario: one
Given a step passes
"""
And a file named "features/step_definitions/cucumber_steps.js" with:
"""
import {Given} from '@cucumber/cucumber'

Given(/^a step passes$/, function() {});
"""
When I run cucumber-js with `--require features/**/*.js`
Then it fails
And the error output contains the text:
"""
Error: Cucumber expected a CommonJS module
"""
8 changes: 6 additions & 2 deletions src/api/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IdGenerator } from '@cucumber/messages'
import { ISupportCodeLibrary } from '../support_code_library_builder/types'
import supportCodeLibraryBuilder from '../support_code_library_builder'
import { pathToFileURL } from 'url'
import tryRequire from '../try_require'

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { importer } = require('../importer')
Expand All @@ -24,10 +25,13 @@ export async function getSupportCodeLibrary({
requirePaths,
importPaths,
})
requireModules.map((module) => require(module))
requirePaths.map((path) => require(path))

requireModules.map((module) => tryRequire(module))
davidjgoss marked this conversation as resolved.
Show resolved Hide resolved
requirePaths.map((path) => tryRequire(path))

for (const path of importPaths) {
await importer(pathToFileURL(path))
}

return supportCodeLibraryBuilder.finalize()
}
5 changes: 3 additions & 2 deletions src/runtime/parallel/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
IWorkerCommandInitialize,
IWorkerCommandRun,
} from './command_types'
import tryRequire from '../../try_require'

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { importer } = require('../../importer')
Expand Down Expand Up @@ -74,8 +75,8 @@ export default class Worker {
requirePaths,
importPaths,
})
requireModules.map((module) => require(module))
requirePaths.map((module) => require(module))
requireModules.map((module) => tryRequire(module))
requirePaths.map((module) => tryRequire(module))
for (const path of importPaths) {
await importer(pathToFileURL(path))
}
Expand Down
22 changes: 22 additions & 0 deletions src/try_require.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Provides a try guarded require call that will throw a more detailed error when
* the ERR_REQUIRE_ESM error code is encountered.
*
* @param {string} path File path to require from.
*/
export default function tryRequire(path: string) {
try {
return require(path)
} catch (error) {
if (error.code === 'ERR_REQUIRE_ESM') {
throw Error(
`Cucumber expected a CommonJS module at '${path}' but found an ES module.
Either change the file to CommonJS syntax or use the --import directive instead of --require.

Original error message: ${error.message}`
)
} else {
throw error
}
}
}