@nx/cypress 0.0.0-pr-22179-271588f

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 (116) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +68 -0
  3. package/executors.json +9 -0
  4. package/generators.json +37 -0
  5. package/index.d.ts +11 -0
  6. package/index.js +20 -0
  7. package/migrations.json +111 -0
  8. package/package.json +58 -0
  9. package/plugin.d.ts +1 -0
  10. package/plugin.js +6 -0
  11. package/plugins/cypress-preset.d.ts +69 -0
  12. package/plugins/cypress-preset.js +154 -0
  13. package/src/executors/cypress/cypress.impl.d.ts +40 -0
  14. package/src/executors/cypress/cypress.impl.js +182 -0
  15. package/src/executors/cypress/schema.json +186 -0
  16. package/src/generators/base-setup/base-setup.d.ts +12 -0
  17. package/src/generators/base-setup/base-setup.js +80 -0
  18. package/src/generators/base-setup/files/common/__directory__/fixtures/example.json +5 -0
  19. package/src/generators/base-setup/files/common/__directory__/support/commands.ts__ext__ +35 -0
  20. package/src/generators/base-setup/files/common/__directory__/tsconfig.json__ext__ +20 -0
  21. package/src/generators/base-setup/files/config-js-cjs/__directory__/support/commands.js__ext__ +35 -0
  22. package/src/generators/base-setup/files/config-js-cjs/cypress.config.js__ext__ +3 -0
  23. package/src/generators/base-setup/files/config-js-esm/__directory__/support/commands.js__ext__ +35 -0
  24. package/src/generators/base-setup/files/config-js-esm/cypress.config.js__ext__ +3 -0
  25. package/src/generators/base-setup/files/config-ts/__directory__/support/commands.ts__ext__ +35 -0
  26. package/src/generators/base-setup/files/config-ts/cypress.config.ts__ext__ +3 -0
  27. package/src/generators/component-configuration/component-configuration.d.ts +6 -0
  28. package/src/generators/component-configuration/component-configuration.js +165 -0
  29. package/src/generators/component-configuration/files/__directory__/support/component-index.html +16 -0
  30. package/src/generators/component-configuration/files/__directory__/support/component.ts__ext__ +27 -0
  31. package/src/generators/component-configuration/schema.d.ts +14 -0
  32. package/src/generators/component-configuration/schema.json +43 -0
  33. package/src/generators/configuration/configuration.d.ts +23 -0
  34. package/src/generators/configuration/configuration.js +220 -0
  35. package/src/generators/configuration/files/v10/__directory__/e2e/app.cy.ts__tmpl__ +13 -0
  36. package/src/generators/configuration/files/v10/__directory__/support/app.po.ts__tmpl__ +1 -0
  37. package/src/generators/configuration/files/v10/__directory__/support/e2e.ts__tmpl__ +17 -0
  38. package/src/generators/configuration/files/v9/__directory__/fixtures/example.json__tmpl__ +4 -0
  39. package/src/generators/configuration/files/v9/__directory__/integration/app.spec.ts__tmpl__ +13 -0
  40. package/src/generators/configuration/files/v9/__directory__/plugins/index.js +22 -0
  41. package/src/generators/configuration/files/v9/__directory__/support/app.po.ts__tmpl__ +1 -0
  42. package/src/generators/configuration/files/v9/__directory__/support/commands.ts__tmpl__ +33 -0
  43. package/src/generators/configuration/files/v9/__directory__/support/index.ts__tmpl__ +17 -0
  44. package/src/generators/configuration/files/v9/__directory__/tsconfig.json +10 -0
  45. package/src/generators/configuration/files/v9/cypress.json +12 -0
  46. package/src/generators/configuration/schema.json +96 -0
  47. package/src/generators/cypress-project/cypress-project.d.ts +16 -0
  48. package/src/generators/cypress-project/cypress-project.js +213 -0
  49. package/src/generators/cypress-project/files/v10-and-after/cypress.config.ts__tmpl__ +10 -0
  50. package/src/generators/cypress-project/files/v10-and-after/src/e2e/app.cy.ts__tmpl__ +13 -0
  51. package/src/generators/cypress-project/files/v10-and-after/src/fixtures/example.json__tmpl__ +4 -0
  52. package/src/generators/cypress-project/files/v10-and-after/src/support/app.po.ts__tmpl__ +1 -0
  53. package/src/generators/cypress-project/files/v10-and-after/src/support/commands.ts__tmpl__ +33 -0
  54. package/src/generators/cypress-project/files/v10-and-after/src/support/e2e.ts__tmpl__ +17 -0
  55. package/src/generators/cypress-project/files/v10-and-after/tsconfig.json +10 -0
  56. package/src/generators/cypress-project/files/v9-and-under/cypress.json +12 -0
  57. package/src/generators/cypress-project/files/v9-and-under/src/fixtures/example.json__tmpl__ +4 -0
  58. package/src/generators/cypress-project/files/v9-and-under/src/integration/app.spec.ts__tmpl__ +13 -0
  59. package/src/generators/cypress-project/files/v9-and-under/src/plugins/index.js +22 -0
  60. package/src/generators/cypress-project/files/v9-and-under/src/support/app.po.ts__tmpl__ +1 -0
  61. package/src/generators/cypress-project/files/v9-and-under/src/support/commands.ts__tmpl__ +33 -0
  62. package/src/generators/cypress-project/files/v9-and-under/src/support/index.ts__tmpl__ +17 -0
  63. package/src/generators/cypress-project/files/v9-and-under/tsconfig.json +10 -0
  64. package/src/generators/cypress-project/schema.d.ts +17 -0
  65. package/src/generators/cypress-project/schema.json +78 -0
  66. package/src/generators/init/init.d.ts +6 -0
  67. package/src/generators/init/init.js +97 -0
  68. package/src/generators/init/schema.d.ts +7 -0
  69. package/src/generators/init/schema.json +34 -0
  70. package/src/generators/migrate-to-cypress-11/conversion.util.d.ts +39 -0
  71. package/src/generators/migrate-to-cypress-11/conversion.util.js +246 -0
  72. package/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.d.ts +3 -0
  73. package/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.js +93 -0
  74. package/src/generators/migrate-to-cypress-11/schema.json +15 -0
  75. package/src/migrations/update-15-0-0/add-cypress-inputs.d.ts +2 -0
  76. package/src/migrations/update-15-0-0/add-cypress-inputs.js +42 -0
  77. package/src/migrations/update-15-0-0/update-cy-mount-usage.d.ts +5 -0
  78. package/src/migrations/update-15-0-0/update-cy-mount-usage.js +119 -0
  79. package/src/migrations/update-15-1-0/cypress-11.d.ts +6 -0
  80. package/src/migrations/update-15-1-0/cypress-11.js +114 -0
  81. package/src/migrations/update-15-5-0/helpers.d.ts +3 -0
  82. package/src/migrations/update-15-5-0/helpers.js +39 -0
  83. package/src/migrations/update-15-5-0/update-to-cypress-12.d.ts +24 -0
  84. package/src/migrations/update-15-5-0/update-to-cypress-12.js +180 -0
  85. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +2 -0
  86. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +9 -0
  87. package/src/migrations/update-16-2-0/update-cy-tsconfig.d.ts +3 -0
  88. package/src/migrations/update-16-2-0/update-cy-tsconfig.js +77 -0
  89. package/src/migrations/update-16-4-0/tsconfig-sourcemaps.d.ts +3 -0
  90. package/src/migrations/update-16-4-0/tsconfig-sourcemaps.js +62 -0
  91. package/src/migrations/update-16-8-0/cypress-13.d.ts +7 -0
  92. package/src/migrations/update-16-8-0/cypress-13.js +179 -0
  93. package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.d.ts +2 -0
  94. package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.js +12 -0
  95. package/src/plugins/plugin.d.ts +8 -0
  96. package/src/plugins/plugin.js +195 -0
  97. package/src/plugins/preprocessor-vite.d.ts +32 -0
  98. package/src/plugins/preprocessor-vite.js +97 -0
  99. package/src/utils/add-linter.d.ts +22 -0
  100. package/src/utils/add-linter.js +93 -0
  101. package/src/utils/config.d.ts +17 -0
  102. package/src/utils/config.js +115 -0
  103. package/src/utils/constants.d.ts +4 -0
  104. package/src/utils/constants.js +7 -0
  105. package/src/utils/ct-helpers.d.ts +16 -0
  106. package/src/utils/ct-helpers.js +86 -0
  107. package/src/utils/cypress-version.d.ts +5 -0
  108. package/src/utils/cypress-version.js +33 -0
  109. package/src/utils/find-target-options.d.ts +17 -0
  110. package/src/utils/find-target-options.js +136 -0
  111. package/src/utils/project-name.d.ts +3 -0
  112. package/src/utils/project-name.js +19 -0
  113. package/src/utils/start-dev-server.d.ts +9 -0
  114. package/src/utils/start-dev-server.js +157 -0
  115. package/src/utils/versions.d.ts +9 -0
  116. package/src/utils/versions.js +12 -0
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getProjectCypressConfigPath = exports.addMountDefinition = exports.addDefaultCTConfig = exports.addDefaultE2EConfig = exports.CYPRESS_CONFIG_FILE_NAME_PATTERN = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ exports.CYPRESS_CONFIG_FILE_NAME_PATTERN = 'cypress.config.{js,ts,mjs,cjs}';
6
+ const TS_QUERY_COMMON_JS_EXPORT_SELECTOR = 'BinaryExpression:has(Identifier[name="module"]):has(Identifier[name="exports"])';
7
+ const TS_QUERY_EXPORT_CONFIG_PREFIX = `:matches(ExportAssignment, ${TS_QUERY_COMMON_JS_EXPORT_SELECTOR}) `;
8
+ async function addDefaultE2EConfig(cyConfigContents, options, baseUrl) {
9
+ if (!cyConfigContents) {
10
+ throw new Error('The passed in cypress config file is empty!');
11
+ }
12
+ const { tsquery } = await Promise.resolve().then(() => require('@phenomnomnominal/tsquery'));
13
+ const isCommonJS = tsquery.query(cyConfigContents, TS_QUERY_COMMON_JS_EXPORT_SELECTOR).length >
14
+ 0;
15
+ const testingTypeConfig = tsquery.query(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} PropertyAssignment:has(Identifier[name="e2e"])`);
16
+ let updatedConfigContents = cyConfigContents;
17
+ if (testingTypeConfig.length === 0) {
18
+ const configValue = `nxE2EPreset(__filename, ${JSON.stringify(options)})`;
19
+ updatedConfigContents = tsquery.replace(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} ObjectLiteralExpression:first-child`, (node) => {
20
+ let baseUrlContents = baseUrl ? `,\nbaseUrl: '${baseUrl}'` : '';
21
+ if (node.properties.length > 0) {
22
+ return `{
23
+ ${node.properties.map((p) => p.getText()).join(',\n')},
24
+ e2e: { ...${configValue}${baseUrlContents} }
25
+ }`;
26
+ }
27
+ return `{
28
+ e2e: { ...${configValue}${baseUrlContents} }
29
+ }`;
30
+ });
31
+ return isCommonJS
32
+ ? `const { nxE2EPreset } = require('@nx/cypress/plugins/cypress-preset');
33
+
34
+ ${updatedConfigContents}`
35
+ : `import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
36
+
37
+ ${updatedConfigContents}`;
38
+ }
39
+ return updatedConfigContents;
40
+ }
41
+ exports.addDefaultE2EConfig = addDefaultE2EConfig;
42
+ /**
43
+ * Adds the nxComponentTestingPreset to the cypress config file
44
+ * Make sure after calling this the correct import statement is addeda
45
+ * to bring in the nxComponentTestingPreset function
46
+ **/
47
+ async function addDefaultCTConfig(cyConfigContents, options = {}) {
48
+ if (!cyConfigContents) {
49
+ throw new Error('The passed in cypress config file is empty!');
50
+ }
51
+ const { tsquery } = await Promise.resolve().then(() => require('@phenomnomnominal/tsquery'));
52
+ const testingTypeConfig = tsquery.query(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} PropertyAssignment:has(Identifier[name="component"])`);
53
+ let updatedConfigContents = cyConfigContents;
54
+ if (testingTypeConfig.length === 0) {
55
+ let configValue = 'nxComponentTestingPreset(__filename)';
56
+ if (options) {
57
+ if (options.bundler !== 'vite') {
58
+ // vite is the default bundler, so we don't need to set it
59
+ delete options.bundler;
60
+ }
61
+ if (Object.keys(options).length) {
62
+ configValue = `nxComponentTestingPreset(__filename, ${JSON.stringify(options)})`;
63
+ }
64
+ }
65
+ updatedConfigContents = tsquery.replace(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} ObjectLiteralExpression:first-child`, (node) => {
66
+ if (node.properties.length > 0) {
67
+ return `{
68
+ ${node.properties.map((p) => p.getText()).join(',\n')},
69
+ component: ${configValue}
70
+ }`;
71
+ }
72
+ return `{
73
+ component: ${configValue}
74
+ }`;
75
+ });
76
+ }
77
+ return updatedConfigContents;
78
+ }
79
+ exports.addDefaultCTConfig = addDefaultCTConfig;
80
+ /**
81
+ * Adds the mount command for Cypress
82
+ * Make sure after calling this the correct import statement is added
83
+ * to bring in the correct mount from cypress.
84
+ **/
85
+ async function addMountDefinition(cmpCommandFileContents) {
86
+ if (!cmpCommandFileContents) {
87
+ throw new Error('The passed in cypress component file is empty!');
88
+ }
89
+ const { tsquery } = await Promise.resolve().then(() => require('@phenomnomnominal/tsquery'));
90
+ const hasMountCommand = tsquery.query(cmpCommandFileContents, 'CallExpression StringLiteral[value="mount"]')?.length > 0;
91
+ if (hasMountCommand) {
92
+ return cmpCommandFileContents;
93
+ }
94
+ const mountCommand = `Cypress.Commands.add('mount', mount);`;
95
+ const updatedInterface = tsquery.replace(cmpCommandFileContents, 'InterfaceDeclaration', (node) => {
96
+ return `interface ${node.name.getText()}${node.typeParameters
97
+ ? `<${node.typeParameters.map((p) => p.getText()).join(', ')}>`
98
+ : ''} {
99
+ ${node.members.map((m) => m.getText()).join('\n ')}
100
+ mount: typeof mount;
101
+ }`;
102
+ });
103
+ return `${updatedInterface}\n${mountCommand}`;
104
+ }
105
+ exports.addMountDefinition = addMountDefinition;
106
+ function getProjectCypressConfigPath(tree, projectRoot) {
107
+ const cypressConfigPaths = (0, devkit_1.glob)(tree, [
108
+ (0, devkit_1.joinPathFragments)(projectRoot, exports.CYPRESS_CONFIG_FILE_NAME_PATTERN),
109
+ ]);
110
+ if (cypressConfigPaths.length === 0) {
111
+ throw new Error(`Could not find a cypress config file in ${projectRoot}.`);
112
+ }
113
+ return cypressConfigPaths[0];
114
+ }
115
+ exports.getProjectCypressConfigPath = getProjectCypressConfigPath;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Key used to store options used by the nx plugin for @nx/cypress.
3
+ */
4
+ export declare const NX_PLUGIN_OPTIONS = "__NxPluginOptions__";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NX_PLUGIN_OPTIONS = void 0;
4
+ /**
5
+ * Key used to store options used by the nx plugin for @nx/cypress.
6
+ */
7
+ exports.NX_PLUGIN_OPTIONS = '__NxPluginOptions__';
@@ -0,0 +1,16 @@
1
+ import type { ExecutorContext, ProjectGraph } from '@nx/devkit';
2
+ import { ProjectConfiguration, TargetConfiguration } from '@nx/devkit';
3
+ export declare const CY_FILE_MATCHER: RegExp;
4
+ /**
5
+ * return a path to a temp css file
6
+ * temp file is scoped to the project root
7
+ * i.e. <context.root>/tmp/<project-root>/ct-styles.css
8
+ */
9
+ export declare function getTempTailwindPath(context: ExecutorContext): string;
10
+ /**
11
+ * Checks if the childProjectName is a descendent of the parentProjectName
12
+ * in the project graph
13
+ **/
14
+ export declare function isCtProjectUsingBuildProject(graph: ProjectGraph, parentProjectName: string, childProjectName: string, seen?: Set<string>): boolean;
15
+ export declare function getProjectConfigByPath(graph: ProjectGraph, configPath: string): ProjectConfiguration;
16
+ export declare function createExecutorContext(graph: ProjectGraph, targets: Record<string, TargetConfiguration>, projectName: string, targetName: string, configurationName: string): ExecutorContext;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createExecutorContext = exports.getProjectConfigByPath = exports.isCtProjectUsingBuildProject = exports.getTempTailwindPath = exports.CY_FILE_MATCHER = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const path_1 = require("path");
6
+ const fs_1 = require("fs");
7
+ const find_project_for_path_1 = require("nx/src/project-graph/utils/find-project-for-path");
8
+ const project_graph_1 = require("nx/src/project-graph/project-graph");
9
+ const configuration_1 = require("nx/src/config/configuration");
10
+ exports.CY_FILE_MATCHER = new RegExp(/\.cy\.[tj]sx?$/);
11
+ /**
12
+ * return a path to a temp css file
13
+ * temp file is scoped to the project root
14
+ * i.e. <context.root>/tmp/<project-root>/ct-styles.css
15
+ */
16
+ function getTempTailwindPath(context) {
17
+ if (!context.projectName) {
18
+ throw new Error('No project name found in context');
19
+ }
20
+ const project = context?.projectGraph.nodes[context.projectName];
21
+ if (!project) {
22
+ throw new Error(`No project found in project graph for ${context.projectName}`);
23
+ }
24
+ if (project?.data?.root) {
25
+ return (0, path_1.join)(context.root, 'tmp', project.data.root, 'ct-styles.css');
26
+ }
27
+ }
28
+ exports.getTempTailwindPath = getTempTailwindPath;
29
+ /**
30
+ * Checks if the childProjectName is a descendent of the parentProjectName
31
+ * in the project graph
32
+ **/
33
+ function isCtProjectUsingBuildProject(graph, parentProjectName, childProjectName, seen = new Set()) {
34
+ if (seen.has(parentProjectName)) {
35
+ return false;
36
+ }
37
+ seen.add(parentProjectName);
38
+ const isProjectDirectDep = graph.dependencies[parentProjectName].some((p) => p.target === childProjectName);
39
+ if (isProjectDirectDep) {
40
+ return true;
41
+ }
42
+ const maybeIntermediateProjects = graph.dependencies[parentProjectName].filter((p) => !graph.externalNodes[p.target]);
43
+ for (const maybeIntermediateProject of maybeIntermediateProjects) {
44
+ if (isCtProjectUsingBuildProject(graph, maybeIntermediateProject.target, childProjectName, seen)) {
45
+ return true;
46
+ }
47
+ }
48
+ return false;
49
+ }
50
+ exports.isCtProjectUsingBuildProject = isCtProjectUsingBuildProject;
51
+ function getProjectConfigByPath(graph, configPath) {
52
+ const configFileFromWorkspaceRoot = (0, path_1.relative)(devkit_1.workspaceRoot, configPath);
53
+ const normalizedPathFromWorkspaceRoot = (0, devkit_1.normalizePath)((0, fs_1.lstatSync)(configPath).isFile()
54
+ ? configFileFromWorkspaceRoot.replace((0, path_1.extname)(configPath), '')
55
+ : configFileFromWorkspaceRoot);
56
+ const projectRootMappings = (0, find_project_for_path_1.createProjectRootMappings)(graph.nodes);
57
+ const componentTestingProjectName = (0, find_project_for_path_1.findProjectForPath)(normalizedPathFromWorkspaceRoot, projectRootMappings);
58
+ if (!componentTestingProjectName ||
59
+ !graph.nodes[componentTestingProjectName]?.data) {
60
+ throw new Error((0, devkit_1.stripIndents) `Unable to find the project configuration that includes ${normalizedPathFromWorkspaceRoot}.
61
+ Found project name? ${componentTestingProjectName}.
62
+ Graph has data? ${!!graph.nodes[componentTestingProjectName]?.data}`);
63
+ }
64
+ // make sure name is set since it can be undefined
65
+ graph.nodes[componentTestingProjectName].data.name ??=
66
+ componentTestingProjectName;
67
+ return graph.nodes[componentTestingProjectName].data;
68
+ }
69
+ exports.getProjectConfigByPath = getProjectConfigByPath;
70
+ function createExecutorContext(graph, targets, projectName, targetName, configurationName) {
71
+ const projectsConfigurations = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(graph);
72
+ const nxJsonConfiguration = (0, configuration_1.readNxJson)();
73
+ return {
74
+ cwd: process.cwd(),
75
+ projectGraph: graph,
76
+ target: targets[targetName],
77
+ targetName,
78
+ configurationName,
79
+ root: devkit_1.workspaceRoot,
80
+ isVerbose: false,
81
+ projectName,
82
+ projectsConfigurations,
83
+ nxJsonConfiguration,
84
+ };
85
+ }
86
+ exports.createExecutorContext = createExecutorContext;
@@ -0,0 +1,5 @@
1
+ export declare function installedCypressVersion(): number;
2
+ /**
3
+ * will not throw if cypress is not installed
4
+ */
5
+ export declare function assertMinimumCypressVersion(minVersion: number): void;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertMinimumCypressVersion = exports.installedCypressVersion = void 0;
4
+ let cypressPackageJson;
5
+ let loadedCypress = false;
6
+ function installedCypressVersion() {
7
+ if (!loadedCypress) {
8
+ try {
9
+ cypressPackageJson = require('cypress/package.json');
10
+ }
11
+ catch { }
12
+ }
13
+ if (!cypressPackageJson) {
14
+ return null;
15
+ }
16
+ const cypressPackageVersion = cypressPackageJson.version;
17
+ const majorVersion = cypressPackageVersion.split('.')[0];
18
+ if (!majorVersion) {
19
+ return 0;
20
+ }
21
+ return +majorVersion;
22
+ }
23
+ exports.installedCypressVersion = installedCypressVersion;
24
+ /**
25
+ * will not throw if cypress is not installed
26
+ */
27
+ function assertMinimumCypressVersion(minVersion) {
28
+ const version = installedCypressVersion();
29
+ if (version && version < minVersion) {
30
+ throw new Error(`Cypress version of ${minVersion} or higher is not installed. Expected Cypress v${minVersion}+, found Cypress v${version} instead.`);
31
+ }
32
+ }
33
+ exports.assertMinimumCypressVersion = assertMinimumCypressVersion;
@@ -0,0 +1,17 @@
1
+ import { TargetConfiguration, Tree } from '@nx/devkit';
2
+ interface FindTargetOptions {
3
+ project: string;
4
+ /**
5
+ * contains buildable target such as react app or angular app
6
+ * <project>:<target>[:<configuration>]
7
+ */
8
+ buildTarget?: string;
9
+ validExecutorNames: Set<string>;
10
+ skipGetOptions?: boolean;
11
+ }
12
+ export interface FoundTarget {
13
+ config?: TargetConfiguration;
14
+ target: string;
15
+ }
16
+ export declare function findBuildConfig(tree: Tree, options: FindTargetOptions): Promise<FoundTarget>;
17
+ export {};
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findBuildConfig = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const configuration_1 = require("nx/src/config/configuration");
6
+ const project_graph_1 = require("nx/src/project-graph/project-graph");
7
+ async function findBuildConfig(tree, options) {
8
+ try {
9
+ // attempt to use the provided target
10
+ const graph = await (0, devkit_1.createProjectGraphAsync)();
11
+ if (options.buildTarget) {
12
+ return {
13
+ target: options.buildTarget,
14
+ config: findInTarget(tree, graph, options),
15
+ };
16
+ }
17
+ // check to see if there is a valid config in the given project
18
+ const selfProject = findTargetOptionsInProject(tree, graph, options.project, options);
19
+ if (selfProject) {
20
+ return selfProject;
21
+ }
22
+ // attempt to find any projects with the valid config in the graph that consumes this project
23
+ return await findInGraph(tree, graph, options);
24
+ }
25
+ catch (e) {
26
+ devkit_1.logger.error(e);
27
+ throw new Error((0, devkit_1.stripIndents) `Error trying to find build configuration. ${options.buildTarget
28
+ ? 'Try using an app of the same framework for the --build-target.'
29
+ : 'Try manually specifying the build target with the --build-target flag.'}
30
+ Provided project? ${options.project}
31
+ Provided build target? ${options.buildTarget}
32
+ Provided Executors? ${[...options.validExecutorNames].join(', ')}`);
33
+ }
34
+ }
35
+ exports.findBuildConfig = findBuildConfig;
36
+ function findInTarget(tree, graph, options) {
37
+ const { project, target, configuration } = (0, devkit_1.parseTargetString)(options.buildTarget, graph);
38
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, project);
39
+ const executorName = projectConfig?.targets?.[target]?.executor;
40
+ if (!options.validExecutorNames.has(executorName)) {
41
+ devkit_1.logger.error((0, devkit_1.stripIndents) `NX The provided build target, ${options.buildTarget}, uses the '${executorName}' executor.
42
+ But only the follow executors are allowed
43
+ ${Array.from(options.validExecutorNames)
44
+ .map((ve) => ` - ${ve}`)
45
+ .join('\n')}
46
+
47
+ ${frameworkHelperMessage(Array.from(options.buildTarget), executorName)}
48
+ This is most likely because the provided --build-target is not a build target for an application or framework.
49
+ For example, the provide build target, '${options.buildTarget}' is:
50
+ - the build target for a buildable/publishable library instead of an app.
51
+ - using a different framework than expected like react library using an angular or next app build target.
52
+
53
+ If you do not have an app in the workspace to you can make a new app with 'nx g app' and use it just for component testing
54
+ `);
55
+ throw new Error('The provided --build-target does not use an executor in the allow list of executors defined.');
56
+ }
57
+ const foundConfig = configuration || projectConfig?.targets?.[target]?.defaultConfiguration;
58
+ return (0, devkit_1.readTargetOptions)({ project, target, configuration: foundConfig }, createExecutorContext(graph, projectConfig.targets, project, target, foundConfig));
59
+ }
60
+ function frameworkHelperMessage(validExecutorNames, executorName) {
61
+ const executorsToFramework = {
62
+ '@nx/webpack:webpack': 'react',
63
+ '@nx/vite:build': 'react',
64
+ '@nrwl/webpack:webpack': 'react',
65
+ '@nrwl/vite:build': 'react',
66
+ '@nx/angular:webpack-browser': 'angular',
67
+ '@nrwl/angular:webpack-browser': 'angular',
68
+ '@angular-devkit/build-angular:browser': 'angular',
69
+ '@nx/next:build': 'next',
70
+ '@nrwl/next:build': 'next',
71
+ };
72
+ const buildTargetFramework = executorsToFramework[executorName];
73
+ const invokedGeneratorFramework = validExecutorNames.find((e) => !!executorsToFramework[e]);
74
+ if (buildTargetFramework &&
75
+ invokedGeneratorFramework &&
76
+ buildTargetFramework !== invokedGeneratorFramework) {
77
+ return `It looks like you're using a different plugin generator than the --build-target framework is set up for.
78
+ The provided build target is configured for ${buildTargetFramework} instead of ${invokedGeneratorFramework}.
79
+ Try using @nx/${buildTargetFramework} instead.`;
80
+ }
81
+ return '';
82
+ }
83
+ async function findInGraph(tree, graph, options) {
84
+ const parents = findParentsOfProject(graph, options.project);
85
+ const potentialTargets = [];
86
+ for (const parent of parents) {
87
+ const parentProject = findTargetOptionsInProject(tree, graph, parent.target, options);
88
+ if (parentProject) {
89
+ potentialTargets.push(parentProject);
90
+ }
91
+ }
92
+ if (potentialTargets.length > 1) {
93
+ devkit_1.logger.warn((0, devkit_1.stripIndents) `Multiple potential targets found for ${options.project}. Found ${potentialTargets.length}.
94
+ Using ${potentialTargets[0].target}.
95
+ To specify a different target use the --build-target flag.
96
+ `);
97
+ }
98
+ return potentialTargets[0];
99
+ }
100
+ function findParentsOfProject(graph, projectName) {
101
+ const reversedGraph = (0, devkit_1.reverse)(graph);
102
+ return reversedGraph.dependencies[projectName]
103
+ ? Object.values(reversedGraph.dependencies[projectName])
104
+ : [];
105
+ }
106
+ function findTargetOptionsInProject(tree, graph, projectName, options) {
107
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, projectName);
108
+ const includes = options.validExecutorNames;
109
+ for (const targetName in projectConfig.targets) {
110
+ const targetConfig = projectConfig.targets[targetName];
111
+ if (includes.has(targetConfig.executor)) {
112
+ return {
113
+ target: `${projectName}:${targetName}`,
114
+ config: !options.skipGetOptions
115
+ ? (0, devkit_1.readTargetOptions)({ project: projectName, target: targetName }, createExecutorContext(graph, projectConfig.targets, projectName, targetName, null))
116
+ : null,
117
+ };
118
+ }
119
+ }
120
+ }
121
+ function createExecutorContext(graph, targets, projectName, targetName, configurationName) {
122
+ const nxJsonConfiguration = (0, configuration_1.readNxJson)();
123
+ const projectsConfigurations = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(graph);
124
+ return {
125
+ cwd: process.cwd(),
126
+ projectGraph: graph,
127
+ target: targets[targetName],
128
+ targetName,
129
+ configurationName,
130
+ root: devkit_1.workspaceRoot,
131
+ isVerbose: false,
132
+ projectName,
133
+ projectsConfigurations,
134
+ nxJsonConfiguration,
135
+ };
136
+ }
@@ -0,0 +1,3 @@
1
+ export declare function getUnscopedLibName(libRoot: string): string;
2
+ export declare function getE2eProjectName(targetProjectName: string, targetLibRoot: string, cypressDirectory?: string): string;
3
+ export declare function filePathPrefix(directory: string): string;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filePathPrefix = exports.getE2eProjectName = exports.getUnscopedLibName = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ function getUnscopedLibName(libRoot) {
6
+ return libRoot.slice(libRoot.lastIndexOf('/') + 1);
7
+ }
8
+ exports.getUnscopedLibName = getUnscopedLibName;
9
+ function getE2eProjectName(targetProjectName, targetLibRoot, cypressDirectory) {
10
+ if (cypressDirectory) {
11
+ return `${filePathPrefix(cypressDirectory)}-${getUnscopedLibName(targetLibRoot)}-e2e`;
12
+ }
13
+ return `${targetProjectName}-e2e`;
14
+ }
15
+ exports.getE2eProjectName = getE2eProjectName;
16
+ function filePathPrefix(directory) {
17
+ return `${(0, devkit_1.names)(directory).fileName}`.replace(new RegExp('/', 'g'), '-');
18
+ }
19
+ exports.filePathPrefix = filePathPrefix;
@@ -0,0 +1,9 @@
1
+ import { ExecutorContext } from '@nx/devkit';
2
+ import { CypressExecutorOptions } from '../executors/cypress/cypress.impl';
3
+ export declare function startDevServer(opts: Omit<CypressExecutorOptions, 'cypressConfig'>, context: ExecutorContext): AsyncGenerator<{
4
+ baseUrl: any;
5
+ portLockFilePath?: undefined;
6
+ } | {
7
+ baseUrl: any;
8
+ portLockFilePath: string;
9
+ }, void, unknown>;
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startDevServer = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const path_1 = require("path");
6
+ const detectPort = require("detect-port");
7
+ const executor_utils_1 = require("nx/src/command-line/run/executor-utils");
8
+ const fs_1 = require("fs");
9
+ async function* startDevServer(opts, context) {
10
+ // no dev server, return the provisioned base url
11
+ if (!opts.devServerTarget || opts.skipServe) {
12
+ yield { baseUrl: opts.baseUrl };
13
+ return;
14
+ }
15
+ const parsedDevServerTarget = (0, devkit_1.parseTargetString)(opts.devServerTarget, context);
16
+ const [targetSupportsWatchOpt] = getValueFromSchema(context, parsedDevServerTarget, 'watch');
17
+ const overrides = {
18
+ // @NOTE: Do not forward watch option if not supported by the target dev server,
19
+ // this is relevant for running Cypress against dev server target that does not support this option,
20
+ // for instance @nguniversal/builders:ssr-dev-server.
21
+ ...(targetSupportsWatchOpt ? { watch: opts.watch } : {}),
22
+ };
23
+ if (opts.port === 'cypress-auto') {
24
+ const freePort = await getPortForProject(context, parsedDevServerTarget);
25
+ overrides['port'] = freePort;
26
+ }
27
+ else if (opts.port !== undefined) {
28
+ overrides['port'] = opts.port;
29
+ // zero is a special case that means any valid port so there is no reason to try to 'lock it'
30
+ if (opts.port !== 0) {
31
+ const didLock = attemptToLockPort(opts.port);
32
+ if (!didLock) {
33
+ devkit_1.logger.warn((0, devkit_1.stripIndents) `${opts.port} is potentially already in use by another cypress run.
34
+ If the port is in use, try using a different port value or passing --port='cypress-auto' to find a free port.`);
35
+ }
36
+ }
37
+ }
38
+ for await (const output of await (0, devkit_1.runExecutor)(parsedDevServerTarget, overrides, context)) {
39
+ if (!output.success && !opts.watch)
40
+ throw new Error('Could not compile application files');
41
+ if (!opts.baseUrl &&
42
+ !output.baseUrl &&
43
+ !output.info?.baseUrl &&
44
+ (output.port || output.info?.port)) {
45
+ output.baseUrl = `http://localhost:${output.info.port}`;
46
+ }
47
+ yield {
48
+ baseUrl: opts.baseUrl || output.baseUrl || output.info?.baseUrl,
49
+ portLockFilePath: overrides.port && (0, path_1.join)(__dirname, `${overrides.port}.txt`),
50
+ };
51
+ }
52
+ }
53
+ exports.startDevServer = startDevServer;
54
+ /**
55
+ * try to find a free port for the project to run on
56
+ * will return undefined if no port is found or the project doesn't have a port option
57
+ **/
58
+ async function getPortForProject(context, target, defaultPort = 4200) {
59
+ const fmtTarget = (0, devkit_1.targetToTargetString)(target);
60
+ const [hasPortOpt, schemaPortValue] = getValueFromSchema(context, target, 'port');
61
+ let freePort;
62
+ if (hasPortOpt) {
63
+ let normalizedPortValue;
64
+ if (!schemaPortValue) {
65
+ devkit_1.logger.info(`NX ${fmtTarget} did not have a defined port value, checking for free port with the default value of ${defaultPort}`);
66
+ normalizedPortValue = defaultPort;
67
+ }
68
+ else {
69
+ normalizedPortValue = Number(schemaPortValue);
70
+ }
71
+ if (isNaN(normalizedPortValue)) {
72
+ devkit_1.output.warn({
73
+ title: `Port Not a Number`,
74
+ bodyLines: [
75
+ `The port value found was not a number or can't be parsed to a number`,
76
+ `When reading the devServerTarget (${fmtTarget}) schema, expected ${schemaPortValue} to be a number but got NaN.`,
77
+ `Nx will use the default value of ${defaultPort} instead.`,
78
+ `You can manually specify a port by setting the 'port' option`,
79
+ ],
80
+ });
81
+ normalizedPortValue = defaultPort;
82
+ }
83
+ try {
84
+ let attempts = 0;
85
+ // make sure when this check happens in parallel,
86
+ // we don't let the same port be used by multiple projects
87
+ do {
88
+ freePort = await detectPort(freePort || normalizedPortValue);
89
+ if (attemptToLockPort(freePort)) {
90
+ break;
91
+ }
92
+ attempts++;
93
+ // increment port in case the lock file isn't cleaned up
94
+ freePort++;
95
+ } while (attempts < 20);
96
+ devkit_1.logger.info(`NX Using port ${freePort} for ${fmtTarget}`);
97
+ }
98
+ catch (err) {
99
+ throw new Error((0, devkit_1.stripIndents) `Unable to find a free port for the dev server, ${fmtTarget}.
100
+ You can disable auto port detection by specifing a port or not passing a value to --port`);
101
+ }
102
+ }
103
+ else {
104
+ devkit_1.output.warn({
105
+ title: `No Port Option Found`,
106
+ bodyLines: [
107
+ `The 'port' option is set to 'cypress-auto', but the devServerTarget (${fmtTarget}) does not have a port option.`,
108
+ `Because of this, Nx is unable to verify the port is free before starting the dev server.`,
109
+ `This might cause issues if the devServerTarget is trying to use a port that is already in use.`,
110
+ ],
111
+ });
112
+ }
113
+ return freePort;
114
+ }
115
+ /**
116
+ * Check if the given target has the given property in it's options.
117
+ * if the property is does not have a default value or is not in the actual executor options,
118
+ * the value will be undefined even if it's in the executor schema.
119
+ **/
120
+ function getValueFromSchema(context, target, property) {
121
+ let targetOpts;
122
+ try {
123
+ targetOpts = (0, devkit_1.readTargetOptions)(target, context);
124
+ }
125
+ catch (e) {
126
+ throw new Error(`Unable to read the target options for ${(0, devkit_1.targetToTargetString)(target)}.
127
+ Are you sure this is a valid target?
128
+ Was trying to read the target for the property: '${property}', but got the following error:
129
+ ${e.message || e}`);
130
+ }
131
+ let targetHasOpt = Object.keys(targetOpts).includes(property);
132
+ if (!targetHasOpt) {
133
+ // NOTE: readTargetOptions doesn't apply non defaulted values, i.e. @nx/vite has a port options but is optional
134
+ // so we double check the schema if readTargetOptions didn't return a value for the property
135
+ const projectConfig = context.projectsConfigurations?.projects?.[target.project];
136
+ const targetConfig = projectConfig.targets[target.target];
137
+ const [collection, executor] = targetConfig.executor.split(':');
138
+ const { schema } = (0, executor_utils_1.getExecutorInformation)(collection, executor, context.root, context.projectsConfigurations.projects);
139
+ // NOTE: schema won't have a default since readTargetOptions would have
140
+ // already set that and this check wouldn't need to be made
141
+ targetHasOpt = Object.keys(schema.properties).includes(property);
142
+ }
143
+ return [targetHasOpt, targetOpts[property]];
144
+ }
145
+ function attemptToLockPort(port) {
146
+ const portLockFilePath = (0, path_1.join)(__dirname, `${port}.txt`);
147
+ try {
148
+ if ((0, fs_1.existsSync)(portLockFilePath)) {
149
+ return false;
150
+ }
151
+ (0, fs_1.writeFileSync)(portLockFilePath, 'locked');
152
+ return true;
153
+ }
154
+ catch (err) {
155
+ return false;
156
+ }
157
+ }
@@ -0,0 +1,9 @@
1
+ export declare const nxVersion: any;
2
+ export declare const eslintPluginCypressVersion = "^2.13.4";
3
+ export declare const typesNodeVersion = "18.16.9";
4
+ export declare const cypressViteDevServerVersion = "^2.2.1";
5
+ export declare const cypressVersion = "^13.6.6";
6
+ export declare const cypressWebpackVersion = "^2.0.0";
7
+ export declare const webpackHttpPluginVersion = "^5.5.0";
8
+ export declare const viteVersion = "~5.0.0";
9
+ export declare const htmlWebpackPluginVersion = "^5.5.0";
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.htmlWebpackPluginVersion = exports.viteVersion = exports.webpackHttpPluginVersion = exports.cypressWebpackVersion = exports.cypressVersion = exports.cypressViteDevServerVersion = exports.typesNodeVersion = exports.eslintPluginCypressVersion = exports.nxVersion = void 0;
4
+ exports.nxVersion = require('../../package.json').version;
5
+ exports.eslintPluginCypressVersion = '^2.13.4';
6
+ exports.typesNodeVersion = '18.16.9';
7
+ exports.cypressViteDevServerVersion = '^2.2.1';
8
+ exports.cypressVersion = '^13.6.6';
9
+ exports.cypressWebpackVersion = '^2.0.0';
10
+ exports.webpackHttpPluginVersion = '^5.5.0';
11
+ exports.viteVersion = '~5.0.0';
12
+ exports.htmlWebpackPluginVersion = '^5.5.0';