@nx/playwright 24.0.0-pr.37405.acdaf31 → 24.0.0-rc.0
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/index.d.ts +1 -1
- package/dist/index.js +1 -3
- package/dist/src/executors/playwright/{playwright.impl.d.ts → schema.d.ts} +0 -5
- package/dist/src/executors/playwright/schema.js +2 -0
- package/dist/src/executors/wait-for-webserver/schema.json +1 -0
- package/dist/src/executors/wait-for-webserver/wait-for-webserver.impl.js +10 -1
- package/dist/src/generators/configuration/configuration.js +15 -67
- package/dist/src/generators/configuration/files/playwright.config.mts.template +12 -6
- package/dist/src/generators/configuration/schema.d.ts +10 -6
- package/dist/src/generators/configuration/schema.json +8 -6
- package/dist/src/generators/init/init.js +2 -8
- package/dist/src/generators/init/schema.d.ts +0 -1
- package/dist/src/migrations/update-24-0-0/finish-inferred-conversion.md +12 -0
- package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.d.ts +6 -0
- package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.js +10 -0
- package/dist/src/migrations/update-24-0-0/remove-deprecated-executors.md +40 -0
- package/dist/src/plugins/plugin.d.ts +20 -4
- package/dist/src/plugins/plugin.js +17 -12
- package/dist/src/utils/add-linter.d.ts +0 -5
- package/dist/src/utils/add-linter.js +1 -2
- package/executors.json +0 -5
- package/migrations.json +7 -0
- package/package.json +5 -5
- package/dist/src/executors/playwright/playwright.impl.js +0 -83
- package/dist/src/executors/playwright/schema.json +0 -166
- package/dist/src/utils/deprecation.d.ts +0 -3
- package/dist/src/utils/deprecation.js +0 -16
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { PlaywrightExecutorSchema } from './src/executors/playwright/schema';
|
|
2
2
|
export { initGenerator } from './src/generators/init/init';
|
|
3
3
|
export { configurationGenerator } from './src/generators/configuration/configuration';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.configurationGenerator = exports.initGenerator =
|
|
4
|
-
var playwright_impl_1 = require("./src/executors/playwright/playwright.impl");
|
|
5
|
-
Object.defineProperty(exports, "playwrightExecutor", { enumerable: true, get: function () { return playwright_impl_1.playwrightExecutor; } });
|
|
3
|
+
exports.configurationGenerator = exports.initGenerator = void 0;
|
|
6
4
|
var init_1 = require("./src/generators/init/init");
|
|
7
5
|
Object.defineProperty(exports, "initGenerator", { enumerable: true, get: function () { return init_1.initGenerator; } });
|
|
8
6
|
var configuration_1 = require("./src/generators/configuration/configuration");
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ExecutorContext } from '@nx/devkit';
|
|
2
1
|
export interface PlaywrightExecutorSchema {
|
|
3
2
|
browser?: 'all' | 'chromium' | 'firefox' | 'webkit' | string;
|
|
4
3
|
config?: string;
|
|
@@ -33,7 +32,3 @@ export interface PlaywrightExecutorSchema {
|
|
|
33
32
|
skipInstall?: boolean;
|
|
34
33
|
cacheDir?: string;
|
|
35
34
|
}
|
|
36
|
-
export declare function playwrightExecutor(options: PlaywrightExecutorSchema, context: ExecutorContext): Promise<{
|
|
37
|
-
success: boolean;
|
|
38
|
-
}>;
|
|
39
|
-
export default playwrightExecutor;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"title": "Schema for Playwright Wait For Web Server Executor",
|
|
5
5
|
"description": "Waits for the E2E web server(s) to be ready.",
|
|
6
6
|
"type": "object",
|
|
7
|
+
"x-deprecated": "The `@nx/playwright:wait-for-webserver` executor is deprecated and will be removed in Nx v25. The e2e targets wait for the dev server's `readyWhen` instead.",
|
|
7
8
|
"properties": {
|
|
8
9
|
"servers": {
|
|
9
10
|
"type": "array",
|
|
@@ -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
|
|
@@ -7,7 +7,6 @@ const internal_1 = require("@nx/devkit/internal");
|
|
|
7
7
|
const devkit_1 = require("@nx/devkit");
|
|
8
8
|
const js_1 = require("@nx/js");
|
|
9
9
|
const internal_2 = require("@nx/js/internal");
|
|
10
|
-
const deprecation_1 = require("../../utils/deprecation");
|
|
11
10
|
const child_process_1 = require("child_process");
|
|
12
11
|
const path = tslib_1.__importStar(require("path"));
|
|
13
12
|
const add_linter_1 = require("../../utils/add-linter");
|
|
@@ -16,7 +15,7 @@ const versions_1 = require("../../utils/versions");
|
|
|
16
15
|
const init_1 = require("../init/init");
|
|
17
16
|
const internal_3 = require("@nx/eslint/internal");
|
|
18
17
|
function configurationGenerator(tree, options) {
|
|
19
|
-
return configurationGeneratorInternal(tree,
|
|
18
|
+
return configurationGeneratorInternal(tree, options);
|
|
20
19
|
}
|
|
21
20
|
async function configurationGeneratorInternal(tree, rawOptions) {
|
|
22
21
|
(0, assert_supported_playwright_version_1.assertSupportedPlaywrightVersion)(tree);
|
|
@@ -25,7 +24,6 @@ async function configurationGeneratorInternal(tree, rawOptions) {
|
|
|
25
24
|
tasks.push(await (0, init_1.initGenerator)(tree, {
|
|
26
25
|
skipFormat: true,
|
|
27
26
|
skipPackageJson: options.skipPackageJson,
|
|
28
|
-
addPlugin: options.addPlugin,
|
|
29
27
|
}));
|
|
30
28
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
31
29
|
const offsetFromProjectRoot = (0, devkit_1.offsetFromRoot)(projectConfig.root);
|
|
@@ -44,6 +42,8 @@ async function configurationGeneratorInternal(tree, rawOptions) {
|
|
|
44
42
|
webServerAddress: options.webServerAddress ?? null,
|
|
45
43
|
isTsSolutionSetup,
|
|
46
44
|
...options,
|
|
45
|
+
...getCiWebServer(options),
|
|
46
|
+
toJsStringLiteral,
|
|
47
47
|
});
|
|
48
48
|
const playwrightConfigFile = options.js
|
|
49
49
|
? 'playwright.config.mjs'
|
|
@@ -135,23 +135,14 @@ async function configurationGeneratorInternal(tree, rawOptions) {
|
|
|
135
135
|
}
|
|
136
136
|
ignoreTestOutput(tree, options);
|
|
137
137
|
}
|
|
138
|
-
const hasPlugin = (0, devkit_1.readNxJson)(tree).plugins?.some((p) => typeof p === 'string'
|
|
139
|
-
? p === '@nx/playwright/plugin'
|
|
140
|
-
: p.plugin === '@nx/playwright/plugin');
|
|
141
|
-
if (!hasPlugin) {
|
|
142
|
-
(0, deprecation_1.warnPlaywrightExecutorGenerating)();
|
|
143
|
-
addE2eTarget(tree, options);
|
|
144
|
-
setupE2ETargetDefaults(tree);
|
|
145
|
-
}
|
|
146
138
|
tasks.push(await (0, add_linter_1.addLinterToPlaywrightProject)(tree, {
|
|
147
139
|
project: options.project,
|
|
148
140
|
linter: options.linter,
|
|
149
141
|
skipPackageJson: options.skipPackageJson,
|
|
150
142
|
js: options.js,
|
|
151
143
|
directory: options.directory,
|
|
152
|
-
enableTypedLinting:
|
|
144
|
+
enableTypedLinting: options.enableTypedLinting,
|
|
153
145
|
rootProject: options.rootProject ?? projectConfig.root === '.',
|
|
154
|
-
addPlugin: options.addPlugin,
|
|
155
146
|
}));
|
|
156
147
|
if (options.js) {
|
|
157
148
|
const { ModuleKind } = (0, internal_2.ensureTypescript)();
|
|
@@ -179,10 +170,6 @@ async function configurationGeneratorInternal(tree, rawOptions) {
|
|
|
179
170
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
180
171
|
}
|
|
181
172
|
async function normalizeOptions(tree, options) {
|
|
182
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
183
|
-
const addPlugin = options.addPlugin ??
|
|
184
|
-
(process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
185
|
-
nxJson.useInferencePlugins !== false);
|
|
186
173
|
const linter = await (0, internal_2.normalizeLinterOption)(tree, options.linter);
|
|
187
174
|
if (!options.webServerCommand || !options.webServerAddress) {
|
|
188
175
|
const { webServerCommand, webServerAddress } = await promptForMissingServeData(options.project);
|
|
@@ -191,11 +178,21 @@ async function normalizeOptions(tree, options) {
|
|
|
191
178
|
}
|
|
192
179
|
return {
|
|
193
180
|
...options,
|
|
194
|
-
addPlugin,
|
|
195
181
|
linter,
|
|
196
182
|
directory: options.directory ?? 'e2e',
|
|
197
183
|
};
|
|
198
184
|
}
|
|
185
|
+
function getCiWebServer(options) {
|
|
186
|
+
const differs = (ciValue, value) => ciValue && ciValue !== value ? ciValue : null;
|
|
187
|
+
return {
|
|
188
|
+
ciWebServerCommand: differs(options.ciWebServerCommand, options.webServerCommand),
|
|
189
|
+
ciWebServerAddress: differs(options.ciWebServerAddress, options.webServerAddress),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// The template inserts the result with `<%-`, since `<%=` would HTML-escape it.
|
|
193
|
+
function toJsStringLiteral(value) {
|
|
194
|
+
return `'${JSON.stringify(value).slice(1, -1).replace(/'/g, "\\'")}'`;
|
|
195
|
+
}
|
|
199
196
|
async function promptForMissingServeData(projectName) {
|
|
200
197
|
if (!(0, internal_1.isInteractive)()) {
|
|
201
198
|
return {
|
|
@@ -248,55 +245,6 @@ function recommendVsCodeExtensions(tree) {
|
|
|
248
245
|
});
|
|
249
246
|
}
|
|
250
247
|
}
|
|
251
|
-
function setupE2ETargetDefaults(tree) {
|
|
252
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
253
|
-
if (!nxJson.namedInputs) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
// E2e targets depend on all their project's sources + production sources of dependencies
|
|
257
|
-
const productionFileSet = !!nxJson.namedInputs?.production;
|
|
258
|
-
// Either a `target: 'e2e'` default or a default keyed on the executor
|
|
259
|
-
// we're about to scaffold will apply to the new target — consider both
|
|
260
|
-
// before deciding to add cache/inputs. Target-keyed wins when both are
|
|
261
|
-
// present.
|
|
262
|
-
const existingForTarget = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
|
|
263
|
-
target: 'e2e',
|
|
264
|
-
});
|
|
265
|
-
const existingForExecutor = (0, internal_1.findTargetDefault)(nxJson.targetDefaults, {
|
|
266
|
-
executor: '@nx/playwright:playwright',
|
|
267
|
-
});
|
|
268
|
-
const existingCache = existingForTarget?.cache ?? existingForExecutor?.cache;
|
|
269
|
-
const existingInputs = existingForTarget?.inputs ?? existingForExecutor?.inputs;
|
|
270
|
-
const patch = {};
|
|
271
|
-
if (existingCache === undefined) {
|
|
272
|
-
patch.cache = true;
|
|
273
|
-
}
|
|
274
|
-
if (existingInputs === undefined) {
|
|
275
|
-
patch.inputs = ['default', productionFileSet ? '^production' : '^default'];
|
|
276
|
-
}
|
|
277
|
-
if (Object.keys(patch).length > 0) {
|
|
278
|
-
(0, internal_1.upsertTargetDefault)(tree, nxJson, { target: 'e2e', ...patch });
|
|
279
|
-
(0, devkit_1.updateNxJson)(tree, nxJson);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
function addE2eTarget(tree, options) {
|
|
283
|
-
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
284
|
-
if (projectConfig?.targets?.e2e) {
|
|
285
|
-
throw new Error(`Project ${options.project} already has an e2e target.
|
|
286
|
-
Rename or remove the existing e2e target.`);
|
|
287
|
-
}
|
|
288
|
-
projectConfig.targets ??= {};
|
|
289
|
-
projectConfig.targets.e2e = {
|
|
290
|
-
executor: '@nx/playwright:playwright',
|
|
291
|
-
outputs: [`{workspaceRoot}/dist/.playwright/${projectConfig.root}`],
|
|
292
|
-
options: {
|
|
293
|
-
// Generator emits `playwright.config.mts` (`.mjs` for `--js`) so the
|
|
294
|
-
// legacy executor's `--config` flag must point at the same extension.
|
|
295
|
-
config: `${projectConfig.root}/playwright.config.${options.js ? 'mjs' : 'mts'}`,
|
|
296
|
-
},
|
|
297
|
-
};
|
|
298
|
-
(0, devkit_1.updateProjectConfiguration)(tree, options.project, projectConfig);
|
|
299
|
-
}
|
|
300
248
|
function ignoreTestOutput(tree, options) {
|
|
301
249
|
// Make sure playwright outputs are not linted.
|
|
302
250
|
if (options.linter === 'eslint') {
|
|
@@ -1,9 +1,15 @@
|
|
|
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
|
+
|
|
5
|
+
<% const switchesOnCI = webServerCommand && webServerAddress && (ciWebServerCommand || ciWebServerAddress); %><% if (switchesOnCI) { %>const isCI = !!process.env['CI'];
|
|
6
|
+
<% } %><% if (switchesOnCI && ciWebServerAddress) { %>// getReadyUrl moves the address to the port the server task reported.
|
|
7
|
+
const webServerAddress = getReadyUrl(isCI ? <%- toJsStringLiteral(ciWebServerAddress) %> : <%- toJsStringLiteral(webServerAddress) %>);
|
|
4
8
|
|
|
5
9
|
// For CI, you may want to set BASE_URL to the deployed application.
|
|
6
|
-
const baseURL = process.env['BASE_URL'] ||
|
|
10
|
+
const baseURL = process.env['BASE_URL'] || webServerAddress;<% } else { %>// For CI, you may want to set BASE_URL to the deployed application.
|
|
11
|
+
<% if (webServerCommand && webServerAddress) { %>// getReadyUrl moves the address to the port the dev server task reported.
|
|
12
|
+
const baseURL = process.env['BASE_URL'] || getReadyUrl(<%- toJsStringLiteral(webServerAddress) %>);<% } else { %>const baseURL = process.env['BASE_URL'] || <%- toJsStringLiteral(webServerAddress || 'http://localhost:3000') %>;<% } %><% } %>
|
|
7
13
|
|
|
8
14
|
/**
|
|
9
15
|
* Read environment variables from file.
|
|
@@ -28,14 +34,14 @@ export default defineConfig({
|
|
|
28
34
|
baseURL,
|
|
29
35
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
30
36
|
trace: 'on-first-retry',
|
|
31
|
-
}
|
|
32
|
-
/* Run your local dev server before starting the tests */<% if(webServerCommand && webServerAddress) {%>
|
|
37
|
+
},<% if(webServerCommand && webServerAddress) {%>
|
|
33
38
|
webServer: {
|
|
34
|
-
command:
|
|
35
|
-
url:
|
|
39
|
+
command: <% if (ciWebServerCommand) { %>isCI ? <%- toJsStringLiteral(ciWebServerCommand) %> : <%- toJsStringLiteral(webServerCommand) %><% } else { %><%- toJsStringLiteral(webServerCommand) %><% } %>,
|
|
40
|
+
url: <% if (ciWebServerAddress) { %>webServerAddress<% } else { %>getReadyUrl(<%- toJsStringLiteral(webServerAddress) %>)<% } %>,
|
|
36
41
|
reuseExistingServer: true,
|
|
37
42
|
cwd: workspaceRoot
|
|
38
43
|
},<% } else {%>
|
|
44
|
+
/* Run your local dev server before starting the tests */
|
|
39
45
|
// webServer: {
|
|
40
46
|
// command: 'npm run start',
|
|
41
47
|
// url: 'http://127.0.0.1:3000',
|
|
@@ -12,10 +12,6 @@ export interface ConfigurationGeneratorSchema {
|
|
|
12
12
|
skipInstall?: boolean;
|
|
13
13
|
linter?: LinterType;
|
|
14
14
|
enableTypedLinting?: boolean; // default is false
|
|
15
|
-
/**
|
|
16
|
-
* @deprecated Use `enableTypedLinting` instead. This option will be removed in Nx v24.
|
|
17
|
-
*/
|
|
18
|
-
setParserOptionsProject?: boolean; // default is false
|
|
19
15
|
/**
|
|
20
16
|
* command to give playwright to run the web server
|
|
21
17
|
* @example: "npx nx serve my-fe-app"
|
|
@@ -26,12 +22,20 @@ export interface ConfigurationGeneratorSchema {
|
|
|
26
22
|
* @example: "http://localhost:4200"
|
|
27
23
|
**/
|
|
28
24
|
webServerAddress?: string;
|
|
25
|
+
/**
|
|
26
|
+
* command to run the web server when `CI` is set; defaults to `webServerCommand`
|
|
27
|
+
* @example: "npx nx serve-static my-fe-app"
|
|
28
|
+
**/
|
|
29
|
+
ciWebServerCommand?: string;
|
|
30
|
+
/**
|
|
31
|
+
* address of the web server when `CI` is set; defaults to `webServerAddress`
|
|
32
|
+
* @example: "http://localhost:4300"
|
|
33
|
+
**/
|
|
34
|
+
ciWebServerAddress?: string;
|
|
29
35
|
rootProject?: boolean;
|
|
30
|
-
addPlugin?: boolean;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
export interface NormalizedGeneratorOptions extends ConfigurationGeneratorSchema {
|
|
34
|
-
addPlugin: boolean;
|
|
35
39
|
directory: string;
|
|
36
40
|
linter: LinterType;
|
|
37
41
|
}
|
|
@@ -39,17 +39,19 @@
|
|
|
39
39
|
"type": "string",
|
|
40
40
|
"description": "The address of the web server."
|
|
41
41
|
},
|
|
42
|
+
"ciWebServerCommand": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "The command to start the web server when the `CI` environment variable is set. Defaults to `webServerCommand`."
|
|
45
|
+
},
|
|
46
|
+
"ciWebServerAddress": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "The address of the web server when the `CI` environment variable is set. Defaults to `webServerAddress`."
|
|
49
|
+
},
|
|
42
50
|
"enableTypedLinting": {
|
|
43
51
|
"type": "boolean",
|
|
44
52
|
"description": "Whether to enable typed linting. For flat configs, this configures the recommended `parserOptions.projectService` and `tsconfigRootDir`. For legacy `.eslintrc` configs, this configures `parserOptions.project`. We do not enable this by default for lint performance reasons.",
|
|
45
53
|
"default": false
|
|
46
54
|
},
|
|
47
|
-
"setParserOptionsProject": {
|
|
48
|
-
"type": "boolean",
|
|
49
|
-
"description": "Deprecated alias for `enableTypedLinting`.",
|
|
50
|
-
"default": false,
|
|
51
|
-
"x-deprecated": "Use `enableTypedLinting` instead. This option will be removed in Nx v24."
|
|
52
|
-
},
|
|
53
55
|
"skipFormat": {
|
|
54
56
|
"description": "Skip formatting files.",
|
|
55
57
|
"type": "boolean",
|
|
@@ -8,24 +8,18 @@ const plugin_1 = require("../../plugins/plugin");
|
|
|
8
8
|
const assert_supported_playwright_version_1 = require("../../utils/assert-supported-playwright-version");
|
|
9
9
|
const versions_1 = require("../../utils/versions");
|
|
10
10
|
function initGenerator(tree, options) {
|
|
11
|
-
return initGeneratorInternal(tree,
|
|
11
|
+
return initGeneratorInternal(tree, options);
|
|
12
12
|
}
|
|
13
13
|
async function initGeneratorInternal(tree, options) {
|
|
14
14
|
(0, assert_supported_playwright_version_1.assertSupportedPlaywrightVersion)(tree);
|
|
15
15
|
const tasks = [];
|
|
16
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
17
|
-
const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
|
|
18
|
-
nxJson.useInferencePlugins !== false;
|
|
19
|
-
options.addPlugin ??= addPluginDefault;
|
|
20
16
|
if (!options.skipPackageJson) {
|
|
21
17
|
tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
|
|
22
18
|
'@nx/playwright': versions_1.nxVersion,
|
|
23
19
|
'@playwright/test': versions_1.playwrightVersion,
|
|
24
20
|
}, undefined, options.keepExistingVersions ?? true));
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
await (0, internal_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/playwright/plugin', plugin_1.createNodesV2, { targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] }, options.updatePackageScripts);
|
|
28
|
-
}
|
|
22
|
+
await (0, internal_1.addPlugin)(tree, await (0, devkit_1.createProjectGraphAsync)(), '@nx/playwright/plugin', plugin_1.createNodesV2, { targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] }, options.updatePackageScripts);
|
|
29
23
|
if (!options.skipFormat) {
|
|
30
24
|
await (0, devkit_1.formatFiles)(tree);
|
|
31
25
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Replace removed @nx/playwright executors with inferred tasks
|
|
2
|
+
|
|
3
|
+
Nx 24 removed `@nx/playwright:playwright` (including old `@nrwl` aliases).
|
|
4
|
+
|
|
5
|
+
Before changing anything, check for leftover work: a project target, a package.json target or a `targetDefaults` entry still uses a removed executor, or the advisory context reports a conversion error. If none applies, make no changes and stop. Treat each advisory-context item as pending work.
|
|
6
|
+
|
|
7
|
+
1. Inspect all affected projects and workspace defaults. Repair config-loading errors first. Do not restore executor registrations or install older Nx packages.
|
|
8
|
+
2. Preserve Playwright config, browser projects, CI sharding and webServer orchestration.
|
|
9
|
+
3. Register `@nx/playwright/plugin` with options/includes that preserve custom target names and mixed inferred/explicit projects. Replace remaining removed-executor targets, including those in package.json and filtered targetDefaults. Transfer their behavior before removing obsolete defaults. Preserve configurations, dependencies, cache inputs/outputs and environment behavior. Do not silently delete unsupported options or unrelated targets. Migrate old @nrwl aliases too.
|
|
10
|
+
4. Run project graph creation with the daemon and graph cache disabled (`NX_DAEMON=false NX_CACHE_PROJECT_GRAPH=false`), using the workspace package manager. Inspect resolved project targets and verify each migrated entrypoint exists and is inferred (a thin alias to an inferred target is acceptable). Resolve graph errors before completing this migration, even if task validation was skipped. Configs must load for subsequent migrations.
|
|
11
|
+
5. By default run relevant real builds/tests with task cache disabled, including alternate configurations. Honor an existing preference to skip expensive task validation; otherwise offer that option when validation is slow. Skipping expensive tasks never skips conversion or the graph check. Report each skipped task as unverified. Never weaken assertions or change application behavior to make checks pass.
|
|
12
|
+
6. Report converted projects, graph validation, task results and any skipped checks. Unconverted targets or a broken graph mean the migration is incomplete. Investigate task failures and distinguish missing environment prerequisites from conversion regressions; do not claim a working workspace with unresolved regressions.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = update;
|
|
4
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
5
|
+
function update(tree) {
|
|
6
|
+
return (0, internal_1.migrateRemovedExecutors)(tree, ['@nx/playwright:playwright', '@nrwl/playwright:playwright'], async (tree, options) => {
|
|
7
|
+
const { convertToInferred } = require('../../generators/convert-to-inferred/convert-to-inferred');
|
|
8
|
+
return convertToInferred(tree, options);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#### Convert `@nx/playwright:playwright` targets to inferred tasks
|
|
2
|
+
|
|
3
|
+
Nx 24 removes the `@nx/playwright:playwright` executor and its `@nrwl/playwright:playwright` alias. The migration registers `@nx/playwright/plugin` in `nx.json` and converts the targets that use those executors to inferred tasks. Options the plugin does not infer stay on the target. A target with nothing left to override is removed from project configuration. When several projects share the same remaining options, those options move to a `targetDefaults` entry scoped to the plugin. `targetDefaults` entries keyed by a removed executor are removed once no target uses that executor.
|
|
4
|
+
|
|
5
|
+
The migration lists the targets the converter cannot convert safely. In agentic runs, an AI prompt finishes them and validates the project graph.
|
|
6
|
+
|
|
7
|
+
#### Sample code changes
|
|
8
|
+
|
|
9
|
+
##### Before
|
|
10
|
+
|
|
11
|
+
```json title="myapp-e2e/project.json"
|
|
12
|
+
{
|
|
13
|
+
"name": "myapp-e2e",
|
|
14
|
+
"targets": {
|
|
15
|
+
"e2e": {
|
|
16
|
+
"executor": "@nx/playwright:playwright",
|
|
17
|
+
"outputs": ["{workspaceRoot}/dist/.playwright/myapp-e2e"],
|
|
18
|
+
"options": {
|
|
19
|
+
"config": "myapp-e2e/playwright.config.ts"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
##### After
|
|
27
|
+
|
|
28
|
+
```json title="nx.json"
|
|
29
|
+
{
|
|
30
|
+
"plugins": [
|
|
31
|
+
{
|
|
32
|
+
"plugin": "@nx/playwright/plugin",
|
|
33
|
+
"options": {
|
|
34
|
+
"ciTargetName": "e2e-ci",
|
|
35
|
+
"targetName": "e2e"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
@@ -7,15 +7,31 @@ export interface PlaywrightPluginOptions {
|
|
|
7
7
|
* for a server to be ready before failing. Overrides the `timeout` each
|
|
8
8
|
* Playwright `webServer` configures. Defaults to that configured timeout,
|
|
9
9
|
* or 60000 when neither is set.
|
|
10
|
+
*
|
|
11
|
+
* @deprecated Wait for the web server task's `readyWhen` instead, which
|
|
12
|
+
* `waitForServerReady` turns on. This option will be removed in Nx 25.
|
|
10
13
|
*/
|
|
11
14
|
webServerTimeout?: number;
|
|
12
15
|
/**
|
|
13
|
-
* Whether to infer a task that
|
|
14
|
-
* Playwright test tasks run.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* Whether to infer a task that probes the web server's port or url before the
|
|
17
|
+
* Playwright test tasks run. Defaults to false: the test tasks wait for the
|
|
18
|
+
* web server task's `readyWhen` instead. Turn it on for a server without a
|
|
19
|
+
* `readyWhen`, which counts as ready once it starts, so that Playwright's own
|
|
20
|
+
* probe doesn't miss and start a second server.
|
|
21
|
+
*
|
|
22
|
+
* @deprecated The test tasks wait for the web server task's `readyWhen`.
|
|
23
|
+
* This option will be removed in Nx 25.
|
|
17
24
|
*/
|
|
18
25
|
waitForWebServer?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Whether the inferred dependencies on the web server tasks wait for those
|
|
28
|
+
* tasks' `readyWhen` (`waitFor: 'ready'`) rather than for them to start.
|
|
29
|
+
* Defaults to true.
|
|
30
|
+
*
|
|
31
|
+
* @deprecated Leave it unset to wait for the web server task's `readyWhen`,
|
|
32
|
+
* the only behavior in Nx 25. This option will be removed in Nx 25.
|
|
33
|
+
*/
|
|
34
|
+
waitForServerReady?: boolean;
|
|
19
35
|
}
|
|
20
36
|
export declare const createNodes: CreateNodes<PlaywrightPluginOptions>;
|
|
21
37
|
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,
|
|
@@ -215,14 +215,15 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
|
215
215
|
: ['default', '^default']),
|
|
216
216
|
...tsconfigJsonInputs,
|
|
217
217
|
{ externalDependencies: ['@playwright/test'] },
|
|
218
|
+
{ env: 'CI' },
|
|
218
219
|
],
|
|
219
220
|
outputs: getTargetOutputs(testOutput, reporterOutputs, context.workspaceRoot, projectRoot),
|
|
220
221
|
};
|
|
221
222
|
if (e2eReadyTargetName) {
|
|
222
|
-
targets[e2eReadyTargetName] = buildWaitForWebserverTarget(e2eChain, options.webServerTimeout);
|
|
223
|
+
targets[e2eReadyTargetName] = buildWaitForWebserverTarget(e2eChain, options.webServerTimeout, options.waitForServerReady);
|
|
223
224
|
}
|
|
224
225
|
if (ciReadyTargetName && ciReadyTargetName !== e2eReadyTargetName) {
|
|
225
|
-
targets[ciReadyTargetName] = buildWaitForWebserverTarget(ciChain, options.webServerTimeout);
|
|
226
|
+
targets[ciReadyTargetName] = buildWaitForWebserverTarget(ciChain, options.webServerTimeout, options.waitForServerReady);
|
|
226
227
|
}
|
|
227
228
|
if (options.ciTargetName) {
|
|
228
229
|
// ensure the blob reporter output is the directory containing the blob
|
|
@@ -239,13 +240,14 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
|
239
240
|
: ['default', '^default']),
|
|
240
241
|
...tsconfigJsonInputs,
|
|
241
242
|
{ externalDependencies: ['@playwright/test'] },
|
|
243
|
+
{ env: 'CI' },
|
|
242
244
|
],
|
|
243
245
|
outputs: getTargetOutputs(testOutput, ciReporterOutputs, context.workspaceRoot, projectRoot),
|
|
244
246
|
};
|
|
245
247
|
// Unconditionally: the chains can differ in ways the shared-gate check
|
|
246
248
|
// deliberately ignores (an extra uncovered server flips parallelism), and
|
|
247
249
|
// re-deriving is a no-op when they match.
|
|
248
|
-
applyChainDependsOn(ciBaseTargetConfig, ciChain, ciReadyTargetName);
|
|
250
|
+
applyChainDependsOn(ciBaseTargetConfig, ciChain, ciReadyTargetName, options.waitForServerReady);
|
|
249
251
|
const groupName = 'E2E (CI)';
|
|
250
252
|
metadata = { targetGroups: { [groupName]: [] } };
|
|
251
253
|
const ciTargetGroup = metadata.targetGroups[groupName];
|
|
@@ -279,7 +281,7 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
|
279
281
|
const targetName = `${options.ciTargetName}--${relativeSpecFilePath}`;
|
|
280
282
|
ciTargetGroup.push(targetName);
|
|
281
283
|
targets[targetName] = {
|
|
282
|
-
...(0, internal_1.applyTestFileDirectives)(ciBaseTargetConfig, context.workspaceRoot, testFile,
|
|
284
|
+
...(0, internal_1.applyTestFileDirectives)(ciBaseTargetConfig, context.workspaceRoot, testFile, { ignoreServerInputs: true }),
|
|
283
285
|
options: {
|
|
284
286
|
...ciBaseTargetConfig.options,
|
|
285
287
|
env: getAtomizedTaskEnvVars(reporterOutputs, outputSubfolder),
|
|
@@ -400,7 +402,8 @@ function normalizeOptions(options) {
|
|
|
400
402
|
targetName: options?.targetName ?? 'e2e',
|
|
401
403
|
ciTargetName,
|
|
402
404
|
mergeReportsTargetName: `${ciTargetName}--merge-reports`,
|
|
403
|
-
waitForWebServer: options?.waitForWebServer ??
|
|
405
|
+
waitForWebServer: options?.waitForWebServer ?? false,
|
|
406
|
+
waitForServerReady: options?.waitForServerReady !== false,
|
|
404
407
|
};
|
|
405
408
|
}
|
|
406
409
|
function getTestOutput(playwrightConfig) {
|
|
@@ -546,7 +549,7 @@ function sameChain(a, b) {
|
|
|
546
549
|
return (JSON.stringify(a.commandTasks) === JSON.stringify(b.commandTasks) &&
|
|
547
550
|
JSON.stringify(a.readinessServers) === JSON.stringify(b.readinessServers));
|
|
548
551
|
}
|
|
549
|
-
function buildWaitForWebserverTarget(chain, webServerTimeout) {
|
|
552
|
+
function buildWaitForWebserverTarget(chain, webServerTimeout, waitForServerReady) {
|
|
550
553
|
return {
|
|
551
554
|
executor: '@nx/playwright:wait-for-webserver',
|
|
552
555
|
cache: false,
|
|
@@ -554,7 +557,7 @@ function buildWaitForWebserverTarget(chain, webServerTimeout) {
|
|
|
554
557
|
servers: chain.readinessServers,
|
|
555
558
|
...(webServerTimeout != null ? { timeout: webServerTimeout } : {}),
|
|
556
559
|
},
|
|
557
|
-
dependsOn: getDependsOn(chain.commandTasks),
|
|
560
|
+
dependsOn: getDependsOn(chain.commandTasks, waitForServerReady),
|
|
558
561
|
metadata: {
|
|
559
562
|
technologies: ['playwright'],
|
|
560
563
|
description: 'Waits for the E2E web server(s) to be ready before the Playwright test tasks run.',
|
|
@@ -693,11 +696,12 @@ function chainRequiresSerialization(chain) {
|
|
|
693
696
|
// was inferred). Set together with parallelism so a config that inherits one
|
|
694
697
|
// state (the atomized CI base copies the e2e config) cannot end up carrying
|
|
695
698
|
// both.
|
|
696
|
-
function applyChainDependsOn(targetConfig, chain, readyTargetName) {
|
|
699
|
+
function applyChainDependsOn(targetConfig, chain, readyTargetName, waitForServerReady) {
|
|
697
700
|
if (chain.commandTasks.length) {
|
|
701
|
+
const serverDependsOn = getDependsOn(chain.commandTasks, waitForServerReady);
|
|
698
702
|
targetConfig.dependsOn = readyTargetName
|
|
699
|
-
? [...
|
|
700
|
-
:
|
|
703
|
+
? [...serverDependsOn, { target: readyTargetName }]
|
|
704
|
+
: serverDependsOn;
|
|
701
705
|
}
|
|
702
706
|
else {
|
|
703
707
|
delete targetConfig.dependsOn;
|
|
@@ -709,7 +713,7 @@ function applyChainDependsOn(targetConfig, chain, readyTargetName) {
|
|
|
709
713
|
delete targetConfig.parallelism;
|
|
710
714
|
}
|
|
711
715
|
}
|
|
712
|
-
function getDependsOn(tasks) {
|
|
716
|
+
function getDependsOn(tasks, waitForServerReady) {
|
|
713
717
|
const projectsPerTask = new Map();
|
|
714
718
|
for (const { project, target } of tasks) {
|
|
715
719
|
if (!projectsPerTask.has(target)) {
|
|
@@ -720,6 +724,7 @@ function getDependsOn(tasks) {
|
|
|
720
724
|
return Array.from(projectsPerTask.entries()).map(([target, projects]) => ({
|
|
721
725
|
projects,
|
|
722
726
|
target,
|
|
727
|
+
...(waitForServerReady ? { waitFor: 'ready' } : {}),
|
|
723
728
|
}));
|
|
724
729
|
}
|
|
725
730
|
function normalizeOutput(path, workspaceRoot, projectRoot) {
|
|
@@ -4,10 +4,6 @@ export interface PlaywrightLinterOptions {
|
|
|
4
4
|
project: string;
|
|
5
5
|
linter: LinterType;
|
|
6
6
|
enableTypedLinting?: boolean;
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated Use `enableTypedLinting` instead. This option will be removed in Nx v24.
|
|
9
|
-
*/
|
|
10
|
-
setParserOptionsProject?: boolean;
|
|
11
7
|
skipPackageJson: boolean;
|
|
12
8
|
rootProject: boolean;
|
|
13
9
|
js?: boolean;
|
|
@@ -15,6 +11,5 @@ export interface PlaywrightLinterOptions {
|
|
|
15
11
|
* Directory from the project root, where the playwright files will be located.
|
|
16
12
|
**/
|
|
17
13
|
directory: string;
|
|
18
|
-
addPlugin?: boolean;
|
|
19
14
|
}
|
|
20
15
|
export declare function addLinterToPlaywrightProject(tree: Tree, options: PlaywrightLinterOptions): Promise<GeneratorCallback>;
|
|
@@ -12,7 +12,7 @@ async function addLinterToPlaywrightProject(tree, options) {
|
|
|
12
12
|
const tasks = [];
|
|
13
13
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
14
14
|
const eslintFile = (0, internal_1.findEslintFile)(tree, projectConfig.root);
|
|
15
|
-
const enableTypedLinting =
|
|
15
|
+
const { enableTypedLinting } = options;
|
|
16
16
|
// An existing ESLint config means the project is already registered, so skip
|
|
17
17
|
// straight to the Playwright-specific shaping below.
|
|
18
18
|
if (options.linter !== 'eslint' || !eslintFile) {
|
|
@@ -23,7 +23,6 @@ async function addLinterToPlaywrightProject(tree, options) {
|
|
|
23
23
|
enableTypedLinting,
|
|
24
24
|
skipPackageJson: options.skipPackageJson,
|
|
25
25
|
rootProject: options.rootProject,
|
|
26
|
-
addPlugin: options.addPlugin,
|
|
27
26
|
}));
|
|
28
27
|
}
|
|
29
28
|
// Everything below configures ESLint — predefined configs, `extends`, ignore
|
package/executors.json
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"executors": {
|
|
3
|
-
"playwright": {
|
|
4
|
-
"implementation": "./dist/src/executors/playwright/playwright.impl",
|
|
5
|
-
"schema": "./dist/src/executors/playwright/schema.json",
|
|
6
|
-
"description": "Run Playwright tests."
|
|
7
|
-
},
|
|
8
3
|
"merge-reports": {
|
|
9
4
|
"implementation": "./dist/src/executors/merge-reports/merge-reports.impl",
|
|
10
5
|
"schema": "./dist/src/executors/merge-reports/schema.json",
|
package/migrations.json
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
"description": "Rename imports of `createNodesV2` from `@nx/playwright/plugin` to the canonical `createNodes` export.",
|
|
6
6
|
"implementation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes",
|
|
7
7
|
"documentation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.md"
|
|
8
|
+
},
|
|
9
|
+
"remove-deprecated-executors": {
|
|
10
|
+
"version": "24.0.0-beta.3",
|
|
11
|
+
"description": "Converts targets using the removed `@nx/playwright` executors to inferred tasks; an AI prompt finishes the targets the converter cannot convert safely and validates the project graph.",
|
|
12
|
+
"implementation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors",
|
|
13
|
+
"prompt": "./dist/src/migrations/update-24-0-0/finish-inferred-conversion.md",
|
|
14
|
+
"documentation": "./dist/src/migrations/update-24-0-0/remove-deprecated-executors.md"
|
|
8
15
|
}
|
|
9
16
|
}
|
|
10
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/playwright",
|
|
3
|
-
"version": "24.0.0-
|
|
3
|
+
"version": "24.0.0-rc.0",
|
|
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-
|
|
79
|
-
"@nx/eslint": "24.0.0-
|
|
80
|
-
"@nx/js": "24.0.0-
|
|
78
|
+
"@nx/devkit": "24.0.0-rc.0",
|
|
79
|
+
"@nx/eslint": "24.0.0-rc.0",
|
|
80
|
+
"@nx/js": "24.0.0-rc.0",
|
|
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-
|
|
87
|
+
"nx": "24.0.0-rc.0"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
90
|
"@playwright/test": "^1.36.0"
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.playwrightExecutor = playwrightExecutor;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const child_process_1 = require("child_process");
|
|
6
|
-
const deprecation_1 = require("../../utils/deprecation");
|
|
7
|
-
async function playwrightExecutor(options, context) {
|
|
8
|
-
(0, deprecation_1.warnPlaywrightExecutorDeprecation)();
|
|
9
|
-
const projectRoot = context.projectGraph?.nodes?.[context?.projectName]?.data?.root;
|
|
10
|
-
if (!projectRoot) {
|
|
11
|
-
throw new Error(`Unable to find the Project Root for ${context.projectName}. Is it set in the project.json?`);
|
|
12
|
-
}
|
|
13
|
-
if (!options.skipInstall) {
|
|
14
|
-
devkit_1.output.log({
|
|
15
|
-
title: 'Ensuring Playwright is installed.',
|
|
16
|
-
bodyLines: ['use --skipInstall to skip installation.'],
|
|
17
|
-
});
|
|
18
|
-
const pmc = (0, devkit_1.getPackageManagerCommand)();
|
|
19
|
-
(0, child_process_1.execSync)(`${pmc.exec} playwright install`, {
|
|
20
|
-
cwd: devkit_1.workspaceRoot,
|
|
21
|
-
stdio: 'inherit',
|
|
22
|
-
windowsHide: true,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
const args = createArgs(options);
|
|
26
|
-
const env = options.cacheDir
|
|
27
|
-
? { ...process.env, PWTEST_CACHE_DIR: options.cacheDir }
|
|
28
|
-
: undefined;
|
|
29
|
-
const p = runPlaywright(args, context.root, env);
|
|
30
|
-
p.stdout.on('data', (message) => {
|
|
31
|
-
process.stdout.write(message);
|
|
32
|
-
});
|
|
33
|
-
p.stderr.on('data', (message) => {
|
|
34
|
-
process.stderr.write(message);
|
|
35
|
-
});
|
|
36
|
-
return new Promise((resolve) => {
|
|
37
|
-
p.on('close', (code) => {
|
|
38
|
-
resolve({ success: code === 0 });
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function createArgs(opts, exclude = ['skipInstall', 'cacheDir']) {
|
|
43
|
-
const args = [];
|
|
44
|
-
const { testFiles, ...rest } = opts;
|
|
45
|
-
if (testFiles) {
|
|
46
|
-
args.push(...testFiles);
|
|
47
|
-
}
|
|
48
|
-
for (const key in rest) {
|
|
49
|
-
if (exclude.includes(key))
|
|
50
|
-
continue;
|
|
51
|
-
const value = opts[key];
|
|
52
|
-
// NOTE: playwright doesn't accept pascalCase args, only kebab-case
|
|
53
|
-
const arg = (0, devkit_1.names)(key).fileName;
|
|
54
|
-
if (Array.isArray(value)) {
|
|
55
|
-
args.push(...value.map((v) => `--${arg}=${v.trim()}`));
|
|
56
|
-
}
|
|
57
|
-
else if (typeof value === 'boolean') {
|
|
58
|
-
// NOTE: playwright don't accept --arg=false, instead just don't pass the arg.
|
|
59
|
-
if (value) {
|
|
60
|
-
args.push(`--${arg}`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
args.push(`--${arg}=${value}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return args;
|
|
68
|
-
}
|
|
69
|
-
function runPlaywright(args, cwd, env) {
|
|
70
|
-
try {
|
|
71
|
-
const cli = require.resolve('@playwright/test/cli');
|
|
72
|
-
return (0, child_process_1.fork)(cli, ['test', ...args], {
|
|
73
|
-
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
74
|
-
cwd,
|
|
75
|
-
...(env ? { env } : {}),
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
catch (e) {
|
|
79
|
-
console.error(e);
|
|
80
|
-
throw new Error('Unable to run playwright. Is @playwright/test installed?');
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
exports.default = playwrightExecutor;
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/schema",
|
|
3
|
-
"version": 2,
|
|
4
|
-
"title": "Playwright executor",
|
|
5
|
-
"description": "Run Playwright tests.",
|
|
6
|
-
"x-deprecated": "The `@nx/playwright:playwright` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/playwright:convert-to-inferred` to migrate to the `@nx/playwright/plugin` inferred targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.",
|
|
7
|
-
"type": "object",
|
|
8
|
-
"properties": {
|
|
9
|
-
"browser": {
|
|
10
|
-
"type": "string",
|
|
11
|
-
"description": "Browser to use for tests, one of 'all', 'chromium', 'firefox' or 'webkit'. If a playwright config is provided/discovered then the browserName value is expected from the configured 'projects'",
|
|
12
|
-
"x-priority": "important"
|
|
13
|
-
},
|
|
14
|
-
"config": {
|
|
15
|
-
"type": "string",
|
|
16
|
-
"description": "Configuration file, or a test directory with optional",
|
|
17
|
-
"x-completion-type": "file",
|
|
18
|
-
"x-completion-glob": "playwright?(*)@(.js|.cjs|.mjs|.ts|.cts|.mtx)",
|
|
19
|
-
"x-priority": "important"
|
|
20
|
-
},
|
|
21
|
-
"debug": {
|
|
22
|
-
"type": "boolean",
|
|
23
|
-
"description": "Run tests with Playwright Inspector. Shortcut for 'PWDEBUG=1' environment variable and '--timeout=0',--max-failures=1 --headed --workers=1' options"
|
|
24
|
-
},
|
|
25
|
-
"lastFailed": {
|
|
26
|
-
"type": "boolean",
|
|
27
|
-
"description": "Run only the tests that failed in the last run"
|
|
28
|
-
},
|
|
29
|
-
"forbidOnly": {
|
|
30
|
-
"type": "boolean",
|
|
31
|
-
"description": "Fail if test.only is called"
|
|
32
|
-
},
|
|
33
|
-
"fullyParallel": {
|
|
34
|
-
"type": "boolean",
|
|
35
|
-
"description": "Run all tests in parallel"
|
|
36
|
-
},
|
|
37
|
-
"grep": {
|
|
38
|
-
"alias": "g",
|
|
39
|
-
"type": "string",
|
|
40
|
-
"description": "Only run tests matching this regular expression"
|
|
41
|
-
},
|
|
42
|
-
"globalTimeout": {
|
|
43
|
-
"type": "number",
|
|
44
|
-
"description": "Maximum time this test suite can run in milliseconds"
|
|
45
|
-
},
|
|
46
|
-
"grepInvert": {
|
|
47
|
-
"alias": "gv",
|
|
48
|
-
"type": "string",
|
|
49
|
-
"description": "Only run tests that do not match this regular expression"
|
|
50
|
-
},
|
|
51
|
-
"testFiles": {
|
|
52
|
-
"alias": "t",
|
|
53
|
-
"type": "array",
|
|
54
|
-
"description": "Test files to run",
|
|
55
|
-
"items": {
|
|
56
|
-
"type": "string"
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"headed": {
|
|
60
|
-
"type": "boolean",
|
|
61
|
-
"description": "Run tests in headed browsers",
|
|
62
|
-
"x-priority": "important"
|
|
63
|
-
},
|
|
64
|
-
"ignoreSnapshots": {
|
|
65
|
-
"type": "boolean",
|
|
66
|
-
"description": "Ignore screenshot and snapshot expectations"
|
|
67
|
-
},
|
|
68
|
-
"workers": {
|
|
69
|
-
"alias": "j",
|
|
70
|
-
"oneOf": [{ "type": "number" }, { "type": "string" }],
|
|
71
|
-
"description": "Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker"
|
|
72
|
-
},
|
|
73
|
-
"list": {
|
|
74
|
-
"type": "boolean",
|
|
75
|
-
"description": "Collect all the tests and report them, but do not run"
|
|
76
|
-
},
|
|
77
|
-
"maxFailures": {
|
|
78
|
-
"alias": "x",
|
|
79
|
-
"oneOf": [{ "type": "number" }, { "type": "boolean" }],
|
|
80
|
-
"description": "Stop after the first N failures"
|
|
81
|
-
},
|
|
82
|
-
"noDeps": {
|
|
83
|
-
"type": "boolean",
|
|
84
|
-
"description": "Do not run project dependencies"
|
|
85
|
-
},
|
|
86
|
-
"output": {
|
|
87
|
-
"type": "string",
|
|
88
|
-
"description": "Folder for output artifacts"
|
|
89
|
-
},
|
|
90
|
-
"passWithNoTests": {
|
|
91
|
-
"type": "boolean",
|
|
92
|
-
"description": "Makes test run succeed even if no tests were found",
|
|
93
|
-
"default": true
|
|
94
|
-
},
|
|
95
|
-
"project": {
|
|
96
|
-
"description": "Only run tests from the specified list of projects",
|
|
97
|
-
"type": "array",
|
|
98
|
-
"items": {
|
|
99
|
-
"type": "string"
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
"quiet": {
|
|
103
|
-
"alias": "q",
|
|
104
|
-
"type": "boolean",
|
|
105
|
-
"description": "Suppress stdio"
|
|
106
|
-
},
|
|
107
|
-
"repeatEach": {
|
|
108
|
-
"type": "number",
|
|
109
|
-
"description": "Run each test N times"
|
|
110
|
-
},
|
|
111
|
-
"reporter": {
|
|
112
|
-
"type": "string",
|
|
113
|
-
"description": "Common Reporter values to use, comma-separated, 'list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html', 'blob'. To configure reporter options, use the playwright configuration."
|
|
114
|
-
},
|
|
115
|
-
"retries": {
|
|
116
|
-
"type": "number",
|
|
117
|
-
"description": "Maximum retry count for flaky tests, zero for no retries"
|
|
118
|
-
},
|
|
119
|
-
"shard": {
|
|
120
|
-
"type": "string",
|
|
121
|
-
"description": "Shard tests and execute only the selected shard, specify in the form 'current/all', 1-based, for example '3/5'"
|
|
122
|
-
},
|
|
123
|
-
"timeout": {
|
|
124
|
-
"type": "number",
|
|
125
|
-
"description": "Specify test timeout threshold in milliseconds, zero for unlimited"
|
|
126
|
-
},
|
|
127
|
-
"trace": {
|
|
128
|
-
"type": "string",
|
|
129
|
-
"enum": [
|
|
130
|
-
"on",
|
|
131
|
-
"off",
|
|
132
|
-
"on-first-retry",
|
|
133
|
-
"on-all-retries",
|
|
134
|
-
"retain-on-failure"
|
|
135
|
-
],
|
|
136
|
-
"description": "Force tracing mode, can be 'on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure'"
|
|
137
|
-
},
|
|
138
|
-
"updateSnapshots": {
|
|
139
|
-
"alias": "u",
|
|
140
|
-
"type": "boolean",
|
|
141
|
-
"description": "Update snapshots with actual results. Snapshots will be created if missing."
|
|
142
|
-
},
|
|
143
|
-
"ui": {
|
|
144
|
-
"type": "boolean",
|
|
145
|
-
"description": "Run tests in interactive UI mode"
|
|
146
|
-
},
|
|
147
|
-
"uiHost": {
|
|
148
|
-
"type": "string",
|
|
149
|
-
"description": "Host to serve UI on; specifying this option opens UI in a browser tab"
|
|
150
|
-
},
|
|
151
|
-
"uiPort": {
|
|
152
|
-
"type": "number",
|
|
153
|
-
"description": "Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab"
|
|
154
|
-
},
|
|
155
|
-
"skipInstall": {
|
|
156
|
-
"type": "boolean",
|
|
157
|
-
"description": "Skip running playwright install before running playwright tests. This is to ensure that playwright browsers are installed before running tests.",
|
|
158
|
-
"default": false
|
|
159
|
-
},
|
|
160
|
-
"cacheDir": {
|
|
161
|
-
"type": "string",
|
|
162
|
-
"description": "Directory for Playwright internal cache (browser binaries, etc.). Sets the PWTEST_CACHE_DIR environment variable."
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
"required": []
|
|
166
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export declare const PLAYWRIGHT_EXECUTOR_DEPRECATION_MESSAGE = "The `@nx/playwright:playwright` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/playwright:convert-to-inferred` to migrate to the `@nx/playwright/plugin` inferred targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.";
|
|
2
|
-
export declare function warnPlaywrightExecutorDeprecation(): void;
|
|
3
|
-
export declare function warnPlaywrightExecutorGenerating(): void;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PLAYWRIGHT_EXECUTOR_DEPRECATION_MESSAGE = void 0;
|
|
4
|
-
exports.warnPlaywrightExecutorDeprecation = warnPlaywrightExecutorDeprecation;
|
|
5
|
-
exports.warnPlaywrightExecutorGenerating = warnPlaywrightExecutorGenerating;
|
|
6
|
-
const devkit_1 = require("@nx/devkit");
|
|
7
|
-
// TODO(v24): Remove the @nx/playwright:playwright executor. The inferred
|
|
8
|
-
// plugin (@nx/playwright/plugin) and the convert-to-inferred generator stay
|
|
9
|
-
// supported.
|
|
10
|
-
exports.PLAYWRIGHT_EXECUTOR_DEPRECATION_MESSAGE = 'The `@nx/playwright:playwright` executor is deprecated and will be removed in Nx v24. Run `nx g @nx/playwright:convert-to-inferred` to migrate to the `@nx/playwright/plugin` inferred targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.';
|
|
11
|
-
function warnPlaywrightExecutorDeprecation() {
|
|
12
|
-
devkit_1.logger.warn(exports.PLAYWRIGHT_EXECUTOR_DEPRECATION_MESSAGE);
|
|
13
|
-
}
|
|
14
|
-
function warnPlaywrightExecutorGenerating() {
|
|
15
|
-
devkit_1.logger.warn('Generating a target that uses the deprecated `@nx/playwright:playwright` executor. The executor will be removed in Nx v24. Run `nx g @nx/playwright:convert-to-inferred` next to migrate this target to the `@nx/playwright/plugin` inferred plugin and prevent future generators from emitting executor targets. See https://nx.dev/docs/guides/tasks--caching/convert-to-inferred for details.');
|
|
16
|
-
}
|