@gnuechtel/nx-cucumber 2.0.0 → 2.1.0-14848049561

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gnuechtel/nx-cucumber",
3
- "version": "2.0.0",
3
+ "version": "2.1.0-14848049561",
4
4
  "description": "Plugin to use Cucumber within Nx workspaces",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -12,8 +12,8 @@
12
12
  "@nx/devkit": ">=22 <23",
13
13
  "minimatch": "^10.0.0",
14
14
  "tslib": "^2.3.0",
15
- "@gnuechtel/shared-coverage": "2.0.0",
16
- "@gnuechtel/shared-util": "2.0.0"
15
+ "@gnuechtel/shared-coverage": "2.1.0-14848049561",
16
+ "@gnuechtel/shared-util": "2.1.0-14848049561"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "@cucumber/cucumber": ">=9 <13",
@@ -7,16 +7,11 @@ const minimatch_1 = require("minimatch");
7
7
  const path_1 = require("path");
8
8
  const cucumberJsAdapter = {
9
9
  name: 'cucumber-js',
10
- configFilePattern: 'cucumber.js',
10
+ configFilePattern: 'cucumber.{js,cjs,mjs,ts,mts,cts,json,yaml,yml}',
11
11
  technologies: ['@cucumber/cucumber'],
12
12
  targets: {
13
13
  e2e: {
14
14
  command: 'npx cucumber-js',
15
- defaultOptions: {
16
- env: {
17
- TS_NODE_PROJECT: '',
18
- },
19
- },
20
15
  dependsOn: ['^build'],
21
16
  },
22
17
  },
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../../libs/nx-cucumber/src/adapters/registry.ts"],"names":[],"mappings":";;AAwBA,gDAEC;AAMD,4DAMC;AAOD,gDAKC;AAlDD,yCAAsC;AACtC,+BAAgC;AAGhC,MAAM,iBAAiB,GAAsB;IAC3C,IAAI,EAAE,aAAa;IACnB,iBAAiB,EAAE,aAAa;IAChC,YAAY,EAAE,CAAC,oBAAoB,CAAC;IACpC,OAAO,EAAE;QACP,GAAG,EAAE;YACH,OAAO,EAAE,iBAAiB;YAC1B,cAAc,EAAE;gBACd,GAAG,EAAE;oBACH,eAAe,EAAE,EAAE;iBACpB;aACF;YACD,SAAS,EAAE,CAAC,QAAQ,CAAC;SACtB;KACF;CACF,CAAC;AAEF;;GAEG;AACH,SAAgB,kBAAkB;IAChC,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,SAAgB,wBAAwB,CACtC,UAAkB,EAClB,QAA6B;IAE7B,MAAM,QAAQ,GAAG,IAAA,eAAQ,EAAC,UAAU,CAAC,CAAC;IACtC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,qBAAS,EAAC,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,QAA6B;IAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;IACxE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpE,OAAO,OAAO,QAAQ,GAAG,CAAC;AAC5B,CAAC","sourcesContent":["import { minimatch } from 'minimatch';\nimport { basename } from 'path';\nimport { AdapterDefinition } from './contract';\n\nconst cucumberJsAdapter: AdapterDefinition = {\n name: 'cucumber-js',\n configFilePattern: 'cucumber.js',\n technologies: ['@cucumber/cucumber'],\n targets: {\n e2e: {\n command: 'npx cucumber-js',\n defaultOptions: {\n env: {\n TS_NODE_PROJECT: '',\n },\n },\n dependsOn: ['^build'],\n },\n },\n};\n\n/**\n * Returns all built-in adapter definitions.\n */\nexport function getBuiltinAdapters(): AdapterDefinition[] {\n return [cucumberJsAdapter];\n}\n\n/**\n * Finds the adapter whose configFilePattern matches the given config file path.\n * Returns undefined if no adapter matches.\n */\nexport function findAdapterForConfigFile(\n configFile: string,\n adapters: AdapterDefinition[]\n): AdapterDefinition | undefined {\n const fileName = basename(configFile);\n return adapters.find((adapter) => minimatch(fileName, adapter.configFilePattern));\n}\n\n/**\n * Builds a combined glob pattern from all registered adapter config file patterns.\n * Used by createNodesV2 to discover adapter-managed projects in one pass.\n * Returns undefined if no adapters are registered.\n */\nexport function buildDiscoveryGlob(adapters: AdapterDefinition[]): string | undefined {\n if (adapters.length === 0) return undefined;\n if (adapters.length === 1) return `**/${adapters[0].configFilePattern}`;\n const patterns = adapters.map((a) => a.configFilePattern).join(',');\n return `**/{${patterns}}`;\n}\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../../libs/nx-cucumber/src/adapters/registry.ts"],"names":[],"mappings":";;AAmBA,gDAEC;AAMD,4DAMC;AAOD,gDAKC;AA7CD,yCAAsC;AACtC,+BAAgC;AAGhC,MAAM,iBAAiB,GAAsB;IAC3C,IAAI,EAAE,aAAa;IACnB,iBAAiB,EAAE,gDAAgD;IACnE,YAAY,EAAE,CAAC,oBAAoB,CAAC;IACpC,OAAO,EAAE;QACP,GAAG,EAAE;YACH,OAAO,EAAE,iBAAiB;YAC1B,SAAS,EAAE,CAAC,QAAQ,CAAC;SACtB;KACF;CACF,CAAC;AAEF;;GAEG;AACH,SAAgB,kBAAkB;IAChC,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,SAAgB,wBAAwB,CACtC,UAAkB,EAClB,QAA6B;IAE7B,MAAM,QAAQ,GAAG,IAAA,eAAQ,EAAC,UAAU,CAAC,CAAC;IACtC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,qBAAS,EAAC,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,QAA6B;IAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;IACxE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpE,OAAO,OAAO,QAAQ,GAAG,CAAC;AAC5B,CAAC","sourcesContent":["import { minimatch } from 'minimatch';\nimport { basename } from 'path';\nimport { AdapterDefinition } from './contract';\n\nconst cucumberJsAdapter: AdapterDefinition = {\n name: 'cucumber-js',\n configFilePattern: 'cucumber.{js,cjs,mjs,ts,mts,cts,json,yaml,yml}',\n technologies: ['@cucumber/cucumber'],\n targets: {\n e2e: {\n command: 'npx cucumber-js',\n dependsOn: ['^build'],\n },\n },\n};\n\n/**\n * Returns all built-in adapter definitions.\n */\nexport function getBuiltinAdapters(): AdapterDefinition[] {\n return [cucumberJsAdapter];\n}\n\n/**\n * Finds the adapter whose configFilePattern matches the given config file path.\n * Returns undefined if no adapter matches.\n */\nexport function findAdapterForConfigFile(\n configFile: string,\n adapters: AdapterDefinition[]\n): AdapterDefinition | undefined {\n const fileName = basename(configFile);\n return adapters.find((adapter) => minimatch(fileName, adapter.configFilePattern));\n}\n\n/**\n * Builds a combined glob pattern from all registered adapter config file patterns.\n * Used by createNodesV2 to discover adapter-managed projects in one pass.\n * Returns undefined if no adapters are registered.\n */\nexport function buildDiscoveryGlob(adapters: AdapterDefinition[]): string | undefined {\n if (adapters.length === 0) return undefined;\n if (adapters.length === 1) return `**/${adapters[0].configFilePattern}`;\n const patterns = adapters.map((a) => a.configFilePattern).join(',');\n return `**/{${patterns}}`;\n}\n"]}
@@ -0,0 +1,72 @@
1
+ <% if (isTypeScript) { %>import type { IConfiguration } from '@cucumber/cucumber';
2
+ import { pathToFileURL } from 'url';
3
+ <% } else { %>const { pathToFileURL } = require('url');
4
+ <% } %>const outputDir = 'dist/e2e/<%= projectRoot %>';
5
+ const runMetadataFormatter = pathToFileURL(
6
+ require.resolve('@gnuechtel/nx-cucumber/src/core/cucumber-run-metadata-formatter.js')
7
+ ).href;
8
+ const worldParameters = {
9
+ outputDirectory: outputDir,<% if (isPlaywright) { %>
10
+ baseUrl: '<%= baseUrl %>',
11
+ disableVideoFiles: true,
12
+ disableVideoAttachments: true,<% } %>
13
+ };
14
+ <% if (isTypeScript) { %>
15
+ const config: { [profile: string]: Partial<IConfiguration> } = {
16
+ default: {
17
+ paths: ['<%= projectRoot %>/features/**/*.feature'],
18
+ requireModule: ['ts-node/register', 'tsconfig-paths/register'],
19
+ require: [
20
+ '<%= projectRoot %>/src/**/!(*.d|*.spec|*.test).ts',<% if (playwrightRequires !== '[]') { %>
21
+ ...<%- playwrightRequires %>,<% } %>
22
+ ],
23
+ tags: 'not @ignore',
24
+ format: [
25
+ 'summary',
26
+ 'progress-bar',
27
+ `json:${outputDir}/reports/cucumber-json/cucumber-test-report.json`,
28
+ `message:${outputDir}/reports/cucumber-messages/cucumber-messages.ndjson`,
29
+ `html:${outputDir}/reports/html/cucumber-test-report-builtin.html`,
30
+ [runMetadataFormatter, `${outputDir}/reports/metadata/cucumber-run-metadata.json`],
31
+ `junit:${outputDir}/reports/test-results/cucumber-test-report.xml`,
32
+ ],
33
+ formatOptions: {
34
+ nxCucumberRunMetadata: {
35
+ worldParameters,
36
+ },
37
+ },
38
+ worldParameters,
39
+ publishQuiet: true,
40
+ },
41
+ };
42
+
43
+ export default config;
44
+ <% } else { %>
45
+ module.exports = {
46
+ default: {
47
+ paths: ['<%= projectRoot %>/features/**/*.feature'],
48
+ requireModule: ['ts-node/register', 'tsconfig-paths/register'],
49
+ require: [
50
+ '<%= projectRoot %>/src/**/!(*.d|*.spec|*.test).ts',<% if (playwrightRequires !== '[]') { %>
51
+ ...<%- playwrightRequires %>,<% } %>
52
+ ],
53
+ tags: 'not @ignore',
54
+ format: [
55
+ 'summary',
56
+ 'progress-bar',
57
+ `json:${outputDir}/reports/cucumber-json/cucumber-test-report.json`,
58
+ `message:${outputDir}/reports/cucumber-messages/cucumber-messages.ndjson`,
59
+ `html:${outputDir}/reports/html/cucumber-test-report-builtin.html`,
60
+ [runMetadataFormatter, `${outputDir}/reports/metadata/cucumber-run-metadata.json`],
61
+ `junit:${outputDir}/reports/test-results/cucumber-test-report.xml`,
62
+ ],
63
+ formatOptions: {
64
+ nxCucumberRunMetadata: {
65
+ worldParameters,
66
+ },
67
+ },
68
+ worldParameters,
69
+ publishQuiet: true,
70
+ },
71
+ };
72
+ <% } %>
@@ -1,6 +1,9 @@
1
- process.env.TS_NODE_PROJECT = '<%= projectRoot %>/tsconfig.json';
1
+ <% if (isTypeScript) { %>import type { IConfiguration } from '@cucumber/cucumber';
2
+ <% } %>import { pathToFileURL } from 'url';
3
+ import { createRequire } from 'module';
4
+
5
+ const require = createRequire(import.meta.url);
2
6
  const outputDir = 'dist/e2e/<%= projectRoot %>';
3
- const { pathToFileURL } = require('url');
4
7
  const runMetadataFormatter = pathToFileURL(
5
8
  require.resolve('@gnuechtel/nx-cucumber/src/core/cucumber-run-metadata-formatter.js')
6
9
  ).href;
@@ -10,8 +13,11 @@ const worldParameters = {
10
13
  disableVideoFiles: true,
11
14
  disableVideoAttachments: true,<% } %>
12
15
  };
13
- module.exports = {
14
- default: {
16
+ <% if (isTypeScript) { %>
17
+ const config: { [profile: string]: Partial<IConfiguration> } = {
18
+ <% } else { %>
19
+ const config = {
20
+ <% } %> default: {
15
21
  paths: ['<%= projectRoot %>/features/**/*.feature'],
16
22
  requireModule: ['ts-node/register', 'tsconfig-paths/register'],
17
23
  require: [
@@ -37,3 +43,5 @@ module.exports = {
37
43
  publishQuiet: true,
38
44
  },
39
45
  };
46
+
47
+ export default config;
@@ -0,0 +1,37 @@
1
+ {
2
+ "default": {
3
+ "paths": ["<%= projectRoot %>/features/**/*.feature"],
4
+ "requireModule": ["ts-node/register", "tsconfig-paths/register"],
5
+ "require": [
6
+ "<%= projectRoot %>/src/**/!(*.d|*.spec|*.test).ts"<% for (const req of playwrightRequiresArray) { %>,
7
+ "<%= req %>"<% } %>
8
+ ],
9
+ "tags": "not @ignore",
10
+ "format": [
11
+ "summary",
12
+ "progress-bar",
13
+ "json:dist/e2e/<%= projectRoot %>/reports/cucumber-json/cucumber-test-report.json",
14
+ "message:dist/e2e/<%= projectRoot %>/reports/cucumber-messages/cucumber-messages.ndjson",
15
+ "html:dist/e2e/<%= projectRoot %>/reports/html/cucumber-test-report-builtin.html",
16
+ ["@gnuechtel/nx-cucumber/src/core/cucumber-run-metadata-formatter.js", "dist/e2e/<%= projectRoot %>/reports/metadata/cucumber-run-metadata.json"],
17
+ "junit:dist/e2e/<%= projectRoot %>/reports/test-results/cucumber-test-report.xml"
18
+ ],
19
+ "formatOptions": {
20
+ "nxCucumberRunMetadata": {
21
+ "worldParameters": {
22
+ "outputDirectory": "dist/e2e/<%= projectRoot %>"<% if (isPlaywright) { %>,
23
+ "baseUrl": "<%= baseUrl %>",
24
+ "disableVideoFiles": true,
25
+ "disableVideoAttachments": true<% } %>
26
+ }
27
+ }
28
+ },
29
+ "worldParameters": {
30
+ "outputDirectory": "dist/e2e/<%= projectRoot %>"<% if (isPlaywright) { %>,
31
+ "baseUrl": "<%= baseUrl %>",
32
+ "disableVideoFiles": true,
33
+ "disableVideoAttachments": true<% } %>
34
+ },
35
+ "publishQuiet": true
36
+ }
37
+ }
@@ -0,0 +1,32 @@
1
+ default:
2
+ paths:
3
+ - <%= projectRoot %>/features/**/*.feature
4
+ requireModule:
5
+ - ts-node/register
6
+ - tsconfig-paths/register
7
+ require:
8
+ - <%= projectRoot %>/src/**/!(*.d|*.spec|*.test).ts<% for (const req of playwrightRequiresArray) { %>
9
+ - <%= req %><% } %>
10
+ tags: not @ignore
11
+ format:
12
+ - summary
13
+ - progress-bar
14
+ - json:dist/e2e/<%= projectRoot %>/reports/cucumber-json/cucumber-test-report.json
15
+ - message:dist/e2e/<%= projectRoot %>/reports/cucumber-messages/cucumber-messages.ndjson
16
+ - html:dist/e2e/<%= projectRoot %>/reports/html/cucumber-test-report-builtin.html
17
+ - - "@gnuechtel/nx-cucumber/src/core/cucumber-run-metadata-formatter.js"
18
+ - dist/e2e/<%= projectRoot %>/reports/metadata/cucumber-run-metadata.json
19
+ - junit:dist/e2e/<%= projectRoot %>/reports/test-results/cucumber-test-report.xml
20
+ formatOptions:
21
+ nxCucumberRunMetadata:
22
+ worldParameters:
23
+ outputDirectory: dist/e2e/<%= projectRoot %><% if (isPlaywright) { %>
24
+ baseUrl: "<%= baseUrl %>"
25
+ disableVideoFiles: true
26
+ disableVideoAttachments: true<% } %>
27
+ worldParameters:
28
+ outputDirectory: dist/e2e/<%= projectRoot %><% if (isPlaywright) { %>
29
+ baseUrl: "<%= baseUrl %>"
30
+ disableVideoFiles: true
31
+ disableVideoAttachments: true<% } %>
32
+ publishQuiet: true
@@ -64,12 +64,12 @@ async function run() {
64
64
  await sleep(500);
65
65
  }
66
66
 
67
- // Run cucumber. TS_NODE_PROJECT is cleared to prevent ts-node config
68
- // leakage from any parent Nx process that set it for a different project.
67
+ // Run cucumber. TS_NODE_PROJECT is set to the project's own tsconfig so that
68
+ // ts-node compiles step definitions with the correct settings.
69
69
  const { status } = cp.spawnSync(TEST_CMD, {
70
70
  shell: true,
71
71
  stdio: 'inherit',
72
- env: { ...process.env, TS_NODE_PROJECT: '' },
72
+ env: { ...process.env, TS_NODE_PROJECT: '<%= projectRoot %>/tsconfig.json' },
73
73
  });
74
74
 
75
75
  teardown();
@@ -9,6 +9,9 @@ const test_run_options_1 = require("../../core/test-run-options");
9
9
  async function cucumberJsGenerator(tree, options) {
10
10
  if (!options.testRunner)
11
11
  options.testRunner = test_run_options_1.defaultTestRunner;
12
+ if (!options.configFormat)
13
+ options.configFormat = 'js';
14
+ assertConfigFormatSupported(tree, options.configFormat);
12
15
  ensureProjectExists(tree, options.project);
13
16
  options.name = normalizeGeneratedProjectName(options.project, options.name);
14
17
  if (!options.directory)
@@ -45,8 +48,13 @@ async function cucumberJsGenerator(tree, options) {
45
48
  'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-hooks.js',
46
49
  ]
47
50
  : [];
51
+ const configFormat = options.configFormat;
52
+ const configFileName = `cucumber.${configFormat}`;
53
+ const configShapeDir = resolveConfigShapeDir(configFormat);
54
+ const isTypeScript = ['ts', 'mts', 'cts'].includes(configFormat);
55
+ const isEsmModule = ['mjs', 'mts'].includes(configFormat);
48
56
  const serveCommand = isPlaywright && baseUrl && serveTarget ? buildServeCommand(tree, options.project, serveTarget, baseUrl) : '';
49
- const testCommand = `npx cucumber-js --config ${projectRoot}/cucumber.js`;
57
+ const testCommand = `npx cucumber-js --config ${projectRoot}/${configFileName}`;
50
58
  const templateProjectName = parseScopedProjectName(options.project).name;
51
59
  const substitutions = {
52
60
  ...options,
@@ -55,7 +63,10 @@ async function cucumberJsGenerator(tree, options) {
55
63
  workspaceRootRelative,
56
64
  projectRoot,
57
65
  playwrightRequires: JSON.stringify(playwrightRequires),
66
+ playwrightRequiresArray: playwrightRequires,
58
67
  isPlaywright,
68
+ isTypeScript,
69
+ isEsmModule,
59
70
  baseUrl: baseUrl || '',
60
71
  serveTarget: serveTarget || '',
61
72
  port: baseUrl ? readPortFromUrl(baseUrl) : 0,
@@ -63,6 +74,7 @@ async function cucumberJsGenerator(tree, options) {
63
74
  testCommandJson: JSON.stringify(testCommand),
64
75
  };
65
76
  (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files', 'all'), projectRoot, substitutions);
77
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files', 'config', configShapeDir), projectRoot, substitutions);
66
78
  (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files', options.testRunner), projectRoot, substitutions);
67
79
  const customWorldFiles = path.join(__dirname, 'files', `${options.testRunner}.custom-world`);
68
80
  if (options.customWorld && (0, fs_1.existsSync)(customWorldFiles)) {
@@ -147,6 +159,58 @@ function parseScopedProjectName(value) {
147
159
  name: raw.slice(separatorIndex + 1),
148
160
  };
149
161
  }
162
+ const TYPESCRIPT_CONFIG_FORMATS = ['ts', 'mts', 'cts'];
163
+ const MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG = '12.4.0';
164
+ // cucumber-js only loads TypeScript config files (.ts/.mts/.cts) from 12.4.0 onwards
165
+ // (versions 10.0-12.3 reject them with "Unsupported configuration file extension").
166
+ // Fail fast with an actionable error instead of letting the user hit that at run time.
167
+ function assertConfigFormatSupported(tree, configFormat) {
168
+ if (!TYPESCRIPT_CONFIG_FORMATS.includes(configFormat))
169
+ return;
170
+ const cucumberVersion = readInstalledCucumberVersion(tree);
171
+ if (cucumberVersion && isBelowVersion(cucumberVersion, MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG)) {
172
+ throw new Error(`Cucumber configuration format "${configFormat}" requires @cucumber/cucumber >=${MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG}, ` +
173
+ `but found ${cucumberVersion}. Choose a different --config-format (js, cjs, mjs, json, yaml) ` +
174
+ `or upgrade @cucumber/cucumber.`);
175
+ }
176
+ }
177
+ function readInstalledCucumberVersion(tree) {
178
+ const packageJsonPath = 'node_modules/@cucumber/cucumber/package.json';
179
+ if (!tree.exists(packageJsonPath))
180
+ return undefined;
181
+ try {
182
+ const content = tree.read(packageJsonPath, 'utf-8');
183
+ const version = content ? JSON.parse(content).version : undefined;
184
+ return typeof version === 'string' ? version : undefined;
185
+ }
186
+ catch {
187
+ return undefined;
188
+ }
189
+ }
190
+ function isBelowVersion(version, minimum) {
191
+ const toParts = (value) => value
192
+ .split('-')[0]
193
+ .split('.')
194
+ .map((part) => parseInt(part, 10) || 0);
195
+ const [vMajor, vMinor, vPatch] = toParts(version);
196
+ const [mMajor, mMinor, mPatch] = toParts(minimum);
197
+ if (vMajor !== mMajor)
198
+ return vMajor < mMajor;
199
+ if (vMinor !== mMinor)
200
+ return vMinor < mMinor;
201
+ return vPatch < mPatch;
202
+ }
203
+ function resolveConfigShapeDir(configFormat) {
204
+ if (configFormat === 'json')
205
+ return 'json';
206
+ if (configFormat === 'yaml' || configFormat === 'yml')
207
+ return 'yaml';
208
+ // cucumber-js loads .mjs/.mts/.ts via dynamic import (ESM), so they need the
209
+ // import.meta-based shape; .cjs/.cts/.js are require-loaded and stay CommonJS.
210
+ if (configFormat === 'mjs' || configFormat === 'mts' || configFormat === 'ts')
211
+ return 'esm';
212
+ return 'cjs';
213
+ }
150
214
  function registerPlugin(tree) {
151
215
  if (!tree.exists('nx.json'))
152
216
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../../../../libs/nx-cucumber/src/generators/project/project.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n Tree,\n addDependenciesToPackageJson,\n normalizePath,\n offsetFromRoot,\n getWorkspaceLayout,\n readProjectConfiguration,\n updateJson,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport { CucumberJsGeneratorSchema } from './schema';\nimport { existsSync } from 'fs';\nimport { defaultTestRunner } from '../../core/test-run-options';\n\nexport async function cucumberJsGenerator(tree: Tree, options: CucumberJsGeneratorSchema) {\n if (!options.testRunner) options.testRunner = defaultTestRunner;\n ensureProjectExists(tree, options.project);\n options.name = normalizeGeneratedProjectName(options.project, options.name);\n if (!options.directory) options.directory = defaultProjectDirectory(options.name);\n const isPlaywright = options.testRunner === 'playwright';\n const baseUrl = isPlaywright ? 'http://localhost:4200' : undefined;\n const serveTarget = isPlaywright ? `${options.project}:serve` : undefined;\n\n const normalizedDirectory = normalizePath(options.directory);\n const workspaceLayout = getWorkspaceLayout(tree);\n const skipAppsDir = workspaceLayout.appsDir === '.' || options.ignoreWorkspaceLayout;\n const parentDir = workspaceLayout.appsDir && !skipAppsDir ? workspaceLayout.appsDir + '/' : '';\n const projectRoot = `${parentDir}${normalizedDirectory}`;\n const workspaceRootRelative = offsetFromRoot(projectRoot).replace(/\\/$/, '');\n const playwrightTargets =\n isPlaywright && baseUrl && serveTarget ? buildPlaywrightTargets(options.name, projectRoot) : {};\n\n addProjectConfiguration(tree, options.name, {\n root: projectRoot,\n sourceRoot: `${projectRoot}/src`,\n projectType: 'application',\n targets: {\n lint: {\n executor: '@nx/eslint:lint',\n outputs: ['{options.outputFile}'],\n options: {\n lintFilePatterns: [`${projectRoot}/**/*.ts`],\n },\n },\n ...playwrightTargets,\n },\n implicitDependencies: [options.project],\n });\n\n const playwrightRequires =\n options.testRunner === 'playwright'\n ? [\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-world-default.js',\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-hooks.js',\n ]\n : [];\n\n const serveCommand =\n isPlaywright && baseUrl && serveTarget ? buildServeCommand(tree, options.project, serveTarget, baseUrl) : '';\n const testCommand = `npx cucumber-js --config ${projectRoot}/cucumber.js`;\n const templateProjectName = parseScopedProjectName(options.project).name;\n\n const substitutions = {\n ...options,\n project: templateProjectName,\n testedProject: options.project,\n workspaceRootRelative,\n projectRoot,\n playwrightRequires: JSON.stringify(playwrightRequires),\n isPlaywright,\n baseUrl: baseUrl || '',\n serveTarget: serveTarget || '',\n port: baseUrl ? readPortFromUrl(baseUrl) : 0,\n serveCommandJson: JSON.stringify(serveCommand),\n testCommandJson: JSON.stringify(testCommand),\n };\n\n generateFiles(tree, path.join(__dirname, 'files', 'all'), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', options.testRunner), projectRoot, substitutions);\n\n const customWorldFiles = path.join(__dirname, 'files', `${options.testRunner}.custom-world`);\n if (options.customWorld && existsSync(customWorldFiles)) {\n generateFiles(tree, customWorldFiles, projectRoot, substitutions);\n }\n\n registerPlugin(tree);\n\n await formatFiles(tree);\n\n const additionalDevDependencies: Record<string, string> = {\n 'ts-node': '10.9.1',\n 'tsconfig-paths': '4.2.0',\n };\n\n const installTask = addDependenciesToPackageJson(tree, {}, additionalDevDependencies);\n return options.skipInstall ? () => undefined : installTask;\n}\n\nfunction buildPlaywrightTargets(e2eProjectName: string, projectRoot: string) {\n return {\n 'e2e-prepare': {\n cache: false,\n command: buildPlaywrightPrepareCommand(),\n },\n e2e: {\n command: `node ${projectRoot}/run-e2e.js`,\n },\n 'e2e-ci': {\n command: `npx nx run ${e2eProjectName}:e2e-prepare && npx nx run ${e2eProjectName}:e2e`,\n },\n };\n}\n\nfunction buildPlaywrightPrepareCommand() {\n return `node -e \"const { execSync } = require('node:child_process'); const installCommand = process.platform === 'linux' ? 'npx playwright install --with-deps chromium' : 'npx playwright install chromium'; execSync(installCommand, { stdio: 'inherit' });\"`;\n}\n\nfunction buildServeCommand(tree: Tree, projectName: string, serveTarget: string, baseUrl: string) {\n const port = readPortFromUrl(baseUrl);\n const executor = readServeExecutor(tree, projectName);\n return executor === '@nx/vite:dev-server'\n ? `npx nx run ${serveTarget} --port=${port} --strictPort`\n : `npx nx run ${serveTarget}`;\n}\n\nfunction readServeExecutor(tree: Tree, projectName: string) {\n return readProjectConfiguration(tree, projectName).targets?.['serve']?.executor;\n}\n\nfunction readPortFromUrl(url: string) {\n const parsedUrl = new URL(url);\n if (parsedUrl.port) return parsedUrl.port;\n return parsedUrl.protocol === 'https:' ? '443' : '80';\n}\n\nfunction ensureProjectExists(tree: Tree, projectName: string) {\n try {\n readProjectConfiguration(tree, projectName);\n } catch {\n throw new Error(`Project \"${projectName}\" does not exist in this workspace.`);\n }\n}\n\nfunction normalizeGeneratedProjectName(projectName: string, requestedName?: string) {\n const sourceProject = parseScopedProjectName(projectName);\n const requestedProject = parseScopedProjectName(requestedName?.trim() || '');\n if (requestedProject.raw.length < 1) {\n const inferredName = `${sourceProject.name}-e2e`;\n return sourceProject.scope ? `${sourceProject.scope}/${inferredName}` : inferredName;\n }\n if (requestedProject.scope) return requestedProject.raw;\n return sourceProject.scope ? `${sourceProject.scope}/${requestedProject.name}` : requestedProject.name;\n}\n\nfunction defaultProjectDirectory(projectName: string) {\n return parseScopedProjectName(projectName).name;\n}\n\nfunction parseScopedProjectName(value: string) {\n const raw = value.trim();\n if (!raw.startsWith('@')) {\n return { raw, scope: '', name: raw };\n }\n const separatorIndex = raw.indexOf('/');\n if (separatorIndex < 1 || separatorIndex >= raw.length - 1) {\n return { raw, scope: '', name: raw };\n }\n return {\n raw,\n scope: raw.slice(0, separatorIndex),\n name: raw.slice(separatorIndex + 1),\n };\n}\n\nfunction registerPlugin(tree: Tree) {\n if (!tree.exists('nx.json')) return;\n updateJson(tree, 'nx.json', (json) => {\n if (!Array.isArray(json.plugins)) json.plugins = [];\n if (!json.plugins.includes('@gnuechtel/nx-cucumber')) {\n json.plugins.push('@gnuechtel/nx-cucumber');\n }\n return json;\n });\n}\n\nexport default cucumberJsGenerator;\n"]}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../../../../libs/nx-cucumber/src/generators/project/project.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n Tree,\n addDependenciesToPackageJson,\n normalizePath,\n offsetFromRoot,\n getWorkspaceLayout,\n readProjectConfiguration,\n updateJson,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport { ConfigFormat, CucumberJsGeneratorSchema } from './schema';\nimport { existsSync } from 'fs';\nimport { defaultTestRunner } from '../../core/test-run-options';\n\nexport async function cucumberJsGenerator(tree: Tree, options: CucumberJsGeneratorSchema) {\n if (!options.testRunner) options.testRunner = defaultTestRunner;\n if (!options.configFormat) options.configFormat = 'js';\n assertConfigFormatSupported(tree, options.configFormat);\n ensureProjectExists(tree, options.project);\n options.name = normalizeGeneratedProjectName(options.project, options.name);\n if (!options.directory) options.directory = defaultProjectDirectory(options.name);\n const isPlaywright = options.testRunner === 'playwright';\n const baseUrl = isPlaywright ? 'http://localhost:4200' : undefined;\n const serveTarget = isPlaywright ? `${options.project}:serve` : undefined;\n\n const normalizedDirectory = normalizePath(options.directory);\n const workspaceLayout = getWorkspaceLayout(tree);\n const skipAppsDir = workspaceLayout.appsDir === '.' || options.ignoreWorkspaceLayout;\n const parentDir = workspaceLayout.appsDir && !skipAppsDir ? workspaceLayout.appsDir + '/' : '';\n const projectRoot = `${parentDir}${normalizedDirectory}`;\n const workspaceRootRelative = offsetFromRoot(projectRoot).replace(/\\/$/, '');\n const playwrightTargets =\n isPlaywright && baseUrl && serveTarget ? buildPlaywrightTargets(options.name, projectRoot) : {};\n\n addProjectConfiguration(tree, options.name, {\n root: projectRoot,\n sourceRoot: `${projectRoot}/src`,\n projectType: 'application',\n targets: {\n lint: {\n executor: '@nx/eslint:lint',\n outputs: ['{options.outputFile}'],\n options: {\n lintFilePatterns: [`${projectRoot}/**/*.ts`],\n },\n },\n ...playwrightTargets,\n },\n implicitDependencies: [options.project],\n });\n\n const playwrightRequires =\n options.testRunner === 'playwright'\n ? [\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-world-default.js',\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-hooks.js',\n ]\n : [];\n\n const configFormat = options.configFormat!;\n const configFileName = `cucumber.${configFormat}`;\n const configShapeDir = resolveConfigShapeDir(configFormat);\n const isTypeScript = ['ts', 'mts', 'cts'].includes(configFormat);\n const isEsmModule = ['mjs', 'mts'].includes(configFormat);\n\n const serveCommand =\n isPlaywright && baseUrl && serveTarget ? buildServeCommand(tree, options.project, serveTarget, baseUrl) : '';\n const testCommand = `npx cucumber-js --config ${projectRoot}/${configFileName}`;\n const templateProjectName = parseScopedProjectName(options.project).name;\n\n const substitutions = {\n ...options,\n project: templateProjectName,\n testedProject: options.project,\n workspaceRootRelative,\n projectRoot,\n playwrightRequires: JSON.stringify(playwrightRequires),\n playwrightRequiresArray: playwrightRequires,\n isPlaywright,\n isTypeScript,\n isEsmModule,\n baseUrl: baseUrl || '',\n serveTarget: serveTarget || '',\n port: baseUrl ? readPortFromUrl(baseUrl) : 0,\n serveCommandJson: JSON.stringify(serveCommand),\n testCommandJson: JSON.stringify(testCommand),\n };\n\n generateFiles(tree, path.join(__dirname, 'files', 'all'), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', 'config', configShapeDir), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', options.testRunner), projectRoot, substitutions);\n\n const customWorldFiles = path.join(__dirname, 'files', `${options.testRunner}.custom-world`);\n if (options.customWorld && existsSync(customWorldFiles)) {\n generateFiles(tree, customWorldFiles, projectRoot, substitutions);\n }\n\n registerPlugin(tree);\n\n await formatFiles(tree);\n\n const additionalDevDependencies: Record<string, string> = {\n 'ts-node': '10.9.1',\n 'tsconfig-paths': '4.2.0',\n };\n\n const installTask = addDependenciesToPackageJson(tree, {}, additionalDevDependencies);\n return options.skipInstall ? () => undefined : installTask;\n}\n\nfunction buildPlaywrightTargets(e2eProjectName: string, projectRoot: string) {\n return {\n 'e2e-prepare': {\n cache: false,\n command: buildPlaywrightPrepareCommand(),\n },\n e2e: {\n command: `node ${projectRoot}/run-e2e.js`,\n },\n 'e2e-ci': {\n command: `npx nx run ${e2eProjectName}:e2e-prepare && npx nx run ${e2eProjectName}:e2e`,\n },\n };\n}\n\nfunction buildPlaywrightPrepareCommand() {\n return `node -e \"const { execSync } = require('node:child_process'); const installCommand = process.platform === 'linux' ? 'npx playwright install --with-deps chromium' : 'npx playwright install chromium'; execSync(installCommand, { stdio: 'inherit' });\"`;\n}\n\nfunction buildServeCommand(tree: Tree, projectName: string, serveTarget: string, baseUrl: string) {\n const port = readPortFromUrl(baseUrl);\n const executor = readServeExecutor(tree, projectName);\n return executor === '@nx/vite:dev-server'\n ? `npx nx run ${serveTarget} --port=${port} --strictPort`\n : `npx nx run ${serveTarget}`;\n}\n\nfunction readServeExecutor(tree: Tree, projectName: string) {\n return readProjectConfiguration(tree, projectName).targets?.['serve']?.executor;\n}\n\nfunction readPortFromUrl(url: string) {\n const parsedUrl = new URL(url);\n if (parsedUrl.port) return parsedUrl.port;\n return parsedUrl.protocol === 'https:' ? '443' : '80';\n}\n\nfunction ensureProjectExists(tree: Tree, projectName: string) {\n try {\n readProjectConfiguration(tree, projectName);\n } catch {\n throw new Error(`Project \"${projectName}\" does not exist in this workspace.`);\n }\n}\n\nfunction normalizeGeneratedProjectName(projectName: string, requestedName?: string) {\n const sourceProject = parseScopedProjectName(projectName);\n const requestedProject = parseScopedProjectName(requestedName?.trim() || '');\n if (requestedProject.raw.length < 1) {\n const inferredName = `${sourceProject.name}-e2e`;\n return sourceProject.scope ? `${sourceProject.scope}/${inferredName}` : inferredName;\n }\n if (requestedProject.scope) return requestedProject.raw;\n return sourceProject.scope ? `${sourceProject.scope}/${requestedProject.name}` : requestedProject.name;\n}\n\nfunction defaultProjectDirectory(projectName: string) {\n return parseScopedProjectName(projectName).name;\n}\n\nfunction parseScopedProjectName(value: string) {\n const raw = value.trim();\n if (!raw.startsWith('@')) {\n return { raw, scope: '', name: raw };\n }\n const separatorIndex = raw.indexOf('/');\n if (separatorIndex < 1 || separatorIndex >= raw.length - 1) {\n return { raw, scope: '', name: raw };\n }\n return {\n raw,\n scope: raw.slice(0, separatorIndex),\n name: raw.slice(separatorIndex + 1),\n };\n}\n\nconst TYPESCRIPT_CONFIG_FORMATS: ConfigFormat[] = ['ts', 'mts', 'cts'];\nconst MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG = '12.4.0';\n\n// cucumber-js only loads TypeScript config files (.ts/.mts/.cts) from 12.4.0 onwards\n// (versions 10.0-12.3 reject them with \"Unsupported configuration file extension\").\n// Fail fast with an actionable error instead of letting the user hit that at run time.\nfunction assertConfigFormatSupported(tree: Tree, configFormat: ConfigFormat) {\n if (!TYPESCRIPT_CONFIG_FORMATS.includes(configFormat)) return;\n const cucumberVersion = readInstalledCucumberVersion(tree);\n if (cucumberVersion && isBelowVersion(cucumberVersion, MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG)) {\n throw new Error(\n `Cucumber configuration format \"${configFormat}\" requires @cucumber/cucumber >=${MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG}, ` +\n `but found ${cucumberVersion}. Choose a different --config-format (js, cjs, mjs, json, yaml) ` +\n `or upgrade @cucumber/cucumber.`\n );\n }\n}\n\nfunction readInstalledCucumberVersion(tree: Tree): string | undefined {\n const packageJsonPath = 'node_modules/@cucumber/cucumber/package.json';\n if (!tree.exists(packageJsonPath)) return undefined;\n try {\n const content = tree.read(packageJsonPath, 'utf-8');\n const version = content ? JSON.parse(content).version : undefined;\n return typeof version === 'string' ? version : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isBelowVersion(version: string, minimum: string): boolean {\n const toParts = (value: string) =>\n value\n .split('-')[0]\n .split('.')\n .map((part) => parseInt(part, 10) || 0);\n const [vMajor, vMinor, vPatch] = toParts(version);\n const [mMajor, mMinor, mPatch] = toParts(minimum);\n if (vMajor !== mMajor) return vMajor < mMajor;\n if (vMinor !== mMinor) return vMinor < mMinor;\n return vPatch < mPatch;\n}\n\nfunction resolveConfigShapeDir(configFormat: ConfigFormat): string {\n if (configFormat === 'json') return 'json';\n if (configFormat === 'yaml' || configFormat === 'yml') return 'yaml';\n // cucumber-js loads .mjs/.mts/.ts via dynamic import (ESM), so they need the\n // import.meta-based shape; .cjs/.cts/.js are require-loaded and stay CommonJS.\n if (configFormat === 'mjs' || configFormat === 'mts' || configFormat === 'ts') return 'esm';\n return 'cjs';\n}\n\nfunction registerPlugin(tree: Tree) {\n if (!tree.exists('nx.json')) return;\n updateJson(tree, 'nx.json', (json) => {\n if (!Array.isArray(json.plugins)) json.plugins = [];\n if (!json.plugins.includes('@gnuechtel/nx-cucumber')) {\n json.plugins.push('@gnuechtel/nx-cucumber');\n }\n return json;\n });\n}\n\nexport default cucumberJsGenerator;\n"]}
@@ -1,10 +1,13 @@
1
1
  import { TestRunner } from '../../core/test-run-options';
2
2
 
3
+ export type ConfigFormat = 'js' | 'cjs' | 'mjs' | 'ts' | 'mts' | 'cts' | 'json' | 'yaml' | 'yml';
4
+
3
5
  export type CucumberJsGeneratorSchema = {
4
6
  project: string;
5
7
  name?: string;
6
8
  directory?: string;
7
9
  testRunner?: TestRunner;
10
+ configFormat?: ConfigFormat;
8
11
  customWorld?: boolean;
9
12
  ignoreWorkspaceLayout?: boolean;
10
13
  skipInstall?: boolean;
@@ -39,6 +39,12 @@
39
39
  "type": "boolean",
40
40
  "default": false
41
41
  },
42
+ "configFormat": {
43
+ "type": "string",
44
+ "enum": ["js", "cjs", "mjs", "ts", "mts", "cts", "json", "yaml", "yml"],
45
+ "default": "js",
46
+ "description": "The cucumber-js configuration file format"
47
+ },
42
48
  "skipInstall": {
43
49
  "type": "boolean",
44
50
  "description": "Skip package installation",
@@ -52,6 +52,10 @@ function buildTargetsForAdapter(adapter, projectRoot, configFilePath, namedInput
52
52
  command: `${adapterTarget.command} --config ${configFilePath}`,
53
53
  options: {
54
54
  ...(adapterTarget.defaultOptions ?? {}),
55
+ env: {
56
+ ...adapterTarget.defaultOptions?.['env'],
57
+ TS_NODE_PROJECT: (0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.json'),
58
+ },
55
59
  },
56
60
  cache: adapterTarget.continuous ? false : true,
57
61
  inputs: adapterTarget.inputs ?? [...defaultInputs, { externalDependencies: adapter.technologies }],
@@ -1 +1 @@
1
- {"version":3,"file":"create-nodes.js","sourceRoot":"","sources":["../../../../../libs/nx-cucumber/src/plugin/create-nodes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateNodesResultV2,\n CreateNodesV2,\n ProjectConfiguration,\n TargetConfiguration,\n createNodesFromFiles,\n readJsonFile,\n writeJsonFile,\n} from '@nx/devkit';\nimport { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';\nimport { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';\nimport { existsSync, readdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { hashObject } from 'nx/src/devkit-internals';\nimport { workspaceDataDirectory } from 'nx/src/utils/cache-directory';\nimport { AdapterDefinition, AdapterTargetConfig, AdapterTargetName, ADAPTER_TARGET_NAMES } from '../adapters/contract';\nimport { buildDiscoveryGlob, findAdapterForConfigFile, getBuiltinAdapters } from '../adapters/registry';\n\nexport interface NxCucumberPluginOptions {\n /** Override the primary e2e target name (default: 'e2e') */\n e2eTargetName?: string;\n /** Override the UI mode target name (default: 'e2e-ui') */\n e2eUiTargetName?: string;\n /** Override the parallel target name (default: 'e2e-parallel') */\n e2eParallelTargetName?: string;\n}\n\nconst DEFAULT_TARGET_NAMES: Record<AdapterTargetName, string> = {\n e2e: 'e2e',\n 'e2e-ui': 'e2e-ui',\n 'e2e-parallel': 'e2e-parallel',\n};\n\nfunction resolveTargetName(key: AdapterTargetName, options?: NxCucumberPluginOptions): string {\n if (key === 'e2e' && options?.e2eTargetName) return options.e2eTargetName;\n if (key === 'e2e-ui' && options?.e2eUiTargetName) return options.e2eUiTargetName;\n if (key === 'e2e-parallel' && options?.e2eParallelTargetName) return options.e2eParallelTargetName;\n return DEFAULT_TARGET_NAMES[key];\n}\n\nexport function readTargetsCache(cachePath: string): Record<string, TargetsResult> {\n return process.env['NX_CACHE_PROJECT_GRAPH'] !== 'false' && existsSync(cachePath) ? readJsonFile(cachePath) : {};\n}\n\nfunction writeTargetsToCache(cachePath: string, results: Record<string, TargetsResult>): void {\n writeJsonFile(cachePath, results);\n}\n\ninterface TargetsResult {\n targets: Record<string, TargetConfiguration>;\n metadata: ProjectConfiguration['metadata'];\n}\n\n/**\n * Builds Nx targets from an adapter definition for a specific project.\n */\nexport function buildTargetsForAdapter(\n adapter: AdapterDefinition,\n projectRoot: string,\n configFilePath: string,\n namedInputs: Record<string, unknown[]>,\n options?: NxCucumberPluginOptions\n): TargetsResult {\n const targets: Record<string, TargetConfiguration> = {};\n const targetGroup: string[] = [];\n\n const defaultInputs = 'production' in namedInputs ? ['production', '^production'] : ['default', '^default'];\n\n for (const key of ADAPTER_TARGET_NAMES) {\n const adapterTarget: AdapterTargetConfig | undefined = adapter.targets[key];\n if (!adapterTarget) continue;\n\n const targetName = resolveTargetName(key, options);\n const defaultOutputs = [`{workspaceRoot}/dist/e2e/${projectRoot}`];\n\n targets[targetName] = {\n command: `${adapterTarget.command} --config ${configFilePath}`,\n options: {\n ...(adapterTarget.defaultOptions ?? {}),\n },\n cache: adapterTarget.continuous ? false : true,\n inputs: adapterTarget.inputs ?? [...defaultInputs, { externalDependencies: adapter.technologies }],\n outputs: adapterTarget.outputs ?? defaultOutputs,\n ...(adapterTarget.dependsOn ? { dependsOn: adapterTarget.dependsOn } : {}),\n ...(adapterTarget.continuous ? { continuous: true } : {}),\n metadata: {\n technologies: adapter.technologies,\n description: `Run ${adapter.name} ${key} tests`,\n help: {\n command: `${adapterTarget.command} --help`,\n example: {},\n },\n },\n };\n\n targetGroup.push(targetName);\n }\n\n return {\n targets,\n metadata: {\n targetGroups: {\n [adapter.name]: targetGroup,\n },\n },\n };\n}\n\n/**\n * Checks whether the given directory is a valid Nx project\n * (contains project.json or package.json).\n */\nexport function isProjectRoot(workspaceRoot: string, projectRoot: string): boolean {\n const dir = join(workspaceRoot, projectRoot);\n if (!existsSync(dir)) return false;\n const files = readdirSync(dir);\n return files.includes('project.json') || files.includes('package.json');\n}\n\n/**\n * Reads user-defined targets from project.json to avoid conflicts.\n */\nexport function getUserDefinedTargets(workspaceRoot: string, projectRoot: string): Set<string> {\n const projectJsonPath = join(workspaceRoot, projectRoot, 'project.json');\n if (!existsSync(projectJsonPath)) return new Set();\n try {\n const config = readJsonFile<ProjectConfiguration>(projectJsonPath);\n return new Set(Object.keys(config.targets ?? {}));\n } catch {\n return new Set();\n }\n}\n\n/**\n * Removes targets that conflict with user-defined targets in project.json.\n */\nexport function filterConflictingTargets(result: TargetsResult, userTargets: Set<string>): TargetsResult {\n if (userTargets.size === 0) return result;\n\n const filtered: Record<string, TargetConfiguration> = {};\n const filteredGroup: string[] = [];\n\n for (const [name, target] of Object.entries(result.targets)) {\n if (!userTargets.has(name)) {\n filtered[name] = target;\n filteredGroup.push(name);\n }\n }\n\n const groupKey = Object.keys(result.metadata?.targetGroups ?? {})[0];\n\n return {\n targets: filtered,\n metadata: groupKey ? { targetGroups: { [groupKey]: filteredGroup } } : result.metadata,\n };\n}\n\nexport const createNodesV2: CreateNodesV2<NxCucumberPluginOptions> = [\n createDiscoveryGlob(),\n async (configFiles, options, context): Promise<CreateNodesResultV2> => {\n const adapters = getBuiltinAdapters();\n if (adapters.length === 0) return [];\n\n const optionsHash = hashObject(options ?? {});\n const cachePath = join(workspaceDataDirectory, `nx-cucumber-${optionsHash}.hash`);\n const targetsCache = readTargetsCache(cachePath);\n\n try {\n return await createNodesFromFiles(\n async (configFilePath, opts, ctx) => {\n const projectRoot = dirname(configFilePath);\n\n if (!isProjectRoot(ctx.workspaceRoot, projectRoot)) {\n return {};\n }\n\n const adapter = findAdapterForConfigFile(configFilePath, adapters);\n if (!adapter) return {};\n\n const hash = await calculateHashForCreateNodes(projectRoot, opts ?? {}, ctx);\n\n if (!targetsCache[hash]) {\n const namedInputs = getNamedInputs(projectRoot, ctx);\n const result = buildTargetsForAdapter(adapter, projectRoot, configFilePath, namedInputs, opts ?? undefined);\n const userTargets = getUserDefinedTargets(ctx.workspaceRoot, projectRoot);\n targetsCache[hash] = filterConflictingTargets(result, userTargets);\n }\n\n const { targets, metadata } = targetsCache[hash];\n\n return {\n projects: {\n [projectRoot]: {\n root: projectRoot,\n targets,\n metadata,\n },\n },\n };\n },\n configFiles,\n options,\n context\n );\n } finally {\n writeTargetsToCache(cachePath, targetsCache);\n }\n },\n];\n\n/**\n * Builds the glob at module load time from registered adapters.\n * Returns a no-match pattern if no adapters are registered yet.\n */\nfunction createDiscoveryGlob(): string {\n const adapters = getBuiltinAdapters();\n return buildDiscoveryGlob(adapters) ?? '**/__nx-cucumber-no-adapters__';\n}\n"]}
1
+ {"version":3,"file":"create-nodes.js","sourceRoot":"","sources":["../../../../../libs/nx-cucumber/src/plugin/create-nodes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateNodesResultV2,\n CreateNodesV2,\n ProjectConfiguration,\n TargetConfiguration,\n createNodesFromFiles,\n joinPathFragments,\n readJsonFile,\n writeJsonFile,\n} from '@nx/devkit';\nimport { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';\nimport { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';\nimport { existsSync, readdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { hashObject } from 'nx/src/devkit-internals';\nimport { workspaceDataDirectory } from 'nx/src/utils/cache-directory';\nimport { AdapterDefinition, AdapterTargetConfig, AdapterTargetName, ADAPTER_TARGET_NAMES } from '../adapters/contract';\nimport { buildDiscoveryGlob, findAdapterForConfigFile, getBuiltinAdapters } from '../adapters/registry';\n\nexport interface NxCucumberPluginOptions {\n /** Override the primary e2e target name (default: 'e2e') */\n e2eTargetName?: string;\n /** Override the UI mode target name (default: 'e2e-ui') */\n e2eUiTargetName?: string;\n /** Override the parallel target name (default: 'e2e-parallel') */\n e2eParallelTargetName?: string;\n}\n\nconst DEFAULT_TARGET_NAMES: Record<AdapterTargetName, string> = {\n e2e: 'e2e',\n 'e2e-ui': 'e2e-ui',\n 'e2e-parallel': 'e2e-parallel',\n};\n\nfunction resolveTargetName(key: AdapterTargetName, options?: NxCucumberPluginOptions): string {\n if (key === 'e2e' && options?.e2eTargetName) return options.e2eTargetName;\n if (key === 'e2e-ui' && options?.e2eUiTargetName) return options.e2eUiTargetName;\n if (key === 'e2e-parallel' && options?.e2eParallelTargetName) return options.e2eParallelTargetName;\n return DEFAULT_TARGET_NAMES[key];\n}\n\nexport function readTargetsCache(cachePath: string): Record<string, TargetsResult> {\n return process.env['NX_CACHE_PROJECT_GRAPH'] !== 'false' && existsSync(cachePath) ? readJsonFile(cachePath) : {};\n}\n\nfunction writeTargetsToCache(cachePath: string, results: Record<string, TargetsResult>): void {\n writeJsonFile(cachePath, results);\n}\n\ninterface TargetsResult {\n targets: Record<string, TargetConfiguration>;\n metadata: ProjectConfiguration['metadata'];\n}\n\n/**\n * Builds Nx targets from an adapter definition for a specific project.\n */\nexport function buildTargetsForAdapter(\n adapter: AdapterDefinition,\n projectRoot: string,\n configFilePath: string,\n namedInputs: Record<string, unknown[]>,\n options?: NxCucumberPluginOptions\n): TargetsResult {\n const targets: Record<string, TargetConfiguration> = {};\n const targetGroup: string[] = [];\n\n const defaultInputs = 'production' in namedInputs ? ['production', '^production'] : ['default', '^default'];\n\n for (const key of ADAPTER_TARGET_NAMES) {\n const adapterTarget: AdapterTargetConfig | undefined = adapter.targets[key];\n if (!adapterTarget) continue;\n\n const targetName = resolveTargetName(key, options);\n const defaultOutputs = [`{workspaceRoot}/dist/e2e/${projectRoot}`];\n\n targets[targetName] = {\n command: `${adapterTarget.command} --config ${configFilePath}`,\n options: {\n ...(adapterTarget.defaultOptions ?? {}),\n env: {\n ...(adapterTarget.defaultOptions?.['env'] as Record<string, string> | undefined),\n TS_NODE_PROJECT: joinPathFragments(projectRoot, 'tsconfig.json'),\n },\n },\n cache: adapterTarget.continuous ? false : true,\n inputs: adapterTarget.inputs ?? [...defaultInputs, { externalDependencies: adapter.technologies }],\n outputs: adapterTarget.outputs ?? defaultOutputs,\n ...(adapterTarget.dependsOn ? { dependsOn: adapterTarget.dependsOn } : {}),\n ...(adapterTarget.continuous ? { continuous: true } : {}),\n metadata: {\n technologies: adapter.technologies,\n description: `Run ${adapter.name} ${key} tests`,\n help: {\n command: `${adapterTarget.command} --help`,\n example: {},\n },\n },\n };\n\n targetGroup.push(targetName);\n }\n\n return {\n targets,\n metadata: {\n targetGroups: {\n [adapter.name]: targetGroup,\n },\n },\n };\n}\n\n/**\n * Checks whether the given directory is a valid Nx project\n * (contains project.json or package.json).\n */\nexport function isProjectRoot(workspaceRoot: string, projectRoot: string): boolean {\n const dir = join(workspaceRoot, projectRoot);\n if (!existsSync(dir)) return false;\n const files = readdirSync(dir);\n return files.includes('project.json') || files.includes('package.json');\n}\n\n/**\n * Reads user-defined targets from project.json to avoid conflicts.\n */\nexport function getUserDefinedTargets(workspaceRoot: string, projectRoot: string): Set<string> {\n const projectJsonPath = join(workspaceRoot, projectRoot, 'project.json');\n if (!existsSync(projectJsonPath)) return new Set();\n try {\n const config = readJsonFile<ProjectConfiguration>(projectJsonPath);\n return new Set(Object.keys(config.targets ?? {}));\n } catch {\n return new Set();\n }\n}\n\n/**\n * Removes targets that conflict with user-defined targets in project.json.\n */\nexport function filterConflictingTargets(result: TargetsResult, userTargets: Set<string>): TargetsResult {\n if (userTargets.size === 0) return result;\n\n const filtered: Record<string, TargetConfiguration> = {};\n const filteredGroup: string[] = [];\n\n for (const [name, target] of Object.entries(result.targets)) {\n if (!userTargets.has(name)) {\n filtered[name] = target;\n filteredGroup.push(name);\n }\n }\n\n const groupKey = Object.keys(result.metadata?.targetGroups ?? {})[0];\n\n return {\n targets: filtered,\n metadata: groupKey ? { targetGroups: { [groupKey]: filteredGroup } } : result.metadata,\n };\n}\n\nexport const createNodesV2: CreateNodesV2<NxCucumberPluginOptions> = [\n createDiscoveryGlob(),\n async (configFiles, options, context): Promise<CreateNodesResultV2> => {\n const adapters = getBuiltinAdapters();\n if (adapters.length === 0) return [];\n\n const optionsHash = hashObject(options ?? {});\n const cachePath = join(workspaceDataDirectory, `nx-cucumber-${optionsHash}.hash`);\n const targetsCache = readTargetsCache(cachePath);\n\n try {\n return await createNodesFromFiles(\n async (configFilePath, opts, ctx) => {\n const projectRoot = dirname(configFilePath);\n\n if (!isProjectRoot(ctx.workspaceRoot, projectRoot)) {\n return {};\n }\n\n const adapter = findAdapterForConfigFile(configFilePath, adapters);\n if (!adapter) return {};\n\n const hash = await calculateHashForCreateNodes(projectRoot, opts ?? {}, ctx);\n\n if (!targetsCache[hash]) {\n const namedInputs = getNamedInputs(projectRoot, ctx);\n const result = buildTargetsForAdapter(adapter, projectRoot, configFilePath, namedInputs, opts ?? undefined);\n const userTargets = getUserDefinedTargets(ctx.workspaceRoot, projectRoot);\n targetsCache[hash] = filterConflictingTargets(result, userTargets);\n }\n\n const { targets, metadata } = targetsCache[hash];\n\n return {\n projects: {\n [projectRoot]: {\n root: projectRoot,\n targets,\n metadata,\n },\n },\n };\n },\n configFiles,\n options,\n context\n );\n } finally {\n writeTargetsToCache(cachePath, targetsCache);\n }\n },\n];\n\n/**\n * Builds the glob at module load time from registered adapters.\n * Returns a no-match pattern if no adapters are registered yet.\n */\nfunction createDiscoveryGlob(): string {\n const adapters = getBuiltinAdapters();\n return buildDiscoveryGlob(adapters) ?? '**/__nx-cucumber-no-adapters__';\n}\n"]}