@nx/playwright 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/src/executors/wait-for-webserver/wait-for-webserver.impl.js +10 -1
- package/dist/src/generators/configuration/files/playwright.config.mts.template +4 -3
- 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 +40 -0
- package/dist/src/plugins/plugin.d.ts +6 -0
- package/dist/src/plugins/plugin.js +13 -10
- package/migrations.json +6 -0
- package/package.json +5 -5
|
@@ -21,7 +21,7 @@ const FALLBACK_RETRY_DELAY = 1_000;
|
|
|
21
21
|
// nothing, so it must not replace what the previous probe saw.
|
|
22
22
|
const NO_OBSERVATION = 'the deadline passed before the server responded';
|
|
23
23
|
async function waitForWebserverExecutor(options, context) {
|
|
24
|
-
const servers = options.servers ?? [];
|
|
24
|
+
const servers = withReadyUrl(options.servers ?? []);
|
|
25
25
|
if (servers.length === 0) {
|
|
26
26
|
devkit_1.logger.error('@nx/playwright:wait-for-webserver requires at least one server to wait for.');
|
|
27
27
|
return { success: false };
|
|
@@ -49,6 +49,15 @@ async function waitForWebserverExecutor(options, context) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
exports.default = waitForWebserverExecutor;
|
|
52
|
+
// The address the server task reported when it signaled readiness. It names no
|
|
53
|
+
// server, so it only moves the url of a gate waiting for exactly one.
|
|
54
|
+
function withReadyUrl(servers) {
|
|
55
|
+
const readyUrl = process.env.NX_READY_URL;
|
|
56
|
+
if (!readyUrl || servers.length !== 1 || servers[0].port != null) {
|
|
57
|
+
return servers;
|
|
58
|
+
}
|
|
59
|
+
return [{ ...servers[0], url: (0, devkit_1.getReadyUrl)(servers[0].url) }];
|
|
60
|
+
}
|
|
52
61
|
// A malformed URL, an out-of-range port and a proxy that cannot be used are all
|
|
53
62
|
// inputs that can never become valid, so they are rejected up front instead of
|
|
54
63
|
// being retried until the timeout and reported as a slow server. An unusable
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { defineConfig, devices } from '@playwright/test';
|
|
2
2
|
import { nxE2EPreset } from '@nx/playwright/preset';
|
|
3
|
-
<% if (webServerCommand && webServerAddress) { %>import { workspaceRoot } from '@nx/devkit';<% } %>
|
|
3
|
+
<% if (webServerCommand && webServerAddress) { %>import { getReadyUrl, workspaceRoot } from '@nx/devkit';<% } %>
|
|
4
4
|
|
|
5
5
|
// For CI, you may want to set BASE_URL to the deployed application.
|
|
6
|
-
|
|
6
|
+
<% if (webServerCommand && webServerAddress) { %>// getReadyUrl moves the address to the port the dev server task reported.
|
|
7
|
+
const baseURL = process.env['BASE_URL'] || getReadyUrl('<%= webServerAddress %>');<% } else { %>const baseURL = process.env['BASE_URL'] || '<% if(webServerAddress) {%><%= webServerAddress %><% } else {%>http://localhost:3000<% } %>';<% } %>
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Read environment variables from file.
|
|
@@ -32,7 +33,7 @@ export default defineConfig({
|
|
|
32
33
|
/* Run your local dev server before starting the tests */<% if(webServerCommand && webServerAddress) {%>
|
|
33
34
|
webServer: {
|
|
34
35
|
command: '<%= webServerCommand %>',
|
|
35
|
-
url: '<%= webServerAddress %>',
|
|
36
|
+
url: getReadyUrl('<%= webServerAddress %>'),
|
|
36
37
|
reuseExistingServer: true,
|
|
37
38
|
cwd: workspaceRoot
|
|
38
39
|
},<% } else {%>
|
|
@@ -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/playwright/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,40 @@
|
|
|
1
|
+
#### Keep Playwright e2e tasks from waiting for the dev server to be ready
|
|
2
|
+
|
|
3
|
+
`@nx/playwright/plugin` has a new `waitForServerReady` option, on by default. With it on, the inferred e2e tasks wait for the dev server task's `readyWhen` and get the address it reported in `NX_READY_URL`. Before, they only waited for the dev server task to start.
|
|
4
|
+
|
|
5
|
+
This migration sets `waitForServerReady: false` on every `@nx/playwright/plugin` entry in `nx.json`, so existing workspaces keep the old behavior. Entries that already set the option stay as they are. To opt in, remove the option or set it to `true`.
|
|
6
|
+
|
|
7
|
+
#### Sample code changes
|
|
8
|
+
|
|
9
|
+
##### Before
|
|
10
|
+
|
|
11
|
+
```json title="nx.json"
|
|
12
|
+
{
|
|
13
|
+
"plugins": [
|
|
14
|
+
"@nx/playwright/plugin",
|
|
15
|
+
{
|
|
16
|
+
"plugin": "@nx/playwright/plugin",
|
|
17
|
+
"include": ["apps/admin-e2e/**"],
|
|
18
|
+
"options": { "targetName": "e2e" }
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
##### After
|
|
25
|
+
|
|
26
|
+
```json title="nx.json"
|
|
27
|
+
{
|
|
28
|
+
"plugins": [
|
|
29
|
+
{
|
|
30
|
+
"plugin": "@nx/playwright/plugin",
|
|
31
|
+
"options": { "waitForServerReady": false }
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"plugin": "@nx/playwright/plugin",
|
|
35
|
+
"include": ["apps/admin-e2e/**"],
|
|
36
|
+
"options": { "targetName": "e2e", "waitForServerReady": false }
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
@@ -16,6 +16,12 @@ export interface PlaywrightPluginOptions {
|
|
|
16
16
|
* true.
|
|
17
17
|
*/
|
|
18
18
|
waitForWebServer?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the inferred dependencies on the web server tasks wait for those
|
|
21
|
+
* tasks' `readyWhen` (`waitFor: 'ready'`) rather than for them to start.
|
|
22
|
+
* Defaults to true.
|
|
23
|
+
*/
|
|
24
|
+
waitForServerReady?: boolean;
|
|
19
25
|
}
|
|
20
26
|
export declare const createNodes: CreateNodes<PlaywrightPluginOptions>;
|
|
21
27
|
export declare const createNodesV2: CreateNodes<PlaywrightPluginOptions>;
|
|
@@ -205,7 +205,7 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
|
205
205
|
},
|
|
206
206
|
},
|
|
207
207
|
};
|
|
208
|
-
applyChainDependsOn(baseTargetConfig, e2eChain, e2eReadyTargetName);
|
|
208
|
+
applyChainDependsOn(baseTargetConfig, e2eChain, e2eReadyTargetName, options.waitForServerReady);
|
|
209
209
|
targets[options.targetName] = {
|
|
210
210
|
...baseTargetConfig,
|
|
211
211
|
cache: true,
|
|
@@ -219,10 +219,10 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
|
219
219
|
outputs: getTargetOutputs(testOutput, reporterOutputs, context.workspaceRoot, projectRoot),
|
|
220
220
|
};
|
|
221
221
|
if (e2eReadyTargetName) {
|
|
222
|
-
targets[e2eReadyTargetName] = buildWaitForWebserverTarget(e2eChain, options.webServerTimeout);
|
|
222
|
+
targets[e2eReadyTargetName] = buildWaitForWebserverTarget(e2eChain, options.webServerTimeout, options.waitForServerReady);
|
|
223
223
|
}
|
|
224
224
|
if (ciReadyTargetName && ciReadyTargetName !== e2eReadyTargetName) {
|
|
225
|
-
targets[ciReadyTargetName] = buildWaitForWebserverTarget(ciChain, options.webServerTimeout);
|
|
225
|
+
targets[ciReadyTargetName] = buildWaitForWebserverTarget(ciChain, options.webServerTimeout, options.waitForServerReady);
|
|
226
226
|
}
|
|
227
227
|
if (options.ciTargetName) {
|
|
228
228
|
// ensure the blob reporter output is the directory containing the blob
|
|
@@ -245,7 +245,7 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
|
245
245
|
// Unconditionally: the chains can differ in ways the shared-gate check
|
|
246
246
|
// deliberately ignores (an extra uncovered server flips parallelism), and
|
|
247
247
|
// re-deriving is a no-op when they match.
|
|
248
|
-
applyChainDependsOn(ciBaseTargetConfig, ciChain, ciReadyTargetName);
|
|
248
|
+
applyChainDependsOn(ciBaseTargetConfig, ciChain, ciReadyTargetName, options.waitForServerReady);
|
|
249
249
|
const groupName = 'E2E (CI)';
|
|
250
250
|
metadata = { targetGroups: { [groupName]: [] } };
|
|
251
251
|
const ciTargetGroup = metadata.targetGroups[groupName];
|
|
@@ -401,6 +401,7 @@ function normalizeOptions(options) {
|
|
|
401
401
|
ciTargetName,
|
|
402
402
|
mergeReportsTargetName: `${ciTargetName}--merge-reports`,
|
|
403
403
|
waitForWebServer: options?.waitForWebServer ?? true,
|
|
404
|
+
waitForServerReady: options?.waitForServerReady !== false,
|
|
404
405
|
};
|
|
405
406
|
}
|
|
406
407
|
function getTestOutput(playwrightConfig) {
|
|
@@ -546,7 +547,7 @@ function sameChain(a, b) {
|
|
|
546
547
|
return (JSON.stringify(a.commandTasks) === JSON.stringify(b.commandTasks) &&
|
|
547
548
|
JSON.stringify(a.readinessServers) === JSON.stringify(b.readinessServers));
|
|
548
549
|
}
|
|
549
|
-
function buildWaitForWebserverTarget(chain, webServerTimeout) {
|
|
550
|
+
function buildWaitForWebserverTarget(chain, webServerTimeout, waitForServerReady) {
|
|
550
551
|
return {
|
|
551
552
|
executor: '@nx/playwright:wait-for-webserver',
|
|
552
553
|
cache: false,
|
|
@@ -554,7 +555,7 @@ function buildWaitForWebserverTarget(chain, webServerTimeout) {
|
|
|
554
555
|
servers: chain.readinessServers,
|
|
555
556
|
...(webServerTimeout != null ? { timeout: webServerTimeout } : {}),
|
|
556
557
|
},
|
|
557
|
-
dependsOn: getDependsOn(chain.commandTasks),
|
|
558
|
+
dependsOn: getDependsOn(chain.commandTasks, waitForServerReady),
|
|
558
559
|
metadata: {
|
|
559
560
|
technologies: ['playwright'],
|
|
560
561
|
description: 'Waits for the E2E web server(s) to be ready before the Playwright test tasks run.',
|
|
@@ -693,11 +694,12 @@ function chainRequiresSerialization(chain) {
|
|
|
693
694
|
// was inferred). Set together with parallelism so a config that inherits one
|
|
694
695
|
// state (the atomized CI base copies the e2e config) cannot end up carrying
|
|
695
696
|
// both.
|
|
696
|
-
function applyChainDependsOn(targetConfig, chain, readyTargetName) {
|
|
697
|
+
function applyChainDependsOn(targetConfig, chain, readyTargetName, waitForServerReady) {
|
|
697
698
|
if (chain.commandTasks.length) {
|
|
699
|
+
const serverDependsOn = getDependsOn(chain.commandTasks, waitForServerReady);
|
|
698
700
|
targetConfig.dependsOn = readyTargetName
|
|
699
|
-
? [...
|
|
700
|
-
:
|
|
701
|
+
? [...serverDependsOn, { target: readyTargetName }]
|
|
702
|
+
: serverDependsOn;
|
|
701
703
|
}
|
|
702
704
|
else {
|
|
703
705
|
delete targetConfig.dependsOn;
|
|
@@ -709,7 +711,7 @@ function applyChainDependsOn(targetConfig, chain, readyTargetName) {
|
|
|
709
711
|
delete targetConfig.parallelism;
|
|
710
712
|
}
|
|
711
713
|
}
|
|
712
|
-
function getDependsOn(tasks) {
|
|
714
|
+
function getDependsOn(tasks, waitForServerReady) {
|
|
713
715
|
const projectsPerTask = new Map();
|
|
714
716
|
for (const { project, target } of tasks) {
|
|
715
717
|
if (!projectsPerTask.has(target)) {
|
|
@@ -720,6 +722,7 @@ function getDependsOn(tasks) {
|
|
|
720
722
|
return Array.from(projectsPerTask.entries()).map(([target, projects]) => ({
|
|
721
723
|
projects,
|
|
722
724
|
target,
|
|
725
|
+
...(waitForServerReady ? { waitFor: 'ready' } : {}),
|
|
723
726
|
}));
|
|
724
727
|
}
|
|
725
728
|
function normalizeOutput(path, workspaceRoot, projectRoot) {
|
package/migrations.json
CHANGED
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
"implementation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors",
|
|
13
13
|
"prompt": "./dist/src/migrations/update-24-0-0/finish-inferred-conversion.md",
|
|
14
14
|
"documentation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors.md"
|
|
15
|
+
},
|
|
16
|
+
"update-24-0-0-disable-wait-for-server-ready": {
|
|
17
|
+
"version": "24.0.0-beta.4",
|
|
18
|
+
"description": "Sets `waitForServerReady: false` on `@nx/playwright/plugin` entries in `nx.json` so existing Playwright e2e tasks keep starting without waiting for the dev server to report it is ready.",
|
|
19
|
+
"implementation": "./dist/src/migrations/update-24-0-0/disable-wait-for-server-ready",
|
|
20
|
+
"documentation": "./dist/src/migrations/update-24-0-0/disable-wait-for-server-ready.md"
|
|
15
21
|
}
|
|
16
22
|
}
|
|
17
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/playwright",
|
|
3
|
-
"version": "24.0.0-beta.
|
|
3
|
+
"version": "24.0.0-beta.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -75,16 +75,16 @@
|
|
|
75
75
|
"supportsOptionalMigrations": true
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@nx/devkit": "24.0.0-beta.
|
|
79
|
-
"@nx/eslint": "24.0.0-beta.
|
|
80
|
-
"@nx/js": "24.0.0-beta.
|
|
78
|
+
"@nx/devkit": "24.0.0-beta.4",
|
|
79
|
+
"@nx/eslint": "24.0.0-beta.4",
|
|
80
|
+
"@nx/js": "24.0.0-beta.4",
|
|
81
81
|
"https-proxy-agent": "^7.0.6",
|
|
82
82
|
"minimatch": "10.2.5",
|
|
83
83
|
"semver": "^7.6.3",
|
|
84
84
|
"tslib": "^2.3.0"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
|
-
"nx": "24.0.0-beta.
|
|
87
|
+
"nx": "24.0.0-beta.4"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
90
|
"@playwright/test": "^1.36.0"
|