feat(misc): remove usages of @nx/cypress:cypress-project internally (#19766)
This commit is contained in:
parent
1389fc0dab
commit
b5ed979b90
@ -33,6 +33,11 @@
|
||||
"type": "string",
|
||||
"description": "A directory where the project is placed relative from the project root",
|
||||
"default": "cypress"
|
||||
},
|
||||
"jsx": {
|
||||
"description": "Whether or not this project uses JSX.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"required": ["project"],
|
||||
|
||||
@ -81,6 +81,11 @@
|
||||
"enum": ["vite", "webpack", "none"],
|
||||
"x-prompt": "Which Cypress bundler do you want to use?",
|
||||
"default": "webpack"
|
||||
},
|
||||
"jsx": {
|
||||
"description": "Whether or not this project uses JSX.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"required": ["project"],
|
||||
|
||||
@ -57,12 +57,6 @@
|
||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||
"default": false
|
||||
},
|
||||
"standaloneConfig": {
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside workspace.json.",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"x-deprecated": "Nx only supports standaloneConfig"
|
||||
},
|
||||
"skipPackageJson": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
|
||||
@ -33,12 +33,6 @@
|
||||
"enum": ["eslint", "none"],
|
||||
"default": "eslint"
|
||||
},
|
||||
"standaloneConfig": {
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"x-deprecated": "Nx only supports standaloneConfig"
|
||||
},
|
||||
"ciTargetName": {
|
||||
"type": "string",
|
||||
"description": "The name of the devServerTarget to use for the Cypress CI configuration. Used to control if using <storybook-project>:static-storybook:ci or <storybook-project>:storybook:ci",
|
||||
@ -49,6 +43,11 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"projectNameAndRootFormat": {
|
||||
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
||||
"type": "string",
|
||||
"enum": ["as-provided", "derived"]
|
||||
}
|
||||
},
|
||||
"required": ["name"],
|
||||
|
||||
@ -369,6 +369,7 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
@ -383,9 +384,12 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh
|
||||
},
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.js",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -609,6 +613,7 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
@ -623,9 +628,12 @@ exports[`app --project-name-and-root-format=derived should generate correctly wh
|
||||
},
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.js",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -874,6 +882,7 @@ exports[`app --strict should enable strict type checking: e2e tsconfig.json 1`]
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
@ -888,9 +897,12 @@ exports[`app --strict should enable strict type checking: e2e tsconfig.json 1`]
|
||||
},
|
||||
"extends": "../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.js",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
`;
|
||||
@ -1218,6 +1230,7 @@ exports[`app not nested should generate files: e2e tsconfig.json 1`] = `
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "commonjs",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
@ -1232,9 +1245,12 @@ exports[`app not nested should generate files: e2e tsconfig.json 1`] = `
|
||||
},
|
||||
"extends": "../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.js",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
@ -10,23 +10,27 @@ import {
|
||||
} from '@nx/devkit';
|
||||
import { nxVersion } from '../../../utils/versions';
|
||||
import type { NormalizedSchema } from './normalized-schema';
|
||||
import { cypressProjectGenerator } from '@nx/cypress';
|
||||
import { configurationGenerator } from '@nx/cypress';
|
||||
|
||||
export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
// TODO: This can call `@nx/web:static-config` generator when ready
|
||||
addFileServerTarget(tree, options, 'serve-static');
|
||||
|
||||
await cypressProjectGenerator(tree, {
|
||||
name: options.e2eProjectName,
|
||||
directory: options.e2eProjectRoot,
|
||||
// the name and root are already normalized, instruct the generator to use them as is
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
project: options.name,
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
tags: [],
|
||||
implicitDependencies: [options.name],
|
||||
});
|
||||
await configurationGenerator(tree, {
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
linter: options.linter,
|
||||
standaloneConfig: options.standaloneConfig,
|
||||
skipPackageJson: options.skipPackageJson,
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.name}:serve:development`,
|
||||
});
|
||||
} else if (options.e2eTestRunner === 'playwright') {
|
||||
const { configurationGenerator: playwrightConfigurationGenerator } =
|
||||
@ -35,6 +39,7 @@ export async function addE2e(tree: Tree, options: NormalizedSchema) {
|
||||
nxVersion
|
||||
);
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
|
||||
@ -13,7 +13,7 @@ import { librarySecondaryEntryPointGenerator } from '../library-secondary-entry-
|
||||
import { generateTestApplication, generateTestLibrary } from '../utils/testing';
|
||||
import { cypressComponentConfiguration } from './cypress-component-configuration';
|
||||
|
||||
let projectGraph: ProjectGraph;
|
||||
let projectGraph: ProjectGraph = { nodes: {}, dependencies: {} };
|
||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
||||
jest.mock('@nx/devkit', () => ({
|
||||
...jest.requireActual<any>('@nx/devkit'),
|
||||
|
||||
@ -337,11 +337,11 @@ export class E2eMigrator extends ProjectMigrator<SupportedTargets> {
|
||||
private async migrateCypressE2eProject(): Promise<void> {
|
||||
const oldCypressConfigFilePath = this.getOldCypressConfigFilePath();
|
||||
|
||||
// TODO(v18): This needs to be removed before v18 since the generator is going away.
|
||||
await cypressProjectGenerator(this.tree, {
|
||||
name: this.project.name,
|
||||
project: this.appName,
|
||||
linter: this.isProjectUsingEsLint ? Linter.EsLint : Linter.None,
|
||||
standaloneConfig: true,
|
||||
skipFormat: true,
|
||||
});
|
||||
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
import { configurationGenerator } from './src/generators/configuration/configuration';
|
||||
import { componentConfigurationGenerator } from './src/generators/component-configuration/component-configuration';
|
||||
import { cypressProjectGenerator as _cypressProjectGenerator } from './src/generators/cypress-project/cypress-project';
|
||||
|
||||
export { configurationGenerator, componentConfigurationGenerator };
|
||||
|
||||
// Maintain backwards compatibility with the old names in case community plugins used them.
|
||||
/** @deprecated Use `configurationGenerator` instead. */
|
||||
// TODO(v18): Remove old name
|
||||
/** @deprecated Use `configurationGenerator` instead. It will be removed in Nx 18. */
|
||||
export const cypressComponentConfiguration = componentConfigurationGenerator;
|
||||
|
||||
export { configurationGenerator as cypressE2EConfigurationGenerator };
|
||||
export { cypressProjectGenerator } from './src/generators/cypress-project/cypress-project';
|
||||
// TODO(v18): Remove project generator
|
||||
/** @deprecated Add a new project and call `configurationGenerator` instead. It will be removed in Nx 18. */
|
||||
export const cypressProjectGenerator = _cypressProjectGenerator;
|
||||
export { cypressInitGenerator } from './src/generators/init/init';
|
||||
export { migrateCypressProject } from './src/generators/migrate-to-cypress-11/migrate-to-cypress-11';
|
||||
|
||||
@ -17,6 +17,7 @@ export interface CypressBaseSetupSchema {
|
||||
* default is `cypress`
|
||||
* */
|
||||
directory?: string;
|
||||
jsx?: boolean;
|
||||
}
|
||||
|
||||
export function addBaseCypressSetup(
|
||||
@ -33,6 +34,7 @@ export function addBaseCypressSetup(
|
||||
|
||||
generateFiles(tree, join(__dirname, 'files'), projectConfig.root, {
|
||||
...opts,
|
||||
jsx: !!opts.jsx,
|
||||
offsetFromRoot: offsetFromRoot(projectConfig.root),
|
||||
offsetFromProjectRoot: opts.hasTsConfig ? opts.offsetFromProjectRoot : '',
|
||||
tsConfigPath: opts.hasTsConfig
|
||||
|
||||
@ -12,9 +12,9 @@
|
||||
"**/*.js",
|
||||
"<%= offsetFromProjectRoot %>cypress.config.ts",
|
||||
"<%= offsetFromProjectRoot %>**/*.cy.ts",
|
||||
"<%= offsetFromProjectRoot %>**/*.cy.tsx",
|
||||
<% if (jsx) { %> "<%= offsetFromProjectRoot %>**/*.cy.tsx",<% } %>
|
||||
"<%= offsetFromProjectRoot %>**/*.cy.js",
|
||||
"<%= offsetFromProjectRoot %>**/*.cy.jsx",
|
||||
<% if (jsx) { %>"<%= offsetFromProjectRoot %>**/*.cy.jsx",<% } %>
|
||||
"<%= offsetFromProjectRoot %>**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@ -100,6 +100,7 @@ describe('Cypress Component Configuration', () => {
|
||||
await componentConfigurationGenerator(tree, {
|
||||
project: 'cool-lib',
|
||||
skipFormat: false,
|
||||
jsx: true,
|
||||
});
|
||||
const projectConfig = readProjectConfiguration(tree, 'cool-lib');
|
||||
expect(tree.exists('libs/cool-lib/cypress.config.ts')).toEqual(true);
|
||||
|
||||
@ -85,6 +85,7 @@ function addProjectFiles(
|
||||
addBaseCypressSetup(tree, {
|
||||
project: opts.project,
|
||||
directory: opts.directory,
|
||||
jsx: opts.jsx,
|
||||
});
|
||||
|
||||
generateFiles(
|
||||
|
||||
@ -3,4 +3,5 @@ export interface CypressComponentConfigurationSchema {
|
||||
skipFormat: boolean;
|
||||
directory?: string;
|
||||
bundler?: 'webpack' | 'vite';
|
||||
jsx?: boolean;
|
||||
}
|
||||
|
||||
@ -31,6 +31,11 @@
|
||||
"type": "string",
|
||||
"description": "A directory where the project is placed relative from the project root",
|
||||
"default": "cypress"
|
||||
},
|
||||
"jsx": {
|
||||
"description": "Whether or not this project uses JSX.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"required": ["project"],
|
||||
|
||||
@ -52,11 +52,6 @@ describe('Cypress e2e configuration', () => {
|
||||
expect(readProjectConfiguration(tree, 'my-app').targets.e2e)
|
||||
.toMatchInlineSnapshot(`
|
||||
{
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "my-app:serve:production",
|
||||
},
|
||||
},
|
||||
"executor": "@nx/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/my-app/cypress.config.ts",
|
||||
@ -85,9 +80,7 @@ describe('Cypress e2e configuration', () => {
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.tsx",
|
||||
"**/*.cy.js",
|
||||
"**/*.cy.jsx",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
@ -208,9 +201,7 @@ describe('Cypress e2e configuration', () => {
|
||||
"**/*.js",
|
||||
"../../cypress.config.ts",
|
||||
"../../**/*.cy.ts",
|
||||
"../../**/*.cy.tsx",
|
||||
"../../**/*.cy.js",
|
||||
"../../**/*.cy.jsx",
|
||||
"../../**/*.d.ts",
|
||||
],
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ export interface CypressE2EConfigSchema {
|
||||
devServerTarget?: string;
|
||||
linter?: Linter;
|
||||
port?: number | 'cypress-auto';
|
||||
jsx?: boolean;
|
||||
}
|
||||
|
||||
type NormalizedSchema = ReturnType<typeof normalizeOptions>;
|
||||
@ -55,10 +56,12 @@ export async function configurationGenerator(
|
||||
}
|
||||
await addFiles(tree, opts);
|
||||
addTarget(tree, opts);
|
||||
addLinterToCyProject(tree, {
|
||||
|
||||
const linterTask = await addLinterToCyProject(tree, {
|
||||
...opts,
|
||||
cypressDir: opts.directory,
|
||||
});
|
||||
tasks.push(linterTask);
|
||||
|
||||
if (!opts.skipFormat) {
|
||||
await formatFiles(tree);
|
||||
@ -132,6 +135,7 @@ async function addFiles(tree: Tree, options: NormalizedSchema) {
|
||||
addBaseCypressSetup(tree, {
|
||||
project: options.project,
|
||||
directory: options.directory,
|
||||
jsx: options.jsx,
|
||||
});
|
||||
|
||||
const cyFile = joinPathFragments(projectConfig.root, 'cypress.config.ts');
|
||||
@ -197,18 +201,25 @@ function addTarget(tree: Tree, opts: NormalizedSchema) {
|
||||
port: opts.port,
|
||||
};
|
||||
|
||||
projectConfig.targets.e2e.configurations = {
|
||||
[parsedTarget.configuration || 'production']: {
|
||||
devServerTarget: `${opts.devServerTarget}${
|
||||
parsedTarget.configuration ? '' : ':production'
|
||||
}`,
|
||||
},
|
||||
};
|
||||
const devServerProjectConfig = readProjectConfiguration(
|
||||
tree,
|
||||
parsedTarget.project
|
||||
);
|
||||
// Add production e2e target if serve target is found
|
||||
if (
|
||||
parsedTarget.configuration !== 'production' &&
|
||||
devServerProjectConfig.targets?.[parsedTarget.target]?.configurations?.[
|
||||
'production'
|
||||
]
|
||||
) {
|
||||
projectConfig.targets.e2e.configurations ??= {};
|
||||
projectConfig.targets.e2e.configurations['production'] = {
|
||||
devServerTarget: `${parsedTarget.project}:${parsedTarget.target}:production`,
|
||||
};
|
||||
}
|
||||
// Add ci/static e2e target if serve target is found
|
||||
if (devServerProjectConfig.targets?.['serve-static']) {
|
||||
projectConfig.targets.e2e.configurations ??= {};
|
||||
projectConfig.targets.e2e.configurations.ci = {
|
||||
devServerTarget: `${parsedTarget.project}:serve-static`,
|
||||
};
|
||||
|
||||
@ -84,6 +84,11 @@
|
||||
"enum": ["vite", "webpack", "none"],
|
||||
"x-prompt": "Which Cypress bundler do you want to use?",
|
||||
"default": "webpack"
|
||||
},
|
||||
"jsx": {
|
||||
"description": "Whether or not this project uses JSX.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"required": ["project"],
|
||||
|
||||
@ -11,7 +11,6 @@ export interface Schema {
|
||||
js?: boolean;
|
||||
skipFormat?: boolean;
|
||||
setParserOptionsProject?: boolean;
|
||||
standaloneConfig?: boolean;
|
||||
skipPackageJson?: boolean;
|
||||
bundler?: 'webpack' | 'vite' | 'none';
|
||||
}
|
||||
|
||||
@ -59,12 +59,6 @@
|
||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||
"default": false
|
||||
},
|
||||
"standaloneConfig": {
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside workspace.json.",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"x-deprecated": "Nx only supports standaloneConfig"
|
||||
},
|
||||
"skipPackageJson": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
|
||||
@ -12,18 +12,24 @@ import { NormalizedSchema } from './normalize-options';
|
||||
|
||||
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { cypressProjectGenerator } = ensurePackage<
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
return cypressProjectGenerator(host, {
|
||||
addProjectConfiguration(host, options.e2eProjectName, {
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
tags: [],
|
||||
implicitDependencies: [options.projectName],
|
||||
});
|
||||
return configurationGenerator(host, {
|
||||
...options,
|
||||
linter: Linter.EsLint,
|
||||
name: options.e2eProjectName,
|
||||
directory: options.e2eProjectRoot,
|
||||
// the name and root are already normalized, instruct the generator to use them as is
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
project: options.projectName,
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:serve`,
|
||||
jsx: true,
|
||||
});
|
||||
} else if (options.e2eTestRunner === 'playwright') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
|
||||
@ -29,6 +29,7 @@ export async function cypressComponentConfiguration(
|
||||
await baseCyCtConfig(tree, {
|
||||
project: options.project,
|
||||
skipFormat: true,
|
||||
jsx: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@ -132,14 +132,14 @@ exports[`app generated files content - as-provided should create all new files i
|
||||
"my-app/.eslintrc.json",
|
||||
"my-app/vite.config.ts",
|
||||
"my-app/tsconfig.spec.json",
|
||||
"my-app-e2e/cypress.config.ts",
|
||||
"my-app-e2e/src/e2e/app.cy.ts",
|
||||
"my-app-e2e/src/fixtures/example.json",
|
||||
"my-app-e2e/src/support/app.po.ts",
|
||||
"my-app-e2e/src/support/commands.ts",
|
||||
"my-app-e2e/src/support/e2e.ts",
|
||||
"my-app-e2e/tsconfig.json",
|
||||
"my-app-e2e/project.json",
|
||||
"my-app-e2e/src/e2e/app.cy.ts",
|
||||
"my-app-e2e/src/support/app.po.ts",
|
||||
"my-app-e2e/src/support/e2e.ts",
|
||||
"my-app-e2e/src/fixtures/example.json",
|
||||
"my-app-e2e/src/support/commands.ts",
|
||||
"my-app-e2e/cypress.config.ts",
|
||||
"my-app-e2e/tsconfig.json",
|
||||
"my-app-e2e/.eslintrc.json",
|
||||
]
|
||||
`;
|
||||
|
||||
@ -12,17 +12,25 @@ import { NormalizedSchema } from '../schema';
|
||||
|
||||
export async function addE2e(host: Tree, options: NormalizedSchema) {
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { cypressProjectGenerator } = ensurePackage<
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
return cypressProjectGenerator(host, {
|
||||
addProjectConfiguration(host, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
tags: [],
|
||||
implicitDependencies: [options.projectName],
|
||||
});
|
||||
return await configurationGenerator(host, {
|
||||
...options,
|
||||
linter: Linter.EsLint,
|
||||
name: options.e2eProjectName,
|
||||
directory: options.e2eProjectRoot,
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
project: options.projectName,
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
bundler: 'vite',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:serve`,
|
||||
jsx: true,
|
||||
});
|
||||
} else if (options.e2eTestRunner === 'playwright') {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
|
||||
@ -143,6 +143,7 @@ describe('app', () => {
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "../dist/out-tsc",
|
||||
"sourceMap": false,
|
||||
"types": [
|
||||
@ -152,9 +153,14 @@ describe('app', () => {
|
||||
},
|
||||
"extends": "../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.tsx",
|
||||
"**/*.cy.js",
|
||||
"**/*.cy.jsx",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
`);
|
||||
|
||||
@ -15,31 +15,42 @@ export async function addE2e(
|
||||
options: NormalizedSchema
|
||||
): Promise<GeneratorCallback> {
|
||||
switch (options.e2eTestRunner) {
|
||||
case 'cypress':
|
||||
case 'cypress': {
|
||||
webStaticServeGenerator(tree, {
|
||||
buildTarget: `${options.projectName}:build`,
|
||||
targetName: 'serve-static',
|
||||
});
|
||||
|
||||
const { cypressProjectGenerator } = ensurePackage<
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
|
||||
return await cypressProjectGenerator(tree, {
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
implicitDependencies: [options.projectName],
|
||||
tags: [],
|
||||
});
|
||||
|
||||
return await configurationGenerator(tree, {
|
||||
...options,
|
||||
name: options.e2eProjectName,
|
||||
directory: options.e2eProjectRoot,
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
// the name and root are already normalized, instruct the generator to use them as is
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
project: options.projectName,
|
||||
bundler: options.bundler === 'rspack' ? 'webpack' : options.bundler,
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:serve`,
|
||||
jsx: true,
|
||||
});
|
||||
case 'playwright':
|
||||
}
|
||||
case 'playwright': {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/playwright')
|
||||
>('@nx/playwright', nxVersion);
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
@ -58,6 +69,7 @@ export async function addE2e(
|
||||
}`,
|
||||
webServerAddress: 'http://localhost:4200',
|
||||
});
|
||||
}
|
||||
case 'none':
|
||||
default:
|
||||
return () => {};
|
||||
|
||||
@ -25,6 +25,7 @@ export async function cypressComponentConfigGenerator(
|
||||
const installTask = await baseCyCtConfig(tree, {
|
||||
project: options.project,
|
||||
skipFormat: true,
|
||||
jsx: true,
|
||||
});
|
||||
|
||||
const found = await addCTTargetWithBuildTarget(tree, {
|
||||
|
||||
@ -1,19 +1,13 @@
|
||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
||||
import { readJson, readProjectConfiguration, Tree } from '@nx/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import { Linter } from '@nx/eslint';
|
||||
import { libraryGenerator } from '@nx/js';
|
||||
import { cypressProjectGenerator } from './cypress-project';
|
||||
|
||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
||||
describe('@nx/storybook:cypress-project', () => {
|
||||
let tree: Tree;
|
||||
let mockedInstalledCypressVersion: jest.Mock<
|
||||
ReturnType<typeof installedCypressVersion>
|
||||
> = installedCypressVersion as never;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
||||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
await libraryGenerator(tree, {
|
||||
name: 'test-ui-lib',
|
||||
@ -36,19 +30,6 @@ describe('@nx/storybook:cypress-project', () => {
|
||||
expect(cypressConfig).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should update cypress.json file if present', async () => {
|
||||
mockedInstalledCypressVersion.mockReturnValue(9);
|
||||
|
||||
await cypressProjectGenerator(tree, {
|
||||
name: 'test-ui-lib',
|
||||
linter: Linter.EsLint,
|
||||
});
|
||||
|
||||
expect(tree.exists('apps/test-ui-lib-e2e/cypress.json')).toBeTruthy();
|
||||
const cypressConfig = readJson(tree, 'apps/test-ui-lib-e2e/cypress.json');
|
||||
expect(cypressConfig.baseUrl).toEqual('http://localhost:4400');
|
||||
});
|
||||
|
||||
it('should update `angular.json` file', async () => {
|
||||
await cypressProjectGenerator(tree, {
|
||||
name: 'test-ui-lib',
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import { getE2eProjectName } from '@nx/cypress/src/utils/project-name';
|
||||
import {
|
||||
cypressInitGenerator as _cypressInitGenerator,
|
||||
cypressProjectGenerator as _cypressProjectGenerator,
|
||||
} from '@nx/cypress';
|
||||
import {
|
||||
getE2eProjectName,
|
||||
getUnscopedLibName,
|
||||
} from '@nx/cypress/src/utils/project-name';
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
ensurePackage,
|
||||
formatFiles,
|
||||
generateFiles,
|
||||
GeneratorCallback,
|
||||
joinPathFragments,
|
||||
readJson,
|
||||
readProjectConfiguration,
|
||||
runTasksInSerial,
|
||||
@ -18,9 +14,11 @@ import {
|
||||
updateProjectConfiguration,
|
||||
} from '@nx/devkit';
|
||||
import { Linter } from '@nx/eslint';
|
||||
|
||||
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||
import { join } from 'path';
|
||||
|
||||
import { safeFileDelete } from '../../utils/utilities';
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
|
||||
export interface CypressConfigureSchema {
|
||||
name: string;
|
||||
@ -30,31 +28,61 @@ export interface CypressConfigureSchema {
|
||||
standaloneConfig?: boolean;
|
||||
ciTargetName?: string;
|
||||
skipFormat?: boolean;
|
||||
projectNameAndRootFormat?: 'as-provided' | 'derived';
|
||||
}
|
||||
|
||||
export async function cypressProjectGenerator(
|
||||
tree: Tree,
|
||||
schema: CypressConfigureSchema
|
||||
) {
|
||||
return await cypressProjectGeneratorInternal(tree, {
|
||||
projectNameAndRootFormat: 'derived',
|
||||
...schema,
|
||||
});
|
||||
}
|
||||
|
||||
export async function cypressProjectGeneratorInternal(
|
||||
tree: Tree,
|
||||
schema: CypressConfigureSchema
|
||||
) {
|
||||
const { configurationGenerator, cypressInitGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
|
||||
const e2eName = schema.name ? `${schema.name}-e2e` : undefined;
|
||||
const { projectName, projectRoot } = await determineProjectNameAndRootOptions(
|
||||
tree,
|
||||
{
|
||||
name: e2eName,
|
||||
projectType: 'application',
|
||||
directory: schema.directory,
|
||||
projectNameAndRootFormat: schema.projectNameAndRootFormat,
|
||||
callingGenerator: '@nx/storybook:cypress-project',
|
||||
}
|
||||
);
|
||||
const libConfig = readProjectConfiguration(tree, schema.name);
|
||||
const libRoot = libConfig.root;
|
||||
const cypressProjectName = `${
|
||||
schema.directory ? getUnscopedLibName(libRoot) : schema.name
|
||||
}-e2e`;
|
||||
|
||||
const tasks: GeneratorCallback[] = [];
|
||||
|
||||
if (!projectAlreadyHasCypress(tree)) {
|
||||
tasks.push(await _cypressInitGenerator(tree, {}));
|
||||
tasks.push(await cypressInitGenerator(tree, {}));
|
||||
}
|
||||
|
||||
const installTask = await _cypressProjectGenerator(tree, {
|
||||
name: cypressProjectName,
|
||||
project: schema.name,
|
||||
addProjectConfiguration(tree, projectName, {
|
||||
root: projectRoot,
|
||||
projectType: 'application',
|
||||
sourceRoot: joinPathFragments(projectRoot, 'src'),
|
||||
targets: {},
|
||||
implicitDependencies: [projectName],
|
||||
});
|
||||
|
||||
const installTask = await configurationGenerator(tree, {
|
||||
project: projectName,
|
||||
js: schema.js,
|
||||
linter: schema.linter,
|
||||
directory: schema.directory,
|
||||
standaloneConfig: schema.standaloneConfig,
|
||||
directory: projectRoot,
|
||||
devServerTarget: `${schema.name}:storybook`,
|
||||
skipFormat: true,
|
||||
});
|
||||
tasks.push(installTask);
|
||||
|
||||
@ -33,12 +33,6 @@
|
||||
"enum": ["eslint", "none"],
|
||||
"default": "eslint"
|
||||
},
|
||||
"standaloneConfig": {
|
||||
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"x-deprecated": "Nx only supports standaloneConfig"
|
||||
},
|
||||
"ciTargetName": {
|
||||
"type": "string",
|
||||
"description": "The name of the devServerTarget to use for the Cypress CI configuration. Used to control if using <storybook-project>:static-storybook:ci or <storybook-project>:storybook:ci",
|
||||
@ -49,6 +43,11 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"x-priority": "internal"
|
||||
},
|
||||
"projectNameAndRootFormat": {
|
||||
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
||||
"type": "string",
|
||||
"enum": ["as-provided", "derived"]
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
|
||||
@ -15,30 +15,39 @@ export async function addE2e(
|
||||
options: NormalizedSchema
|
||||
): Promise<GeneratorCallback> {
|
||||
switch (options.e2eTestRunner) {
|
||||
case 'cypress':
|
||||
case 'cypress': {
|
||||
webStaticServeGenerator(tree, {
|
||||
buildTarget: `${options.projectName}:build`,
|
||||
targetName: 'serve-static',
|
||||
});
|
||||
|
||||
const { cypressProjectGenerator } = ensurePackage<
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
|
||||
return await cypressProjectGenerator(tree, {
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
tags: [],
|
||||
implicitDependencies: [options.projectName],
|
||||
});
|
||||
return await configurationGenerator(tree, {
|
||||
...options,
|
||||
name: options.e2eProjectName,
|
||||
directory: options.e2eProjectRoot,
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
project: options.projectName,
|
||||
project: options.e2eProjectName,
|
||||
directory: 'src',
|
||||
bundler: 'vite',
|
||||
skipFormat: true,
|
||||
devServerTarget: `${options.projectName}:serve`,
|
||||
jsx: true,
|
||||
});
|
||||
case 'playwright':
|
||||
}
|
||||
case 'playwright': {
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/playwright')
|
||||
>('@nx/playwright', nxVersion);
|
||||
addProjectConfiguration(tree, options.e2eProjectName, {
|
||||
projectType: 'application',
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
targets: {},
|
||||
@ -57,6 +66,7 @@ export async function addE2e(
|
||||
}`,
|
||||
webServerAddress: 'http://localhost:4200',
|
||||
});
|
||||
}
|
||||
case 'none':
|
||||
default:
|
||||
return () => {};
|
||||
|
||||
@ -86,6 +86,7 @@ describe('app', () => {
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "../dist/out-tsc",
|
||||
"sourceMap": false,
|
||||
"types": [
|
||||
@ -95,9 +96,12 @@ describe('app', () => {
|
||||
},
|
||||
"extends": "../tsconfig.base.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.js",
|
||||
"**/*.ts",
|
||||
"**/*.js",
|
||||
"cypress.config.ts",
|
||||
"**/*.cy.ts",
|
||||
"**/*.cy.js",
|
||||
"**/*.d.ts",
|
||||
],
|
||||
}
|
||||
`);
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
generateFiles,
|
||||
GeneratorCallback,
|
||||
getPackageManagerCommand,
|
||||
getWorkspaceLayout,
|
||||
joinPathFragments,
|
||||
names,
|
||||
offsetFromRoot,
|
||||
@ -282,16 +281,22 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
||||
}
|
||||
|
||||
if (options.e2eTestRunner === 'cypress') {
|
||||
const { cypressProjectGenerator } = ensurePackage<
|
||||
const { configurationGenerator } = ensurePackage<
|
||||
typeof import('@nx/cypress')
|
||||
>('@nx/cypress', nxVersion);
|
||||
const cypressTask = await cypressProjectGenerator(host, {
|
||||
addProjectConfiguration(host, options.e2eProjectName, {
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
projectType: 'application',
|
||||
targets: {},
|
||||
tags: [],
|
||||
implicitDependencies: [options.projectName],
|
||||
});
|
||||
const cypressTask = await configurationGenerator(host, {
|
||||
...options,
|
||||
name: options.e2eProjectName,
|
||||
directory: options.e2eProjectRoot,
|
||||
// the name and root are already normalized, instruct the generator to use them as is
|
||||
projectNameAndRootFormat: 'as-provided',
|
||||
project: options.projectName,
|
||||
project: options.e2eProjectName,
|
||||
devServerTarget: `${options.projectName}:serve`,
|
||||
directory: 'src',
|
||||
skipFormat: true,
|
||||
});
|
||||
tasks.push(cypressTask);
|
||||
@ -299,7 +304,6 @@ export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
|
||||
const { configurationGenerator: playwrightConfigGenerator } = ensurePackage<
|
||||
typeof import('@nx/playwright')
|
||||
>('@nx/playwright', nxVersion);
|
||||
|
||||
addProjectConfiguration(host, options.e2eProjectName, {
|
||||
root: options.e2eProjectRoot,
|
||||
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user