@nx/cypress 16.8.0-beta.4 → 16.8.0-beta.6

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 (35) hide show
  1. package/migrations.json +6 -0
  2. package/package.json +7 -7
  3. package/plugins/cypress-preset.d.ts +0 -3
  4. package/plugins/cypress-preset.js +15 -7
  5. package/src/executors/cypress/cypress.impl.d.ts +1 -0
  6. package/src/executors/cypress/cypress.impl.js +180 -210
  7. package/src/executors/cypress/schema.json +4 -0
  8. package/src/generators/base-setup/base-setup.js +15 -5
  9. package/src/generators/component-configuration/component-configuration.js +42 -30
  10. package/src/generators/configuration/configuration.js +87 -70
  11. package/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.js +75 -78
  12. package/src/generators/cypress-project/cypress-project.js +76 -63
  13. package/src/generators/init/init.js +16 -18
  14. package/src/generators/migrate-to-cypress-11/conversion.util.js +22 -16
  15. package/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.js +38 -35
  16. package/src/migrations/update-12-8-0/remove-typescript-plugin.js +23 -26
  17. package/src/migrations/update-14-6-1/update-cypress-configs-presets.js +79 -68
  18. package/src/migrations/update-14-7-0/update-cypress-version-if-10.js +1 -2
  19. package/src/migrations/update-15-0-0/add-cypress-inputs.js +24 -29
  20. package/src/migrations/update-15-0-0/update-cy-mount-usage.js +25 -29
  21. package/src/migrations/update-15-1-0/cypress-11.js +34 -37
  22. package/src/migrations/update-15-5-0/update-to-cypress-12.js +3 -5
  23. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +3 -6
  24. package/src/migrations/update-16-2-0/update-cy-tsconfig.js +25 -24
  25. package/src/migrations/update-16-4-0/tsconfig-sourcemaps.js +52 -49
  26. package/src/migrations/update-16-8-0/cypress-13.d.ts +7 -0
  27. package/src/migrations/update-16-8-0/cypress-13.js +179 -0
  28. package/src/plugins/preprocessor-vite.js +7 -5
  29. package/src/utils/add-linter.js +78 -81
  30. package/src/utils/config.js +54 -62
  31. package/src/utils/ct-helpers.js +6 -8
  32. package/src/utils/cypress-version.js +1 -1
  33. package/src/utils/find-target-options.js +37 -43
  34. package/src/utils/versions.d.ts +1 -1
  35. package/src/utils/versions.js +1 -1
package/migrations.json CHANGED
@@ -59,6 +59,12 @@
59
59
  "version": "16.4.0-beta.10",
60
60
  "description": "Remove tsconfig.e2e.json and add settings to project tsconfig.json. tsConfigs executor option is now deprecated. The project level tsconfig.json file should be used instead.",
61
61
  "implementation": "./src/migrations/update-16-4-0/tsconfig-sourcemaps"
62
+ },
63
+ "update-16-8-0-cypress-13": {
64
+ "cli": "nx",
65
+ "version": "16.8.0-beta.4",
66
+ "description": "Update to Cypress v13. Most noteable change is video recording is off by default. This migration will only update if the workspace is already on Cypress v12. https://docs.cypress.io/guides/references/migration-guide#Migrating-to-Cypress-130",
67
+ "implementation": "./src/migrations/update-16-8-0/cypress-13"
62
68
  }
63
69
  },
64
70
  "packageJsonUpdates": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/cypress",
3
- "version": "16.8.0-beta.4",
3
+ "version": "16.8.0-beta.6",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Cypress contains executors and generators allowing your workspace to use the powerful Cypress integration testing capabilities.",
6
6
  "repository": {
@@ -34,17 +34,17 @@
34
34
  "migrations": "./migrations.json"
35
35
  },
36
36
  "dependencies": {
37
- "@nrwl/cypress": "16.8.0-beta.4",
38
- "@nx/devkit": "16.8.0-beta.4",
39
- "@nx/js": "16.8.0-beta.4",
40
- "@nx/linter": "16.8.0-beta.4",
37
+ "@nrwl/cypress": "16.8.0-beta.6",
38
+ "@nx/devkit": "16.8.0-beta.6",
39
+ "@nx/js": "16.8.0-beta.6",
40
+ "@nx/linter": "16.8.0-beta.6",
41
41
  "@phenomnomnominal/tsquery": "~5.0.1",
42
42
  "detect-port": "^1.5.1",
43
43
  "semver": "7.5.3",
44
44
  "tslib": "^2.3.0"
45
45
  },
46
46
  "peerDependencies": {
47
- "cypress": ">= 3 < 13"
47
+ "cypress": ">= 3 < 14"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "cypress": {
@@ -55,5 +55,5 @@
55
55
  "access": "public"
56
56
  },
57
57
  "type": "commonjs",
58
- "gitHead": "c9aad2dc8c2b34531cf61549bff872e68c481e4e"
58
+ "gitHead": "0cc6ba996f2ef09f00b932c8eacf42de642457f3"
59
59
  }
@@ -1,7 +1,6 @@
1
1
  interface BaseCypressPreset {
2
2
  videosFolder: string;
3
3
  screenshotsFolder: string;
4
- video: boolean;
5
4
  chromeWebSecurity: boolean;
6
5
  }
7
6
  export interface NxComponentTestingOptions {
@@ -39,7 +38,6 @@ export declare function nxE2EPreset(pathToConfig: string, options?: NxCypressE2E
39
38
  fixturesFolder: string;
40
39
  videosFolder: string;
41
40
  screenshotsFolder: string;
42
- video: boolean;
43
41
  chromeWebSecurity: boolean;
44
42
  } | {
45
43
  setupNodeEvents(on: any): void;
@@ -49,7 +47,6 @@ export declare function nxE2EPreset(pathToConfig: string, options?: NxCypressE2E
49
47
  fixturesFolder: string;
50
48
  videosFolder: string;
51
49
  screenshotsFolder: string;
52
- video: boolean;
53
50
  chromeWebSecurity: boolean;
54
51
  };
55
52
  export type NxCypressE2EPresetOptions = {
@@ -8,7 +8,7 @@ const preprocessor_vite_1 = require("../src/plugins/preprocessor-vite");
8
8
  function nxBaseCypressPreset(pathToConfig, options) {
9
9
  // used to set babel settings for react CT.
10
10
  process.env.NX_CYPRESS_COMPONENT_TEST =
11
- (options === null || options === void 0 ? void 0 : options.testingType) === 'component' ? 'true' : 'false';
11
+ options?.testingType === 'component' ? 'true' : 'false';
12
12
  // prevent from placing path outside the root of the workspace
13
13
  // if they pass in a file or directory
14
14
  const normalizedPath = (0, fs_1.lstatSync)(pathToConfig).isDirectory()
@@ -21,7 +21,6 @@ function nxBaseCypressPreset(pathToConfig, options) {
21
21
  return {
22
22
  videosFolder,
23
23
  screenshotsFolder,
24
- video: true,
25
24
  chromeWebSecurity: false,
26
25
  };
27
26
  }
@@ -43,12 +42,21 @@ exports.nxBaseCypressPreset = nxBaseCypressPreset;
43
42
  * @param pathToConfig will be used to construct the output paths for videos and screenshots
44
43
  */
45
44
  function nxE2EPreset(pathToConfig, options) {
46
- const basePath = (options === null || options === void 0 ? void 0 : options.cypressDir) || 'src';
47
- const baseConfig = Object.assign(Object.assign({}, nxBaseCypressPreset(pathToConfig)), { fileServerFolder: '.', supportFile: `${basePath}/support/e2e.ts`, specPattern: `${basePath}/**/*.cy.{js,jsx,ts,tsx}`, fixturesFolder: `${basePath}/fixtures` });
48
- if ((options === null || options === void 0 ? void 0 : options.bundler) === 'vite') {
49
- return Object.assign(Object.assign({}, baseConfig), { setupNodeEvents(on) {
45
+ const basePath = options?.cypressDir || 'src';
46
+ const baseConfig = {
47
+ ...nxBaseCypressPreset(pathToConfig),
48
+ fileServerFolder: '.',
49
+ supportFile: `${basePath}/support/e2e.ts`,
50
+ specPattern: `${basePath}/**/*.cy.{js,jsx,ts,tsx}`,
51
+ fixturesFolder: `${basePath}/fixtures`,
52
+ };
53
+ if (options?.bundler === 'vite') {
54
+ return {
55
+ ...baseConfig,
56
+ setupNodeEvents(on) {
50
57
  on('file:preprocessor', (0, preprocessor_vite_1.default)());
51
- } });
58
+ },
59
+ };
52
60
  }
53
61
  return baseConfig;
54
62
  }
@@ -33,6 +33,7 @@ export interface CypressExecutorOptions extends Json {
33
33
  tag?: string;
34
34
  port?: number | 'cypress-auto';
35
35
  quiet?: boolean;
36
+ runnerUi?: boolean;
36
37
  }
37
38
  export default function cypressExecutor(options: CypressExecutorOptions, context: ExecutorContext): Promise<{
38
39
  success: any;
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
3
  const devkit_1 = require("@nx/devkit");
5
4
  const executor_utils_1 = require("nx/src/command-line/run/executor-utils");
6
5
  const fs_1 = require("fs");
@@ -9,48 +8,35 @@ const ct_helpers_1 = require("../../utils/ct-helpers");
9
8
  const cypress_version_1 = require("../../utils/cypress-version");
10
9
  const detectPort = require("detect-port");
11
10
  const Cypress = require('cypress'); // @NOTE: Importing via ES6 messes the whole test dependencies.
12
- function cypressExecutor(options, context) {
13
- var _a, e_1, _b, _c;
14
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
15
- options = normalizeOptions(options, context);
16
- // this is used by cypress component testing presets to build the executor contexts with the correct configuration options.
17
- process.env.NX_CYPRESS_TARGET_CONFIGURATION = context.configurationName;
18
- let success;
11
+ async function cypressExecutor(options, context) {
12
+ options = normalizeOptions(options, context);
13
+ // this is used by cypress component testing presets to build the executor contexts with the correct configuration options.
14
+ process.env.NX_CYPRESS_TARGET_CONFIGURATION = context.configurationName;
15
+ let success;
16
+ for await (const devServerValues of startDevServer(options, context)) {
19
17
  try {
20
- for (var _d = true, _e = tslib_1.__asyncValues(startDevServer(options, context)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
21
- _c = _f.value;
22
- _d = false;
23
- const devServerValues = _c;
24
- try {
25
- success = yield runCypress(devServerValues.baseUrl, Object.assign(Object.assign({}, options), { portLockFilePath: devServerValues.portLockFilePath }));
26
- if (!options.watch)
27
- break;
28
- }
29
- catch (e) {
30
- devkit_1.logger.error(e.message);
31
- success = false;
32
- if (!options.watch)
33
- break;
34
- }
35
- }
18
+ success = await runCypress(devServerValues.baseUrl, {
19
+ ...options,
20
+ portLockFilePath: devServerValues.portLockFilePath,
21
+ });
22
+ if (!options.watch)
23
+ break;
36
24
  }
37
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
38
- finally {
39
- try {
40
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
41
- }
42
- finally { if (e_1) throw e_1.error; }
25
+ catch (e) {
26
+ devkit_1.logger.error(e.message);
27
+ success = false;
28
+ if (!options.watch)
29
+ break;
43
30
  }
44
- return { success };
45
- });
31
+ }
32
+ return { success };
46
33
  }
47
34
  exports.default = cypressExecutor;
48
35
  function normalizeOptions(options, context) {
49
- var _a, _b, _c;
50
36
  options.env = options.env || {};
51
37
  if (options.testingType === 'component') {
52
- const project = (_b = (_a = context === null || context === void 0 ? void 0 : context.projectGraph) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b[context.projectName];
53
- if ((_c = project === null || project === void 0 ? void 0 : project.data) === null || _c === void 0 ? void 0 : _c.root) {
38
+ const project = context?.projectGraph?.nodes?.[context.projectName];
39
+ if (project?.data?.root) {
54
40
  options.ctTailwindPath = (0, ct_helpers_1.getTempTailwindPath)(context);
55
41
  }
56
42
  }
@@ -104,202 +90,187 @@ A generator to migrate from v8 to v10 is provided. See https://nx.dev/cypress/v1
104
90
  `);
105
91
  }
106
92
  }
107
- function startDevServer(opts, context) {
108
- var _a, _b, _c;
109
- return tslib_1.__asyncGenerator(this, arguments, function* startDevServer_1() {
110
- var _d, e_2, _e, _f;
111
- // no dev server, return the provisioned base url
112
- if (!opts.devServerTarget || opts.skipServe) {
113
- yield yield tslib_1.__await({ baseUrl: opts.baseUrl });
114
- return yield tslib_1.__await(void 0);
115
- }
116
- const parsedDevServerTarget = (0, devkit_1.parseTargetString)(opts.devServerTarget, context.projectGraph);
117
- const [targetSupportsWatchOpt] = getValueFromSchema(context, parsedDevServerTarget, 'watch');
118
- const overrides = Object.assign({}, (targetSupportsWatchOpt ? { watch: opts.watch } : {}));
119
- if (opts.port === 'cypress-auto') {
120
- const freePort = yield tslib_1.__await(getPortForProject(context, parsedDevServerTarget));
121
- overrides['port'] = freePort;
122
- }
123
- else if (opts.port !== undefined) {
124
- overrides['port'] = opts.port;
125
- // zero is a special case that means any valid port so there is no reason to try to 'lock it'
126
- if (opts.port !== 0) {
127
- const didLock = attemptToLockPort(opts.port);
128
- if (!didLock) {
129
- devkit_1.logger.warn((0, devkit_1.stripIndents) `${opts.port} is potentially already in use by another cypress run.
93
+ async function* startDevServer(opts, context) {
94
+ // no dev server, return the provisioned base url
95
+ if (!opts.devServerTarget || opts.skipServe) {
96
+ yield { baseUrl: opts.baseUrl };
97
+ return;
98
+ }
99
+ const parsedDevServerTarget = (0, devkit_1.parseTargetString)(opts.devServerTarget, context.projectGraph);
100
+ const [targetSupportsWatchOpt] = getValueFromSchema(context, parsedDevServerTarget, 'watch');
101
+ const overrides = {
102
+ // @NOTE: Do not forward watch option if not supported by the target dev server,
103
+ // this is relevant for running Cypress against dev server target that does not support this option,
104
+ // for instance @nguniversal/builders:ssr-dev-server.
105
+ ...(targetSupportsWatchOpt ? { watch: opts.watch } : {}),
106
+ };
107
+ if (opts.port === 'cypress-auto') {
108
+ const freePort = await getPortForProject(context, parsedDevServerTarget);
109
+ overrides['port'] = freePort;
110
+ }
111
+ else if (opts.port !== undefined) {
112
+ overrides['port'] = opts.port;
113
+ // zero is a special case that means any valid port so there is no reason to try to 'lock it'
114
+ if (opts.port !== 0) {
115
+ const didLock = attemptToLockPort(opts.port);
116
+ if (!didLock) {
117
+ devkit_1.logger.warn((0, devkit_1.stripIndents) `${opts.port} is potentially already in use by another cypress run.
130
118
  If the port is in use, try using a different port value or passing --port='cypress-auto' to find a free port.`);
131
- }
132
- }
133
- }
134
- try {
135
- for (var _g = true, _h = tslib_1.__asyncValues(yield tslib_1.__await((0, devkit_1.runExecutor)(parsedDevServerTarget, overrides, context))), _j; _j = yield tslib_1.__await(_h.next()), _d = _j.done, !_d; _g = true) {
136
- _f = _j.value;
137
- _g = false;
138
- const output = _f;
139
- if (!output.success && !opts.watch)
140
- throw new Error('Could not compile application files');
141
- if (!opts.baseUrl &&
142
- !output.baseUrl &&
143
- !((_a = output.info) === null || _a === void 0 ? void 0 : _a.baseUrl) &&
144
- ((_b = output.info) === null || _b === void 0 ? void 0 : _b.port)) {
145
- output.baseUrl = `http://localhost:${output.info.port}`;
146
- }
147
- yield yield tslib_1.__await({
148
- baseUrl: opts.baseUrl || output.baseUrl || ((_c = output.info) === null || _c === void 0 ? void 0 : _c.baseUrl),
149
- portLockFilePath: overrides.port && (0, path_1.join)(__dirname, `${overrides.port}.txt`),
150
- });
151
119
  }
152
120
  }
153
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
154
- finally {
155
- try {
156
- if (!_g && !_d && (_e = _h.return)) yield tslib_1.__await(_e.call(_h));
157
- }
158
- finally { if (e_2) throw e_2.error; }
121
+ }
122
+ for await (const output of await (0, devkit_1.runExecutor)(parsedDevServerTarget, overrides, context)) {
123
+ if (!output.success && !opts.watch)
124
+ throw new Error('Could not compile application files');
125
+ if (!opts.baseUrl &&
126
+ !output.baseUrl &&
127
+ !output.info?.baseUrl &&
128
+ output.info?.port) {
129
+ output.baseUrl = `http://localhost:${output.info.port}`;
159
130
  }
160
- });
131
+ yield {
132
+ baseUrl: opts.baseUrl || output.baseUrl || output.info?.baseUrl,
133
+ portLockFilePath: overrides.port && (0, path_1.join)(__dirname, `${overrides.port}.txt`),
134
+ };
135
+ }
161
136
  }
162
137
  /**
163
138
  * @whatItDoes Initialize the Cypress test runner with the provided project configuration.
164
139
  * By default, Cypress will run tests from the CLI without the GUI and provide directly the results in the console output.
165
140
  * If `watch` is `true`: Open Cypress in the interactive GUI to interact directly with the application.
166
141
  */
167
- function runCypress(baseUrl, opts) {
168
- var _a, _b;
169
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
170
- const cypressVersion = (0, cypress_version_1.installedCypressVersion)();
171
- // Cypress expects the folder where a cypress config is present
172
- const projectFolderPath = (0, path_1.dirname)(opts.cypressConfig);
173
- const options = {
174
- project: projectFolderPath,
175
- configFile: (0, path_1.basename)(opts.cypressConfig),
142
+ async function runCypress(baseUrl, opts) {
143
+ const cypressVersion = (0, cypress_version_1.installedCypressVersion)();
144
+ // Cypress expects the folder where a cypress config is present
145
+ const projectFolderPath = (0, path_1.dirname)(opts.cypressConfig);
146
+ const options = {
147
+ project: projectFolderPath,
148
+ configFile: (0, path_1.basename)(opts.cypressConfig),
149
+ };
150
+ // If not, will use the `baseUrl` normally from `cypress.json`
151
+ if (baseUrl) {
152
+ options.config = { baseUrl };
153
+ }
154
+ if (opts.browser) {
155
+ options.browser = opts.browser;
156
+ }
157
+ if (opts.env) {
158
+ options.env = opts.env;
159
+ }
160
+ if (opts.spec) {
161
+ options.spec = opts.spec;
162
+ }
163
+ options.tag = opts.tag;
164
+ options.exit = opts.exit;
165
+ options.headed = opts.headed;
166
+ options.runnerUi = opts.runnerUi;
167
+ if (opts.headless) {
168
+ options.headless = opts.headless;
169
+ }
170
+ options.record = opts.record;
171
+ options.key = opts.key;
172
+ options.parallel = opts.parallel;
173
+ options.ciBuildId = opts.ciBuildId?.toString();
174
+ options.group = opts.group;
175
+ // renamed in cy 10
176
+ if (cypressVersion >= 10) {
177
+ options.config ??= {};
178
+ options.config[opts.testingType] = {
179
+ excludeSpecPattern: opts.ignoreTestFiles,
176
180
  };
177
- // If not, will use the `baseUrl` normally from `cypress.json`
178
- if (baseUrl) {
179
- options.config = { baseUrl };
180
- }
181
- if (opts.browser) {
182
- options.browser = opts.browser;
183
- }
184
- if (opts.env) {
185
- options.env = opts.env;
186
- }
187
- if (opts.spec) {
188
- options.spec = opts.spec;
189
- }
190
- options.tag = opts.tag;
191
- options.exit = opts.exit;
192
- options.headed = opts.headed;
193
- if (opts.headless) {
194
- options.headless = opts.headless;
195
- }
196
- options.record = opts.record;
197
- options.key = opts.key;
198
- options.parallel = opts.parallel;
199
- options.ciBuildId = (_a = opts.ciBuildId) === null || _a === void 0 ? void 0 : _a.toString();
200
- options.group = opts.group;
201
- // renamed in cy 10
202
- if (cypressVersion >= 10) {
203
- (_b = options.config) !== null && _b !== void 0 ? _b : (options.config = {});
204
- options.config[opts.testingType] = {
205
- excludeSpecPattern: opts.ignoreTestFiles,
206
- };
207
- }
208
- else {
209
- options.ignoreTestFiles = opts.ignoreTestFiles;
210
- }
211
- if (opts.reporter) {
212
- options.reporter = opts.reporter;
213
- }
214
- if (opts.reporterOptions) {
215
- options.reporterOptions = opts.reporterOptions;
216
- }
217
- if (opts.quiet) {
218
- options.quiet = opts.quiet;
219
- }
220
- options.testingType = opts.testingType;
221
- const result = yield (opts.watch
222
- ? Cypress.open(options)
223
- : Cypress.run(options));
224
- cleanupTmpFile(opts.ctTailwindPath);
225
- cleanupTmpFile(opts.portLockFilePath);
226
- if (process.env.NX_VERBOSE_LOGGING === 'true' && opts.portLockFilePath) {
227
- (0, fs_1.readdirSync)((0, path_1.dirname)(opts.portLockFilePath)).forEach((f) => {
228
- if (f.endsWith('.txt')) {
229
- devkit_1.logger.debug(`Lock file ${f} still present`);
230
- }
231
- });
232
- }
233
- /**
234
- * `cypress.open` is returning `0` and is not of the same type as `cypress.run`.
235
- * `cypress.open` is the graphical UI, so it will be obvious to know what wasn't
236
- * working. Forcing the build to success when `cypress.open` is used.
237
- */
238
- return !result.totalFailed && !result.failures;
239
- });
181
+ }
182
+ else {
183
+ options.ignoreTestFiles = opts.ignoreTestFiles;
184
+ }
185
+ if (opts.reporter) {
186
+ options.reporter = opts.reporter;
187
+ }
188
+ if (opts.reporterOptions) {
189
+ options.reporterOptions = opts.reporterOptions;
190
+ }
191
+ if (opts.quiet) {
192
+ options.quiet = opts.quiet;
193
+ }
194
+ options.testingType = opts.testingType;
195
+ const result = await (opts.watch
196
+ ? Cypress.open(options)
197
+ : Cypress.run(options));
198
+ cleanupTmpFile(opts.ctTailwindPath);
199
+ cleanupTmpFile(opts.portLockFilePath);
200
+ if (process.env.NX_VERBOSE_LOGGING === 'true' && opts.portLockFilePath) {
201
+ (0, fs_1.readdirSync)((0, path_1.dirname)(opts.portLockFilePath)).forEach((f) => {
202
+ if (f.endsWith('.txt')) {
203
+ devkit_1.logger.debug(`Lock file ${f} still present`);
204
+ }
205
+ });
206
+ }
207
+ /**
208
+ * `cypress.open` is returning `0` and is not of the same type as `cypress.run`.
209
+ * `cypress.open` is the graphical UI, so it will be obvious to know what wasn't
210
+ * working. Forcing the build to success when `cypress.open` is used.
211
+ */
212
+ return !result.totalFailed && !result.failures;
240
213
  }
241
214
  /**
242
215
  * try to find a free port for the project to run on
243
216
  * will return undefined if no port is found or the project doesn't have a port option
244
217
  **/
245
- function getPortForProject(context, target, defaultPort = 4200) {
246
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
247
- const fmtTarget = (0, devkit_1.targetToTargetString)(target);
248
- const [hasPortOpt, schemaPortValue] = getValueFromSchema(context, target, 'port');
249
- let freePort;
250
- if (hasPortOpt) {
251
- let normalizedPortValue;
252
- if (!schemaPortValue) {
253
- devkit_1.logger.info(`NX ${fmtTarget} did not have a defined port value, checking for free port with the default value of ${defaultPort}`);
254
- normalizedPortValue = defaultPort;
255
- }
256
- else {
257
- normalizedPortValue = Number(schemaPortValue);
258
- }
259
- if (isNaN(normalizedPortValue)) {
260
- devkit_1.output.warn({
261
- title: `Port Not a Number`,
262
- bodyLines: [
263
- `The port value found was not a number or can't be parsed to a number`,
264
- `When reading the devServerTarget (${fmtTarget}) schema, expected ${schemaPortValue} to be a number but got NaN.`,
265
- `Nx will use the default value of ${defaultPort} instead.`,
266
- `You can manually specify a port by setting the 'port' option`,
267
- ],
268
- });
269
- normalizedPortValue = defaultPort;
270
- }
271
- try {
272
- let attempts = 0;
273
- // make sure when this check happens in parallel,
274
- // we don't let the same port be used by multiple projects
275
- do {
276
- freePort = yield detectPort(freePort || normalizedPortValue);
277
- if (attemptToLockPort(freePort)) {
278
- break;
279
- }
280
- attempts++;
281
- // increment port in case the lock file isn't cleaned up
282
- freePort++;
283
- } while (attempts < 20);
284
- devkit_1.logger.info(`NX Using port ${freePort} for ${fmtTarget}`);
285
- }
286
- catch (err) {
287
- throw new Error((0, devkit_1.stripIndents) `Unable to find a free port for the dev server, ${fmtTarget}.
288
- You can disable auto port detection by specifing a port or not passing a value to --port`);
289
- }
218
+ async function getPortForProject(context, target, defaultPort = 4200) {
219
+ const fmtTarget = (0, devkit_1.targetToTargetString)(target);
220
+ const [hasPortOpt, schemaPortValue] = getValueFromSchema(context, target, 'port');
221
+ let freePort;
222
+ if (hasPortOpt) {
223
+ let normalizedPortValue;
224
+ if (!schemaPortValue) {
225
+ devkit_1.logger.info(`NX ${fmtTarget} did not have a defined port value, checking for free port with the default value of ${defaultPort}`);
226
+ normalizedPortValue = defaultPort;
290
227
  }
291
228
  else {
229
+ normalizedPortValue = Number(schemaPortValue);
230
+ }
231
+ if (isNaN(normalizedPortValue)) {
292
232
  devkit_1.output.warn({
293
- title: `No Port Option Found`,
233
+ title: `Port Not a Number`,
294
234
  bodyLines: [
295
- `The 'port' option is set to 'cypress-auto', but the devServerTarget (${fmtTarget}) does not have a port option.`,
296
- `Because of this, Nx is unable to verify the port is free before starting the dev server.`,
297
- `This might cause issues if the devServerTarget is trying to use a port that is already in use.`,
235
+ `The port value found was not a number or can't be parsed to a number`,
236
+ `When reading the devServerTarget (${fmtTarget}) schema, expected ${schemaPortValue} to be a number but got NaN.`,
237
+ `Nx will use the default value of ${defaultPort} instead.`,
238
+ `You can manually specify a port by setting the 'port' option`,
298
239
  ],
299
240
  });
241
+ normalizedPortValue = defaultPort;
300
242
  }
301
- return freePort;
302
- });
243
+ try {
244
+ let attempts = 0;
245
+ // make sure when this check happens in parallel,
246
+ // we don't let the same port be used by multiple projects
247
+ do {
248
+ freePort = await detectPort(freePort || normalizedPortValue);
249
+ if (attemptToLockPort(freePort)) {
250
+ break;
251
+ }
252
+ attempts++;
253
+ // increment port in case the lock file isn't cleaned up
254
+ freePort++;
255
+ } while (attempts < 20);
256
+ devkit_1.logger.info(`NX Using port ${freePort} for ${fmtTarget}`);
257
+ }
258
+ catch (err) {
259
+ throw new Error((0, devkit_1.stripIndents) `Unable to find a free port for the dev server, ${fmtTarget}.
260
+ You can disable auto port detection by specifing a port or not passing a value to --port`);
261
+ }
262
+ }
263
+ else {
264
+ devkit_1.output.warn({
265
+ title: `No Port Option Found`,
266
+ bodyLines: [
267
+ `The 'port' option is set to 'cypress-auto', but the devServerTarget (${fmtTarget}) does not have a port option.`,
268
+ `Because of this, Nx is unable to verify the port is free before starting the dev server.`,
269
+ `This might cause issues if the devServerTarget is trying to use a port that is already in use.`,
270
+ ],
271
+ });
272
+ }
273
+ return freePort;
303
274
  }
304
275
  /**
305
276
  * Check if the given target has the given property in it's options.
@@ -307,7 +278,6 @@ You can disable auto port detection by specifing a port or not passing a value t
307
278
  * the value will be undefined even if it's in the executor schema.
308
279
  **/
309
280
  function getValueFromSchema(context, target, property) {
310
- var _a, _b;
311
281
  let targetOpts;
312
282
  try {
313
283
  targetOpts = (0, devkit_1.readTargetOptions)(target, context);
@@ -322,7 +292,7 @@ ${e.message || e}`);
322
292
  if (!targetHasOpt) {
323
293
  // NOTE: readTargetOptions doesn't apply non defaulted values, i.e. @nx/vite has a port options but is optional
324
294
  // so we double check the schema if readTargetOptions didn't return a value for the property
325
- const projectConfig = (_b = (_a = context.projectsConfigurations) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b[target.project];
295
+ const projectConfig = context.projectsConfigurations?.projects?.[target.project];
326
296
  const targetConfig = projectConfig.targets[target.target];
327
297
  const [collection, executor] = targetConfig.executor.split(':');
328
298
  const { schema } = (0, executor_utils_1.getExecutorInformation)(collection, executor, context.root);
@@ -164,6 +164,10 @@
164
164
  "type": "boolean",
165
165
  "description": "If passed, Cypress output will not be printed to stdout. Only output from the configured Mocha reporter will print.",
166
166
  "default": false
167
+ },
168
+ "runnerUi": {
169
+ "type": "boolean",
170
+ "description": "Displays the Cypress Runner UI. Useful for when Test Replay is enabled and you would still like the Cypress Runner UI to be displayed for screenshots and video."
167
171
  }
168
172
  },
169
173
  "additionalProperties": true,
@@ -10,9 +10,15 @@ function addBaseCypressSetup(tree, options) {
10
10
  return;
11
11
  }
12
12
  const opts = normalizeOptions(tree, projectConfig, options);
13
- (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), projectConfig.root, Object.assign(Object.assign({}, opts), { offsetFromRoot: (0, devkit_1.offsetFromRoot)(projectConfig.root), offsetFromProjectRoot: opts.hasTsConfig ? opts.offsetFromProjectRoot : '', tsConfigPath: opts.hasTsConfig
13
+ (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), projectConfig.root, {
14
+ ...opts,
15
+ offsetFromRoot: (0, devkit_1.offsetFromRoot)(projectConfig.root),
16
+ offsetFromProjectRoot: opts.hasTsConfig ? opts.offsetFromProjectRoot : '',
17
+ tsConfigPath: opts.hasTsConfig
14
18
  ? `${opts.offsetFromProjectRoot}tsconfig.json`
15
- : (0, js_1.getRelativePathToRootTsConfig)(tree, projectConfig.root), ext: '' }));
19
+ : (0, js_1.getRelativePathToRootTsConfig)(tree, projectConfig.root),
20
+ ext: '',
21
+ });
16
22
  if (opts.hasTsConfig) {
17
23
  (0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'), (json) => {
18
24
  // tsconfig doesn't have references so it shouldn't add them
@@ -35,12 +41,16 @@ function addBaseCypressSetup(tree, options) {
35
41
  }
36
42
  exports.addBaseCypressSetup = addBaseCypressSetup;
37
43
  function normalizeOptions(tree, projectConfig, options) {
38
- var _a;
39
- (_a = options.directory) !== null && _a !== void 0 ? _a : (options.directory = 'cypress');
44
+ options.directory ??= 'cypress';
40
45
  const offsetFromProjectRoot = options.directory
41
46
  .split('/')
42
47
  .map((_) => '..')
43
48
  .join('/');
44
49
  const hasTsConfig = tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'));
45
- return Object.assign(Object.assign({}, options), { projectConfig, offsetFromProjectRoot: `${offsetFromProjectRoot}/`, hasTsConfig });
50
+ return {
51
+ ...options,
52
+ projectConfig,
53
+ offsetFromProjectRoot: `${offsetFromProjectRoot}/`,
54
+ hasTsConfig,
55
+ };
46
56
  }