@nx/playwright 19.6.0-canary.20240808-333ab77 → 19.6.0-canary.20240813-c72ba9b

Sign up to get free protection for your applications and to get access to all the features.
package/migrations.json CHANGED
@@ -17,6 +17,12 @@
17
17
  "version": "19.6.0-beta.0",
18
18
  "description": "Use serve-static or preview for webServerCommand.",
19
19
  "implementation": "./src/migrations/update-19-6-0/use-serve-static-preview-for-command"
20
+ },
21
+ "update-19-6-0-add-e2e-ci-target-defaults": {
22
+ "cli": "nx",
23
+ "version": "19.6.0-beta.1",
24
+ "description": "Add inferred ciTargetNames to targetDefaults with dependsOn to ensure dependent application builds are scheduled before atomized tasks.",
25
+ "implementation": "./src/migrations/update-19-6-0/add-e2e-ci-target-defaults"
20
26
  }
21
27
  }
22
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/playwright",
3
- "version": "19.6.0-canary.20240808-333ab77",
3
+ "version": "19.6.0-canary.20240813-c72ba9b",
4
4
  "type": "commonjs",
5
5
  "homepage": "https://nx.dev",
6
6
  "private": false,
@@ -35,9 +35,11 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@phenomnomnominal/tsquery": "~5.0.1",
38
- "@nx/devkit": "19.6.0-canary.20240808-333ab77",
39
- "@nx/eslint": "19.6.0-canary.20240808-333ab77",
40
- "@nx/js": "19.6.0-canary.20240808-333ab77",
38
+ "@nx/devkit": "19.6.0-canary.20240813-c72ba9b",
39
+ "@nx/eslint": "19.6.0-canary.20240813-c72ba9b",
40
+ "@nx/webpack": "19.6.0-canary.20240813-c72ba9b",
41
+ "@nx/vite": "19.6.0-canary.20240813-c72ba9b",
42
+ "@nx/js": "19.6.0-canary.20240813-c72ba9b",
41
43
  "tslib": "^2.3.0",
42
44
  "minimatch": "9.0.3"
43
45
  },
@@ -6,6 +6,7 @@ const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaul
6
6
  const internal_api_1 = require("nx/src/project-graph/plugins/internal-api");
7
7
  const devkit_internals_1 = require("nx/src/devkit-internals");
8
8
  const tsquery_1 = require("@phenomnomnominal/tsquery");
9
+ const path_1 = require("path");
9
10
  async function addE2eCiTargetDefaults(tree) {
10
11
  const pluginName = '@nx/playwright/plugin';
11
12
  const graph = await (0, devkit_1.createProjectGraphAsync)();
@@ -65,6 +66,9 @@ async function addE2eCiTargetDefaults(tree) {
65
66
  serveStaticProject = matches[2];
66
67
  }
67
68
  const resolvedServeStaticTarget = graph.nodes[serveStaticProject].data.targets[serveStaticTarget];
69
+ if (!resolvedServeStaticTarget) {
70
+ continue;
71
+ }
68
72
  let resolvedBuildTarget;
69
73
  if (resolvedServeStaticTarget.dependsOn) {
70
74
  resolvedBuildTarget = resolvedServeStaticTarget.dependsOn.join(',');
@@ -76,7 +80,8 @@ async function addE2eCiTargetDefaults(tree) {
76
80
  .buildTarget
77
81
  : resolvedServeStaticTarget.options.buildTarget) ?? 'build';
78
82
  }
79
- const buildTarget = `^${resolvedBuildTarget}`;
83
+ const targetDependsOnSelf = graph.nodes[serveStaticProject].data.root === (0, path_1.dirname)(configFile);
84
+ const buildTarget = `${targetDependsOnSelf ? '' : '^'}${resolvedBuildTarget}`;
80
85
  await (0, target_defaults_utils_1.addE2eCiTargetDefaults)(tree, pluginName, buildTarget, configFile);
81
86
  }
82
87
  }
@@ -4,9 +4,15 @@ exports.default = default_1;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const tsquery_1 = require("@phenomnomnominal/tsquery");
6
6
  const add_e2e_ci_target_defaults_1 = require("./add-e2e-ci-target-defaults");
7
+ const internal_api_1 = require("nx/src/project-graph/plugins/internal-api");
8
+ const retrieve_workspace_files_1 = require("nx/src/project-graph/utils/retrieve-workspace-files");
9
+ const error_types_1 = require("nx/src/project-graph/error-types");
10
+ const plugin_1 = require("@nx/webpack/src/plugins/plugin");
11
+ const plugin_2 = require("@nx/vite/plugin");
7
12
  async function default_1(tree) {
8
13
  const graph = await (0, devkit_1.createProjectGraphAsync)();
9
- (0, devkit_1.visitNotIgnoredFiles)(tree, '', (path) => {
14
+ const collectedProjects = [];
15
+ (0, devkit_1.visitNotIgnoredFiles)(tree, '', async (path) => {
10
16
  if (!path.endsWith('playwright.config.ts')) {
11
17
  return;
12
18
  }
@@ -23,8 +29,8 @@ async function default_1(tree) {
23
29
  const command = commandValueNode.getText();
24
30
  let project;
25
31
  if (command.includes('nx run')) {
26
- const NX_TARGET_REGEX = "(?<=nx run )[^']+";
27
- const matches = command.match(NX_TARGET_REGEX);
32
+ const NX_RUN_TARGET_REGEX = "(?<=nx run )[^']+";
33
+ const matches = command.match(NX_RUN_TARGET_REGEX);
28
34
  if (!matches) {
29
35
  return;
30
36
  }
@@ -48,15 +54,38 @@ async function default_1(tree) {
48
54
  (0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'vite.config.ts'),
49
55
  (0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'vite.config.js'),
50
56
  ].find((p) => tree.exists(p));
51
- if (!pathToViteConfig) {
52
- const newCommand = `${(0, devkit_1.getPackageManagerCommand)().exec} nx run ${project}:serve-static`;
53
- tree.write(path, `${playwrightConfigFileContents.slice(0, commandValueNode.getStart())}"${newCommand}"${playwrightConfigFileContents.slice(commandValueNode.getEnd())}`);
57
+ const pathToWebpackConfig = [
58
+ (0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'webpack.config.ts'),
59
+ (0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'webpack.config.js'),
60
+ ].find((p) => tree.exists(p));
61
+ collectedProjects.push({
62
+ projectName: project,
63
+ configFile: pathToWebpackConfig ?? pathToViteConfig,
64
+ configFileType: pathToWebpackConfig ? 'webpack' : 'vite',
65
+ playwrightConfigFile: path,
66
+ commandValueNode,
67
+ });
68
+ });
69
+ for (const projectToMigrate of collectedProjects) {
70
+ let playwrightConfigFileContents = tree.read(projectToMigrate.playwrightConfigFile, 'utf-8');
71
+ const targetName = await getServeStaticTargetNameForConfigFile(tree, projectToMigrate.configFileType === 'webpack'
72
+ ? '@nx/webpack/plugin'
73
+ : '@nx/vite/plugin', projectToMigrate.configFile, projectToMigrate.configFileType === 'webpack'
74
+ ? 'serve-static'
75
+ : 'preview', projectToMigrate.configFileType === 'webpack'
76
+ ? 'serveStaticTargetName'
77
+ : 'previewTargetName', projectToMigrate.configFileType === 'webpack'
78
+ ? plugin_1.createNodesV2
79
+ : plugin_2.createNodesV2);
80
+ const oldCommand = projectToMigrate.commandValueNode.getText();
81
+ const newCommand = oldCommand.replace(/nx.*[^"']/, `nx run ${projectToMigrate.projectName}:${targetName}`);
82
+ if (projectToMigrate.configFileType === 'webpack') {
83
+ tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, projectToMigrate.commandValueNode.getStart())}${newCommand}${playwrightConfigFileContents.slice(projectToMigrate.commandValueNode.getEnd())}`);
54
84
  }
55
85
  else {
56
- const newCommand = `${(0, devkit_1.getPackageManagerCommand)().exec} nx run ${project}:preview`;
57
- tree.write(path, `${playwrightConfigFileContents.slice(0, commandValueNode.getStart())}"${newCommand}"${playwrightConfigFileContents.slice(commandValueNode.getEnd())}`);
58
- playwrightConfigFileContents = tree.read(path, 'utf-8');
59
- ast = tsquery_1.tsquery.ast(playwrightConfigFileContents);
86
+ tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, projectToMigrate.commandValueNode.getStart())}${newCommand}${playwrightConfigFileContents.slice(projectToMigrate.commandValueNode.getEnd())}`);
87
+ playwrightConfigFileContents = tree.read(projectToMigrate.playwrightConfigFile, 'utf-8');
88
+ let ast = tsquery_1.tsquery.ast(playwrightConfigFileContents);
60
89
  const BASE_URL_SELECTOR = 'VariableDeclaration:has(Identifier[name=baseURL])';
61
90
  const baseUrlNodes = (0, tsquery_1.tsquery)(ast, BASE_URL_SELECTOR, {
62
91
  visitAllChildren: true,
@@ -66,8 +95,8 @@ async function default_1(tree) {
66
95
  }
67
96
  const baseUrlNode = baseUrlNodes[0];
68
97
  const newBaseUrlVariableDeclaration = "baseURL = process.env['BASE_URL'] || 'http://localhost:4300';";
69
- tree.write(path, `${playwrightConfigFileContents.slice(0, baseUrlNode.getStart())}${newBaseUrlVariableDeclaration}${playwrightConfigFileContents.slice(baseUrlNode.getEnd())}`);
70
- playwrightConfigFileContents = tree.read(path, 'utf-8');
98
+ tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, baseUrlNode.getStart())}${newBaseUrlVariableDeclaration}${playwrightConfigFileContents.slice(baseUrlNode.getEnd())}`);
99
+ playwrightConfigFileContents = tree.read(projectToMigrate.playwrightConfigFile, 'utf-8');
71
100
  ast = tsquery_1.tsquery.ast(playwrightConfigFileContents);
72
101
  const WEB_SERVER_URL_SELECTOR = 'PropertyAssignment:has(Identifier[name=webServer]) PropertyAssignment:has(Identifier[name=url]) > StringLiteral';
73
102
  const webServerUrlNodes = (0, tsquery_1.tsquery)(ast, WEB_SERVER_URL_SELECTOR, {
@@ -78,9 +107,40 @@ async function default_1(tree) {
78
107
  }
79
108
  const webServerUrlNode = webServerUrlNodes[0];
80
109
  const newWebServerUrl = "'http://localhost:4300'";
81
- tree.write(path, `${playwrightConfigFileContents.slice(0, webServerUrlNode.getStart())}${newWebServerUrl}${playwrightConfigFileContents.slice(webServerUrlNode.getEnd())}`);
110
+ tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, webServerUrlNode.getStart())}${newWebServerUrl}${playwrightConfigFileContents.slice(webServerUrlNode.getEnd())}`);
82
111
  }
83
- });
112
+ }
84
113
  await (0, add_e2e_ci_target_defaults_1.default)(tree);
85
114
  await (0, devkit_1.formatFiles)(tree);
86
115
  }
116
+ async function getServeStaticTargetNameForConfigFile(tree, pluginName, configFile, defaultTargetName, targetNamePluginOption, createNodesV2) {
117
+ const nxJson = (0, devkit_1.readNxJson)(tree);
118
+ const matchingPluginRegistrations = nxJson.plugins?.filter((p) => typeof p === 'string' ? p === pluginName : p.plugin === pluginName);
119
+ if (!matchingPluginRegistrations) {
120
+ return defaultTargetName;
121
+ }
122
+ let targetName = defaultTargetName;
123
+ for (const plugin of matchingPluginRegistrations) {
124
+ let projectConfigs;
125
+ try {
126
+ const loadedPlugin = new internal_api_1.LoadedNxPlugin({ createNodesV2, name: pluginName }, plugin);
127
+ projectConfigs = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)([loadedPlugin], tree.root, nxJson);
128
+ }
129
+ catch (e) {
130
+ if (e instanceof error_types_1.ProjectConfigurationsError) {
131
+ projectConfigs = e.partialProjectConfigurationsResult;
132
+ }
133
+ else {
134
+ throw e;
135
+ }
136
+ }
137
+ if (projectConfigs.matchingProjectFiles.includes(configFile)) {
138
+ targetName =
139
+ typeof plugin === 'string'
140
+ ? defaultTargetName
141
+ : plugin.options?.[targetNamePluginOption] ??
142
+ defaultTargetName;
143
+ }
144
+ }
145
+ return targetName;
146
+ }