@nx/cypress 24.0.0-beta.3 → 24.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugins/cypress-preset.js +47 -3
- package/dist/src/migrations/update-23-3-0/upgrade-to-cypress-16.js +3 -2
- package/dist/src/migrations/update-24-0-0/disable-wait-for-server-ready.d.ts +4 -0
- package/dist/src/migrations/update-24-0-0/disable-wait-for-server-ready.js +35 -0
- package/dist/src/migrations/update-24-0-0/disable-wait-for-server-ready.md +33 -0
- package/dist/src/plugins/plugin.d.ts +5 -0
- package/dist/src/plugins/plugin.js +3 -0
- package/dist/src/utils/find-target-options.js +0 -24
- package/migrations.json +7 -0
- package/package.json +5 -5
|
@@ -130,6 +130,19 @@ function nxE2EPreset(pathToConfig, options) {
|
|
|
130
130
|
if (options?.bundler === 'vite') {
|
|
131
131
|
on('file:preprocessor', (0, preprocessor_vite_1.default)(options?.viteConfigOverrides));
|
|
132
132
|
}
|
|
133
|
+
// Set by Nx when the web server task already reported it is ready
|
|
134
|
+
const readyUrl = process.env.NX_READY_URL;
|
|
135
|
+
if (readyUrl && isBaseUrlOverridden(config, options)) {
|
|
136
|
+
console.log(`Testing against ${config.baseUrl} from --config or CYPRESS_BASE_URL, not the server Nx started on ${readyUrl}`);
|
|
137
|
+
await waitForServer(config.baseUrl, options?.webServerConfig, (ms) => `${config.baseUrl} did not respond within ${ms}ms. This can be configured in cypress.config.ts.`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (readyUrl) {
|
|
141
|
+
config.baseUrl = (0, devkit_1.getReadyUrl)(config.baseUrl);
|
|
142
|
+
console.log(`Testing against the server Nx started on ${config.baseUrl}`);
|
|
143
|
+
// Cypress only applies config changes returned from setupNodeEvents.
|
|
144
|
+
return config;
|
|
145
|
+
}
|
|
133
146
|
if (!options?.webServerCommands) {
|
|
134
147
|
return;
|
|
135
148
|
}
|
|
@@ -158,23 +171,54 @@ function nxE2EPreset(pathToConfig, options) {
|
|
|
158
171
|
};
|
|
159
172
|
return baseConfig;
|
|
160
173
|
}
|
|
161
|
-
|
|
174
|
+
// Cypress keeps the config file's values in rawJson, without --config, and
|
|
175
|
+
// reports CYPRESS_BASE_URL as from 'env'. A config file that reads
|
|
176
|
+
// CYPRESS_BASE_URL has it in rawJson too. Inferred CI targets pass ciBaseUrl.
|
|
177
|
+
function isBaseUrlOverridden(config, options) {
|
|
178
|
+
if (!config.baseUrl) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (config.resolved?.baseUrl?.from === 'env') {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
const isInferredCiTarget = !!options?.ciWebServerCommand &&
|
|
185
|
+
config.env?.webServerCommand === options.ciWebServerCommand;
|
|
186
|
+
return (!isSameUrl(config.baseUrl, config.rawJson?.e2e?.baseUrl) &&
|
|
187
|
+
!(isInferredCiTarget && isSameUrl(config.baseUrl, options.ciBaseUrl)));
|
|
188
|
+
}
|
|
189
|
+
function isSameUrl(url, other) {
|
|
190
|
+
if (typeof other !== 'string') {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
return new URL(url).href === new URL(other).href;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return url === other;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function waitForServer(url, webServerConfig, timeoutMessage = (ms) => `Web server failed to start in ${ms}ms. This can be configured in cypress.config.ts.`) {
|
|
162
201
|
return new Promise((resolve, reject) => {
|
|
163
202
|
let pollTimeout;
|
|
164
203
|
const { protocol } = new URL(url);
|
|
204
|
+
let settled = false;
|
|
165
205
|
const timeoutDuration = webServerConfig?.timeout ?? 60 * 1000;
|
|
166
206
|
const timeout = setTimeout(() => {
|
|
207
|
+
settled = true;
|
|
167
208
|
clearTimeout(pollTimeout);
|
|
168
|
-
reject(new Error(
|
|
209
|
+
reject(new Error(timeoutMessage(timeoutDuration)));
|
|
169
210
|
}, timeoutDuration);
|
|
170
211
|
const makeRequest = protocol === 'https:' ? https_1.request : http_1.request;
|
|
171
212
|
function pollForServer() {
|
|
172
213
|
const request = makeRequest(url, () => {
|
|
214
|
+
settled = true;
|
|
173
215
|
clearTimeout(timeout);
|
|
174
216
|
resolve();
|
|
175
217
|
});
|
|
176
218
|
request.on('error', () => {
|
|
177
|
-
|
|
219
|
+
if (!settled) {
|
|
220
|
+
pollTimeout = setTimeout(pollForServer, 100);
|
|
221
|
+
}
|
|
178
222
|
});
|
|
179
223
|
// Don't forget to end the request
|
|
180
224
|
request.end();
|
|
@@ -29,8 +29,9 @@ const NX_WEBPACK_CT_PRESETS = [
|
|
|
29
29
|
'@nx/react/plugins/component-testing',
|
|
30
30
|
];
|
|
31
31
|
// Re-collects the Cypress 16 migrations: below their version, above every
|
|
32
|
-
// 23.2.x. `--from` is exclusive.
|
|
33
|
-
|
|
32
|
+
// 23.2.x. `--from` is exclusive. `--include=all` overrides nx.json and the
|
|
33
|
+
// prompt: `required` skips the upgrade and `optional` rejects `--from`.
|
|
34
|
+
const REPLAN_COMMAND = `npx nx migrate @nx/cypress@${versions_1.nxVersion} --from=@nx/cypress@23.3.0-beta.0 --include=all`;
|
|
34
35
|
const RERUN_COMMAND = `${REPLAN_COMMAND} && npx nx migrate --run-migration=@nx/cypress:upgrade-to-cypress-16`;
|
|
35
36
|
let ts;
|
|
36
37
|
async function upgradeToCypress16(tree) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = update;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const pluginName = '@nx/cypress/plugin';
|
|
6
|
+
async function update(tree) {
|
|
7
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
8
|
+
if (!nxJson?.plugins) {
|
|
9
|
+
return { skipAgentic: true };
|
|
10
|
+
}
|
|
11
|
+
let changed = false;
|
|
12
|
+
nxJson.plugins = nxJson.plugins.map((plugin) => {
|
|
13
|
+
if (typeof plugin === 'string') {
|
|
14
|
+
if (plugin !== pluginName) {
|
|
15
|
+
return plugin;
|
|
16
|
+
}
|
|
17
|
+
changed = true;
|
|
18
|
+
return { plugin, options: { waitForServerReady: false } };
|
|
19
|
+
}
|
|
20
|
+
if (plugin.plugin !== pluginName) {
|
|
21
|
+
return plugin;
|
|
22
|
+
}
|
|
23
|
+
const options = (plugin.options ?? {});
|
|
24
|
+
if (options.waitForServerReady !== undefined) {
|
|
25
|
+
return plugin;
|
|
26
|
+
}
|
|
27
|
+
changed = true;
|
|
28
|
+
return { ...plugin, options: { ...options, waitForServerReady: false } };
|
|
29
|
+
});
|
|
30
|
+
if (!changed) {
|
|
31
|
+
return { skipAgentic: true };
|
|
32
|
+
}
|
|
33
|
+
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
34
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
35
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#### Keep the Cypress e2e tasks from waiting for the dev server to be ready
|
|
2
|
+
|
|
3
|
+
The `@nx/cypress/plugin` option `waitForServerReady` now defaults to `true`.
|
|
4
|
+
With it on, the inferred e2e tasks wait for the dev server task's `readyWhen` check, and `nxE2EPreset` tests against the address the server reported instead of `baseUrl`.
|
|
5
|
+
|
|
6
|
+
This migration sets `waitForServerReady` to `false` on every `@nx/cypress/plugin` entry in `nx.json`, so existing workspaces keep the old behavior.
|
|
7
|
+
It expands a string entry into an object entry, keeps `include`, `exclude`, and other options, and leaves an entry alone when it already sets `waitForServerReady`.
|
|
8
|
+
To opt in later, set the option to `true`.
|
|
9
|
+
|
|
10
|
+
#### Sample code changes
|
|
11
|
+
|
|
12
|
+
##### Before
|
|
13
|
+
|
|
14
|
+
```json title="nx.json"
|
|
15
|
+
{
|
|
16
|
+
"plugins": ["@nx/cypress/plugin"]
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
##### After
|
|
21
|
+
|
|
22
|
+
```json title="nx.json"
|
|
23
|
+
{
|
|
24
|
+
"plugins": [
|
|
25
|
+
{
|
|
26
|
+
"plugin": "@nx/cypress/plugin",
|
|
27
|
+
"options": {
|
|
28
|
+
"waitForServerReady": false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
```
|
|
@@ -5,6 +5,11 @@ export interface CypressPluginOptions {
|
|
|
5
5
|
openTargetName?: string;
|
|
6
6
|
componentTestingTargetName?: string;
|
|
7
7
|
ciComponentTestingTargetName?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Wait for the web server task's `readyWhen` and test against the URL it
|
|
10
|
+
* reports. Defaults to `true`.
|
|
11
|
+
*/
|
|
12
|
+
waitForServerReady?: boolean;
|
|
8
13
|
}
|
|
9
14
|
export declare const createNodes: CreateNodes<CypressPluginOptions>;
|
|
10
15
|
export declare const createNodesV2: CreateNodes<CypressPluginOptions>;
|
|
@@ -177,6 +177,7 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
|
|
|
177
177
|
};
|
|
178
178
|
const webServerCommands = pluginPresetOptions?.webServerCommands;
|
|
179
179
|
const shouldReuseExistingServer = pluginPresetOptions?.reuseExistingServer ?? true;
|
|
180
|
+
const waitForServer = options.waitForServerReady === false ? {} : { waitFor: 'ready' };
|
|
180
181
|
const namedInputs = (0, internal_1.getNamedInputs)(projectRoot, context);
|
|
181
182
|
const targets = {};
|
|
182
183
|
let metadata;
|
|
@@ -211,6 +212,7 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
|
|
|
211
212
|
{
|
|
212
213
|
projects: [webServerCommandTask.project],
|
|
213
214
|
target: webServerCommandTask.target,
|
|
215
|
+
...waitForServer,
|
|
214
216
|
},
|
|
215
217
|
];
|
|
216
218
|
}
|
|
@@ -291,6 +293,7 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
|
|
|
291
293
|
{
|
|
292
294
|
target: ciWebServerCommandTask.target,
|
|
293
295
|
projects: [ciWebServerCommandTask.project],
|
|
296
|
+
...waitForServer,
|
|
294
297
|
},
|
|
295
298
|
];
|
|
296
299
|
}
|
|
@@ -42,7 +42,6 @@ ${Array.from(options.validExecutorNames)
|
|
|
42
42
|
.map((ve) => ` - ${ve}`)
|
|
43
43
|
.join('\n')}
|
|
44
44
|
|
|
45
|
-
${frameworkHelperMessage(Array.from(options.buildTarget), executorName)}
|
|
46
45
|
This is most likely because the provided --build-target is not a build target for an application or framework.
|
|
47
46
|
For example, the provide build target, '${options.buildTarget}' is:
|
|
48
47
|
- the build target for a buildable/publishable library instead of an app.
|
|
@@ -55,29 +54,6 @@ If you do not have an app in the workspace to you can make a new app with 'nx g
|
|
|
55
54
|
const foundConfig = configuration || projectConfig?.targets?.[target]?.defaultConfiguration;
|
|
56
55
|
return (0, devkit_1.readTargetOptions)({ project, target, configuration: foundConfig }, createExecutorContext(graph, projectConfig.targets, project, target, foundConfig));
|
|
57
56
|
}
|
|
58
|
-
function frameworkHelperMessage(validExecutorNames, executorName) {
|
|
59
|
-
const executorsToFramework = {
|
|
60
|
-
'@nx/webpack:webpack': 'react',
|
|
61
|
-
'@nx/vite:build': 'react',
|
|
62
|
-
'@nrwl/webpack:webpack': 'react',
|
|
63
|
-
'@nrwl/vite:build': 'react',
|
|
64
|
-
'@nx/angular:webpack-browser': 'angular',
|
|
65
|
-
'@nrwl/angular:webpack-browser': 'angular',
|
|
66
|
-
'@angular-devkit/build-angular:browser': 'angular',
|
|
67
|
-
'@nx/next:build': 'next',
|
|
68
|
-
'@nrwl/next:build': 'next',
|
|
69
|
-
};
|
|
70
|
-
const buildTargetFramework = executorsToFramework[executorName];
|
|
71
|
-
const invokedGeneratorFramework = validExecutorNames.find((e) => !!executorsToFramework[e]);
|
|
72
|
-
if (buildTargetFramework &&
|
|
73
|
-
invokedGeneratorFramework &&
|
|
74
|
-
buildTargetFramework !== invokedGeneratorFramework) {
|
|
75
|
-
return `It looks like you're using a different plugin generator than the --build-target framework is set up for.
|
|
76
|
-
The provided build target is configured for ${buildTargetFramework} instead of ${invokedGeneratorFramework}.
|
|
77
|
-
Try using @nx/${buildTargetFramework} instead.`;
|
|
78
|
-
}
|
|
79
|
-
return '';
|
|
80
|
-
}
|
|
81
57
|
async function findInGraph(tree, graph, options) {
|
|
82
58
|
const parents = findParentsOfProject(graph, options.project);
|
|
83
59
|
const potentialTargets = [];
|
package/migrations.json
CHANGED
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
"requires": {
|
|
105
105
|
"cypress": ">=15.0.0 <16.0.0"
|
|
106
106
|
},
|
|
107
|
+
"optionalUpdate": true,
|
|
107
108
|
"description": "Moves a Cypress 15 workspace to Cypress 16: bumps `cypress` and the declared `@cypress/*-dev-server` packages unless a Vite component testing config, or a config whose bundler cannot be determined statically, resolves a Vite below 8, applies the Cypress 16 config option, `overwriteQuery` and `cypress/angular` rewrites, and hands the remaining source changes to an AI prompt.",
|
|
108
109
|
"implementation": "./dist/src/migrations/update-23-3-0/upgrade-to-cypress-16",
|
|
109
110
|
"prompt": "./dist/src/migrations/update-23-3-0/ai-instructions-for-cypress-16.md",
|
|
@@ -115,6 +116,12 @@
|
|
|
115
116
|
"implementation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors",
|
|
116
117
|
"prompt": "./dist/src/migrations/update-24-0-0/finish-inferred-conversion.md",
|
|
117
118
|
"documentation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors.md"
|
|
119
|
+
},
|
|
120
|
+
"disable-wait-for-server-ready": {
|
|
121
|
+
"version": "24.0.0-beta.4",
|
|
122
|
+
"description": "Sets `waitForServerReady: false` on `@nx/cypress/plugin` entries in `nx.json` so existing Cypress e2e tasks keep starting without waiting for the dev server to report it is ready.",
|
|
123
|
+
"implementation": "./dist/src/migrations/update-24-0-0/disable-wait-for-server-ready",
|
|
124
|
+
"documentation": "./dist/src/migrations/update-24-0-0/disable-wait-for-server-ready.md"
|
|
118
125
|
}
|
|
119
126
|
},
|
|
120
127
|
"packageJsonUpdates": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/cypress",
|
|
3
|
-
"version": "24.0.0-beta.
|
|
3
|
+
"version": "24.0.0-beta.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -84,16 +84,16 @@
|
|
|
84
84
|
"supportsOptionalMigrations": true
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@nx/devkit": "24.0.0-beta.
|
|
88
|
-
"@nx/eslint": "24.0.0-beta.
|
|
89
|
-
"@nx/js": "24.0.0-beta.
|
|
87
|
+
"@nx/devkit": "24.0.0-beta.4",
|
|
88
|
+
"@nx/eslint": "24.0.0-beta.4",
|
|
89
|
+
"@nx/js": "24.0.0-beta.4",
|
|
90
90
|
"@phenomnomnominal/tsquery": "~6.2.0",
|
|
91
91
|
"semver": "^7.6.3",
|
|
92
92
|
"tree-kill": "^1.2.2",
|
|
93
93
|
"tslib": "^2.3.0"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
|
-
"nx": "24.0.0-beta.
|
|
96
|
+
"nx": "24.0.0-beta.4"
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"cypress": ">= 13 < 17"
|