@nx/cypress 17.0.3 → 17.0.5

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.
Files changed (57) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +9 -4
  3. package/generators.json +3 -3
  4. package/index.d.ts +2 -2
  5. package/index.js +4 -4
  6. package/migrations.json +24 -0
  7. package/package.json +6 -6
  8. package/plugin.d.ts +1 -0
  9. package/plugin.js +6 -0
  10. package/plugins/cypress-preset.d.ts +27 -19
  11. package/plugins/cypress-preset.js +102 -11
  12. package/src/executors/cypress/cypress.impl.d.ts +1 -1
  13. package/src/executors/cypress/cypress.impl.js +6 -152
  14. package/src/executors/cypress/schema.json +11 -1
  15. package/src/generators/base-setup/base-setup.d.ts +1 -0
  16. package/src/generators/base-setup/base-setup.js +26 -3
  17. package/src/generators/base-setup/files/config-js-cjs/__directory__/support/commands.js__ext__ +35 -0
  18. package/src/generators/base-setup/files/config-js-cjs/cypress.config.js__ext__ +3 -0
  19. package/src/generators/base-setup/files/config-js-esm/__directory__/support/commands.js__ext__ +35 -0
  20. package/src/generators/base-setup/files/config-ts/__directory__/support/commands.ts__ext__ +35 -0
  21. package/src/generators/base-setup/files/config-ts/cypress.config.ts__ext__ +3 -0
  22. package/src/generators/component-configuration/component-configuration.d.ts +3 -2
  23. package/src/generators/component-configuration/component-configuration.js +50 -27
  24. package/src/generators/component-configuration/files/__directory__/support/component-index.html +4 -1
  25. package/src/generators/component-configuration/schema.d.ts +7 -0
  26. package/src/generators/component-configuration/schema.json +1 -1
  27. package/src/generators/configuration/configuration.d.ts +4 -0
  28. package/src/generators/configuration/configuration.js +90 -26
  29. package/src/generators/configuration/schema.json +1 -1
  30. package/src/generators/cypress-project/cypress-project.js +25 -5
  31. package/src/generators/cypress-project/schema.d.ts +1 -0
  32. package/src/generators/cypress-project/schema.json +1 -1
  33. package/src/generators/init/init.d.ts +2 -0
  34. package/src/generators/init/init.js +71 -15
  35. package/src/generators/init/schema.d.ts +4 -2
  36. package/src/generators/init/schema.json +19 -1
  37. package/src/generators/migrate-to-cypress-11/schema.json +1 -1
  38. package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.d.ts +2 -0
  39. package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.js +12 -0
  40. package/src/plugins/plugin.d.ts +9 -0
  41. package/src/plugins/plugin.js +227 -0
  42. package/src/utils/add-linter.d.ts +1 -0
  43. package/src/utils/add-linter.js +4 -4
  44. package/src/utils/config.d.ts +6 -7
  45. package/src/utils/config.js +39 -12
  46. package/src/utils/constants.d.ts +4 -0
  47. package/src/utils/constants.js +7 -0
  48. package/src/utils/ct-helpers.d.ts +1 -1
  49. package/src/utils/ct-helpers.js +6 -2
  50. package/src/utils/start-dev-server.d.ts +9 -0
  51. package/src/utils/start-dev-server.js +157 -0
  52. package/src/utils/versions.d.ts +3 -3
  53. package/src/utils/versions.js +3 -3
  54. /package/src/generators/base-setup/files/{__directory__ → common/__directory__}/fixtures/example.json +0 -0
  55. /package/src/generators/base-setup/files/{__directory__ → common/__directory__}/support/commands.ts__ext__ +0 -0
  56. /package/src/generators/base-setup/files/{__directory__ → common/__directory__}/tsconfig.json__ext__ +0 -0
  57. /package/src/generators/base-setup/files/{cypress.config.ts__ext__ → config-js-esm/cypress.config.js__ext__} +0 -0
@@ -6,11 +6,12 @@ const js_1 = require("@nx/js");
6
6
  const path_1 = require("path");
7
7
  function addBaseCypressSetup(tree, options) {
8
8
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
9
- if (tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress.config.ts'))) {
9
+ if (tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress.config.ts')) ||
10
+ tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress.config.js'))) {
10
11
  return;
11
12
  }
12
13
  const opts = normalizeOptions(tree, projectConfig, options);
13
- (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), projectConfig.root, {
14
+ const templateVars = {
14
15
  ...opts,
15
16
  jsx: !!opts.jsx,
16
17
  offsetFromRoot: (0, devkit_1.offsetFromRoot)(projectConfig.root),
@@ -19,7 +20,19 @@ function addBaseCypressSetup(tree, options) {
19
20
  ? `${opts.offsetFromProjectRoot}tsconfig.json`
20
21
  : (0, js_1.getRelativePathToRootTsConfig)(tree, projectConfig.root),
21
22
  ext: '',
22
- });
23
+ };
24
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files/common'), projectConfig.root, templateVars);
25
+ if (options.js) {
26
+ if (isEsmProject(tree, projectConfig.root)) {
27
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files/config-js-esm'), projectConfig.root, templateVars);
28
+ }
29
+ else {
30
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files/config-js-cjs'), projectConfig.root, templateVars);
31
+ }
32
+ }
33
+ else {
34
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files/config-ts'), projectConfig.root, templateVars);
35
+ }
23
36
  if (opts.hasTsConfig) {
24
37
  (0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'), (json) => {
25
38
  // tsconfig doesn't have references so it shouldn't add them
@@ -55,3 +68,13 @@ function normalizeOptions(tree, projectConfig, options) {
55
68
  hasTsConfig,
56
69
  };
57
70
  }
71
+ function isEsmProject(tree, projectRoot) {
72
+ let packageJson;
73
+ if (tree.exists((0, devkit_1.joinPathFragments)(projectRoot, 'package.json'))) {
74
+ packageJson = (0, devkit_1.readJson)(tree, (0, devkit_1.joinPathFragments)(projectRoot, 'package.json'));
75
+ }
76
+ else {
77
+ packageJson = (0, devkit_1.readJson)(tree, 'package.json');
78
+ }
79
+ return packageJson.type === 'module';
80
+ }
@@ -0,0 +1,35 @@
1
+ /// <reference types="cypress" />
2
+
3
+ // ***********************************************
4
+ // This example commands.ts shows you how to
5
+ // create various custom commands and overwrite
6
+ // existing commands.
7
+ //
8
+ // For more comprehensive examples of custom
9
+ // commands please read more here:
10
+ // https://on.cypress.io/custom-commands
11
+ // ***********************************************
12
+
13
+ // eslint-disable-next-line @typescript-eslint/no-namespace
14
+ declare namespace Cypress {
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ interface Chainable<Subject> {
17
+ login(email: string, password: string): void;
18
+ }
19
+ }
20
+
21
+ // -- This is a parent command --
22
+ Cypress.Commands.add('login', (email, password) => {
23
+ console.log('Custom command example: Login', email, password);
24
+ });
25
+ //
26
+ // -- This is a child command --
27
+ // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
28
+ //
29
+ //
30
+ // -- This is a dual command --
31
+ // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
32
+ //
33
+ //
34
+ // -- This will overwrite an existing command --
35
+ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
@@ -0,0 +1,3 @@
1
+ const { defineConfig } = require('cypress');
2
+
3
+ module.exports = defineConfig({});
@@ -0,0 +1,35 @@
1
+ /// <reference types="cypress" />
2
+
3
+ // ***********************************************
4
+ // This example commands.ts shows you how to
5
+ // create various custom commands and overwrite
6
+ // existing commands.
7
+ //
8
+ // For more comprehensive examples of custom
9
+ // commands please read more here:
10
+ // https://on.cypress.io/custom-commands
11
+ // ***********************************************
12
+
13
+ // eslint-disable-next-line @typescript-eslint/no-namespace
14
+ declare namespace Cypress {
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ interface Chainable<Subject> {
17
+ login(email: string, password: string): void;
18
+ }
19
+ }
20
+
21
+ // -- This is a parent command --
22
+ Cypress.Commands.add('login', (email, password) => {
23
+ console.log('Custom command example: Login', email, password);
24
+ });
25
+ //
26
+ // -- This is a child command --
27
+ // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
28
+ //
29
+ //
30
+ // -- This is a dual command --
31
+ // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
32
+ //
33
+ //
34
+ // -- This will overwrite an existing command --
35
+ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
@@ -0,0 +1,35 @@
1
+ /// <reference types="cypress" />
2
+
3
+ // ***********************************************
4
+ // This example commands.ts shows you how to
5
+ // create various custom commands and overwrite
6
+ // existing commands.
7
+ //
8
+ // For more comprehensive examples of custom
9
+ // commands please read more here:
10
+ // https://on.cypress.io/custom-commands
11
+ // ***********************************************
12
+
13
+ // eslint-disable-next-line @typescript-eslint/no-namespace
14
+ declare namespace Cypress {
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ interface Chainable<Subject> {
17
+ login(email: string, password: string): void;
18
+ }
19
+ }
20
+
21
+ // -- This is a parent command --
22
+ Cypress.Commands.add('login', (email, password) => {
23
+ console.log('Custom command example: Login', email, password);
24
+ });
25
+ //
26
+ // -- This is a child command --
27
+ // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
28
+ //
29
+ //
30
+ // -- This is a dual command --
31
+ // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
32
+ //
33
+ //
34
+ // -- This will overwrite an existing command --
35
+ // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
@@ -0,0 +1,3 @@
1
+ import { defineConfig } from 'cypress';
2
+
3
+ export default defineConfig({});
@@ -1,5 +1,6 @@
1
- import { ProjectConfiguration, Tree } from '@nx/devkit';
1
+ import { ProjectConfiguration, Tree, GeneratorCallback } from '@nx/devkit';
2
2
  import { CypressComponentConfigurationSchema } from './schema';
3
- export declare function componentConfigurationGenerator(tree: Tree, options: CypressComponentConfigurationSchema): Promise<() => void>;
3
+ export declare function componentConfigurationGenerator(tree: Tree, options: CypressComponentConfigurationSchema): Promise<GeneratorCallback>;
4
+ export declare function componentConfigurationGeneratorInternal(tree: Tree, options: CypressComponentConfigurationSchema): Promise<GeneratorCallback>;
4
5
  export declare function updateTsConfigForComponentTesting(tree: Tree, projectConfig: ProjectConfiguration): void;
5
6
  export default componentConfigurationGenerator;
@@ -1,33 +1,55 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateTsConfigForComponentTesting = exports.componentConfigurationGenerator = void 0;
3
+ exports.updateTsConfigForComponentTesting = exports.componentConfigurationGeneratorInternal = exports.componentConfigurationGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const cypress_version_1 = require("../../utils/cypress-version");
6
6
  const versions_1 = require("../../utils/versions");
7
7
  const base_setup_1 = require("../base-setup/base-setup");
8
- async function componentConfigurationGenerator(tree, options) {
9
- const opts = normalizeOptions(options);
8
+ const init_1 = require("../init/init");
9
+ function componentConfigurationGenerator(tree, options) {
10
+ return componentConfigurationGeneratorInternal(tree, {
11
+ addPlugin: false,
12
+ ...options,
13
+ });
14
+ }
15
+ exports.componentConfigurationGenerator = componentConfigurationGenerator;
16
+ async function componentConfigurationGeneratorInternal(tree, options) {
17
+ const tasks = [];
18
+ const opts = normalizeOptions(tree, options);
19
+ tasks.push(await (0, init_1.default)(tree, {
20
+ ...opts,
21
+ skipFormat: true,
22
+ }));
23
+ const nxJson = (0, devkit_1.readNxJson)(tree);
24
+ const hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string'
25
+ ? p === '@nx/cypress/plugin'
26
+ : p.plugin === '@nx/cypress/plugin');
10
27
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, opts.project);
11
- const installDepsTask = updateDeps(tree, opts);
28
+ tasks.push(updateDeps(tree, opts));
12
29
  addProjectFiles(tree, projectConfig, opts);
13
- addTargetToProject(tree, projectConfig, opts);
14
- updateNxJsonConfiguration(tree);
30
+ if (!hasPlugin || opts.addExplicitTargets) {
31
+ addTargetToProject(tree, projectConfig, opts);
32
+ }
33
+ updateNxJsonConfiguration(tree, hasPlugin);
15
34
  updateTsConfigForComponentTesting(tree, projectConfig);
16
35
  if (!opts.skipFormat) {
17
36
  await (0, devkit_1.formatFiles)(tree);
18
37
  }
19
- return () => {
20
- installDepsTask();
21
- };
38
+ return (0, devkit_1.runTasksInSerial)(...tasks);
22
39
  }
23
- exports.componentConfigurationGenerator = componentConfigurationGenerator;
24
- function normalizeOptions(options) {
40
+ exports.componentConfigurationGeneratorInternal = componentConfigurationGeneratorInternal;
41
+ function normalizeOptions(tree, options) {
25
42
  const cyVersion = (0, cypress_version_1.installedCypressVersion)();
26
43
  if (cyVersion && cyVersion < 10) {
27
44
  throw new Error('Cypress version of 10 or higher is required to use component testing. See the migration guide to upgrade. https://nx.dev/cypress/v11-migration-guide');
28
45
  }
46
+ const nxJson = (0, devkit_1.readNxJson)(tree);
47
+ const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
48
+ nxJson.useInferencePlugins !== false;
29
49
  return {
50
+ addPlugin,
30
51
  ...options,
52
+ framework: options.framework ?? null,
31
53
  directory: options.directory ?? 'cypress',
32
54
  };
33
55
  }
@@ -67,25 +89,26 @@ function addTargetToProject(tree, projectConfig, opts) {
67
89
  };
68
90
  (0, devkit_1.updateProjectConfiguration)(tree, opts.project, projectConfig);
69
91
  }
70
- function updateNxJsonConfiguration(tree) {
92
+ function updateNxJsonConfiguration(tree, hasPlugin) {
71
93
  const nxJson = (0, devkit_1.readNxJson)(tree);
72
- const cacheableOperations = nxJson.tasksRunnerOptions?.default?.options?.cacheableOperations;
73
- if (cacheableOperations && !cacheableOperations.includes('component-test')) {
74
- cacheableOperations.push('component-test');
94
+ const productionFileSet = nxJson.namedInputs?.production;
95
+ if (productionFileSet) {
96
+ nxJson.namedInputs.production = Array.from(new Set([
97
+ ...productionFileSet,
98
+ '!{projectRoot}/cypress/**/*',
99
+ '!{projectRoot}/**/*.cy.[jt]s?(x)',
100
+ '!{projectRoot}/cypress.config.[jt]s',
101
+ ]));
75
102
  }
76
- nxJson.targetDefaults ??= {};
77
- nxJson.targetDefaults['component-test'] ??= {};
78
- nxJson.targetDefaults['component-test'].cache ??= true;
79
- if (nxJson.namedInputs) {
80
- const productionFileSet = nxJson.namedInputs?.production;
81
- if (productionFileSet) {
82
- nxJson.namedInputs.production = Array.from(new Set([
83
- ...productionFileSet,
84
- '!{projectRoot}/cypress/**/*',
85
- '!{projectRoot}/**/*.cy.[jt]s?(x)',
86
- '!{projectRoot}/cypress.config.[jt]s',
87
- ]));
103
+ if (!hasPlugin) {
104
+ const cacheableOperations = nxJson.tasksRunnerOptions?.default?.options?.cacheableOperations;
105
+ if (cacheableOperations &&
106
+ !cacheableOperations.includes('component-test')) {
107
+ cacheableOperations.push('component-test');
88
108
  }
109
+ nxJson.targetDefaults ??= {};
110
+ nxJson.targetDefaults['component-test'] ??= {};
111
+ nxJson.targetDefaults['component-test'].cache ??= true;
89
112
  nxJson.targetDefaults['component-test'] ??= {};
90
113
  nxJson.targetDefaults['component-test'].inputs ??= [
91
114
  'default',
@@ -5,7 +5,10 @@
5
5
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
7
  <title><%= project %> Components App</title>
8
-
8
+ <% if(framework === 'next') { %>
9
+ <!-- Used by Next.js to inject CSS. -->
10
+ <div id="__next_css__DO_NOT_USE__"></div>
11
+ <% } %>
9
12
  </head>
10
13
  <body>
11
14
  <div data-cy-root></div>
@@ -4,4 +4,11 @@ export interface CypressComponentConfigurationSchema {
4
4
  directory?: string;
5
5
  bundler?: 'webpack' | 'vite';
6
6
  jsx?: boolean;
7
+ addPlugin?: boolean;
8
+
9
+ /**
10
+ * @internal
11
+ */
12
+ addExplicitTargets?: boolean;
13
+ framework?: 'next';
7
14
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "NxCypressComponentConfiguration",
4
4
  "cli": "nx",
5
5
  "title": "Set up Cypress component testing for a project",
@@ -14,6 +14,10 @@ export interface CypressE2EConfigSchema {
14
14
  port?: number | 'cypress-auto';
15
15
  jsx?: boolean;
16
16
  rootProject?: boolean;
17
+ webServerCommands?: Record<string, string>;
18
+ ciWebServerCommand?: string;
19
+ addPlugin?: boolean;
17
20
  }
18
21
  export declare function configurationGenerator(tree: Tree, options: CypressE2EConfigSchema): Promise<GeneratorCallback>;
22
+ export declare function configurationGeneratorInternal(tree: Tree, options: CypressE2EConfigSchema): Promise<GeneratorCallback>;
19
23
  export default configurationGenerator;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.configurationGenerator = void 0;
3
+ exports.configurationGeneratorInternal = exports.configurationGenerator = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const js_1 = require("@nx/js");
6
6
  const eslint_1 = require("@nx/eslint");
@@ -11,28 +11,59 @@ const cypress_version_1 = require("../../utils/cypress-version");
11
11
  const versions_1 = require("../../utils/versions");
12
12
  const init_1 = require("../init/init");
13
13
  const base_setup_1 = require("../base-setup/base-setup");
14
- async function configurationGenerator(tree, options) {
14
+ function configurationGenerator(tree, options) {
15
+ return configurationGeneratorInternal(tree, {
16
+ addPlugin: false,
17
+ ...options,
18
+ });
19
+ }
20
+ exports.configurationGenerator = configurationGenerator;
21
+ async function configurationGeneratorInternal(tree, options) {
15
22
  const opts = normalizeOptions(tree, options);
23
+ opts.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false';
16
24
  const tasks = [];
17
25
  if (!(0, cypress_version_1.installedCypressVersion)()) {
18
- tasks.push(await (0, init_1.default)(tree, opts));
26
+ tasks.push(await (0, js_1.initGenerator)(tree, { ...options, skipFormat: true }));
27
+ tasks.push(await (0, init_1.default)(tree, {
28
+ ...opts,
29
+ skipFormat: true,
30
+ }));
19
31
  }
20
- if (opts.bundler === 'vite') {
21
- tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, { vite: versions_1.viteVersion }));
32
+ else if (opts.addPlugin) {
33
+ (0, init_1.addPlugin)(tree);
34
+ }
35
+ const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
36
+ const nxJson = (0, devkit_1.readNxJson)(tree);
37
+ const hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string'
38
+ ? p === '@nx/cypress/plugin'
39
+ : p.plugin === '@nx/cypress/plugin');
40
+ await addFiles(tree, opts, projectGraph, hasPlugin);
41
+ if (!hasPlugin) {
42
+ addTarget(tree, opts);
22
43
  }
23
- await addFiles(tree, opts);
24
- addTarget(tree, opts);
25
44
  const linterTask = await (0, add_linter_1.addLinterToCyProject)(tree, {
26
45
  ...opts,
27
46
  cypressDir: opts.directory,
28
47
  });
29
48
  tasks.push(linterTask);
49
+ if (!opts.skipPackageJson) {
50
+ tasks.push(ensureDependencies(tree, opts));
51
+ }
30
52
  if (!opts.skipFormat) {
31
53
  await (0, devkit_1.formatFiles)(tree);
32
54
  }
33
55
  return (0, devkit_1.runTasksInSerial)(...tasks);
34
56
  }
35
- exports.configurationGenerator = configurationGenerator;
57
+ exports.configurationGeneratorInternal = configurationGeneratorInternal;
58
+ function ensureDependencies(tree, options) {
59
+ const devDependencies = {
60
+ '@types/node': versions_1.typesNodeVersion,
61
+ };
62
+ if (options.bundler === 'vite') {
63
+ devDependencies['vite'] = versions_1.viteVersion;
64
+ }
65
+ return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies);
66
+ }
36
67
  function normalizeOptions(tree, options) {
37
68
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
38
69
  if (projectConfig?.targets?.e2e) {
@@ -41,21 +72,29 @@ Rename or remove the existing e2e target.`);
41
72
  }
42
73
  if (!options.baseUrl &&
43
74
  !options.devServerTarget &&
44
- !projectConfig.targets.serve) {
75
+ !projectConfig?.targets?.serve) {
45
76
  throw new Error(`The project ${options.project} does not have a 'serve' target.
46
77
  In this case you need to provide a devServerTarget,'<projectName>:<targetName>[:<configName>]', or a baseUrl option`);
47
78
  }
48
79
  options.directory ??= 'src';
80
+ const devServerTarget = options.devServerTarget ??
81
+ (projectConfig?.targets?.serve ? `${options.project}:serve` : undefined);
82
+ if (!options.baseUrl && !devServerTarget) {
83
+ throw new Error('Either baseUrl or devServerTarget must be provided');
84
+ }
85
+ const nxJson = (0, devkit_1.readNxJson)(tree);
86
+ options.addPlugin ??=
87
+ process.env.NX_ADD_PLUGINS !== 'false' &&
88
+ nxJson.useInferencePlugins !== false;
49
89
  return {
50
90
  ...options,
51
91
  bundler: options.bundler ?? 'webpack',
52
92
  rootProject: options.rootProject ?? projectConfig.root === '.',
53
93
  linter: options.linter ?? eslint_1.Linter.EsLint,
54
- devServerTarget: options.devServerTarget ??
55
- (projectConfig.targets.serve ? `${options.project}:serve` : undefined),
94
+ devServerTarget,
56
95
  };
57
96
  }
58
- async function addFiles(tree, options) {
97
+ async function addFiles(tree, options, projectGraph, hasPlugin) {
59
98
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
60
99
  const cyVersion = (0, cypress_version_1.installedCypressVersion)();
61
100
  const filesToUse = cyVersion && cyVersion < 10 ? 'v9' : 'v10';
@@ -82,12 +121,37 @@ async function addFiles(tree, options) {
82
121
  project: options.project,
83
122
  directory: options.directory,
84
123
  jsx: options.jsx,
124
+ js: options.js,
85
125
  });
86
- const cyFile = (0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress.config.ts');
126
+ const cyFile = (0, devkit_1.joinPathFragments)(projectConfig.root, options.js ? 'cypress.config.js' : 'cypress.config.ts');
127
+ let webServerCommands;
128
+ let ciWebServerCommand;
129
+ if (hasPlugin && options.webServerCommands && options.ciWebServerCommand) {
130
+ webServerCommands = options.webServerCommands;
131
+ ciWebServerCommand = options.ciWebServerCommand;
132
+ }
133
+ else if (hasPlugin && options.devServerTarget) {
134
+ webServerCommands = {};
135
+ webServerCommands.default = 'nx run ' + options.devServerTarget;
136
+ const parsedTarget = (0, devkit_1.parseTargetString)(options.devServerTarget, projectGraph);
137
+ const devServerProjectConfig = (0, devkit_1.readProjectConfiguration)(tree, parsedTarget.project);
138
+ // Add production e2e target if serve target is found
139
+ if (parsedTarget.configuration !== 'production' &&
140
+ devServerProjectConfig?.targets?.[parsedTarget.target]
141
+ ?.configurations?.['production']) {
142
+ webServerCommands.production = `nx run ${parsedTarget.project}:${parsedTarget.target}:production`;
143
+ }
144
+ // Add ci/static e2e target if serve target is found
145
+ if (devServerProjectConfig?.targets?.['serve-static']) {
146
+ ciWebServerCommand = `nx run ${parsedTarget.project}:serve-static`;
147
+ }
148
+ }
87
149
  const updatedCyConfig = await (0, config_1.addDefaultE2EConfig)(tree.read(cyFile, 'utf-8'), {
88
- directory: options.directory,
89
- bundler: options.bundler,
90
- });
150
+ cypressDir: options.directory,
151
+ bundler: options.bundler === 'vite' ? 'vite' : undefined,
152
+ webServerCommands,
153
+ ciWebServerCommand: ciWebServerCommand,
154
+ }, options.baseUrl);
91
155
  tree.write(cyFile, updatedCyConfig);
92
156
  }
93
157
  if (cyVersion &&
@@ -111,20 +175,17 @@ async function addFiles(tree, options) {
111
175
  function addTarget(tree, opts) {
112
176
  const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, opts.project);
113
177
  const cyVersion = (0, cypress_version_1.installedCypressVersion)();
178
+ projectConfig.targets ??= {};
114
179
  projectConfig.targets.e2e = {
115
180
  executor: '@nx/cypress:cypress',
116
181
  options: {
117
- cypressConfig: (0, devkit_1.joinPathFragments)(projectConfig.root, cyVersion && cyVersion < 10 ? 'cypress.json' : 'cypress.config.ts'),
182
+ cypressConfig: (0, devkit_1.joinPathFragments)(projectConfig.root, cyVersion && cyVersion < 10
183
+ ? 'cypress.json'
184
+ : `cypress.config.${opts.js ? 'js' : 'ts'}`),
118
185
  testingType: 'e2e',
119
186
  },
120
187
  };
121
- if (opts.baseUrl) {
122
- projectConfig.targets.e2e.options = {
123
- ...projectConfig.targets.e2e.options,
124
- baseUrl: opts.baseUrl,
125
- };
126
- }
127
- else if (opts.devServerTarget) {
188
+ if (opts.devServerTarget) {
128
189
  const parsedTarget = (0, devkit_1.parseTargetString)(opts.devServerTarget);
129
190
  projectConfig.targets.e2e.options = {
130
191
  ...projectConfig.targets.e2e.options,
@@ -148,8 +209,11 @@ function addTarget(tree, opts) {
148
209
  };
149
210
  }
150
211
  }
151
- else {
152
- throw new Error('Either baseUrl or devServerTarget must be provided');
212
+ else if (opts.baseUrl) {
213
+ projectConfig.targets.e2e.options = {
214
+ ...projectConfig.targets.e2e.options,
215
+ baseUrl: opts.baseUrl,
216
+ };
153
217
  }
154
218
  (0, devkit_1.updateProjectConfiguration)(tree, opts.project, projectConfig);
155
219
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "NxCypressE2EConfigGenerator",
4
4
  "cli": "nx",
5
5
  "title": "Add a Cypress Configuration.",
@@ -12,6 +12,7 @@ const add_linter_1 = require("../../utils/add-linter");
12
12
  const cypress_version_1 = require("../../utils/cypress-version");
13
13
  const versions_1 = require("../../utils/versions");
14
14
  const init_1 = require("../init/init");
15
+ const log_show_project_command_1 = require("@nx/devkit/src/utils/log-show-project-command");
15
16
  function createFiles(tree, options) {
16
17
  // if not installed or >v10 use v10 folder
17
18
  // else use v9 folder
@@ -119,6 +120,7 @@ function addProject(tree, options) {
119
120
  async function cypressProjectGenerator(host, schema) {
120
121
  return await cypressProjectGeneratorInternal(host, {
121
122
  projectNameAndRootFormat: 'derived',
123
+ addPlugin: false,
122
124
  ...schema,
123
125
  });
124
126
  }
@@ -133,11 +135,11 @@ async function cypressProjectGeneratorInternal(host, schema) {
133
135
  // if there is an installed cypress version, then we don't call
134
136
  // init since we want to keep the existing version that is installed
135
137
  if (!cypressVersion) {
136
- tasks.push(await (0, init_1.cypressInitGenerator)(host, options));
137
- }
138
- if (schema.bundler === 'vite') {
139
- tasks.push((0, devkit_1.addDependenciesToPackageJson)(host, {}, {
140
- vite: versions_1.viteVersion,
138
+ tasks.push(await (0, js_1.initGenerator)(host, { ...options, skipFormat: true }));
139
+ tasks.push(await (0, init_1.cypressInitGenerator)(host, {
140
+ ...options,
141
+ skipFormat: true,
142
+ addPlugin: options.addPlugin,
141
143
  }));
142
144
  }
143
145
  createFiles(host, options);
@@ -150,12 +152,29 @@ async function cypressProjectGeneratorInternal(host, schema) {
150
152
  overwriteExisting: true,
151
153
  });
152
154
  tasks.push(installTask);
155
+ if (!options.skipPackageJson) {
156
+ tasks.push(ensureDependencies(host, options));
157
+ }
153
158
  if (!options.skipFormat) {
154
159
  await (0, devkit_1.formatFiles)(host);
155
160
  }
156
161
  return (0, devkit_1.runTasksInSerial)(...tasks);
157
162
  }
158
163
  exports.cypressProjectGeneratorInternal = cypressProjectGeneratorInternal;
164
+ function ensureDependencies(tree, options) {
165
+ const devDependencies = {
166
+ '@types/node': versions_1.typesNodeVersion,
167
+ };
168
+ if (options.bundler === 'vite') {
169
+ devDependencies['vite'] = versions_1.viteVersion;
170
+ }
171
+ return (0, devkit_1.runTasksInSerial)(...[
172
+ (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies),
173
+ () => {
174
+ (0, log_show_project_command_1.logShowProjectCommand)(options.projectName);
175
+ },
176
+ ]);
177
+ }
159
178
  async function normalizeOptions(host, options) {
160
179
  let maybeRootProject;
161
180
  let isRootProject = false;
@@ -182,6 +201,7 @@ async function normalizeOptions(host, options) {
182
201
  });
183
202
  options.linter = options.linter || eslint_1.Linter.EsLint;
184
203
  options.bundler = options.bundler || 'webpack';
204
+ options.addPlugin ??= process.env.NX_ADD_PLUGINS !== 'false';
185
205
  return {
186
206
  ...options,
187
207
  // other generators depend on the rootProject flag down stream
@@ -13,4 +13,5 @@ export interface Schema {
13
13
  setParserOptionsProject?: boolean;
14
14
  skipPackageJson?: boolean;
15
15
  bundler?: 'webpack' | 'vite' | 'none';
16
+ addPlugin?: boolean;
16
17
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/schema",
2
+ "$schema": "https://json-schema.org/schema",
3
3
  "$id": "NxCypressProjectGeneratorSchema",
4
4
  "cli": "nx",
5
5
  "title": "Create Cypress Configuration for the workspace",
@@ -1,4 +1,6 @@
1
1
  import { GeneratorCallback, Tree } from '@nx/devkit';
2
2
  import { Schema } from './schema';
3
+ export declare function addPlugin(tree: Tree): void;
3
4
  export declare function cypressInitGenerator(tree: Tree, options: Schema): Promise<GeneratorCallback>;
5
+ export declare function cypressInitGeneratorInternal(tree: Tree, options: Schema): Promise<GeneratorCallback>;
4
6
  export default cypressInitGenerator;