fix(testing): application generators should accurately configure e2e projects (#27453)
- feat(devkit): add util for determining the e2e web server info - feat(vite): add util for determining the e2e web server info - feat(webpack): add util for determining the e2e web server info - fix(webpack): allow port override - fix(devkit): e2e web server info util should handle target defaults - feat(webpack): export the e2e web server info utils - fix(vite): rename util - fix(devkit): util should determine the devTarget for cypress - fix(react): improve accuracy of e2e project generation <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> The logic for finding the correct targets and web addresses to use when setting up e2e projects is flawed and missing some key considerations. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> The logic is accurate and usage is simplified across plugins Projects: - [x] Angular - [x] Expo - [x] Next - [x] Nuxt - [x] Vue - [x] Web - [x] Remix - [x] React - [x] React Native ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
57f3701372
commit
320d9f223f
@ -76,7 +76,7 @@
|
||||
"description": "Adds the specified e2e test runner",
|
||||
"type": "string",
|
||||
"enum": ["playwright", "cypress", "detox", "none"],
|
||||
"default": "playwright"
|
||||
"default": "none"
|
||||
},
|
||||
"standaloneConfig": {
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
|
||||
|
||||
@ -35,14 +35,6 @@ describe('file-server', () => {
|
||||
},
|
||||
}
|
||||
);
|
||||
runCLI(
|
||||
`generate @nx/web:static-config --buildTarget=${ngAppName}:build --outputPath=dist/apps/${ngAppName}/browser --no-interactive`,
|
||||
{
|
||||
env: {
|
||||
NX_ADD_PLUGINS: 'false',
|
||||
},
|
||||
}
|
||||
);
|
||||
runCLI(
|
||||
`generate @nx/web:static-config --buildTarget=${reactAppName}:build --targetName=custom-serve-static --no-interactive`,
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Tree } from '@nx/devkit';
|
||||
import { Tree } from '@nx/devkit';
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
addProjectConfiguration,
|
||||
@ -13,6 +13,7 @@ import { nxVersion } from '../../../utils/versions';
|
||||
import { getInstalledAngularVersionInfo } from '../../utils/version-utils';
|
||||
import type { NormalizedSchema } from './normalized-schema';
|
||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
import { E2EWebServerDetails } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
// since e2e are separate projects, default to adding plugins
|
||||
@ -21,12 +22,19 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
process.env.NX_ADD_PLUGINS !== 'false' &&
|
||||
nxJson.useInferencePlugins !== false;
|
||||
|
||||
const e2eWebServerInfo = getAngularE2EWebServerInfo(
|
||||
tree,
|
||||
options.name,
|
||||
options.port
|
||||
);
|
||||
// TODO: This can call `@nx/web:static-config` generator when ready
|
||||
addFileServerTarget(tree, options, 'serve-static', e2eWebServerInfo.e2ePort);
|
||||
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
// TODO: This can call `@nx/web:static-config` generator when ready
|
||||
addFileServerTarget(tree, options, 'serve-static');
|
||||
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
@ -41,8 +49,14 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
linter: options.linter,
|
||||
skipPackageJson: options.skipPackageJson,
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.name}:${options.e2eWebServerTarget}:development`,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
webServerCommands: {
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
production: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
},
|
||||
ciWebServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
rootProject: options.rootProject,
|
||||
addPlugin,
|
||||
});
|
||||
@ -73,10 +87,8 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx ${
|
||||
options.e2eWebServerTarget
|
||||
} ${options.name}`,
|
||||
webServerAddress: options.e2eWebServerAddress,
|
||||
webServerCommand: e2eWebServerInfo.e2eWebServerCommand,
|
||||
webServerAddress: e2eWebServerInfo.e2eWebServerAddress,
|
||||
rootProject: options.rootProject,
|
||||
addPlugin,
|
||||
});
|
||||
@ -94,7 +106,8 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
function addFileServerTarget(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema,
|
||||
targetName: string
|
||||
targetName: string,
|
||||
e2ePort: number
|
||||
) {
|
||||
if (!options.skipPackageJson) {
|
||||
addDependenciesToPackageJson(tree, {}, { '@nx/web': nxVersion });
|
||||
@ -109,7 +122,7 @@ function addFileServerTarget(
|
||||
executor: '@nx/web:file-server',
|
||||
options: {
|
||||
buildTarget: `${options.name}:build`,
|
||||
port: options.e2ePort,
|
||||
port: e2ePort,
|
||||
staticFilePath: isUsingApplicationBuilder
|
||||
? joinPathFragments(options.outputPath, 'browser')
|
||||
: undefined,
|
||||
@ -118,3 +131,32 @@ function addFileServerTarget(
|
||||
};
|
||||
updateProjectConfiguration(tree, options.name, projectConfig);
|
||||
}
|
||||
|
||||
function getAngularE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
portOverride: number
|
||||
): E2EWebServerDetails & { e2ePort: number } {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = portOverride ?? 4200;
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.['serve'] &&
|
||||
(nxJson.targetDefaults?.['serve'].options?.port ||
|
||||
nxJson.targetDefaults?.['serve'].options?.env?.PORT)
|
||||
) {
|
||||
e2ePort =
|
||||
nxJson.targetDefaults?.['serve'].options?.port ||
|
||||
nxJson.targetDefaults?.['serve'].options?.env?.PORT;
|
||||
}
|
||||
|
||||
const pm = getPackageManagerCommand();
|
||||
return {
|
||||
e2eCiBaseUrl: 'http://localhost:4200',
|
||||
e2eCiWebServerCommand: `${pm.exec} nx run ${projectName}:serve-static`,
|
||||
e2eWebServerCommand: `${pm.exec} nx run ${projectName}:serve`,
|
||||
e2eWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
e2eDevServerTarget: `${projectName}:serve`,
|
||||
e2ePort,
|
||||
};
|
||||
}
|
||||
|
||||
@ -26,21 +26,9 @@ export async function normalizeOptions(
|
||||
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())
|
||||
@ -72,9 +60,6 @@ export async function normalizeOptions(
|
||||
appProjectSourceRoot: `${appProjectRoot}/src`,
|
||||
e2eProjectRoot,
|
||||
e2eProjectName,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2ePort,
|
||||
parsedTags,
|
||||
bundler,
|
||||
outputPath: joinPathFragments(
|
||||
|
||||
@ -12,9 +12,6 @@ export interface NormalizedSchema extends Schema {
|
||||
appProjectSourceRoot: string;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2ePort: number;
|
||||
parsedTags: string[];
|
||||
outputPath: string;
|
||||
}
|
||||
|
||||
248
packages/devkit/src/generators/e2e-web-server-info-utils.spec.ts
Normal file
248
packages/devkit/src/generators/e2e-web-server-info-utils.spec.ts
Normal file
@ -0,0 +1,248 @@
|
||||
import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports';
|
||||
import { type Tree, readNxJson, updateNxJson } from 'nx/src/devkit-exports';
|
||||
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||
import { getE2EWebServerInfo } from './e2e-web-server-info-utils';
|
||||
|
||||
describe('getE2EWebServerInfo', () => {
|
||||
let tree: Tree;
|
||||
let tempFs: TempFs;
|
||||
beforeEach(() => {
|
||||
tempFs = new TempFs('e2e-webserver-info');
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
tree.root = tempFs.tempDir;
|
||||
|
||||
tree.write(`app/vite.config.ts`, ``);
|
||||
tempFs.createFileSync(`app/vite.config.ts`, ``);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tempFs.cleanup();
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
it('should use the default values when no plugin is registered and plugins are not being used', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
{
|
||||
plugin: '@nx/vite/plugin',
|
||||
configFilePath: 'app/vite.config.ts',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'previewTargetName',
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'preview',
|
||||
defaultE2EWebServerAddress: 'http://localhost:4200',
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
||||
defaultE2EPort: 4200,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:preview",
|
||||
"e2eDevServerTarget": "app:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the default values of the plugin when the plugin is just a string', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins = ['@nx/vite/plugin'];
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
{
|
||||
plugin: '@nx/vite/plugin',
|
||||
configFilePath: 'app/vite.config.ts',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'previewTargetName',
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'preview',
|
||||
defaultE2EWebServerAddress: 'http://localhost:4200',
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
||||
defaultE2EPort: 4200,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:preview",
|
||||
"e2eDevServerTarget": "app:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the values of the registered plugin when there is no includes or excludes defined', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite:serve',
|
||||
previewTargetName: 'vite:preview',
|
||||
},
|
||||
});
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
{
|
||||
plugin: '@nx/vite/plugin',
|
||||
configFilePath: 'app/vite.config.ts',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'previewTargetName',
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'preview',
|
||||
defaultE2EWebServerAddress: 'http://localhost:4200',
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
||||
defaultE2EPort: 4200,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:vite:preview",
|
||||
"e2eDevServerTarget": "app:vite:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:vite:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle targetDefaults', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite:serve',
|
||||
previewTargetName: 'vite:preview',
|
||||
},
|
||||
});
|
||||
nxJson.targetDefaults ??= {};
|
||||
nxJson.targetDefaults['vite:serve'] = {
|
||||
options: {
|
||||
port: 4400,
|
||||
},
|
||||
};
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
{
|
||||
plugin: '@nx/vite/plugin',
|
||||
configFilePath: 'app/vite.config.ts',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'previewTargetName',
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'preview',
|
||||
defaultE2EWebServerAddress: 'http://localhost:4200',
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
||||
defaultE2EPort: 4200,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:vite:preview",
|
||||
"e2eDevServerTarget": "app:vite:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4400",
|
||||
"e2eWebServerCommand": "npx nx run app:vite:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the values of the correct registered plugin when there are includes or excludes defined', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite:serve',
|
||||
previewTargetName: 'vite:preview',
|
||||
},
|
||||
include: ['libs/**'],
|
||||
});
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite-serve',
|
||||
previewTargetName: 'vite-preview',
|
||||
},
|
||||
include: ['app/**'],
|
||||
});
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
{
|
||||
plugin: '@nx/vite/plugin',
|
||||
configFilePath: 'app/vite.config.ts',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'previewTargetName',
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'preview',
|
||||
defaultE2EWebServerAddress: 'http://localhost:4200',
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
||||
defaultE2EPort: 4400,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:vite-preview",
|
||||
"e2eDevServerTarget": "app:vite-serve",
|
||||
"e2eWebServerAddress": "http://localhost:4400",
|
||||
"e2eWebServerCommand": "npx nx run app:vite-serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
126
packages/devkit/src/generators/e2e-web-server-info-utils.ts
Normal file
126
packages/devkit/src/generators/e2e-web-server-info-utils.ts
Normal file
@ -0,0 +1,126 @@
|
||||
import {
|
||||
type Tree,
|
||||
getPackageManagerCommand,
|
||||
readNxJson,
|
||||
} from 'nx/src/devkit-exports';
|
||||
import type { PackageManagerCommands } from 'nx/src/utils/package-manager';
|
||||
import { findPluginForConfigFile } from '../utils/find-plugin-for-config-file';
|
||||
|
||||
interface E2EWebServerDefaultValues {
|
||||
defaultServeTargetName: string;
|
||||
defaultServeStaticTargetName: string;
|
||||
defaultE2EWebServerAddress: string;
|
||||
defaultE2ECiBaseUrl: string;
|
||||
defaultE2EPort: number;
|
||||
}
|
||||
|
||||
interface E2EWebServerPluginOptions {
|
||||
plugin: string;
|
||||
configFilePath: string;
|
||||
serveTargetName: string;
|
||||
serveStaticTargetName: string;
|
||||
}
|
||||
|
||||
export interface E2EWebServerDetails {
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerCommand: string;
|
||||
e2eCiWebServerCommand: string;
|
||||
e2eCiBaseUrl: string;
|
||||
e2eDevServerTarget: string;
|
||||
}
|
||||
|
||||
export async function getE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
pluginOptions: E2EWebServerPluginOptions,
|
||||
defaultValues: E2EWebServerDefaultValues,
|
||||
isPluginBeingAdded: boolean
|
||||
): Promise<E2EWebServerDetails> {
|
||||
const pm = getPackageManagerCommand();
|
||||
if (isPluginBeingAdded) {
|
||||
return await getE2EWebServerInfoForPlugin(
|
||||
tree,
|
||||
projectName,
|
||||
pluginOptions,
|
||||
defaultValues,
|
||||
pm
|
||||
);
|
||||
} else {
|
||||
return {
|
||||
e2eWebServerAddress: defaultValues.defaultE2EWebServerAddress,
|
||||
e2eWebServerCommand: `${pm.exec} nx run ${projectName}:${defaultValues.defaultServeTargetName}`,
|
||||
e2eCiWebServerCommand: `${pm.exec} nx run ${projectName}:${defaultValues.defaultServeStaticTargetName}`,
|
||||
e2eCiBaseUrl: defaultValues.defaultE2ECiBaseUrl,
|
||||
e2eDevServerTarget: `${projectName}:${defaultValues.defaultServeTargetName}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function getE2EWebServerInfoForPlugin(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
pluginOptions: E2EWebServerPluginOptions,
|
||||
defaultValues: E2EWebServerDefaultValues,
|
||||
pm: PackageManagerCommands
|
||||
): Promise<E2EWebServerDetails> {
|
||||
const foundPlugin = await findPluginForConfigFile(
|
||||
tree,
|
||||
pluginOptions.plugin,
|
||||
pluginOptions.configFilePath
|
||||
);
|
||||
if (
|
||||
!foundPlugin ||
|
||||
typeof foundPlugin === 'string' ||
|
||||
!foundPlugin?.options
|
||||
) {
|
||||
return {
|
||||
e2eWebServerAddress: defaultValues.defaultE2EWebServerAddress,
|
||||
e2eWebServerCommand: `${pm.exec} nx run ${projectName}:${defaultValues.defaultServeTargetName}`,
|
||||
e2eCiWebServerCommand: `${pm.exec} nx run ${projectName}:${defaultValues.defaultServeStaticTargetName}`,
|
||||
e2eCiBaseUrl: defaultValues.defaultE2ECiBaseUrl,
|
||||
e2eDevServerTarget: `${projectName}:${defaultValues.defaultServeTargetName}`,
|
||||
};
|
||||
}
|
||||
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = defaultValues.defaultE2EPort ?? 4200;
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.[
|
||||
foundPlugin.options[pluginOptions.serveTargetName] ??
|
||||
defaultValues.defaultServeTargetName
|
||||
] &&
|
||||
nxJson.targetDefaults?.[
|
||||
foundPlugin.options[pluginOptions.serveTargetName] ??
|
||||
defaultValues.defaultServeTargetName
|
||||
].options?.port
|
||||
) {
|
||||
e2ePort =
|
||||
nxJson.targetDefaults?.[
|
||||
foundPlugin.options[pluginOptions.serveTargetName] ??
|
||||
defaultValues.defaultServeTargetName
|
||||
].options?.port;
|
||||
}
|
||||
|
||||
const e2eWebServerAddress = defaultValues.defaultE2EWebServerAddress.replace(
|
||||
/:\d+/,
|
||||
`:${e2ePort}`
|
||||
);
|
||||
|
||||
return {
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerCommand: `${pm.exec} nx run ${projectName}:${
|
||||
foundPlugin.options[pluginOptions.serveTargetName] ??
|
||||
defaultValues.defaultServeTargetName
|
||||
}`,
|
||||
e2eCiWebServerCommand: `${pm.exec} nx run ${projectName}:${
|
||||
foundPlugin.options[pluginOptions.serveStaticTargetName] ??
|
||||
defaultValues.defaultServeStaticTargetName
|
||||
}`,
|
||||
e2eCiBaseUrl: defaultValues.defaultE2ECiBaseUrl,
|
||||
e2eDevServerTarget: `${projectName}:${
|
||||
foundPlugin.options[pluginOptions.serveTargetName] ??
|
||||
defaultValues.defaultServeTargetName
|
||||
}`,
|
||||
};
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import type { GeneratorCallback, Tree } from '@nx/devkit';
|
||||
import { GeneratorCallback, Tree } from '@nx/devkit';
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
ensurePackage,
|
||||
@ -13,21 +13,29 @@ import { hasExpoPlugin } from '../../../utils/has-expo-plugin';
|
||||
import { NormalizedSchema } from './normalize-options';
|
||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function addE2e(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema
|
||||
): Promise<GeneratorCallback> {
|
||||
const hasPlugin = hasExpoPlugin(tree);
|
||||
if (!hasPlugin) {
|
||||
await webStaticServeGenerator(tree, {
|
||||
buildTarget: `${options.projectName}:export`,
|
||||
targetName: 'serve-static',
|
||||
});
|
||||
}
|
||||
|
||||
const e2eWebServerInfo = await getExpoE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(options.appProjectRoot, 'app.json'),
|
||||
options.addPlugin
|
||||
);
|
||||
|
||||
switch (options.e2eTestRunner) {
|
||||
case 'cypress': {
|
||||
if (!hasPlugin) {
|
||||
await webStaticServeGenerator(tree, {
|
||||
buildTarget: `${options.projectName}:export`,
|
||||
targetName: 'serve-static',
|
||||
});
|
||||
}
|
||||
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
@ -48,12 +56,14 @@ 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}:${options.e2eWebServerTarget}`,
|
||||
port: options.e2ePort,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
ciWebServerCommand: hasPlugin
|
||||
? `nx run ${options.projectName}:serve-static`
|
||||
: undefined,
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
ciWebServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
webServerCommands: {
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
production: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
},
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
jsx: true,
|
||||
rootProject: options.rootProject,
|
||||
});
|
||||
@ -112,10 +122,8 @@ export async function addE2e(
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx ${
|
||||
options.e2eWebServerTarget
|
||||
} ${options.name}`,
|
||||
webServerAddress: options.e2eWebServerAddress,
|
||||
webServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
webServerAddress: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
rootProject: options.rootProject,
|
||||
addPlugin: options.addPlugin,
|
||||
});
|
||||
@ -172,3 +180,39 @@ export async function addE2e(
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
async function getExpoE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string,
|
||||
isPluginBeingAdded: boolean
|
||||
) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = isPluginBeingAdded ? 8081 : 4200;
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.['serve'] &&
|
||||
nxJson.targetDefaults?.['serve'].options?.port
|
||||
) {
|
||||
e2ePort = nxJson.targetDefaults?.['serve'].options?.port;
|
||||
}
|
||||
|
||||
return getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/expo/plugin',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'serveTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'serve-static',
|
||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
|
||||
@ -40,9 +40,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'my-app-e2e',
|
||||
e2ePort: 8081,
|
||||
e2eWebServerAddress: 'http://localhost:8081',
|
||||
e2eWebServerTarget: 'serve',
|
||||
} as NormalizedSchema);
|
||||
});
|
||||
|
||||
@ -75,9 +72,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'myApp-e2e',
|
||||
e2eProjectRoot: 'myApp-e2e',
|
||||
e2ePort: 8081,
|
||||
e2eWebServerAddress: 'http://localhost:8081',
|
||||
e2eWebServerTarget: 'serve',
|
||||
} as NormalizedSchema);
|
||||
});
|
||||
|
||||
@ -112,9 +106,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'directory-e2e',
|
||||
e2ePort: 8081,
|
||||
e2eWebServerAddress: 'http://localhost:8081',
|
||||
e2eWebServerTarget: 'serve',
|
||||
} as NormalizedSchema);
|
||||
});
|
||||
|
||||
@ -147,9 +138,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'directory/my-app-e2e',
|
||||
e2ePort: 8081,
|
||||
e2eWebServerAddress: 'http://localhost:8081',
|
||||
e2eWebServerTarget: 'serve',
|
||||
} as NormalizedSchema);
|
||||
});
|
||||
|
||||
@ -183,9 +171,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'my-app-e2e',
|
||||
e2ePort: 8081,
|
||||
e2eWebServerAddress: 'http://localhost:8081',
|
||||
e2eWebServerTarget: 'serve',
|
||||
} as NormalizedSchema);
|
||||
});
|
||||
});
|
||||
|
||||
@ -12,9 +12,6 @@ export interface NormalizedSchema extends Schema {
|
||||
rootProject: boolean;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2ePort: number;
|
||||
}
|
||||
|
||||
export async function normalizeOptions(
|
||||
@ -46,38 +43,13 @@ export async function normalizeOptions(
|
||||
: [];
|
||||
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,
|
||||
unitTestRunner: options.unitTestRunner || 'jest',
|
||||
e2eTestRunner: options.e2eTestRunner,
|
||||
e2eTestRunner: options.e2eTestRunner || 'none',
|
||||
name: projectNames.projectSimpleName,
|
||||
className,
|
||||
lowerCaseName: className.toLowerCase(),
|
||||
@ -88,8 +60,5 @@ export async function normalizeOptions(
|
||||
rootProject,
|
||||
e2eProjectName,
|
||||
e2eProjectRoot,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2ePort,
|
||||
};
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@
|
||||
"description": "Adds the specified e2e test runner",
|
||||
"type": "string",
|
||||
"enum": ["playwright", "cypress", "detox", "none"],
|
||||
"default": "playwright"
|
||||
"default": "none"
|
||||
},
|
||||
"standaloneConfig": {
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
|
||||
|
||||
@ -13,6 +13,7 @@ import { NormalizedSchema } from './normalize-options';
|
||||
import { webStaticServeGenerator } from '@nx/web';
|
||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
const nxJson = readNxJson(host);
|
||||
@ -22,6 +23,13 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
: p.plugin === '@nx/next/plugin'
|
||||
);
|
||||
|
||||
const e2eWebServerInfo = await getNextE2EWebServerInfo(
|
||||
host,
|
||||
options.projectName,
|
||||
joinPathFragments(options.appProjectRoot, 'next.config.js'),
|
||||
options.addPlugin
|
||||
);
|
||||
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
@ -50,17 +58,16 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
jsx: true,
|
||||
webServerCommands: hasPlugin
|
||||
? {
|
||||
default: `nx run ${options.projectName}:${options.e2eWebServerTarget}`,
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
}
|
||||
: undefined,
|
||||
ciWebServerCommand: hasPlugin
|
||||
? `nx run ${options.projectName}:serve-static`
|
||||
: undefined,
|
||||
ciWebServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
});
|
||||
|
||||
if (
|
||||
@ -116,10 +123,8 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerAddress: `http://127.0.0.1:${options.e2ePort}`,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx ${
|
||||
options.e2eWebServerTarget
|
||||
} ${options.projectName}`,
|
||||
webServerAddress: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
webServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
addPlugin: options.addPlugin,
|
||||
});
|
||||
|
||||
@ -156,3 +161,41 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
}
|
||||
return () => {};
|
||||
}
|
||||
|
||||
async function getNextE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string,
|
||||
isPluginBeingAdded: boolean
|
||||
) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = isPluginBeingAdded ? 3000 : 4200;
|
||||
|
||||
const defaultServeTarget = isPluginBeingAdded ? 'dev' : 'serve';
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.[defaultServeTarget] &&
|
||||
nxJson.targetDefaults?.[defaultServeTarget].options?.port
|
||||
) {
|
||||
e2ePort = nxJson.targetDefaults?.[defaultServeTarget].options?.port;
|
||||
}
|
||||
|
||||
return getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/next/plugin',
|
||||
serveTargetName: 'devTargetName',
|
||||
serveStaticTargetName: 'serveStaticTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: defaultServeTarget,
|
||||
defaultServeStaticTargetName: 'serve-static',
|
||||
defaultE2EWebServerAddress: `http://127.0.0.1:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: `http://localhost:${e2ePort}`,
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,9 +21,6 @@ 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: [],
|
||||
|
||||
@ -11,9 +11,6 @@ export interface NormalizedSchema extends Schema {
|
||||
outputPath: string;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2ePort: number;
|
||||
parsedTags: string[];
|
||||
fileName: string;
|
||||
styledModule: null | string;
|
||||
@ -46,36 +43,8 @@ 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;
|
||||
|
||||
@ -107,9 +76,6 @@ export async function normalizeOptions(
|
||||
appProjectRoot,
|
||||
e2eProjectName,
|
||||
e2eProjectRoot,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2ePort,
|
||||
e2eTestRunner: options.e2eTestRunner || 'playwright',
|
||||
fileName,
|
||||
linter: options.linter || Linter.EsLint,
|
||||
|
||||
@ -3,14 +3,24 @@ import {
|
||||
ensurePackage,
|
||||
getPackageManagerCommand,
|
||||
joinPathFragments,
|
||||
readNxJson,
|
||||
Tree,
|
||||
} from '@nx/devkit';
|
||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
import { nxVersion } from '../../../utils/versions';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
|
||||
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
const e2eWebServerInfo = await getNuxtE2EWebServerInfo(
|
||||
host,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`nuxt.config.${options.js ? 'js' : 'ts'}`
|
||||
)
|
||||
);
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
@ -29,14 +39,13 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
directory: 'src',
|
||||
bundler: 'vite',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`,
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
webServerCommands: {
|
||||
default: `${getPackageManagerCommand().exec} nx ${
|
||||
options.e2eWebServerTarget
|
||||
} ${options.projectName}`,
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
},
|
||||
ciWebServerCommand: `nx run ${options.projectName}:serve-static`,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
ciWebServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
jsx: true,
|
||||
addPlugin: true,
|
||||
});
|
||||
@ -85,10 +94,8 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerAddress: options.e2eWebServerAddress,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx ${
|
||||
options.e2eWebServerTarget
|
||||
} ${options.projectName}`,
|
||||
webServerAddress: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
webServerCommand: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
addPlugin: true,
|
||||
});
|
||||
|
||||
@ -118,3 +125,38 @@ export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
}
|
||||
return () => {};
|
||||
}
|
||||
|
||||
async function getNuxtE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string
|
||||
) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = 4200;
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.['serve'] &&
|
||||
nxJson.targetDefaults?.['serve'].options?.port
|
||||
) {
|
||||
e2ePort = nxJson.targetDefaults?.['serve'].options?.port;
|
||||
}
|
||||
|
||||
return getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/nuxt/plugin',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'serveStaticTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'serve-static',
|
||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@ -32,30 +32,9 @@ export async function normalizeOptions(
|
||||
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())
|
||||
@ -68,9 +47,6 @@ export async function normalizeOptions(
|
||||
appProjectRoot,
|
||||
e2eProjectName,
|
||||
e2eProjectRoot,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2ePort,
|
||||
parsedTags,
|
||||
style: options.style ?? 'none',
|
||||
} as NormalizedSchema;
|
||||
|
||||
@ -23,8 +23,5 @@ export interface NormalizedSchema extends Schema {
|
||||
appProjectRoot: string;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2ePort: number;
|
||||
parsedTags: string[];
|
||||
}
|
||||
|
||||
@ -18,8 +18,6 @@ export async function addE2e(
|
||||
styledModule: null,
|
||||
hasStyles: false,
|
||||
unitTestRunner: 'none',
|
||||
e2eCiWebServerTarget: options.e2eWebServerTarget,
|
||||
e2eCiBaseUrl: options.e2eWebServerAddress,
|
||||
});
|
||||
case 'playwright':
|
||||
return addE2eReact(host, {
|
||||
@ -29,8 +27,6 @@ export async function addE2e(
|
||||
styledModule: null,
|
||||
hasStyles: false,
|
||||
unitTestRunner: 'none',
|
||||
e2eCiWebServerTarget: options.e2eWebServerTarget,
|
||||
e2eCiBaseUrl: options.e2eWebServerAddress,
|
||||
});
|
||||
case 'detox':
|
||||
const { detoxApplicationGenerator } = ensurePackage<
|
||||
|
||||
@ -44,9 +44,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'my-app-e2e',
|
||||
e2ePort: 4200,
|
||||
e2eWebServerAddress: 'http://localhost:4200',
|
||||
e2eWebServerTarget: 'serve',
|
||||
});
|
||||
});
|
||||
|
||||
@ -83,9 +80,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'myApp-e2e',
|
||||
e2ePort: 4200,
|
||||
e2eWebServerAddress: 'http://localhost:4200',
|
||||
e2eWebServerTarget: 'serve',
|
||||
});
|
||||
});
|
||||
|
||||
@ -124,9 +118,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'directory/my-app-e2e',
|
||||
e2ePort: 4200,
|
||||
e2eWebServerAddress: 'http://localhost:4200',
|
||||
e2eWebServerTarget: 'serve',
|
||||
});
|
||||
});
|
||||
|
||||
@ -163,9 +154,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'directory/my-app-e2e',
|
||||
e2eProjectRoot: 'directory/my-app-e2e',
|
||||
e2ePort: 4200,
|
||||
e2eWebServerAddress: 'http://localhost:4200',
|
||||
e2eWebServerTarget: 'serve',
|
||||
});
|
||||
});
|
||||
|
||||
@ -203,9 +191,6 @@ describe('Normalize Options', () => {
|
||||
rootProject: false,
|
||||
e2eProjectName: 'my-app-e2e',
|
||||
e2eProjectRoot: 'my-app-e2e',
|
||||
e2ePort: 4200,
|
||||
e2eWebServerAddress: 'http://localhost:4200',
|
||||
e2eWebServerTarget: 'serve',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -17,9 +17,6 @@ export interface NormalizedSchema extends Schema {
|
||||
rootProject: boolean;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2ePort: number;
|
||||
}
|
||||
|
||||
export async function normalizeOptions(
|
||||
@ -50,34 +47,8 @@ export async function normalizeOptions(
|
||||
const androidProjectRoot = joinPathFragments(appProjectRoot, 'android');
|
||||
const rootProject = appProjectRoot === '.';
|
||||
|
||||
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 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())
|
||||
@ -101,8 +72,5 @@ export async function normalizeOptions(
|
||||
rootProject,
|
||||
e2eProjectName,
|
||||
e2eProjectRoot,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2ePort,
|
||||
};
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ describe('app', () => {
|
||||
import { defineConfig } from 'cypress';
|
||||
|
||||
export default defineConfig({
|
||||
e2e: { ...nxE2EPreset(__filename, {"cypressDir":"src","bundler":"vite","webServerCommands":{"default":"nx run my-app:serve","production":"nx run my-app:preview"},"ciWebServerCommand":"nx run my-app:preview","ciBaseUrl":"http://localhost:4300"}),
|
||||
e2e: { ...nxE2EPreset(__filename, {"cypressDir":"src","bundler":"vite","webServerCommands":{"default":"npx nx run my-app:serve","production":"npx nx run my-app:preview"},"ciWebServerCommand":"npx nx run my-app:preview","ciBaseUrl":"http://localhost:4300"}),
|
||||
baseUrl: 'http://localhost:4200' }
|
||||
});
|
||||
"
|
||||
|
||||
@ -14,6 +14,7 @@ import { hasVitePlugin } from '../../../utils/has-vite-plugin';
|
||||
import { NormalizedSchema } from '../schema';
|
||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
import { E2EWebServerDetails } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function addE2e(
|
||||
tree: Tree,
|
||||
@ -22,6 +23,49 @@ export async function addE2e(
|
||||
const hasNxBuildPlugin =
|
||||
(options.bundler === 'webpack' && hasWebpackPlugin(tree)) ||
|
||||
(options.bundler === 'vite' && hasVitePlugin(tree));
|
||||
|
||||
let e2eWebServerInfo: E2EWebServerDetails = {
|
||||
e2eWebServerAddress: `http://localhost:${options.devServerPort ?? 4200}`,
|
||||
e2eWebServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:serve`,
|
||||
e2eCiWebServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:serve-static`,
|
||||
e2eCiBaseUrl: `http://localhost:4200`,
|
||||
e2eDevServerTarget: `${options.projectName}:serve`,
|
||||
};
|
||||
|
||||
if (options.bundler === 'webpack') {
|
||||
const { getWebpackE2EWebServerInfo } = ensurePackage<
|
||||
typeof import('@nx/webpack')
|
||||
>('@nx/webpack', nxVersion);
|
||||
e2eWebServerInfo = await getWebpackE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`webpack.config.${options.js ? 'js' : 'ts'}`
|
||||
),
|
||||
options.addPlugin,
|
||||
options.devServerPort ?? 4200
|
||||
);
|
||||
} else if (options.bundler === 'vite') {
|
||||
const { getViteE2EWebServerInfo } = ensurePackage<
|
||||
typeof import('@nx/vite')
|
||||
>('@nx/vite', nxVersion);
|
||||
e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||
),
|
||||
options.addPlugin,
|
||||
options.devServerPort ?? 4200
|
||||
);
|
||||
}
|
||||
|
||||
if (!hasNxBuildPlugin) {
|
||||
await webStaticServeGenerator(tree, {
|
||||
buildTarget: `${options.projectName}:build`,
|
||||
@ -51,21 +95,20 @@ 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}:${options.e2eWebServerTarget}`,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
jsx: true,
|
||||
rootProject: options.rootProject,
|
||||
webServerCommands: hasNxBuildPlugin
|
||||
? {
|
||||
default: `nx run ${options.projectName}:${options.e2eWebServerTarget}`,
|
||||
production: `nx run ${options.projectName}:preview`,
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
production: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
}
|
||||
: undefined,
|
||||
ciWebServerCommand: hasNxBuildPlugin
|
||||
? `nx run ${options.projectName}:${options.e2eCiWebServerTarget}`
|
||||
? e2eWebServerInfo.e2eCiWebServerCommand
|
||||
: undefined,
|
||||
ciBaseUrl:
|
||||
options.bundler === 'vite' ? options.e2eCiBaseUrl : undefined,
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
});
|
||||
|
||||
if (
|
||||
@ -127,10 +170,8 @@ export async function addE2e(
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:${options.e2eCiWebServerTarget}`,
|
||||
webServerAddress: options.e2eCiBaseUrl,
|
||||
webServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
webServerAddress: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
rootProject: options.rootProject,
|
||||
addPlugin: options.addPlugin,
|
||||
});
|
||||
|
||||
@ -46,57 +46,8 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
||||
options.rootProject = appProjectRoot === '.';
|
||||
options.projectNameAndRootFormat = projectNameAndRootFormat;
|
||||
|
||||
let e2ePort = options.devServerPort ?? 4200;
|
||||
|
||||
let e2eWebServerTarget = 'serve';
|
||||
let e2eCiWebServerTarget =
|
||||
options.bundler === 'vite' ? 'preview' : 'serve-static';
|
||||
if (options.addPlugin) {
|
||||
if (nxJson.plugins) {
|
||||
for (const plugin of nxJson.plugins) {
|
||||
if (
|
||||
options.bundler === 'vite' &&
|
||||
typeof plugin === 'object' &&
|
||||
plugin.plugin === '@nx/vite/plugin'
|
||||
) {
|
||||
e2eCiWebServerTarget =
|
||||
(plugin.options as VitePluginOptions)?.previewTargetName ??
|
||||
e2eCiWebServerTarget;
|
||||
|
||||
e2eWebServerTarget =
|
||||
(plugin.options as VitePluginOptions)?.serveTargetName ??
|
||||
e2eWebServerTarget;
|
||||
} else if (
|
||||
options.bundler === 'webpack' &&
|
||||
typeof plugin === 'object' &&
|
||||
plugin.plugin === '@nx/webpack/plugin'
|
||||
) {
|
||||
e2eCiWebServerTarget =
|
||||
(plugin.options as WebpackPluginOptions)?.serveStaticTargetName ??
|
||||
e2eCiWebServerTarget;
|
||||
|
||||
e2eWebServerTarget =
|
||||
(plugin.options as WebpackPluginOptions)?.serveTargetName ??
|
||||
e2eWebServerTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 e2eCiBaseUrl =
|
||||
options.bundler === 'vite'
|
||||
? 'http://localhost:4300'
|
||||
: `http://localhost:${e2ePort}`;
|
||||
|
||||
const parsedTags = options.tags
|
||||
? options.tags.split(',').map((s) => s.trim())
|
||||
@ -117,11 +68,6 @@ export async function normalizeOptions<T extends Schema = Schema>(
|
||||
appProjectRoot,
|
||||
e2eProjectName,
|
||||
e2eProjectRoot,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2eCiWebServerTarget,
|
||||
e2eCiBaseUrl,
|
||||
e2ePort,
|
||||
parsedTags,
|
||||
fileName,
|
||||
styledModule,
|
||||
|
||||
@ -37,11 +37,6 @@ export interface NormalizedSchema<T extends Schema = Schema> extends T {
|
||||
appProjectRoot: string;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2eCiWebServerTarget: string;
|
||||
e2eCiBaseUrl: string;
|
||||
e2ePort: number;
|
||||
parsedTags: string[];
|
||||
fileName: string;
|
||||
styledModule: null | SupportedStyles;
|
||||
|
||||
@ -153,7 +153,12 @@ export default defineConfig({
|
||||
e2e: {
|
||||
...nxE2EPreset(__filename, {
|
||||
cypressDir: 'src',
|
||||
webServerCommands: { default: 'nx run test:dev:development' },
|
||||
webServerCommands: {
|
||||
default: 'npx nx run test:dev',
|
||||
production: 'npx nx run test:serve-static',
|
||||
},
|
||||
ciWebServerCommand: 'npx nx run test:serve-static',
|
||||
ciBaseUrl: 'http://localhost:3000',
|
||||
}),
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
@ -189,7 +194,7 @@ export default defineConfig({
|
||||
},
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: 'npx nx dev test',
|
||||
command: 'npx nx run test:serve-static',
|
||||
url: 'http://localhost:3000',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
cwd: workspaceRoot,
|
||||
@ -665,7 +670,12 @@ export default defineConfig({
|
||||
e2e: {
|
||||
...nxE2EPreset(__filename, {
|
||||
cypressDir: 'src',
|
||||
webServerCommands: { default: 'nx run test:dev:development' },
|
||||
webServerCommands: {
|
||||
default: 'npx nx run test:dev',
|
||||
production: 'npx nx run test:serve-static',
|
||||
},
|
||||
ciWebServerCommand: 'npx nx run test:serve-static',
|
||||
ciBaseUrl: 'http://localhost:3000',
|
||||
}),
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
@ -701,7 +711,7 @@ export default defineConfig({
|
||||
},
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: 'npx nx dev test',
|
||||
command: 'npx nx run test:serve-static',
|
||||
url: 'http://localhost:3000',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
cwd: workspaceRoot,
|
||||
@ -1033,7 +1043,12 @@ export default defineConfig({
|
||||
e2e: {
|
||||
...nxE2EPreset(__filename, {
|
||||
cypressDir: 'src',
|
||||
webServerCommands: { default: 'nx run test:dev:development' },
|
||||
webServerCommands: {
|
||||
default: 'npx nx run test:dev',
|
||||
production: 'npx nx run test:serve-static',
|
||||
},
|
||||
ciWebServerCommand: 'npx nx run test:serve-static',
|
||||
ciBaseUrl: 'http://localhost:3000',
|
||||
}),
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
@ -1434,7 +1449,7 @@ export default defineConfig({
|
||||
},
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: {
|
||||
command: 'npx nx dev test',
|
||||
command: 'npx nx run test:serve-static',
|
||||
url: 'http://localhost:3000',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
cwd: workspaceRoot,
|
||||
|
||||
@ -97,7 +97,7 @@ export async function remixApplicationGeneratorInternal(
|
||||
cwd: options.projectRoot,
|
||||
},
|
||||
},
|
||||
['static-serve']: {
|
||||
['serve-static']: {
|
||||
dependsOn: ['build'],
|
||||
command: `remix-serve build/index.js`,
|
||||
options: {
|
||||
|
||||
@ -12,6 +12,7 @@ import { type NormalizedSchema } from './normalize-options';
|
||||
import { getPackageVersion } from '../../../utils/versions';
|
||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||
import { addE2eCiTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
|
||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function addE2E(tree: Tree, options: NormalizedSchema) {
|
||||
const hasRemixPlugin = readNxJson(tree).plugins?.find((p) =>
|
||||
@ -19,6 +20,14 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) {
|
||||
? p === '@nx/remix/plugin'
|
||||
: p.plugin === '@nx/remix/plugin'
|
||||
);
|
||||
|
||||
let e2eWebsServerInfo = await getRemixE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(options.projectRoot, 'remix.config.js'),
|
||||
options.addPlugin ?? Boolean(hasRemixPlugin)
|
||||
);
|
||||
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
@ -37,8 +46,18 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) {
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}:development`,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
devServerTarget: e2eWebsServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebsServerInfo.e2eWebServerAddress,
|
||||
webServerCommands: hasRemixPlugin
|
||||
? {
|
||||
default: e2eWebsServerInfo.e2eWebServerCommand,
|
||||
production: e2eWebsServerInfo.e2eCiWebServerCommand,
|
||||
}
|
||||
: undefined,
|
||||
ciWebServerCommand: hasRemixPlugin
|
||||
? e2eWebsServerInfo.e2eCiWebServerCommand
|
||||
: undefined,
|
||||
ciBaseUrl: e2eWebsServerInfo.e2eCiBaseUrl,
|
||||
addPlugin: options.addPlugin,
|
||||
});
|
||||
|
||||
@ -97,10 +116,8 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) {
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: false,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx ${
|
||||
options.e2eWebServerTarget
|
||||
} ${options.name}`,
|
||||
webServerAddress: options.e2eWebServerAddress,
|
||||
webServerCommand: e2eWebsServerInfo.e2eCiWebServerCommand,
|
||||
webServerAddress: e2eWebsServerInfo.e2eCiBaseUrl,
|
||||
rootProject: options.rootProject,
|
||||
addPlugin: options.addPlugin,
|
||||
});
|
||||
@ -139,3 +156,41 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) {
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
async function getRemixE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string,
|
||||
isPluginBeingAdded: boolean
|
||||
) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = isPluginBeingAdded ? 3000 : 4200;
|
||||
|
||||
const defaultServeTarget = isPluginBeingAdded ? 'dev' : 'serve';
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.[defaultServeTarget] &&
|
||||
nxJson.targetDefaults?.[defaultServeTarget].options?.port
|
||||
) {
|
||||
e2ePort = nxJson.targetDefaults?.[defaultServeTarget].options?.port;
|
||||
}
|
||||
|
||||
return getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/remix/plugin',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'serveStaticTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: defaultServeTarget,
|
||||
defaultServeStaticTargetName: 'serve-static',
|
||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: 'http://localhost:3000',
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
|
||||
@ -9,9 +9,6 @@ export interface NormalizedSchema extends NxRemixGeneratorSchema {
|
||||
projectRoot: string;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2ePort: number;
|
||||
parsedTags: string[];
|
||||
}
|
||||
|
||||
@ -36,35 +33,8 @@ export async function normalizeOptions(
|
||||
nxJson.useInferencePlugins !== false;
|
||||
options.addPlugin ??= addPluginDefault;
|
||||
|
||||
let e2eWebServerTarget = options.addPlugin ? 'dev' : 'serve';
|
||||
if (options.addPlugin) {
|
||||
if (nxJson.plugins) {
|
||||
for (const plugin of nxJson.plugins) {
|
||||
if (
|
||||
typeof plugin === 'object' &&
|
||||
plugin.plugin === '@nx/remix/plugin' &&
|
||||
(plugin.options as RemixPluginOptions).devTargetName
|
||||
) {
|
||||
e2eWebServerTarget = (plugin.options as RemixPluginOptions)
|
||||
.devTargetName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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' : `${projectName}-e2e`;
|
||||
const e2eProjectRoot = options.rootProject ? 'e2e' : `${projectRoot}-e2e`;
|
||||
const e2eWebServerAddress = `http://localhost:${e2ePort}`;
|
||||
|
||||
const parsedTags = options.tags
|
||||
? options.tags.split(',').map((s) => s.trim())
|
||||
@ -77,9 +47,6 @@ export async function normalizeOptions(
|
||||
projectRoot,
|
||||
e2eProjectName,
|
||||
e2eProjectRoot,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2ePort,
|
||||
parsedTags,
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,6 +35,15 @@ exports[`@nx/remix/plugin non-root project should create nodes 1`] = `
|
||||
"cwd": "my-app",
|
||||
},
|
||||
},
|
||||
"serve-static": {
|
||||
"command": "remix-serve build/index.js",
|
||||
"dependsOn": [
|
||||
"build",
|
||||
],
|
||||
"options": {
|
||||
"cwd": "my-app",
|
||||
},
|
||||
},
|
||||
"start": {
|
||||
"command": "remix-serve build/index.js",
|
||||
"dependsOn": [
|
||||
@ -110,6 +119,15 @@ exports[`@nx/remix/plugin root project should create nodes 1`] = `
|
||||
"cwd": ".",
|
||||
},
|
||||
},
|
||||
"serve-static": {
|
||||
"command": "remix-serve build/index.js",
|
||||
"dependsOn": [
|
||||
"build",
|
||||
],
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
},
|
||||
"start": {
|
||||
"command": "remix-serve build/index.js",
|
||||
"dependsOn": [
|
||||
|
||||
@ -45,7 +45,11 @@ export interface RemixPluginOptions {
|
||||
devTargetName?: string;
|
||||
startTargetName?: string;
|
||||
typecheckTargetName?: string;
|
||||
/**
|
||||
* @deprecated Use serveStaticTargetName instead. This option will be removed in Nx 21.
|
||||
*/
|
||||
staticServeTargetName?: string;
|
||||
serveStaticTargetName?: string;
|
||||
}
|
||||
|
||||
export const createNodes: CreateNodes<RemixPluginOptions> = [
|
||||
@ -116,11 +120,17 @@ async function buildRemixTargets(
|
||||
serverBuildPath,
|
||||
options.buildTargetName
|
||||
);
|
||||
// TODO(colum): Remove for Nx 21
|
||||
targets[options.staticServeTargetName] = startTarget(
|
||||
projectRoot,
|
||||
serverBuildPath,
|
||||
options.buildTargetName
|
||||
);
|
||||
targets[options.serveStaticTargetName] = startTarget(
|
||||
projectRoot,
|
||||
serverBuildPath,
|
||||
options.buildTargetName
|
||||
);
|
||||
targets[options.typecheckTargetName] = typecheckTarget(
|
||||
projectRoot,
|
||||
namedInputs,
|
||||
@ -233,7 +243,9 @@ function normalizeOptions(options: RemixPluginOptions) {
|
||||
options.devTargetName ??= 'dev';
|
||||
options.startTargetName ??= 'start';
|
||||
options.typecheckTargetName ??= 'typecheck';
|
||||
// TODO(colum): remove for Nx 21
|
||||
options.staticServeTargetName ??= 'static-serve';
|
||||
options.serveStaticTargetName ??= 'serve-static';
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
export * from './src/utils/versions';
|
||||
export * from './src/utils/generator-utils';
|
||||
export * from './src/utils/e2e-web-server-info-utils';
|
||||
export { type ViteConfigurationGeneratorSchema } from './src/generators/configuration/schema';
|
||||
export { viteConfigurationGenerator } from './src/generators/configuration/configuration';
|
||||
export { type VitestGeneratorSchema } from './src/generators/vitest/schema';
|
||||
|
||||
149
packages/vite/src/utils/e2e-web-server-info-utils.spec.ts
Normal file
149
packages/vite/src/utils/e2e-web-server-info-utils.spec.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import { type Tree, readNxJson, updateNxJson } from 'nx/src/devkit-exports';
|
||||
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||
import { getViteE2EWebServerInfo } from './e2e-web-server-info-utils';
|
||||
|
||||
describe('getViteE2EWebServerInfo', () => {
|
||||
let tree: Tree;
|
||||
let tempFs: TempFs;
|
||||
beforeEach(() => {
|
||||
tempFs = new TempFs('e2e-webserver-info');
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
tree.root = tempFs.tempDir;
|
||||
|
||||
tree.write(`app/vite.config.ts`, ``);
|
||||
tempFs.createFileSync(`app/vite.config.ts`, ``);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tempFs.cleanup();
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
it('should use the default values when no plugin is registered and plugins are not being used', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/vite.config.ts',
|
||||
false
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:preview",
|
||||
"e2eDevServerTarget": "app:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the default values of the plugin when the plugin is just a string', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins = ['@nx/vite/plugin'];
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/vite.config.ts',
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:preview",
|
||||
"e2eDevServerTarget": "app:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the values of the registered plugin when there is no includes or excludes defined', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite:serve',
|
||||
previewTargetName: 'vite:preview',
|
||||
},
|
||||
});
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/vite.config.ts',
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:vite:preview",
|
||||
"e2eDevServerTarget": "app:vite:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:vite:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the values of the correct registered plugin when there are includes or excludes defined', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite:serve',
|
||||
previewTargetName: 'vite:preview',
|
||||
},
|
||||
include: ['libs/**'],
|
||||
});
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/vite/plugin',
|
||||
options: {
|
||||
serveTargetName: 'vite-serve',
|
||||
previewTargetName: 'vite-preview',
|
||||
},
|
||||
include: ['app/**'],
|
||||
});
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/vite.config.ts',
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4300",
|
||||
"e2eCiWebServerCommand": "npx nx run app:vite-preview",
|
||||
"e2eDevServerTarget": "app:vite-serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:vite-serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
39
packages/vite/src/utils/e2e-web-server-info-utils.ts
Normal file
39
packages/vite/src/utils/e2e-web-server-info-utils.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { type Tree, readNxJson } from '@nx/devkit';
|
||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function getViteE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string,
|
||||
isPluginBeingAdded: boolean,
|
||||
e2ePortOverride?: number
|
||||
) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = e2ePortOverride ?? 4200;
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.['serve'] &&
|
||||
nxJson.targetDefaults?.['serve'].options?.port
|
||||
) {
|
||||
e2ePort = nxJson.targetDefaults?.['serve'].options?.port;
|
||||
}
|
||||
|
||||
return getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/vite/plugin',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'previewTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'preview',
|
||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4300',
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
@ -141,10 +141,10 @@ export default defineConfig({
|
||||
cypressDir: 'src',
|
||||
bundler: 'vite',
|
||||
webServerCommands: {
|
||||
default: 'nx run test:serve',
|
||||
production: 'nx run test:preview',
|
||||
default: 'npx nx run test:serve',
|
||||
production: 'npx nx run test:preview',
|
||||
},
|
||||
ciWebServerCommand: 'nx run test:preview',
|
||||
ciWebServerCommand: 'npx nx run test:preview',
|
||||
ciBaseUrl: 'http://localhost:4300',
|
||||
}),
|
||||
baseUrl: 'http://localhost:4200',
|
||||
|
||||
@ -23,16 +23,21 @@ export async function addE2e(
|
||||
? p === '@nx/vite/plugin'
|
||||
: p.plugin === '@nx/vite/plugin'
|
||||
);
|
||||
const e2eWebServerTarget = hasPlugin
|
||||
? typeof hasPlugin === 'string'
|
||||
? 'serve'
|
||||
: (hasPlugin.options as any)?.serveTargetName ?? 'serve'
|
||||
: 'serve';
|
||||
const e2eCiWebServerTarget = hasPlugin
|
||||
? typeof hasPlugin === 'string'
|
||||
? 'preview'
|
||||
: (hasPlugin.options as any)?.previewTargetName ?? 'preview'
|
||||
: 'preview';
|
||||
const { getViteE2EWebServerInfo } = ensurePackage<typeof import('@nx/vite')>(
|
||||
'@nx/vite',
|
||||
nxVersion
|
||||
);
|
||||
const e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
tree,
|
||||
options.projectName,
|
||||
joinPathFragments(
|
||||
options.appProjectRoot,
|
||||
`vite.config.${options.js ? 'js' : 'ts'}`
|
||||
),
|
||||
options.addPlugin,
|
||||
options.devServerPort ?? 4200
|
||||
);
|
||||
|
||||
switch (options.e2eTestRunner) {
|
||||
case 'cypress': {
|
||||
if (!hasPlugin) {
|
||||
@ -60,17 +65,17 @@ export async function addE2e(
|
||||
directory: 'src',
|
||||
bundler: 'vite',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:${e2eWebServerTarget}`,
|
||||
baseUrl: 'http://localhost:4200',
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
jsx: true,
|
||||
webServerCommands: hasPlugin
|
||||
? {
|
||||
default: `nx run ${options.projectName}:${e2eWebServerTarget}`,
|
||||
production: `nx run ${options.projectName}:preview`,
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
production: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
}
|
||||
: undefined,
|
||||
ciWebServerCommand: `nx run ${options.projectName}:${e2eCiWebServerTarget}`,
|
||||
ciBaseUrl: 'http://localhost:4300',
|
||||
ciWebServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
});
|
||||
|
||||
if (
|
||||
@ -130,10 +135,8 @@ export async function addE2e(
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:${e2eCiWebServerTarget}`,
|
||||
webServerAddress: 'http://localhost:4300',
|
||||
webServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
webServerAddress: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
});
|
||||
|
||||
if (
|
||||
|
||||
@ -192,10 +192,10 @@ describe('app', () => {
|
||||
cypressDir: 'src',
|
||||
bundler: 'vite',
|
||||
webServerCommands: {
|
||||
default: 'nx run cool-app:serve',
|
||||
production: 'nx run cool-app:preview',
|
||||
default: 'npx nx run cool-app:serve',
|
||||
production: 'npx nx run cool-app:preview',
|
||||
},
|
||||
ciWebServerCommand: 'nx run cool-app:preview',
|
||||
ciWebServerCommand: 'npx nx run cool-app:preview',
|
||||
ciBaseUrl: 'http://localhost:4300',
|
||||
}),
|
||||
baseUrl: 'http://localhost:4200',
|
||||
@ -225,10 +225,11 @@ describe('app', () => {
|
||||
...nxE2EPreset(__filename, {
|
||||
cypressDir: 'src',
|
||||
webServerCommands: {
|
||||
default: 'nx run cool-app:serve',
|
||||
production: 'nx run cool-app:preview',
|
||||
default: 'npx nx run cool-app:serve',
|
||||
production: 'npx nx run cool-app:serve-static',
|
||||
},
|
||||
ciWebServerCommand: 'nx run cool-app:serve-static',
|
||||
ciWebServerCommand: 'npx nx run cool-app:serve-static',
|
||||
ciBaseUrl: 'http://localhost:4200',
|
||||
}),
|
||||
baseUrl: 'http://localhost:4200',
|
||||
},
|
||||
|
||||
@ -47,17 +47,13 @@ import { VitePluginOptions } from '@nx/vite/src/plugins/plugin';
|
||||
import { WebpackPluginOptions } from '@nx/webpack/src/plugins/plugin';
|
||||
import staticServeConfiguration from '../static-serve/static-serve-configuration';
|
||||
import { findPluginForConfigFile } from '@nx/devkit/src/utils/find-plugin-for-config-file';
|
||||
import { E2EWebServerDetails } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
projectName: string;
|
||||
appProjectRoot: string;
|
||||
e2eProjectName: string;
|
||||
e2eProjectRoot: string;
|
||||
e2eWebServerAddress: string;
|
||||
e2eWebServerTarget: string;
|
||||
e2eCiWebServerTarget: string;
|
||||
e2eCiBaseUrl: string;
|
||||
e2ePort: number;
|
||||
parsedTags: string[];
|
||||
}
|
||||
|
||||
@ -391,6 +387,43 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
||||
spa: true,
|
||||
});
|
||||
}
|
||||
|
||||
let e2eWebServerInfo: E2EWebServerDetails = {
|
||||
e2eWebServerAddress: `http://localhost:4200`,
|
||||
e2eWebServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:serve`,
|
||||
e2eCiWebServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:serve-static`,
|
||||
e2eCiBaseUrl: `http://localhost:4200`,
|
||||
e2eDevServerTarget: `${options.projectName}:serve`,
|
||||
};
|
||||
|
||||
if (options.bundler === 'webpack') {
|
||||
const { getWebpackE2EWebServerInfo } = ensurePackage<
|
||||
typeof import('@nx/webpack')
|
||||
>('@nx/webpack', nxVersion);
|
||||
e2eWebServerInfo = await getWebpackE2EWebServerInfo(
|
||||
host,
|
||||
options.projectName,
|
||||
joinPathFragments(options.appProjectRoot, `webpack.config.js`),
|
||||
options.addPlugin,
|
||||
4200
|
||||
);
|
||||
} else if (options.bundler === 'vite') {
|
||||
const { getViteE2EWebServerInfo } = ensurePackage<
|
||||
typeof import('@nx/vite')
|
||||
>('@nx/vite', nxVersion);
|
||||
e2eWebServerInfo = await getViteE2EWebServerInfo(
|
||||
host,
|
||||
options.projectName,
|
||||
joinPathFragments(options.appProjectRoot, `vite.config.ts`),
|
||||
options.addPlugin,
|
||||
4200
|
||||
);
|
||||
}
|
||||
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
@ -406,20 +439,20 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
||||
const cypressTask = await configurationGenerator(host, {
|
||||
...options,
|
||||
project: options.e2eProjectName,
|
||||
devServerTarget: `${options.projectName}:${options.e2eWebServerTarget}`,
|
||||
baseUrl: options.e2eWebServerAddress,
|
||||
devServerTarget: e2eWebServerInfo.e2eDevServerTarget,
|
||||
baseUrl: e2eWebServerInfo.e2eWebServerAddress,
|
||||
directory: 'src',
|
||||
skipFormat: true,
|
||||
webServerCommands: hasPlugin
|
||||
? {
|
||||
default: `nx run ${options.projectName}:${options.e2eWebServerTarget}`,
|
||||
production: `nx run ${options.projectName}:preview`,
|
||||
default: e2eWebServerInfo.e2eWebServerCommand,
|
||||
production: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
}
|
||||
: undefined,
|
||||
ciWebServerCommand: hasPlugin
|
||||
? `nx run ${options.projectName}:${options.e2eCiWebServerTarget}`
|
||||
? e2eWebServerInfo.e2eCiWebServerCommand
|
||||
: undefined,
|
||||
ciBaseUrl: options.bundler === 'vite' ? options.e2eCiBaseUrl : undefined,
|
||||
ciBaseUrl: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
});
|
||||
|
||||
if (
|
||||
@ -472,10 +505,8 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
||||
js: false,
|
||||
linter: options.linter,
|
||||
setParserOptionsProject: options.setParserOptionsProject,
|
||||
webServerCommand: `${getPackageManagerCommand().exec} nx run ${
|
||||
options.projectName
|
||||
}:${options.e2eCiWebServerTarget}`,
|
||||
webServerAddress: options.e2eCiBaseUrl,
|
||||
webServerCommand: e2eWebServerInfo.e2eCiWebServerCommand,
|
||||
webServerAddress: e2eWebServerInfo.e2eCiBaseUrl,
|
||||
addPlugin: options.addPlugin,
|
||||
});
|
||||
|
||||
@ -590,57 +621,8 @@ async function normalizeOptions(
|
||||
nxJson.useInferencePlugins !== false;
|
||||
options.addPlugin ??= addPluginDefault;
|
||||
|
||||
let e2ePort = 4200;
|
||||
|
||||
let e2eWebServerTarget = 'serve';
|
||||
let e2eCiWebServerTarget =
|
||||
options.bundler === 'vite' ? 'preview' : 'serve-static';
|
||||
if (options.addPlugin) {
|
||||
if (nxJson.plugins) {
|
||||
for (const plugin of nxJson.plugins) {
|
||||
if (
|
||||
options.bundler === 'vite' &&
|
||||
typeof plugin === 'object' &&
|
||||
plugin.plugin === '@nx/vite/plugin'
|
||||
) {
|
||||
e2eCiWebServerTarget =
|
||||
(plugin.options as VitePluginOptions)?.previewTargetName ??
|
||||
e2eCiWebServerTarget;
|
||||
|
||||
e2eWebServerTarget =
|
||||
(plugin.options as VitePluginOptions)?.serveTargetName ??
|
||||
e2eWebServerTarget;
|
||||
} else if (
|
||||
options.bundler === 'webpack' &&
|
||||
typeof plugin === 'object' &&
|
||||
plugin.plugin === '@nx/webpack/plugin'
|
||||
) {
|
||||
e2eCiWebServerTarget =
|
||||
(plugin.options as WebpackPluginOptions)?.serveStaticTargetName ??
|
||||
e2eCiWebServerTarget;
|
||||
|
||||
e2eWebServerTarget =
|
||||
(plugin.options as WebpackPluginOptions)?.serveTargetName ??
|
||||
e2eWebServerTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 e2eCiBaseUrl =
|
||||
options.bundler === 'vite'
|
||||
? 'http://localhost:4300'
|
||||
: `http://localhost:${e2ePort}`;
|
||||
|
||||
const npmScope = getNpmScope(host);
|
||||
|
||||
@ -664,11 +646,6 @@ async function normalizeOptions(
|
||||
appProjectRoot,
|
||||
e2eProjectRoot,
|
||||
e2eProjectName,
|
||||
e2eWebServerAddress,
|
||||
e2eWebServerTarget,
|
||||
e2eCiWebServerTarget,
|
||||
e2eCiBaseUrl,
|
||||
e2ePort,
|
||||
parsedTags,
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,3 +37,4 @@ export * from './src/utils/get-css-module-local-ident';
|
||||
export * from './src/utils/with-nx';
|
||||
export * from './src/utils/with-web';
|
||||
export * from './src/utils/module-federation/public-api';
|
||||
export * from './src/utils/e2e-web-server-info-utils';
|
||||
|
||||
149
packages/webpack/src/utils/e2e-web-server-info-utils.spec.ts
Normal file
149
packages/webpack/src/utils/e2e-web-server-info-utils.spec.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import { type Tree, readNxJson, updateNxJson } from 'nx/src/devkit-exports';
|
||||
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||
import { getWebpackE2EWebServerInfo } from './e2e-web-server-info-utils';
|
||||
|
||||
describe('getWebpackE2EWebServerInfo', () => {
|
||||
let tree: Tree;
|
||||
let tempFs: TempFs;
|
||||
beforeEach(() => {
|
||||
tempFs = new TempFs('e2e-webserver-info');
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
tree.root = tempFs.tempDir;
|
||||
|
||||
tree.write(`app/webpack.config.ts`, ``);
|
||||
tempFs.createFileSync(`app/webpack.config.ts`, ``);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tempFs.cleanup();
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
it('should use the default values when no plugin is registered and plugins are not being used', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getWebpackE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/webpack.config.ts',
|
||||
false
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4200",
|
||||
"e2eCiWebServerCommand": "npx nx run app:serve-static",
|
||||
"e2eDevServerTarget": "app:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the default values of the plugin when the plugin is just a string', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins = ['@nx/webpack/plugin'];
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getWebpackE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/webpack.config.ts',
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4200",
|
||||
"e2eCiWebServerCommand": "npx nx run app:serve-static",
|
||||
"e2eDevServerTarget": "app:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the values of the registered plugin when there is no includes or excludes defined', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/webpack/plugin',
|
||||
options: {
|
||||
serveTargetName: 'webpack:serve',
|
||||
serveStaticTargetName: 'webpack:preview',
|
||||
},
|
||||
});
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getWebpackE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/webpack.config.ts',
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4200",
|
||||
"e2eCiWebServerCommand": "npx nx run app:webpack:preview",
|
||||
"e2eDevServerTarget": "app:webpack:serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:webpack:serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should use the values of the correct registered plugin when there are includes or excludes defined', async () => {
|
||||
// ARRANGE
|
||||
const nxJson = readNxJson(tree);
|
||||
nxJson.plugins ??= [];
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/webpack/plugin',
|
||||
options: {
|
||||
serveTargetName: 'webpack:serve',
|
||||
serveStaticTargetName: 'webpack:preview',
|
||||
},
|
||||
include: ['libs/**'],
|
||||
});
|
||||
nxJson.plugins.push({
|
||||
plugin: '@nx/webpack/plugin',
|
||||
options: {
|
||||
serveTargetName: 'webpack-serve',
|
||||
serveStaticTargetName: 'webpack-preview',
|
||||
},
|
||||
include: ['app/**'],
|
||||
});
|
||||
updateNxJson(tree, nxJson);
|
||||
|
||||
// ACT
|
||||
const e2eWebServerInfo = await getWebpackE2EWebServerInfo(
|
||||
tree,
|
||||
'app',
|
||||
'app/webpack.config.ts',
|
||||
true
|
||||
);
|
||||
|
||||
// ASSERT
|
||||
expect(e2eWebServerInfo).toMatchInlineSnapshot(`
|
||||
{
|
||||
"e2eCiBaseUrl": "http://localhost:4200",
|
||||
"e2eCiWebServerCommand": "npx nx run app:webpack-preview",
|
||||
"e2eDevServerTarget": "app:webpack-serve",
|
||||
"e2eWebServerAddress": "http://localhost:4200",
|
||||
"e2eWebServerCommand": "npx nx run app:webpack-serve",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
39
packages/webpack/src/utils/e2e-web-server-info-utils.ts
Normal file
39
packages/webpack/src/utils/e2e-web-server-info-utils.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { type Tree, readNxJson } from '@nx/devkit';
|
||||
import { getE2EWebServerInfo } from '@nx/devkit/src/generators/e2e-web-server-info-utils';
|
||||
|
||||
export async function getWebpackE2EWebServerInfo(
|
||||
tree: Tree,
|
||||
projectName: string,
|
||||
configFilePath: string,
|
||||
isPluginBeingAdded: boolean,
|
||||
e2ePortOverride?: number
|
||||
) {
|
||||
const nxJson = readNxJson(tree);
|
||||
let e2ePort = e2ePortOverride ?? 4200;
|
||||
|
||||
if (
|
||||
nxJson.targetDefaults?.['serve'] &&
|
||||
nxJson.targetDefaults?.['serve'].options?.port
|
||||
) {
|
||||
e2ePort = nxJson.targetDefaults?.['serve'].options?.port;
|
||||
}
|
||||
|
||||
return getE2EWebServerInfo(
|
||||
tree,
|
||||
projectName,
|
||||
{
|
||||
plugin: '@nx/webpack/plugin',
|
||||
serveTargetName: 'serveTargetName',
|
||||
serveStaticTargetName: 'serveStaticTargetName',
|
||||
configFilePath,
|
||||
},
|
||||
{
|
||||
defaultServeTargetName: 'serve',
|
||||
defaultServeStaticTargetName: 'serve-static',
|
||||
defaultE2EWebServerAddress: `http://localhost:${e2ePort}`,
|
||||
defaultE2ECiBaseUrl: 'http://localhost:4200',
|
||||
defaultE2EPort: e2ePort,
|
||||
},
|
||||
isPluginBeingAdded
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user