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

esm: use specific option for import vs require for support code #1931

Merged
merged 17 commits into from
Feb 26, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions compatibility/cck_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ describe('Cucumber Compatibility Kit', () => {
paths: [`${CCK_FEATURES_PATH}/${suiteName}/${suiteName}${extension}`],
},
support: {
transpileWith: ['ts-node/register'],
paths: [`${CCK_IMPLEMENTATIONS_PATH}/${suiteName}/${suiteName}.ts`],
requireModules: ['ts-node/register'],
requirePaths: [
`${CCK_IMPLEMENTATIONS_PATH}/${suiteName}/${suiteName}.ts`,
],
importPaths: [],
},
formats: {
stdout: 'message',
Expand Down
41 changes: 31 additions & 10 deletions features/esm.feature
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Feature: ES modules support

cucumber-js works with native ES modules

Scenario Outline: native module syntax works in support code, formatters and snippets
Scenario: native module syntax works in support code, formatters and snippets
Given a file named "features/a.feature" with:
"""
Feature:
Expand Down Expand Up @@ -39,18 +39,38 @@ Feature: ES modules support
'default': '--format summary'
}
"""
When I run cucumber-js with `<options> --format ./custom-formatter.js --format-options '{"snippetSyntax": "./custom-snippet-syntax.js"}' <args>`
Then it passes
Examples:
| args |
| |
| --parallel 2 |
When I run cucumber-js with `--import features/**/*.js --format ./custom-formatter.js --format-options '{"snippetSyntax": "./custom-snippet-syntax.js"}'`
Then it runs 2 scenarios
And it passes

Scenario: .mjs support code files are matched by default
Scenario: native modules work with parallel runtime
Given a file named "features/a.feature" with:
"""
Feature:
Scenario:
Scenario: one
Given a step passes

Scenario: two
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 `--import features/**/*.js' --parallel 2`
Then it runs 2 scenarios
And it passes

Scenario: .mjs support code files are discovered automatically if no requires or imports specified
Given a file named "features/a.feature" with:
"""
Feature:
Scenario: one
Given a step passes

Scenario: two
Given a step passes
"""
And a file named "features/step_definitions/cucumber_steps.mjs" with:
Expand All @@ -60,4 +80,5 @@ Feature: ES modules support
Given(/^a step passes$/, function() {});
"""
When I run cucumber-js
Then it passes
Then it runs 2 scenarios
And it passes
7 changes: 7 additions & 0 deletions src/cli/argv_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface IParsedArgvOptions {
formatOptions: IParsedArgvFormatOptions
i18nKeywords: string
i18nLanguages: boolean
import: string[]
language: string
name: string[]
order: PickleOrder
Expand Down Expand Up @@ -140,6 +141,12 @@ const ArgvParser = {
''
)
.option('--i18n-languages', 'list languages', false)
.option(
'--import <GLOB|DIR|FILE>',
'import files before executing features (repeatable)',
ArgvParser.collect,
[]
)
.option(
'--language <ISO 639-1>',
'provide the default language for feature files',
Expand Down
5 changes: 3 additions & 2 deletions src/cli/configuration_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ export async function buildConfiguration(
order: options.order,
},
support: {
transpileWith: options.requireModule,
paths: options.require,
requireModules: options.requireModule,
requirePaths: options.require,
importPaths: options.import,
},
runtime: {
dryRun: options.dryRun,
Expand Down
5 changes: 3 additions & 2 deletions src/cli/configuration_builder_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ describe('buildConfiguration', () => {
tagExpression: '',
},
support: {
paths: [],
transpileWith: [],
requireModules: [],
requirePaths: [],
importPaths: [],
},
})
})
Expand Down
5 changes: 3 additions & 2 deletions src/configuration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ export interface IRunConfiguration {
order?: PickleOrder
}
support: {
transpileWith: string[]
paths: string[]
requireModules: string[]
requirePaths: string[]
importPaths: string[]
}
runtime?: Partial<IRuntimeOptions> & { parallel?: number }
formats?: IFormatterConfiguration
Expand Down
46 changes: 37 additions & 9 deletions src/run/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export async function resolvePaths(
): Promise<{
unexpandedFeaturePaths: string[]
featurePaths: string[]
supportCodePaths: string[]
requirePaths: string[]
importPaths: string[]
}> {
const unexpandedFeaturePaths = await getUnexpandedFeaturePaths(
cwd,
Expand All @@ -20,19 +21,17 @@ export async function resolvePaths(
cwd,
unexpandedFeaturePaths
)
let unexpandedSupportCodePaths = configuration.support.paths ?? []
if (unexpandedSupportCodePaths.length === 0) {
unexpandedSupportCodePaths = getFeatureDirectoryPaths(cwd, featurePaths)
}
const supportCodePaths = await expandPaths(
const { requirePaths, importPaths } = await deriveSupportPaths(
cwd,
unexpandedSupportCodePaths,
'.@(js|mjs)'
featurePaths,
configuration.support.requirePaths,
configuration.support.importPaths
)
return {
unexpandedFeaturePaths,
featurePaths,
supportCodePaths,
requirePaths,
importPaths,
}
}

Expand Down Expand Up @@ -114,3 +113,32 @@ async function expandFeaturePaths(
featurePaths = [...new Set(featurePaths)] // Deduplicate the feature files
return await expandPaths(cwd, featurePaths, '.feature')
}

async function deriveSupportPaths(
cwd: string,
featurePaths: string[],
unexpandedRequirePaths: string[],
unexpandedImportPaths: string[]
): Promise<{
requirePaths: string[]
importPaths: string[]
}> {
if (
unexpandedRequirePaths.length === 0 &&
unexpandedImportPaths.length === 0
) {
const defaultPaths = getFeatureDirectoryPaths(cwd, featurePaths)
const requirePaths = await expandPaths(cwd, defaultPaths, '.js')
const importPaths = await expandPaths(cwd, defaultPaths, '.mjs')
davidjgoss marked this conversation as resolved.
Show resolved Hide resolved
return { requirePaths, importPaths }
}
const requirePaths =
unexpandedRequirePaths.length > 0
? await expandPaths(cwd, unexpandedRequirePaths, '.js')
: []
const importPaths =
unexpandedImportPaths.length > 0
? await expandPaths(cwd, unexpandedImportPaths, '.@(js|cjs|mjs)')
: []
return { requirePaths, importPaths }
}