@cucumber/cucumber 10.2.1 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -28,7 +28,7 @@ Looking to contribute? Read our [code of conduct](https://github.com/cucumber/.g
28
28
  Cucumber is [available on npm](https://www.npmjs.com/package/@cucumber/cucumber):
29
29
 
30
30
  ```shell
31
- $ npm install @cucumber/cucumber
31
+ npm install @cucumber/cucumber
32
32
  ```
33
33
 
34
34
  ## Get Started
@@ -79,7 +79,7 @@ Then('I should have heard {string}', function (expectedResponse) {
79
79
  Finally, run Cucumber:
80
80
 
81
81
  ```shell
82
- $ npx cucumber-js
82
+ npx cucumber-js
83
83
  ```
84
84
 
85
85
  And see the output:
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadConfiguration = void 0;
4
4
  const locate_file_1 = require("../configuration/locate_file");
5
5
  const configuration_1 = require("../configuration");
6
- const validate_configuration_1 = require("../configuration/validate_configuration");
7
6
  const convert_configuration_1 = require("./convert_configuration");
8
7
  const environment_1 = require("./environment");
9
8
  /**
@@ -28,9 +27,9 @@ async function loadConfiguration(options = {}, environment = {}) {
28
27
  const profileConfiguration = configFile
29
28
  ? await (0, configuration_1.fromFile)(logger, cwd, configFile, options.profiles)
30
29
  : {};
31
- const original = (0, configuration_1.mergeConfigurations)(configuration_1.DEFAULT_CONFIGURATION, profileConfiguration, options.provided);
30
+ const original = (0, configuration_1.mergeConfigurations)(configuration_1.DEFAULT_CONFIGURATION, profileConfiguration, (0, configuration_1.parseConfiguration)(logger, 'Provided', options.provided));
32
31
  logger.debug('Resolved configuration:', original);
33
- (0, validate_configuration_1.validateConfiguration)(original, logger);
32
+ (0, configuration_1.validateConfiguration)(original, logger);
34
33
  const runnable = await (0, convert_configuration_1.convertConfiguration)(logger, original, env);
35
34
  return {
36
35
  useConfiguration: original,
@@ -1 +1 @@
1
- {"version":3,"file":"load_configuration.js","sourceRoot":"","sources":["../../src/api/load_configuration.ts"],"names":[],"mappings":";;;AAAA,8DAAyD;AACzD,oDAIyB;AACzB,oFAA+E;AAC/E,mEAA8D;AAC9D,+CAAgD;AAOhD;;;;;;GAMG;AACI,KAAK,UAAU,iBAAiB,CACrC,UAAqC,EAAE,EACvC,cAA+B,EAAE;IAEjC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAA,8BAAgB,EAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,IAAI,IAAA,wBAAU,EAAC,GAAG,CAAC,CAAA;IAClD,IAAI,UAAU,EAAE;QACd,MAAM,CAAC,KAAK,CAAC,sCAAsC,UAAU,GAAG,CAAC,CAAA;KAClE;SAAM,IAAI,UAAU,KAAK,KAAK,EAAE;QAC/B,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAA;KACvD;SAAM;QACL,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;KAC5C;IACD,MAAM,oBAAoB,GAAG,UAAU;QACrC,CAAC,CAAC,MAAM,IAAA,wBAAQ,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC3D,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,QAAQ,GAAG,IAAA,mCAAmB,EAClC,qCAAqB,EACrB,oBAAoB,EACpB,OAAO,CAAC,QAAQ,CACjB,CAAA;IACD,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAA;IACjD,IAAA,8CAAqB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACvC,MAAM,QAAQ,GAAG,MAAM,IAAA,4CAAoB,EAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;IAClE,OAAO;QACL,gBAAgB,EAAE,QAAQ;QAC1B,gBAAgB,EAAE,QAAQ;KAC3B,CAAA;AACH,CAAC;AA5BD,8CA4BC","sourcesContent":["import { locateFile } from '../configuration/locate_file'\nimport {\n DEFAULT_CONFIGURATION,\n fromFile,\n mergeConfigurations,\n} from '../configuration'\nimport { validateConfiguration } from '../configuration/validate_configuration'\nimport { convertConfiguration } from './convert_configuration'\nimport { mergeEnvironment } from './environment'\nimport {\n IRunEnvironment,\n IResolvedConfiguration,\n ILoadConfigurationOptions,\n} from './types'\n\n/**\n * Load user-authored configuration to be used in a test run\n *\n * @public\n * @param options - Coordinates required to find configuration\n * @param environment - Project environment\n */\nexport async function loadConfiguration(\n options: ILoadConfigurationOptions = {},\n environment: IRunEnvironment = {}\n): Promise<IResolvedConfiguration> {\n const { cwd, env, logger } = mergeEnvironment(environment)\n const configFile = options.file ?? locateFile(cwd)\n if (configFile) {\n logger.debug(`Configuration will be loaded from \"${configFile}\"`)\n } else if (configFile === false) {\n logger.debug('Skipping configuration file resolution')\n } else {\n logger.debug('No configuration file found')\n }\n const profileConfiguration = configFile\n ? await fromFile(logger, cwd, configFile, options.profiles)\n : {}\n const original = mergeConfigurations(\n DEFAULT_CONFIGURATION,\n profileConfiguration,\n options.provided\n )\n logger.debug('Resolved configuration:', original)\n validateConfiguration(original, logger)\n const runnable = await convertConfiguration(logger, original, env)\n return {\n useConfiguration: original,\n runConfiguration: runnable,\n }\n}\n"]}
1
+ {"version":3,"file":"load_configuration.js","sourceRoot":"","sources":["../../src/api/load_configuration.ts"],"names":[],"mappings":";;;AAAA,8DAAyD;AACzD,oDAMyB;AACzB,mEAA8D;AAC9D,+CAAgD;AAOhD;;;;;;GAMG;AACI,KAAK,UAAU,iBAAiB,CACrC,UAAqC,EAAE,EACvC,cAA+B,EAAE;IAEjC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAA,8BAAgB,EAAC,WAAW,CAAC,CAAA;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,IAAI,IAAA,wBAAU,EAAC,GAAG,CAAC,CAAA;IAClD,IAAI,UAAU,EAAE;QACd,MAAM,CAAC,KAAK,CAAC,sCAAsC,UAAU,GAAG,CAAC,CAAA;KAClE;SAAM,IAAI,UAAU,KAAK,KAAK,EAAE;QAC/B,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAA;KACvD;SAAM;QACL,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;KAC5C;IACD,MAAM,oBAAoB,GAAG,UAAU;QACrC,CAAC,CAAC,MAAM,IAAA,wBAAQ,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC3D,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,QAAQ,GAAG,IAAA,mCAAmB,EAClC,qCAAqB,EACrB,oBAAoB,EACpB,IAAA,kCAAkB,EAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CACzD,CAAA;IACD,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAA;IACjD,IAAA,qCAAqB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IACvC,MAAM,QAAQ,GAAG,MAAM,IAAA,4CAAoB,EAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;IAClE,OAAO;QACL,gBAAgB,EAAE,QAAQ;QAC1B,gBAAgB,EAAE,QAAQ;KAC3B,CAAA;AACH,CAAC;AA5BD,8CA4BC","sourcesContent":["import { locateFile } from '../configuration/locate_file'\nimport {\n DEFAULT_CONFIGURATION,\n fromFile,\n mergeConfigurations,\n parseConfiguration,\n validateConfiguration,\n} from '../configuration'\nimport { convertConfiguration } from './convert_configuration'\nimport { mergeEnvironment } from './environment'\nimport {\n IRunEnvironment,\n IResolvedConfiguration,\n ILoadConfigurationOptions,\n} from './types'\n\n/**\n * Load user-authored configuration to be used in a test run\n *\n * @public\n * @param options - Coordinates required to find configuration\n * @param environment - Project environment\n */\nexport async function loadConfiguration(\n options: ILoadConfigurationOptions = {},\n environment: IRunEnvironment = {}\n): Promise<IResolvedConfiguration> {\n const { cwd, env, logger } = mergeEnvironment(environment)\n const configFile = options.file ?? locateFile(cwd)\n if (configFile) {\n logger.debug(`Configuration will be loaded from \"${configFile}\"`)\n } else if (configFile === false) {\n logger.debug('Skipping configuration file resolution')\n } else {\n logger.debug('No configuration file found')\n }\n const profileConfiguration = configFile\n ? await fromFile(logger, cwd, configFile, options.profiles)\n : {}\n const original = mergeConfigurations(\n DEFAULT_CONFIGURATION,\n profileConfiguration,\n parseConfiguration(logger, 'Provided', options.provided)\n )\n logger.debug('Resolved configuration:', original)\n validateConfiguration(original, logger)\n const runnable = await convertConfiguration(logger, original, env)\n return {\n useConfiguration: original,\n runConfiguration: runnable,\n }\n}\n"]}
@@ -24,8 +24,16 @@ export interface ILoadConfigurationOptions {
24
24
  /**
25
25
  * Ad-hoc configuration options to be merged over the top of whatever is
26
26
  * loaded from the configuration file/profiles
27
+ * @example
28
+ * \{
29
+ * failFast: true,
30
+ * parallel: 2
31
+ * \}
32
+ * @example "--fail-fast --parallel 2"
33
+ * @remarks
34
+ * This can also be provided as a string of argv-style arguments.
27
35
  */
28
- provided?: Partial<IConfiguration>;
36
+ provided?: Partial<IConfiguration> | string;
29
37
  }
30
38
  /**
31
39
  * Response from {@link loadConfiguration}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"","sourcesContent":["import { Writable } from 'node:stream'\nimport { JsonObject } from 'type-fest'\nimport { IPublishConfig } from '../publish'\nimport { IConfiguration } from '../configuration'\nimport { IPickleOrder } from '../filter'\n\n/**\n * Options for {@link loadConfiguration}\n * @public\n */\nexport interface ILoadConfigurationOptions {\n /**\n * Path to load configuration file from, or `false` to skip\n * @default `cucumber.(json|yaml|yml|js|cjs|mjs)`\n */\n file?: string | false\n /**\n * Zero or more profile names from which to source configuration in the file\n * @remarks\n * If omitted or empty, the `default` profile will be used.\n */\n profiles?: string[]\n /**\n * Ad-hoc configuration options to be merged over the top of whatever is\n * loaded from the configuration file/profiles\n */\n provided?: Partial<IConfiguration>\n}\n\n/**\n * Response from {@link loadConfiguration}\n * @public\n */\nexport interface IResolvedConfiguration {\n /**\n * The final flat configuration object resolved from the configuration\n * file/profiles plus any extra provided\n */\n useConfiguration: IConfiguration\n /**\n * The format that can be passed into {@link runCucumber}\n */\n runConfiguration: IRunConfiguration\n}\n\n/**\n * Options relating to sources (i.e. feature files) - where to load them from,\n * how to interpret, filter and order them\n * @public\n */\nexport interface ISourcesCoordinates {\n /**\n * Default Gherkin dialect\n * @remarks\n * Used if no dialect is specified in the feature file itself.\n */\n defaultDialect: string\n /**\n * Paths and/or glob expressions to feature files\n */\n paths: string[]\n /**\n * Regular expressions of which scenario names should match one of to be run\n */\n names: string[]\n /**\n * Tag expression to filter which scenarios should be run\n */\n tagExpression: string\n /**\n * Run in the order defined, or in a random order\n */\n order: IPickleOrder\n}\n\n/**\n * A pickle that has been successfully compiled from a source\n * @public\n */\nexport interface IPlannedPickle {\n /**\n * Name of the pickle (after parameter resolution)\n */\n name: string\n uri: string\n location: {\n line: number\n column?: number\n }\n}\n\n/**\n * An error encountered when parsing a source\n * @public\n */\nexport interface ISourcesError {\n uri: string\n location: {\n line: number\n column?: number\n }\n /**\n * Error message explaining what went wrong with the parse\n */\n message: string\n}\n\n/**\n * Response from {@link loadSources}\n * @public\n */\nexport interface ILoadSourcesResult {\n /**\n * Pickles that have been successfully compiled, in the order they would be\n * run in\n */\n plan: IPlannedPickle[]\n /**\n * Any errors encountered when parsing sources\n */\n errors: ISourcesError[]\n}\n\n/**\n * Options relating to user code (aka support code) - where to load it from and\n * how to preprocess it\n * @public\n */\nexport interface ISupportCodeCoordinates {\n /**\n * Names of transpilation modules to load, via `require()`\n */\n requireModules: string[]\n /**\n * Paths and/or glob expressions of user code to load, via `require()`\n */\n requirePaths: string[]\n /**\n * Paths and/or glob expressions of user code to load, via `import()`\n */\n importPaths: string[]\n}\n\n/**\n * Options for {@link loadSupport}\n * @public\n * @remarks\n * A subset of {@link IRunConfiguration}\n */\nexport interface ILoadSupportOptions {\n /**\n * @remarks\n * This is needed because the default support path locations are derived from\n * feature file locations.\n */\n sources: ISourcesCoordinates\n support: ISupportCodeCoordinates\n}\n\n/**\n * Options relating to behaviour when actually running tests\n * @public\n */\nexport interface IRunOptionsRuntime {\n /**\n * Perform a dry run, where a test run is prepared but nothing is executed\n */\n dryRun: boolean\n /**\n * Stop running tests when a test fails\n */\n failFast: boolean\n /**\n * Filter out stack frames from Cucumber's code when formatting stack traces\n */\n filterStacktraces: boolean\n /**\n * Run tests in parallel with the given number of worker processes\n */\n parallel: number\n /**\n * Retry failing tests up to the given number of times\n */\n retry: number\n /**\n * Tag expression to filter which scenarios can be retried\n */\n retryTagFilter: string\n /**\n * Fail the test run if there are pending steps\n */\n strict: boolean\n /**\n * Parameters to be passed to the World\n * @remarks\n * The value must be a JSON-serializable object.\n */\n worldParameters: JsonObject\n}\n\n/**\n * Options relating to formatters - which ones to use, where to write their\n * output, how they should behave\n * @public\n */\nexport interface IRunOptionsFormats {\n /**\n * Name/path of the formatter to use for `stdout` output\n */\n stdout: string\n /**\n * Zero or more mappings of file output path (key) to name/path of the\n * formatter to use (value)\n * @example\n * \\{\n * \"./reports/cucumber.html\": \"html\",\n * \"./reports/custom.txt\": \"./custom-formatter.js\"\n * \\}\n */\n files: Record<string, string>\n /**\n * Options for report publication, or `false` to disable publication\n */\n publish: IPublishConfig | false\n /**\n * Options to be provided to formatters\n * @remarks\n * The value must be a JSON-serializable object.\n */\n options: JsonObject\n}\n\n/**\n * Structured configuration object suitable for passing to {@link runCucumber}\n * @public\n */\nexport interface IRunConfiguration {\n sources: ISourcesCoordinates\n support: ISupportCodeCoordinates\n runtime: IRunOptionsRuntime\n formats: IRunOptionsFormats\n}\n\n/**\n * A collection of user-defined code and setup (\"support code\") that can be\n * used for a test run\n * @public\n * @remarks\n * This is mostly a marker interface. The actual instance is a complex object\n * that you shouldn't interact with directly, but some functions return and/or\n * accept it as a means of optimising a test workflow.\n */\nexport interface ISupportCodeLibrary {\n readonly originalCoordinates: ISupportCodeCoordinates\n}\n\n/**\n * Either an actual {@link ISupportCodeLibrary | support code library}, or the\n * {@link ISupportCodeCoordinates | coordinates} required to create and\n * populate one\n * @public\n * @remarks\n * This alias exists because {@link runCucumber} will accept an existing\n * support code library in its options and thus avoid trying to load it again,\n * improving performance and avoiding cache issues for use cases where multiple\n * test runs happen within the same process. Note this is only useful in serial\n * mode, as parallel workers will each load the support code themselves anyway.\n */\nexport type ISupportCodeCoordinatesOrLibrary =\n | ISupportCodeCoordinates\n | ISupportCodeLibrary\n\n/**\n * Options for {@link runCucumber}\n * @public\n */\nexport interface IRunOptions {\n sources: ISourcesCoordinates\n support: ISupportCodeCoordinatesOrLibrary\n runtime: IRunOptionsRuntime\n formats: IRunOptionsFormats\n}\n\n/**\n * Contextual data about the project environment\n * @public\n */\nexport interface IRunEnvironment {\n /**\n * Working directory for the project\n * @default process.cwd()\n */\n cwd?: string\n /**\n * Writable stream where the test run's main formatter output is written\n * @default process.stdout\n */\n stdout?: Writable\n /**\n * Writable stream where the test run's warning/error output is written\n * @default process.stderr\n */\n stderr?: Writable\n /**\n * Environment variables\n * @default process.env\n */\n env?: NodeJS.ProcessEnv\n /**\n * Whether debug logging should be emitted to {@link IRunEnvironment.stderr}\n * @default false\n * @see {@link https://github.com/cucumber/cucumber-js/blob/main/docs/debugging.md}\n */\n debug?: boolean\n}\n\n/**\n * Response from {@link runCucumber}\n * @public\n */\nexport interface IRunResult {\n /**\n * Whether the test run was overall successful\n * @remarks\n * The exact meaning can vary based on the `strict` configuration option.\n */\n success: boolean\n /**\n * The support code library that was used in the test run\n * @remarks\n * This can be reused in subsequent {@link runCucumber} calls,\n * see {@link ISupportCodeCoordinatesOrLibrary}\n */\n support: ISupportCodeLibrary\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"","sourcesContent":["import { Writable } from 'node:stream'\nimport { JsonObject } from 'type-fest'\nimport { IPublishConfig } from '../publish'\nimport { IConfiguration } from '../configuration'\nimport { IPickleOrder } from '../filter'\n\n/**\n * Options for {@link loadConfiguration}\n * @public\n */\nexport interface ILoadConfigurationOptions {\n /**\n * Path to load configuration file from, or `false` to skip\n * @default `cucumber.(json|yaml|yml|js|cjs|mjs)`\n */\n file?: string | false\n /**\n * Zero or more profile names from which to source configuration in the file\n * @remarks\n * If omitted or empty, the `default` profile will be used.\n */\n profiles?: string[]\n /**\n * Ad-hoc configuration options to be merged over the top of whatever is\n * loaded from the configuration file/profiles\n * @example\n * \\{\n * failFast: true,\n * parallel: 2\n * \\}\n * @example \"--fail-fast --parallel 2\"\n * @remarks\n * This can also be provided as a string of argv-style arguments.\n */\n provided?: Partial<IConfiguration> | string\n}\n\n/**\n * Response from {@link loadConfiguration}\n * @public\n */\nexport interface IResolvedConfiguration {\n /**\n * The final flat configuration object resolved from the configuration\n * file/profiles plus any extra provided\n */\n useConfiguration: IConfiguration\n /**\n * The format that can be passed into {@link runCucumber}\n */\n runConfiguration: IRunConfiguration\n}\n\n/**\n * Options relating to sources (i.e. feature files) - where to load them from,\n * how to interpret, filter and order them\n * @public\n */\nexport interface ISourcesCoordinates {\n /**\n * Default Gherkin dialect\n * @remarks\n * Used if no dialect is specified in the feature file itself.\n */\n defaultDialect: string\n /**\n * Paths and/or glob expressions to feature files\n */\n paths: string[]\n /**\n * Regular expressions of which scenario names should match one of to be run\n */\n names: string[]\n /**\n * Tag expression to filter which scenarios should be run\n */\n tagExpression: string\n /**\n * Run in the order defined, or in a random order\n */\n order: IPickleOrder\n}\n\n/**\n * A pickle that has been successfully compiled from a source\n * @public\n */\nexport interface IPlannedPickle {\n /**\n * Name of the pickle (after parameter resolution)\n */\n name: string\n uri: string\n location: {\n line: number\n column?: number\n }\n}\n\n/**\n * An error encountered when parsing a source\n * @public\n */\nexport interface ISourcesError {\n uri: string\n location: {\n line: number\n column?: number\n }\n /**\n * Error message explaining what went wrong with the parse\n */\n message: string\n}\n\n/**\n * Response from {@link loadSources}\n * @public\n */\nexport interface ILoadSourcesResult {\n /**\n * Pickles that have been successfully compiled, in the order they would be\n * run in\n */\n plan: IPlannedPickle[]\n /**\n * Any errors encountered when parsing sources\n */\n errors: ISourcesError[]\n}\n\n/**\n * Options relating to user code (aka support code) - where to load it from and\n * how to preprocess it\n * @public\n */\nexport interface ISupportCodeCoordinates {\n /**\n * Names of transpilation modules to load, via `require()`\n */\n requireModules: string[]\n /**\n * Paths and/or glob expressions of user code to load, via `require()`\n */\n requirePaths: string[]\n /**\n * Paths and/or glob expressions of user code to load, via `import()`\n */\n importPaths: string[]\n}\n\n/**\n * Options for {@link loadSupport}\n * @public\n * @remarks\n * A subset of {@link IRunConfiguration}\n */\nexport interface ILoadSupportOptions {\n /**\n * @remarks\n * This is needed because the default support path locations are derived from\n * feature file locations.\n */\n sources: ISourcesCoordinates\n support: ISupportCodeCoordinates\n}\n\n/**\n * Options relating to behaviour when actually running tests\n * @public\n */\nexport interface IRunOptionsRuntime {\n /**\n * Perform a dry run, where a test run is prepared but nothing is executed\n */\n dryRun: boolean\n /**\n * Stop running tests when a test fails\n */\n failFast: boolean\n /**\n * Filter out stack frames from Cucumber's code when formatting stack traces\n */\n filterStacktraces: boolean\n /**\n * Run tests in parallel with the given number of worker processes\n */\n parallel: number\n /**\n * Retry failing tests up to the given number of times\n */\n retry: number\n /**\n * Tag expression to filter which scenarios can be retried\n */\n retryTagFilter: string\n /**\n * Fail the test run if there are pending steps\n */\n strict: boolean\n /**\n * Parameters to be passed to the World\n * @remarks\n * The value must be a JSON-serializable object.\n */\n worldParameters: JsonObject\n}\n\n/**\n * Options relating to formatters - which ones to use, where to write their\n * output, how they should behave\n * @public\n */\nexport interface IRunOptionsFormats {\n /**\n * Name/path of the formatter to use for `stdout` output\n */\n stdout: string\n /**\n * Zero or more mappings of file output path (key) to name/path of the\n * formatter to use (value)\n * @example\n * \\{\n * \"./reports/cucumber.html\": \"html\",\n * \"./reports/custom.txt\": \"./custom-formatter.js\"\n * \\}\n */\n files: Record<string, string>\n /**\n * Options for report publication, or `false` to disable publication\n */\n publish: IPublishConfig | false\n /**\n * Options to be provided to formatters\n * @remarks\n * The value must be a JSON-serializable object.\n */\n options: JsonObject\n}\n\n/**\n * Structured configuration object suitable for passing to {@link runCucumber}\n * @public\n */\nexport interface IRunConfiguration {\n sources: ISourcesCoordinates\n support: ISupportCodeCoordinates\n runtime: IRunOptionsRuntime\n formats: IRunOptionsFormats\n}\n\n/**\n * A collection of user-defined code and setup (\"support code\") that can be\n * used for a test run\n * @public\n * @remarks\n * This is mostly a marker interface. The actual instance is a complex object\n * that you shouldn't interact with directly, but some functions return and/or\n * accept it as a means of optimising a test workflow.\n */\nexport interface ISupportCodeLibrary {\n readonly originalCoordinates: ISupportCodeCoordinates\n}\n\n/**\n * Either an actual {@link ISupportCodeLibrary | support code library}, or the\n * {@link ISupportCodeCoordinates | coordinates} required to create and\n * populate one\n * @public\n * @remarks\n * This alias exists because {@link runCucumber} will accept an existing\n * support code library in its options and thus avoid trying to load it again,\n * improving performance and avoiding cache issues for use cases where multiple\n * test runs happen within the same process. Note this is only useful in serial\n * mode, as parallel workers will each load the support code themselves anyway.\n */\nexport type ISupportCodeCoordinatesOrLibrary =\n | ISupportCodeCoordinates\n | ISupportCodeLibrary\n\n/**\n * Options for {@link runCucumber}\n * @public\n */\nexport interface IRunOptions {\n sources: ISourcesCoordinates\n support: ISupportCodeCoordinatesOrLibrary\n runtime: IRunOptionsRuntime\n formats: IRunOptionsFormats\n}\n\n/**\n * Contextual data about the project environment\n * @public\n */\nexport interface IRunEnvironment {\n /**\n * Working directory for the project\n * @default process.cwd()\n */\n cwd?: string\n /**\n * Writable stream where the test run's main formatter output is written\n * @default process.stdout\n */\n stdout?: Writable\n /**\n * Writable stream where the test run's warning/error output is written\n * @default process.stderr\n */\n stderr?: Writable\n /**\n * Environment variables\n * @default process.env\n */\n env?: NodeJS.ProcessEnv\n /**\n * Whether debug logging should be emitted to {@link IRunEnvironment.stderr}\n * @default false\n * @see {@link https://github.com/cucumber/cucumber-js/blob/main/docs/debugging.md}\n */\n debug?: boolean\n}\n\n/**\n * Response from {@link runCucumber}\n * @public\n */\nexport interface IRunResult {\n /**\n * Whether the test run was overall successful\n * @remarks\n * The exact meaning can vary based on the `strict` configuration option.\n */\n success: boolean\n /**\n * The support code library that was used in the test run\n * @remarks\n * This can be reused in subsequent {@link runCucumber} calls,\n * see {@link ISupportCodeCoordinatesOrLibrary}\n */\n support: ISupportCodeLibrary\n}\n"]}
@@ -8,12 +8,10 @@ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const node_util_1 = require("node:util");
10
10
  const node_url_1 = require("node:url");
11
- const string_argv_1 = __importDefault(require("string-argv"));
12
11
  const yaml_1 = __importDefault(require("yaml"));
13
12
  const read_pkg_up_1 = __importDefault(require("read-pkg-up"));
14
13
  const merge_configurations_1 = require("./merge_configurations");
15
- const argv_parser_1 = __importDefault(require("./argv_parser"));
16
- const check_schema_1 = require("./check_schema");
14
+ const parse_configuration_1 = require("./parse_configuration");
17
15
  async function fromFile(logger, cwd, file, profiles = []) {
18
16
  const definitions = await loadFile(logger, cwd, file);
19
17
  if (!definitions.default) {
@@ -30,7 +28,7 @@ async function fromFile(logger, cwd, file, profiles = []) {
30
28
  throw new Error(`Requested profile "${profileKey}" doesn't exist`);
31
29
  }
32
30
  });
33
- return (0, merge_configurations_1.mergeConfigurations)({}, ...profiles.map((profileKey) => extractConfiguration(logger, profileKey, definitions[profileKey])));
31
+ return (0, merge_configurations_1.mergeConfigurations)({}, ...profiles.map((profileKey) => (0, parse_configuration_1.parseConfiguration)(logger, `Profile "${profileKey}"`, definitions[profileKey])));
34
32
  }
35
33
  exports.fromFile = fromFile;
36
34
  async function loadFile(logger, cwd, file) {
@@ -85,21 +83,4 @@ async function readPackageJson(filePath) {
85
83
  const parentPackage = await (0, read_pkg_up_1.default)({ cwd: node_path_1.default.dirname(filePath) });
86
84
  return parentPackage?.packageJson;
87
85
  }
88
- function extractConfiguration(logger, name, definition) {
89
- if (typeof definition === 'string') {
90
- logger.debug(`Profile "${name}" value is a string; parsing as argv`);
91
- const { configuration } = argv_parser_1.default.parse([
92
- 'node',
93
- 'cucumber-js',
94
- ...(0, string_argv_1.default)(definition),
95
- ]);
96
- return configuration;
97
- }
98
- try {
99
- return (0, check_schema_1.checkSchema)(definition);
100
- }
101
- catch (error) {
102
- throw new Error(`Requested profile "${name}" failed schema validation: ${error.errors.join(' ')}`);
103
- }
104
- }
105
86
  //# sourceMappingURL=from_file.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"from_file.js","sourceRoot":"","sources":["../../src/configuration/from_file.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\nimport { pathToFileURL } from 'node:url'\nimport stringArgv from 'string-argv'\nimport YAML from 'yaml'\nimport readPkgUp from 'read-pkg-up'\nimport { ILogger } from '../logger'\nimport { IConfiguration } from './types'\nimport { mergeConfigurations } from './merge_configurations'\nimport ArgvParser from './argv_parser'\nimport { checkSchema } from './check_schema'\n\nexport async function fromFile(\n logger: ILogger,\n cwd: string,\n file: string,\n profiles: string[] = []\n): Promise<Partial<IConfiguration>> {\n const definitions = await loadFile(logger, cwd, file)\n if (!definitions.default) {\n logger.debug('No default profile defined in configuration file')\n definitions.default = {}\n }\n if (profiles.length < 1) {\n logger.debug('No profiles specified; using default profile')\n profiles = ['default']\n }\n const definedKeys = Object.keys(definitions)\n profiles.forEach((profileKey) => {\n if (!definedKeys.includes(profileKey)) {\n throw new Error(`Requested profile \"${profileKey}\" doesn't exist`)\n }\n })\n return mergeConfigurations(\n {},\n ...profiles.map((profileKey) =>\n extractConfiguration(logger, profileKey, definitions[profileKey])\n )\n )\n}\n\nasync function loadFile(\n logger: ILogger,\n cwd: string,\n file: string\n): Promise<Record<string, any>> {\n const filePath: string = path.join(cwd, file)\n const extension = path.extname(filePath)\n let definitions\n switch (extension) {\n case '.json':\n definitions = JSON.parse(\n await promisify(fs.readFile)(filePath, { encoding: 'utf-8' })\n )\n break\n case '.yaml':\n case '.yml':\n definitions = YAML.parse(\n await promisify(fs.readFile)(filePath, { encoding: 'utf-8' })\n )\n break\n case '.cjs':\n logger.debug(\n `Loading configuration file \"${file}\" as CommonJS based on extension`\n )\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n definitions = require(filePath)\n break\n case '.mjs':\n logger.debug(\n `Loading configuration file \"${file}\" as ESM based on extension`\n )\n definitions = await import(pathToFileURL(filePath).toString())\n break\n case '.js':\n {\n const parentPackage = await readPackageJson(filePath)\n if (!parentPackage) {\n logger.debug(\n `Loading configuration file \"${file}\" as CommonJS based on absence of a parent package`\n )\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n definitions = require(filePath)\n } else if (parentPackage.type === 'module') {\n logger.debug(\n `Loading configuration file \"${file}\" as ESM based on \"${parentPackage.name}\" package type`\n )\n definitions = await import(pathToFileURL(filePath).toString())\n } else {\n logger.debug(\n `Loading configuration file \"${file}\" as CommonJS based on \"${parentPackage.name}\" package type`\n )\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n definitions = require(filePath)\n }\n }\n break\n default:\n throw new Error(`Unsupported configuration file extension \"${extension}\"`)\n }\n if (typeof definitions !== 'object') {\n throw new Error(`Configuration file ${filePath} does not export an object`)\n }\n return definitions\n}\n\nasync function readPackageJson(filePath: string) {\n const parentPackage = await readPkgUp({ cwd: path.dirname(filePath) })\n return parentPackage?.packageJson\n}\n\nfunction extractConfiguration(\n logger: ILogger,\n name: string,\n definition: any\n): Partial<IConfiguration> {\n if (typeof definition === 'string') {\n logger.debug(`Profile \"${name}\" value is a string; parsing as argv`)\n const { configuration } = ArgvParser.parse([\n 'node',\n 'cucumber-js',\n ...stringArgv(definition),\n ])\n return configuration\n }\n try {\n return checkSchema(definition)\n } catch (error) {\n throw new Error(\n `Requested profile \"${name}\" failed schema validation: ${error.errors.join(\n ' '\n )}`\n )\n }\n}\n"]}
1
+ {"version":3,"file":"from_file.js","sourceRoot":"","sources":["../../src/configuration/from_file.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\nimport { pathToFileURL } from 'node:url'\nimport YAML from 'yaml'\nimport readPkgUp from 'read-pkg-up'\nimport { ILogger } from '../logger'\nimport { IConfiguration } from './types'\nimport { mergeConfigurations } from './merge_configurations'\nimport { parseConfiguration } from './parse_configuration'\n\nexport async function fromFile(\n logger: ILogger,\n cwd: string,\n file: string,\n profiles: string[] = []\n): Promise<Partial<IConfiguration>> {\n const definitions = await loadFile(logger, cwd, file)\n if (!definitions.default) {\n logger.debug('No default profile defined in configuration file')\n definitions.default = {}\n }\n if (profiles.length < 1) {\n logger.debug('No profiles specified; using default profile')\n profiles = ['default']\n }\n const definedKeys = Object.keys(definitions)\n profiles.forEach((profileKey) => {\n if (!definedKeys.includes(profileKey)) {\n throw new Error(`Requested profile \"${profileKey}\" doesn't exist`)\n }\n })\n return mergeConfigurations(\n {},\n ...profiles.map((profileKey) =>\n parseConfiguration(\n logger,\n `Profile \"${profileKey}\"`,\n definitions[profileKey]\n )\n )\n )\n}\n\nasync function loadFile(\n logger: ILogger,\n cwd: string,\n file: string\n): Promise<Record<string, any>> {\n const filePath: string = path.join(cwd, file)\n const extension = path.extname(filePath)\n let definitions\n switch (extension) {\n case '.json':\n definitions = JSON.parse(\n await promisify(fs.readFile)(filePath, { encoding: 'utf-8' })\n )\n break\n case '.yaml':\n case '.yml':\n definitions = YAML.parse(\n await promisify(fs.readFile)(filePath, { encoding: 'utf-8' })\n )\n break\n case '.cjs':\n logger.debug(\n `Loading configuration file \"${file}\" as CommonJS based on extension`\n )\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n definitions = require(filePath)\n break\n case '.mjs':\n logger.debug(\n `Loading configuration file \"${file}\" as ESM based on extension`\n )\n definitions = await import(pathToFileURL(filePath).toString())\n break\n case '.js':\n {\n const parentPackage = await readPackageJson(filePath)\n if (!parentPackage) {\n logger.debug(\n `Loading configuration file \"${file}\" as CommonJS based on absence of a parent package`\n )\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n definitions = require(filePath)\n } else if (parentPackage.type === 'module') {\n logger.debug(\n `Loading configuration file \"${file}\" as ESM based on \"${parentPackage.name}\" package type`\n )\n definitions = await import(pathToFileURL(filePath).toString())\n } else {\n logger.debug(\n `Loading configuration file \"${file}\" as CommonJS based on \"${parentPackage.name}\" package type`\n )\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n definitions = require(filePath)\n }\n }\n break\n default:\n throw new Error(`Unsupported configuration file extension \"${extension}\"`)\n }\n if (typeof definitions !== 'object') {\n throw new Error(`Configuration file ${filePath} does not export an object`)\n }\n return definitions\n}\n\nasync function readPackageJson(filePath: string) {\n const parentPackage = await readPkgUp({ cwd: path.dirname(filePath) })\n return parentPackage?.packageJson\n}\n"]}
@@ -3,5 +3,7 @@ export * from './default_configuration';
3
3
  export * from './from_file';
4
4
  export * from './helpers';
5
5
  export * from './merge_configurations';
6
+ export * from './parse_configuration';
6
7
  export * from './split_format_descriptor';
7
8
  export * from './types';
9
+ export * from './validate_configuration';
@@ -24,6 +24,8 @@ __exportStar(require("./default_configuration"), exports);
24
24
  __exportStar(require("./from_file"), exports);
25
25
  __exportStar(require("./helpers"), exports);
26
26
  __exportStar(require("./merge_configurations"), exports);
27
+ __exportStar(require("./parse_configuration"), exports);
27
28
  __exportStar(require("./split_format_descriptor"), exports);
28
29
  __exportStar(require("./types"), exports);
30
+ __exportStar(require("./validate_configuration"), exports);
29
31
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/configuration/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,6CAAqD;AAA5C,0HAAA,OAAO,OAAc;AAC9B,0DAAuC;AACvC,8CAA2B;AAC3B,4CAAyB;AACzB,yDAAsC;AACtC,4DAAyC;AACzC,0CAAuB","sourcesContent":["export { default as ArgvParser } from './argv_parser'\nexport * from './default_configuration'\nexport * from './from_file'\nexport * from './helpers'\nexport * from './merge_configurations'\nexport * from './split_format_descriptor'\nexport * from './types'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/configuration/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,6CAAqD;AAA5C,0HAAA,OAAO,OAAc;AAC9B,0DAAuC;AACvC,8CAA2B;AAC3B,4CAAyB;AACzB,yDAAsC;AACtC,wDAAqC;AACrC,4DAAyC;AACzC,0CAAuB;AACvB,2DAAwC","sourcesContent":["export { default as ArgvParser } from './argv_parser'\nexport * from './default_configuration'\nexport * from './from_file'\nexport * from './helpers'\nexport * from './merge_configurations'\nexport * from './parse_configuration'\nexport * from './split_format_descriptor'\nexport * from './types'\nexport * from './validate_configuration'\n"]}
@@ -0,0 +1,3 @@
1
+ import { ILogger } from '../logger';
2
+ import { IConfiguration } from './types';
3
+ export declare function parseConfiguration(logger: ILogger, source: string, definition: Partial<IConfiguration> | string | undefined): Partial<IConfiguration>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseConfiguration = void 0;
7
+ const string_argv_1 = __importDefault(require("string-argv"));
8
+ const argv_parser_1 = __importDefault(require("./argv_parser"));
9
+ const check_schema_1 = require("./check_schema");
10
+ function parseConfiguration(logger, source, definition) {
11
+ if (!definition) {
12
+ return {};
13
+ }
14
+ if (typeof definition === 'string') {
15
+ logger.debug(`${source} configuration value is a string; parsing as argv`);
16
+ const { configuration } = argv_parser_1.default.parse([
17
+ 'node',
18
+ 'cucumber-js',
19
+ ...(0, string_argv_1.default)(definition),
20
+ ]);
21
+ return configuration;
22
+ }
23
+ try {
24
+ return (0, check_schema_1.checkSchema)(definition);
25
+ }
26
+ catch (error) {
27
+ throw new Error(`${source} configuration value failed schema validation: ${error.errors.join(' ')}`);
28
+ }
29
+ }
30
+ exports.parseConfiguration = parseConfiguration;
31
+ //# sourceMappingURL=parse_configuration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse_configuration.js","sourceRoot":"","sources":["../../src/configuration/parse_configuration.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAoC;AAGpC,gEAAsC;AACtC,iDAA4C;AAE5C,SAAgB,kBAAkB,CAChC,MAAe,EACf,MAAc,EACd,UAAwD;IAExD,IAAI,CAAC,UAAU,EAAE;QACf,OAAO,EAAE,CAAA;KACV;IACD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;QAClC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,mDAAmD,CAAC,CAAA;QAC1E,MAAM,EAAE,aAAa,EAAE,GAAG,qBAAU,CAAC,KAAK,CAAC;YACzC,MAAM;YACN,aAAa;YACb,GAAG,IAAA,qBAAU,EAAC,UAAU,CAAC;SAC1B,CAAC,CAAA;QACF,OAAO,aAAa,CAAA;KACrB;IACD,IAAI;QACF,OAAO,IAAA,0BAAW,EAAC,UAAU,CAAC,CAAA;KAC/B;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,kDAAkD,KAAK,CAAC,MAAM,CAAC,IAAI,CAC1E,GAAG,CACJ,EAAE,CACJ,CAAA;KACF;AACH,CAAC;AA1BD,gDA0BC","sourcesContent":["import stringArgv from 'string-argv'\nimport { ILogger } from '../logger'\nimport { IConfiguration } from './types'\nimport ArgvParser from './argv_parser'\nimport { checkSchema } from './check_schema'\n\nexport function parseConfiguration(\n logger: ILogger,\n source: string,\n definition: Partial<IConfiguration> | string | undefined\n): Partial<IConfiguration> {\n if (!definition) {\n return {}\n }\n if (typeof definition === 'string') {\n logger.debug(`${source} configuration value is a string; parsing as argv`)\n const { configuration } = ArgvParser.parse([\n 'node',\n 'cucumber-js',\n ...stringArgv(definition),\n ])\n return configuration\n }\n try {\n return checkSchema(definition)\n } catch (error) {\n throw new Error(\n `${source} configuration value failed schema validation: ${error.errors.join(\n ' '\n )}`\n )\n }\n}\n"]}
@@ -8,20 +8,22 @@ const assertion_error_formatter_1 = require("assertion-error-formatter");
8
8
  const error_stack_parser_1 = __importDefault(require("error-stack-parser"));
9
9
  const filter_stack_trace_1 = require("../filter_stack_trace");
10
10
  function formatError(error, filterStackTraces) {
11
- let filteredStack;
12
- if (filterStackTraces) {
13
- try {
14
- filteredStack = (0, filter_stack_trace_1.filterStackTrace)(error_stack_parser_1.default.parse(error))
15
- .map((f) => f.source)
16
- .join('\n');
17
- }
18
- catch {
19
- // if we weren't able to parse and filter, we'll settle for the original
20
- }
11
+ let processedStackTrace;
12
+ try {
13
+ const parsedStack = error_stack_parser_1.default.parse(error);
14
+ const filteredStack = filterStackTraces
15
+ ? (0, filter_stack_trace_1.filterStackTrace)(parsedStack)
16
+ : parsedStack;
17
+ processedStackTrace = filteredStack.map((f) => f.source).join('\n');
18
+ }
19
+ catch {
20
+ // if we weren't able to parse and process, we'll settle for the original
21
21
  }
22
22
  const message = (0, assertion_error_formatter_1.format)(error, {
23
23
  colorFns: {
24
- errorStack: (stack) => filteredStack ? `\n${filteredStack}` : stack,
24
+ errorStack: (stack) => {
25
+ return processedStackTrace ? `\n${processedStackTrace}` : stack;
26
+ },
25
27
  },
26
28
  });
27
29
  return {
@@ -29,6 +31,7 @@ function formatError(error, filterStackTraces) {
29
31
  exception: {
30
32
  type: error.name || 'Error',
31
33
  message: typeof error === 'string' ? error : error.message,
34
+ stackTrace: processedStackTrace ?? error.stack,
32
35
  },
33
36
  };
34
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format_error.js","sourceRoot":"","sources":["../../src/runtime/format_error.ts"],"names":[],"mappings":";;;;;;AACA,yEAAkD;AAClD,4EAAiD;AACjD,8DAAwD;AAExD,SAAgB,WAAW,CACzB,KAAY,EACZ,iBAA0B;IAE1B,IAAI,aAAqB,CAAA;IACzB,IAAI,iBAAiB,EAAE;QACrB,IAAI;YACF,aAAa,GAAG,IAAA,qCAAgB,EAAC,4BAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;iBAC5D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;iBACpB,IAAI,CAAC,IAAI,CAAC,CAAA;SACd;QAAC,MAAM;YACN,wEAAwE;SACzE;KACF;IACD,MAAM,OAAO,GAAG,IAAA,kCAAM,EAAC,KAAK,EAAE;QAC5B,QAAQ,EAAE;YACR,UAAU,EAAE,CAAC,KAAa,EAAE,EAAE,CAC5B,aAAa,CAAC,CAAC,CAAC,KAAK,aAAa,EAAE,CAAC,CAAC,CAAC,KAAK;SAC/C;KACF,CAAC,CAAA;IACF,OAAO;QACL,OAAO;QACP,SAAS,EAAE;YACT,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;YAC3B,OAAO,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;SAC3D;KACF,CAAA;AACH,CAAC;AA3BD,kCA2BC","sourcesContent":["import { TestStepResult } from '@cucumber/messages'\nimport { format } from 'assertion-error-formatter'\nimport errorStackParser from 'error-stack-parser'\nimport { filterStackTrace } from '../filter_stack_trace'\n\nexport function formatError(\n error: Error,\n filterStackTraces: boolean\n): Pick<TestStepResult, 'message' | 'exception'> {\n let filteredStack: string\n if (filterStackTraces) {\n try {\n filteredStack = filterStackTrace(errorStackParser.parse(error))\n .map((f) => f.source)\n .join('\\n')\n } catch {\n // if we weren't able to parse and filter, we'll settle for the original\n }\n }\n const message = format(error, {\n colorFns: {\n errorStack: (stack: string) =>\n filteredStack ? `\\n${filteredStack}` : stack,\n },\n })\n return {\n message,\n exception: {\n type: error.name || 'Error',\n message: typeof error === 'string' ? error : error.message,\n },\n }\n}\n"]}
1
+ {"version":3,"file":"format_error.js","sourceRoot":"","sources":["../../src/runtime/format_error.ts"],"names":[],"mappings":";;;;;;AACA,yEAAkD;AAClD,4EAAiD;AACjD,8DAAwD;AAExD,SAAgB,WAAW,CACzB,KAAY,EACZ,iBAA0B;IAE1B,IAAI,mBAA2B,CAAA;IAC/B,IAAI;QACF,MAAM,WAAW,GAAG,4BAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,aAAa,GAAG,iBAAiB;YACrC,CAAC,CAAC,IAAA,qCAAgB,EAAC,WAAW,CAAC;YAC/B,CAAC,CAAC,WAAW,CAAA;QACf,mBAAmB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;KACpE;IAAC,MAAM;QACN,yEAAyE;KAC1E;IACD,MAAM,OAAO,GAAG,IAAA,kCAAM,EAAC,KAAK,EAAE;QAC5B,QAAQ,EAAE;YACR,UAAU,EAAE,CAAC,KAAa,EAAE,EAAE;gBAC5B,OAAO,mBAAmB,CAAC,CAAC,CAAC,KAAK,mBAAmB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;YACjE,CAAC;SACF;KACF,CAAC,CAAA;IACF,OAAO;QACL,OAAO;QACP,SAAS,EAAE;YACT,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;YAC3B,OAAO,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;YAC1D,UAAU,EAAE,mBAAmB,IAAI,KAAK,CAAC,KAAK;SAC/C;KACF,CAAA;AACH,CAAC;AA7BD,kCA6BC","sourcesContent":["import { TestStepResult } from '@cucumber/messages'\nimport { format } from 'assertion-error-formatter'\nimport errorStackParser from 'error-stack-parser'\nimport { filterStackTrace } from '../filter_stack_trace'\n\nexport function formatError(\n error: Error,\n filterStackTraces: boolean\n): Pick<TestStepResult, 'message' | 'exception'> {\n let processedStackTrace: string\n try {\n const parsedStack = errorStackParser.parse(error)\n const filteredStack = filterStackTraces\n ? filterStackTrace(parsedStack)\n : parsedStack\n processedStackTrace = filteredStack.map((f) => f.source).join('\\n')\n } catch {\n // if we weren't able to parse and process, we'll settle for the original\n }\n const message = format(error, {\n colorFns: {\n errorStack: (stack: string) => {\n return processedStackTrace ? `\\n${processedStackTrace}` : stack\n },\n },\n })\n return {\n message,\n exception: {\n type: error.name || 'Error',\n message: typeof error === 'string' ? error : error.message,\n stackTrace: processedStackTrace ?? error.stack,\n },\n }\n}\n"]}
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "10.2.1";
1
+ export declare const version = "10.3.0";
package/lib/version.js CHANGED
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
4
  // Generated by genversion.
5
- exports.version = '10.2.1';
5
+ exports.version = '10.3.0';
6
6
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AACd,QAAA,OAAO,GAAG,QAAQ,CAAA","sourcesContent":["// Generated by genversion.\nexport const version = '10.2.1'\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AACd,QAAA,OAAO,GAAG,QAAQ,CAAA","sourcesContent":["// Generated by genversion.\nexport const version = '10.3.0'\n"]}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "gherkin",
9
9
  "tests"
10
10
  ],
11
- "version": "10.2.1",
11
+ "version": "10.3.0",
12
12
  "homepage": "https://github.com/cucumber/cucumber-js",
13
13
  "author": "Julien Biezemans <jb@jbpros.com>",
14
14
  "contributors": [
@@ -216,7 +216,7 @@
216
216
  "@cucumber/html-formatter": "21.2.0",
217
217
  "@cucumber/message-streams": "4.0.1",
218
218
  "@cucumber/messages": "24.0.1",
219
- "@cucumber/tag-expressions": "6.0.0",
219
+ "@cucumber/tag-expressions": "6.1.0",
220
220
  "assertion-error-formatter": "^3.0.0",
221
221
  "capital-case": "^1.0.4",
222
222
  "chalk": "^4.1.2",
@@ -251,7 +251,7 @@
251
251
  "yup": "1.2.0"
252
252
  },
253
253
  "devDependencies": {
254
- "@cucumber/compatibility-kit": "14.1.0",
254
+ "@cucumber/compatibility-kit": "15.0.0",
255
255
  "@cucumber/query": "12.0.1",
256
256
  "@microsoft/api-extractor": "7.39.0",
257
257
  "@sinonjs/fake-timers": "10.0.2",