diff --git a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap index f22e4921bd23c..11b543fc29b5b 100644 --- a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap @@ -287,6 +287,7 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh "executor": "@nx/web:file-server", "options": { "buildTarget": "my-dir-my-app:build", + "port": 4200, "spa": true, "staticFilePath": "dist/apps/my-dir/my-app/browser", }, @@ -487,6 +488,7 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh "executor": "@nx/web:file-server", "options": { "buildTarget": "my-app:build", + "port": 4200, "spa": true, "staticFilePath": "dist/apps/my-app/browser", }, @@ -982,6 +984,7 @@ exports[`app nested should create project configs 1`] = ` "executor": "@nx/web:file-server", "options": { "buildTarget": "my-app:build", + "port": 4200, "spa": true, "staticFilePath": "dist/my-dir/my-app/browser", }, @@ -1095,6 +1098,7 @@ exports[`app not nested should create project configs 1`] = ` "executor": "@nx/web:file-server", "options": { "buildTarget": "my-app:build", + "port": 4200, "spa": true, "staticFilePath": "dist/my-app/browser", }, diff --git a/packages/angular/src/generators/application/lib/add-e2e.ts b/packages/angular/src/generators/application/lib/add-e2e.ts index 4d74823f56dd3..390a7e30068d7 100644 --- a/packages/angular/src/generators/application/lib/add-e2e.ts +++ b/packages/angular/src/generators/application/lib/add-e2e.ts @@ -40,8 +40,8 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) { linter: options.linter, skipPackageJson: options.skipPackageJson, skipFormat: true, - devServerTarget: `${options.name}:serve:development`, - baseUrl: 'http://localhost:4200', + devServerTarget: `${options.name}:${options.e2eWebServerTarget}:development`, + baseUrl: options.e2eWebServerAddress, rootProject: options.rootProject, addPlugin, }); @@ -64,10 +64,10 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) { js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerCommand: `${getPackageManagerCommand().exec} nx serve ${ - options.name - }`, - webServerAddress: `http://localhost:${options.port ?? 4200}`, + webServerCommand: `${getPackageManagerCommand().exec} nx ${ + options.e2eWebServerTarget + } ${options.name}`, + webServerAddress: options.e2eWebServerAddress, rootProject: options.rootProject, addPlugin, }); @@ -90,7 +90,7 @@ function addFileServerTarget( executor: '@nx/web:file-server', options: { buildTarget: `${options.name}:build`, - port: options.port, + port: options.e2ePort, staticFilePath: isUsingApplicationBuilder ? joinPathFragments(options.outputPath, 'browser') : undefined, diff --git a/packages/angular/src/generators/application/lib/normalize-options.ts b/packages/angular/src/generators/application/lib/normalize-options.ts index 229d676918921..9b804617bb0d2 100644 --- a/packages/angular/src/generators/application/lib/normalize-options.ts +++ b/packages/angular/src/generators/application/lib/normalize-options.ts @@ -1,4 +1,4 @@ -import { joinPathFragments, type Tree } from '@nx/devkit'; +import { joinPathFragments, readNxJson, type Tree } from '@nx/devkit'; import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { Linter } from '@nx/eslint'; import { E2eTestRunner, UnitTestRunner } from '../../../utils/test-runners'; @@ -25,8 +25,22 @@ export async function normalizeOptions( options.rootProject = appProjectRoot === '.'; options.projectNameAndRootFormat = projectNameAndRootFormat; + const nxJson = readNxJson(host); + let e2eWebServerTarget = 'serve'; + let e2ePort = options.port ?? 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + (nxJson.targetDefaults?.[e2eWebServerTarget].options?.port || + nxJson.targetDefaults?.[e2eWebServerTarget].options?.env?.PORT) + ) { + e2ePort = + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port || + nxJson.targetDefaults?.[e2eWebServerTarget].options?.env?.PORT; + } + const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`; const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; const parsedTags = options.tags ? options.tags.split(',').map((s) => s.trim()) @@ -58,6 +72,9 @@ export async function normalizeOptions( appProjectSourceRoot: `${appProjectRoot}/src`, e2eProjectRoot, e2eProjectName, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, parsedTags, bundler, outputPath: joinPathFragments( diff --git a/packages/angular/src/generators/application/lib/normalized-schema.ts b/packages/angular/src/generators/application/lib/normalized-schema.ts index b1a5dd3675d76..a7f0fef4dad90 100644 --- a/packages/angular/src/generators/application/lib/normalized-schema.ts +++ b/packages/angular/src/generators/application/lib/normalized-schema.ts @@ -11,6 +11,9 @@ export interface NormalizedSchema extends Schema { appProjectSourceRoot: string; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; parsedTags: string[]; outputPath: string; } diff --git a/packages/expo/src/generators/application/lib/add-e2e.ts b/packages/expo/src/generators/application/lib/add-e2e.ts index a54e826a84201..45671e2fb90f3 100644 --- a/packages/expo/src/generators/application/lib/add-e2e.ts +++ b/packages/expo/src/generators/application/lib/add-e2e.ts @@ -16,7 +16,6 @@ export async function addE2e( options: NormalizedSchema ): Promise { const hasPlugin = hasExpoPlugin(tree); - const port = hasPlugin ? 8081 : 4200; switch (options.e2eTestRunner) { case 'cypress': { const hasNxExpoPlugin = hasExpoPlugin(tree); @@ -47,9 +46,9 @@ export async function addE2e( // the name and root are already normalized, instruct the generator to use them as is bundler: 'none', skipFormat: true, - devServerTarget: `${options.projectName}:serve`, - port, - baseUrl: `http://localhost:${port}`, + devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`, + port: options.e2ePort, + baseUrl: options.e2eWebServerAddress, ciWebServerCommand: hasNxExpoPlugin ? `nx run ${options.projectName}:serve-static` : undefined, @@ -76,10 +75,10 @@ export async function addE2e( js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerCommand: `${getPackageManagerCommand().exec} nx serve ${ - options.name - }`, - webServerAddress: `http://localhost:${port}`, + webServerCommand: `${getPackageManagerCommand().exec} nx ${ + options.e2eWebServerTarget + } ${options.name}`, + webServerAddress: options.e2eWebServerAddress, rootProject: options.rootProject, }); } diff --git a/packages/expo/src/generators/application/lib/normalize-options.spec.ts b/packages/expo/src/generators/application/lib/normalize-options.spec.ts index 5ceeb32822f3b..ad39102795aa8 100644 --- a/packages/expo/src/generators/application/lib/normalize-options.spec.ts +++ b/packages/expo/src/generators/application/lib/normalize-options.spec.ts @@ -40,6 +40,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'my-app-e2e', + e2ePort: 8081, + e2eWebServerAddress: 'http://localhost:8081', + e2eWebServerTarget: 'serve', } as NormalizedSchema); }); @@ -72,6 +75,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'myApp-e2e', e2eProjectRoot: 'myApp-e2e', + e2ePort: 8081, + e2eWebServerAddress: 'http://localhost:8081', + e2eWebServerTarget: 'serve', } as NormalizedSchema); }); @@ -106,6 +112,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'directory-e2e', + e2ePort: 8081, + e2eWebServerAddress: 'http://localhost:8081', + e2eWebServerTarget: 'serve', } as NormalizedSchema); }); @@ -138,6 +147,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'directory/my-app-e2e', + e2ePort: 8081, + e2eWebServerAddress: 'http://localhost:8081', + e2eWebServerTarget: 'serve', } as NormalizedSchema); }); @@ -171,6 +183,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'my-app-e2e', + e2ePort: 8081, + e2eWebServerAddress: 'http://localhost:8081', + e2eWebServerTarget: 'serve', } as NormalizedSchema); }); }); diff --git a/packages/expo/src/generators/application/lib/normalize-options.ts b/packages/expo/src/generators/application/lib/normalize-options.ts index a7e6315c260e1..dc835166d8a6b 100644 --- a/packages/expo/src/generators/application/lib/normalize-options.ts +++ b/packages/expo/src/generators/application/lib/normalize-options.ts @@ -1,6 +1,7 @@ import { names, readNxJson, Tree } from '@nx/devkit'; import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { Schema } from '../schema'; +import { ExpoPluginOptions } from '../../../../plugins/plugin'; export interface NormalizedSchema extends Schema { className: string; @@ -11,6 +12,9 @@ export interface NormalizedSchema extends Schema { rootProject: boolean; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; } export async function normalizeOptions( @@ -41,8 +45,34 @@ export async function normalizeOptions( ? options.tags.split(',').map((s) => s.trim()) : []; const rootProject = appProjectRoot === '.'; + + let e2eWebServerTarget = 'serve'; + if (options.addPlugin) { + if (nxJson.plugins) { + for (const plugin of nxJson.plugins) { + if ( + typeof plugin === 'object' && + plugin.plugin === '@nx/expo/plugin' && + (plugin.options as ExpoPluginOptions).serveTargetName + ) { + e2eWebServerTarget = (plugin.options as ExpoPluginOptions) + .serveTargetName; + } + } + } + } + + let e2ePort = options.addPlugin ? 8081 : 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port + ) { + e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options.port; + } + const e2eProjectName = rootProject ? 'e2e' : `${appProjectName}-e2e`; const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; return { ...options, @@ -58,5 +88,8 @@ export async function normalizeOptions( rootProject, e2eProjectName, e2eProjectRoot, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, }; } diff --git a/packages/next/src/generators/application/lib/add-e2e.ts b/packages/next/src/generators/application/lib/add-e2e.ts index b6bf1d9957a27..4856dd7245121 100644 --- a/packages/next/src/generators/application/lib/add-e2e.ts +++ b/packages/next/src/generators/application/lib/add-e2e.ts @@ -48,14 +48,12 @@ export async function addE2e(host: Tree, options: NormalizedSchema) { project: options.e2eProjectName, directory: 'src', skipFormat: true, - devServerTarget: `${options.projectName}:${ - hasPlugin ? 'start' : 'serve' - }`, - baseUrl: `http://localhost:${hasPlugin ? '3000' : '4200'}`, + devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`, + baseUrl: options.e2eWebServerAddress, jsx: true, webServerCommands: hasPlugin ? { - default: `nx run ${options.projectName}:start`, + default: `nx run ${options.projectName}:${options.e2eWebServerTarget}`, } : undefined, ciWebServerCommand: hasPlugin @@ -81,9 +79,9 @@ export async function addE2e(host: Tree, options: NormalizedSchema) { js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerAddress: `http://127.0.0.1:${hasPlugin ? '3000' : '4200'}`, + webServerAddress: `http://127.0.0.1:${options.e2ePort}`, webServerCommand: `${getPackageManagerCommand().exec} nx ${ - hasPlugin ? 'start' : 'serve' + options.e2eWebServerTarget } ${options.projectName}`, addPlugin: options.addPlugin, }); diff --git a/packages/next/src/generators/application/lib/add-linting.spec.ts b/packages/next/src/generators/application/lib/add-linting.spec.ts index 06c15274252b1..bbea7dd92c49b 100644 --- a/packages/next/src/generators/application/lib/add-linting.spec.ts +++ b/packages/next/src/generators/application/lib/add-linting.spec.ts @@ -21,6 +21,9 @@ describe('updateEslint', () => { unitTestRunner: 'jest', e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'my-app-e2e', + e2ePort: 3000, + e2eWebServerTarget: 'start', + e2eWebServerAddress: 'http://localhost:4200', outputPath: 'dist/my-app', name: 'my-app', parsedTags: [], diff --git a/packages/next/src/generators/application/lib/normalize-options.ts b/packages/next/src/generators/application/lib/normalize-options.ts index df3b7fb3655db..eb1c8bba5dc03 100644 --- a/packages/next/src/generators/application/lib/normalize-options.ts +++ b/packages/next/src/generators/application/lib/normalize-options.ts @@ -3,6 +3,7 @@ import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/pr import { Linter } from '@nx/eslint'; import { assertValidStyle } from '@nx/react/src/utils/assertion'; import { Schema } from '../schema'; +import { NextPluginOptions } from '../../../plugins/plugin'; export interface NormalizedSchema extends Schema { projectName: string; @@ -10,6 +11,9 @@ export interface NormalizedSchema extends Schema { outputPath: string; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; parsedTags: string[]; fileName: string; styledModule: null | string; @@ -42,8 +46,36 @@ export async function normalizeOptions( options.addPlugin ??= addPlugin; + let e2eWebServerTarget = options.addPlugin ? 'start' : 'serve'; + if (options.addPlugin) { + if (nxJson.plugins) { + for (const plugin of nxJson.plugins) { + if ( + typeof plugin === 'object' && + plugin.plugin === '@nx/next/plugin' && + (plugin.options as NextPluginOptions).startTargetName + ) { + e2eWebServerTarget = (plugin.options as NextPluginOptions) + .startTargetName; + } + } + } + } + + let e2ePort = options.addPlugin ? 3000 : 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + (nxJson.targetDefaults?.[e2eWebServerTarget].options?.port || + nxJson.targetDefaults?.[e2eWebServerTarget].options?.env?.PORT) + ) { + e2ePort = + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port || + nxJson.targetDefaults?.[e2eWebServerTarget].options?.env?.PORT; + } + const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`; const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; const name = names(options.name).fileName; @@ -75,6 +107,9 @@ export async function normalizeOptions( appProjectRoot, e2eProjectName, e2eProjectRoot, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, e2eTestRunner: options.e2eTestRunner || 'cypress', fileName, linter: options.linter || Linter.EsLint, diff --git a/packages/nuxt/src/generators/application/lib/add-e2e.ts b/packages/nuxt/src/generators/application/lib/add-e2e.ts index d88f7eebc1a73..35fb27fc83484 100644 --- a/packages/nuxt/src/generators/application/lib/add-e2e.ts +++ b/packages/nuxt/src/generators/application/lib/add-e2e.ts @@ -27,14 +27,14 @@ export async function addE2e(host: Tree, options: NormalizedSchema) { directory: 'src', bundler: 'vite', skipFormat: true, - devServerTarget: `${options.projectName}:serve`, + devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`, webServerCommands: { - default: `${getPackageManagerCommand().exec} nx serve ${ - options.projectName - }`, + default: `${getPackageManagerCommand().exec} nx ${ + options.e2eWebServerTarget + } ${options.projectName}`, }, ciWebServerCommand: `nx run ${options.projectName}:serve-static`, - baseUrl: 'http://localhost:4200', + baseUrl: options.e2eWebServerAddress, jsx: true, addPlugin: true, }); @@ -56,10 +56,10 @@ export async function addE2e(host: Tree, options: NormalizedSchema) { js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerAddress: 'http://localhost:4200', - webServerCommand: `${getPackageManagerCommand().exec} nx serve ${ - options.projectName - }`, + webServerAddress: options.e2eWebServerAddress, + webServerCommand: `${getPackageManagerCommand().exec} nx ${ + options.e2eWebServerTarget + } ${options.projectName}`, addPlugin: true, }); } diff --git a/packages/nuxt/src/generators/application/lib/normalize-options.ts b/packages/nuxt/src/generators/application/lib/normalize-options.ts index a214e1f036712..ebefc08288034 100644 --- a/packages/nuxt/src/generators/application/lib/normalize-options.ts +++ b/packages/nuxt/src/generators/application/lib/normalize-options.ts @@ -1,6 +1,7 @@ -import { Tree, extractLayoutDirectory, names } from '@nx/devkit'; +import { Tree, extractLayoutDirectory, names, readNxJson } from '@nx/devkit'; import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { NormalizedSchema, Schema } from '../schema'; +import { NuxtPluginOptions } from '../../../plugins/plugin'; export function normalizeDirectory(options: Schema) { options.directory = options.directory?.replace(/\\{1,2}/g, '/'); @@ -30,8 +31,31 @@ export async function normalizeOptions( options.rootProject = appProjectRoot === '.'; options.projectNameAndRootFormat = projectNameAndRootFormat; + const nxJson = readNxJson(host); + let e2eWebServerTarget = 'serve'; + if (nxJson.plugins) { + for (const plugin of nxJson.plugins) { + if ( + typeof plugin === 'object' && + plugin.plugin === '@nx/nuxt/plugin' && + (plugin.options as NuxtPluginOptions).serveTargetName + ) { + e2eWebServerTarget = (plugin.options as NuxtPluginOptions) + .serveTargetName; + } + } + } + + let e2ePort = 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port + ) { + e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options?.port; + } const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`; const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; const parsedTags = options.tags ? options.tags.split(',').map((s) => s.trim()) @@ -44,6 +68,9 @@ export async function normalizeOptions( appProjectRoot, e2eProjectName, e2eProjectRoot, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, parsedTags, style: options.style ?? 'none', } as NormalizedSchema; diff --git a/packages/nuxt/src/generators/application/schema.d.ts b/packages/nuxt/src/generators/application/schema.d.ts index db84d800e9821..189e2dce4e190 100644 --- a/packages/nuxt/src/generators/application/schema.d.ts +++ b/packages/nuxt/src/generators/application/schema.d.ts @@ -22,5 +22,8 @@ export interface NormalizedSchema extends Schema { appProjectRoot: string; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; parsedTags: string[]; } diff --git a/packages/react-native/src/generators/application/lib/normalize-options.spec.ts b/packages/react-native/src/generators/application/lib/normalize-options.spec.ts index e140ba10fb910..ecbdfa853a836 100644 --- a/packages/react-native/src/generators/application/lib/normalize-options.spec.ts +++ b/packages/react-native/src/generators/application/lib/normalize-options.spec.ts @@ -44,6 +44,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'my-app-e2e', + e2ePort: 4200, + e2eWebServerAddress: 'http://localhost:4200', + e2eWebServerTarget: 'start', }); }); @@ -80,6 +83,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'myApp-e2e', + e2ePort: 4200, + e2eWebServerAddress: 'http://localhost:4200', + e2eWebServerTarget: 'start', }); }); @@ -118,6 +124,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'directory/my-app-e2e', + e2ePort: 4200, + e2eWebServerAddress: 'http://localhost:4200', + e2eWebServerTarget: 'start', }); }); @@ -154,6 +163,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'directory/my-app-e2e', e2eProjectRoot: 'directory/my-app-e2e', + e2ePort: 4200, + e2eWebServerAddress: 'http://localhost:4200', + e2eWebServerTarget: 'start', }); }); @@ -191,6 +203,9 @@ describe('Normalize Options', () => { rootProject: false, e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'my-app-e2e', + e2ePort: 4200, + e2eWebServerAddress: 'http://localhost:4200', + e2eWebServerTarget: 'start', }); }); }); diff --git a/packages/react-native/src/generators/application/lib/normalize-options.ts b/packages/react-native/src/generators/application/lib/normalize-options.ts index 75da521f8d904..1de42bcd1dd5d 100644 --- a/packages/react-native/src/generators/application/lib/normalize-options.ts +++ b/packages/react-native/src/generators/application/lib/normalize-options.ts @@ -1,6 +1,7 @@ import { joinPathFragments, names, readNxJson, Tree } from '@nx/devkit'; import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { Schema } from '../schema'; +import { ReactNativePluginOptions } from '../../../../plugins/plugin'; export interface NormalizedSchema extends Schema { className: string; // app name in class case @@ -15,6 +16,9 @@ export interface NormalizedSchema extends Schema { rootProject: boolean; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; } export async function normalizeOptions( @@ -44,8 +48,35 @@ export async function normalizeOptions( const iosProjectRoot = joinPathFragments(appProjectRoot, 'ios'); const androidProjectRoot = joinPathFragments(appProjectRoot, 'android'); const rootProject = appProjectRoot === '.'; + + let e2eWebServerTarget = 'start'; + if (options.addPlugin) { + if (nxJson.plugins) { + for (const plugin of nxJson.plugins) { + if ( + options.bundler === 'vite' && + typeof plugin === 'object' && + plugin.plugin === '@nx/react-native/plugin' && + (plugin.options as ReactNativePluginOptions).startTargetName + ) { + e2eWebServerTarget = (plugin.options as ReactNativePluginOptions) + .startTargetName; + } + } + } + } + + let e2ePort = 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port + ) { + e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options?.port; + } + const e2eProjectName = rootProject ? 'e2e' : `${fileName}-e2e`; const e2eProjectRoot = rootProject ? 'e2e' : `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; const parsedTags = options.tags ? options.tags.split(',').map((s) => s.trim()) @@ -69,5 +100,8 @@ export async function normalizeOptions( rootProject, e2eProjectName, e2eProjectRoot, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, }; } diff --git a/packages/react/src/generators/application/lib/add-e2e.ts b/packages/react/src/generators/application/lib/add-e2e.ts index e07676505bec6..2602b12ff1e4f 100644 --- a/packages/react/src/generators/application/lib/add-e2e.ts +++ b/packages/react/src/generators/application/lib/add-e2e.ts @@ -49,13 +49,13 @@ export async function addE2e( // the name and root are already normalized, instruct the generator to use them as is bundler: options.bundler === 'rspack' ? 'webpack' : options.bundler, skipFormat: true, - devServerTarget: `${options.projectName}:serve`, - baseUrl: `http://localhost:${options.devServerPort ?? 4200}`, + devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`, + baseUrl: options.e2eWebServerAddress, jsx: true, rootProject: options.rootProject, webServerCommands: hasNxBuildPlugin ? { - default: `nx run ${options.projectName}:serve`, + default: `nx run ${options.projectName}:${options.e2eWebServerTarget}`, production: `nx run ${options.projectName}:preview`, } : undefined, @@ -83,10 +83,10 @@ export async function addE2e( js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerCommand: `${getPackageManagerCommand().exec} nx serve ${ - options.name - }`, - webServerAddress: `http://localhost:${options.devServerPort ?? 4200}`, + webServerCommand: `${getPackageManagerCommand().exec} nx ${ + options.e2eWebServerTarget + } ${options.name}`, + webServerAddress: options.e2eWebServerAddress, rootProject: options.rootProject, addPlugin: options.addPlugin, }); diff --git a/packages/react/src/generators/application/lib/normalize-options.ts b/packages/react/src/generators/application/lib/normalize-options.ts index 81d99c9db42f4..22ca3717d8b9c 100644 --- a/packages/react/src/generators/application/lib/normalize-options.ts +++ b/packages/react/src/generators/application/lib/normalize-options.ts @@ -3,6 +3,8 @@ import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/pr import { assertValidStyle } from '../../../utils/assertion'; import { NormalizedSchema, Schema } from '../schema'; import { findFreePort } from './find-free-port'; +import { VitePluginOptions } from '@nx/vite/src/plugins/plugin'; +import { WebpackPluginOptions } from '@nx/webpack/src/plugins/plugin'; export function normalizeDirectory(options: Schema) { options.directory = options.directory?.replace(/\\{1,2}/g, '/'); @@ -43,8 +45,43 @@ export async function normalizeOptions( options.rootProject = appProjectRoot === '.'; options.projectNameAndRootFormat = projectNameAndRootFormat; + + let e2eWebServerTarget = 'serve'; + if (options.addPlugin) { + if (nxJson.plugins) { + for (const plugin of nxJson.plugins) { + if ( + options.bundler === 'vite' && + typeof plugin === 'object' && + plugin.plugin === '@nx/vite/plugin' && + (plugin.options as VitePluginOptions).serveTargetName + ) { + e2eWebServerTarget = (plugin.options as VitePluginOptions) + .serveTargetName; + } else if ( + options.bundler === 'webpack' && + typeof plugin === 'object' && + plugin.plugin === '@nx/webpack/plugin' && + (plugin.options as WebpackPluginOptions).serveTargetName + ) { + e2eWebServerTarget = (plugin.options as WebpackPluginOptions) + .serveTargetName; + } + } + } + } + + let e2ePort = options.devServerPort ?? 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port + ) { + e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options?.port; + } + const e2eProjectName = options.rootProject ? 'e2e' : `${appProjectName}-e2e`; const e2eProjectRoot = options.rootProject ? 'e2e' : `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; const parsedTags = options.tags ? options.tags.split(',').map((s) => s.trim()) @@ -69,6 +106,9 @@ export async function normalizeOptions( appProjectRoot, e2eProjectName, e2eProjectRoot, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, parsedTags, fileName, styledModule, diff --git a/packages/react/src/generators/application/schema.d.ts b/packages/react/src/generators/application/schema.d.ts index fc3d53b6861a2..f0e26f3e9cc58 100644 --- a/packages/react/src/generators/application/schema.d.ts +++ b/packages/react/src/generators/application/schema.d.ts @@ -36,6 +36,9 @@ export interface NormalizedSchema extends T { appProjectRoot: string; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; parsedTags: string[]; fileName: string; styledModule: null | SupportedStyles; diff --git a/packages/remix/src/generators/application/lib/normalize-options.ts b/packages/remix/src/generators/application/lib/normalize-options.ts index c297b7160e496..0124714fc8e7f 100644 --- a/packages/remix/src/generators/application/lib/normalize-options.ts +++ b/packages/remix/src/generators/application/lib/normalize-options.ts @@ -38,7 +38,6 @@ export async function normalizeOptions( let e2eWebServerTarget = options.addPlugin ? 'dev' : 'serve'; if (options.addPlugin) { - const nxJson = readNxJson(tree); if (nxJson.plugins) { for (const plugin of nxJson.plugins) { if ( diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index a9d393f38ac9f..ebf19ddb3fb9d 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -38,12 +38,17 @@ import { getNpmScope } from '@nx/js/src/utils/package-json/get-npm-scope'; import { hasWebpackPlugin } from '../../utils/has-webpack-plugin'; import { addBuildTargetDefaults } from '@nx/devkit/src/generators/add-build-target-defaults'; import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command'; +import { VitePluginOptions } from '@nx/vite/src/plugins/plugin'; +import { WebpackPluginOptions } from '@nx/webpack/src/plugins/plugin'; interface NormalizedSchema extends Schema { projectName: string; appProjectRoot: string; e2eProjectName: string; e2eProjectRoot: string; + e2eWebServerAddress: string; + e2eWebServerTarget: string; + e2ePort: number; parsedTags: string[]; } @@ -360,8 +365,8 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) { const cypressTask = await configurationGenerator(host, { ...options, project: options.e2eProjectName, - devServerTarget: `${options.projectName}:serve`, - baseUrl: 'http://localhost:4200', + devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`, + baseUrl: options.e2eWebServerAddress, directory: 'src', skipFormat: true, }); @@ -385,10 +390,10 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) { js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerCommand: `${getPackageManagerCommand().exec} nx serve ${ - options.name - }`, - webServerAddress: 'http://localhost:4200', + webServerCommand: `${getPackageManagerCommand().exec} nx ${ + options.e2eWebServerTarget + } ${options.name}`, + webServerAddress: options.e2eWebServerAddress, addPlugin: options.addPlugin, }); tasks.push(playwrightTask); @@ -473,8 +478,42 @@ async function normalizeOptions( nxJson.useInferencePlugins !== false; options.addPlugin ??= addPluginDefault; + let e2eWebServerTarget = 'serve'; + if (options.addPlugin) { + if (nxJson.plugins) { + for (const plugin of nxJson.plugins) { + if ( + options.bundler === 'vite' && + typeof plugin === 'object' && + plugin.plugin === '@nx/vite/plugin' && + (plugin.options as VitePluginOptions).serveTargetName + ) { + e2eWebServerTarget = (plugin.options as VitePluginOptions) + .serveTargetName; + } else if ( + options.bundler === 'webpack' && + typeof plugin === 'object' && + plugin.plugin === '@nx/webpack/plugin' && + (plugin.options as WebpackPluginOptions).serveTargetName + ) { + e2eWebServerTarget = (plugin.options as WebpackPluginOptions) + .serveTargetName; + } + } + } + } + + let e2ePort = 4200; + if ( + nxJson.targetDefaults?.[e2eWebServerTarget] && + nxJson.targetDefaults?.[e2eWebServerTarget].options?.port + ) { + e2ePort = nxJson.targetDefaults?.[e2eWebServerTarget].options?.port; + } + const e2eProjectName = `${appProjectName}-e2e`; const e2eProjectRoot = `${appProjectRoot}-e2e`; + const e2eWebServerAddress = `http://localhost:${e2ePort}`; const npmScope = getNpmScope(host); @@ -501,6 +540,9 @@ async function normalizeOptions( appProjectRoot, e2eProjectRoot, e2eProjectName, + e2eWebServerAddress, + e2eWebServerTarget, + e2ePort, parsedTags, }; }