fix(testing): convert-to-inferred generator should handle legacy cypress executor (#23151)

<!-- 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` -->

## Current Behavior
<!-- This is the behavior we have today -->
The `convert-to-inferred` generator does not handle
`@nrwl/cypress:cypress`.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
The generator should handle the legacy executor

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Colum Ferry 2024-05-02 23:05:59 +01:00 committed by GitHub
parent eddd0d61c1
commit dbad02afe4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 90 additions and 30 deletions

View File

@ -91,6 +91,7 @@ interface CreateCypressTestProjectOptions {
appName: string; appName: string;
appRoot: string; appRoot: string;
e2eTargetName: string; e2eTargetName: string;
legacyExecutor?: boolean;
} }
const defaultCreateCypressTestProjectOptions: CreateCypressTestProjectOptions = const defaultCreateCypressTestProjectOptions: CreateCypressTestProjectOptions =
@ -98,6 +99,7 @@ const defaultCreateCypressTestProjectOptions: CreateCypressTestProjectOptions =
appName: 'myapp-e2e', appName: 'myapp-e2e',
appRoot: 'myapp-e2e', appRoot: 'myapp-e2e',
e2eTargetName: 'e2e', e2eTargetName: 'e2e',
legacyExecutor: false,
}; };
function createTestProject( function createTestProject(
@ -111,7 +113,9 @@ function createTestProject(
projectType: 'application', projectType: 'application',
targets: { targets: {
[projectOpts.e2eTargetName]: { [projectOpts.e2eTargetName]: {
executor: '@nx/cypress:cypress', executor: projectOpts.legacyExecutor
? '@nrwl/cypress:cypress'
: '@nx/cypress:cypress',
options: { options: {
cypressConfig: `${projectOpts.appRoot}/cypress.config.ts`, cypressConfig: `${projectOpts.appRoot}/cypress.config.ts`,
testingType: `e2e`, testingType: `e2e`,
@ -217,7 +221,7 @@ describe('Cypress - Convert Executors To Plugin', () => {
// project.json modifications // project.json modifications
const updatedProject = readProjectConfiguration(tree, project.name); const updatedProject = readProjectConfiguration(tree, project.name);
const targetKeys = Object.keys(updatedProject.targets); const targetKeys = Object.keys(updatedProject.targets);
['test'].forEach((key) => expect(targetKeys).not.toContain(key)); expect(targetKeys).not.toContain('test');
// nx.json modifications // nx.json modifications
const nxJsonPlugins = readNxJson(tree).plugins; const nxJsonPlugins = readNxJson(tree).plugins;
@ -305,6 +309,42 @@ describe('Cypress - Convert Executors To Plugin', () => {
} }
}); });
it('should setup handle legacy executor', async () => {
// ARRANGE
const project = createTestProject(tree, {
e2eTargetName: 'test',
legacyExecutor: true,
});
// ACT
await convertToInferred(tree, { skipFormat: true });
// ASSERT
// project.json modifications
const updatedProject = readProjectConfiguration(tree, project.name);
const targetKeys = Object.keys(updatedProject.targets);
['test'].forEach((key) => expect(targetKeys).not.toContain(key));
// nx.json modifications
const nxJsonPlugins = readNxJson(tree).plugins;
const hasCypressPlugin = nxJsonPlugins.find((plugin) =>
typeof plugin === 'string'
? plugin === '@nx/cypress/plugin'
: plugin.plugin === '@nx/cypress/plugin'
);
expect(hasCypressPlugin).toBeTruthy();
if (typeof hasCypressPlugin !== 'string') {
[
['targetName', 'test'],
['ciTargetName', 'e2e-ci'],
].forEach(([targetOptionName, targetName]) => {
expect(hasCypressPlugin.options[targetOptionName]).toEqual(
targetName
);
});
}
});
it('should setup a new Cypress plugin to match only projects migrated', async () => { it('should setup a new Cypress plugin to match only projects migrated', async () => {
// ARRANGE // ARRANGE
const existingProject = createTestProject(tree, { const existingProject = createTestProject(tree, {

View File

@ -21,7 +21,7 @@ interface Schema {
export async function convertToInferred(tree: Tree, options: Schema) { export async function convertToInferred(tree: Tree, options: Schema) {
const projectGraph = await createProjectGraphAsync(); const projectGraph = await createProjectGraphAsync();
await migrateExecutorToPlugin( let migratedProjects = await migrateExecutorToPlugin(
tree, tree,
projectGraph, projectGraph,
'@nx/cypress:cypress', '@nx/cypress:cypress',
@ -35,6 +35,24 @@ export async function convertToInferred(tree: Tree, options: Schema) {
options.project options.project
); );
migratedProjects += await migrateExecutorToPlugin(
tree,
projectGraph,
'@nrwl/cypress:cypress',
'@nx/cypress/plugin',
(targetName) => ({
targetName,
ciTargetName: 'e2e-ci',
}),
postTargetTransformer,
createNodes,
options.project
);
if (migratedProjects === 0) {
throw new Error('Could not find any targets to migrate.');
}
if (!options.skipFormat) { if (!options.skipFormat) {
await formatFiles(tree); await formatFiles(tree);
} }

View File

@ -74,12 +74,15 @@ class ExecutorToPluginMigrator<T> {
this.#skipTargetFilter = skipTargetFilter ?? ((...args) => [false, '']); this.#skipTargetFilter = skipTargetFilter ?? ((...args) => [false, '']);
} }
async run(): Promise<void> { async run(): Promise<Map<string, Set<string>>> {
await this.#init(); await this.#init();
for (const targetName of this.#targetAndProjectsToMigrate.keys()) { if (this.#targetAndProjectsToMigrate.size > 0) {
this.#migrateTarget(targetName); for (const targetName of this.#targetAndProjectsToMigrate.keys()) {
this.#migrateTarget(targetName);
}
this.#addPlugins();
} }
this.#addPlugins(); return this.#targetAndProjectsToMigrate;
} }
async #init() { async #init() {
@ -239,17 +242,6 @@ class ExecutorToPluginMigrator<T> {
} }
} }
); );
if (this.#targetAndProjectsToMigrate.size === 0) {
const errorMsg = this.#specificProjectToMigrate
? `Project "${
this.#specificProjectToMigrate
}" does not contain any targets using the "${
this.#executor
}" executor. Please select a project that does.`
: `Could not find any targets using the "${this.#executor}" executor.`;
throw new Error(errorMsg);
}
} }
#getTargetDefaultsForExecutor() { #getTargetDefaultsForExecutor() {
@ -270,6 +262,10 @@ class ExecutorToPluginMigrator<T> {
} }
async #getCreateNodesResults() { async #getCreateNodesResults() {
if (this.#targetAndProjectsToMigrate.size === 0) {
return;
}
for (const targetName of this.#targetAndProjectsToMigrate.keys()) { for (const targetName of this.#targetAndProjectsToMigrate.keys()) {
const loadedPlugin = new LoadedNxPlugin( const loadedPlugin = new LoadedNxPlugin(
{ {
@ -312,7 +308,7 @@ export async function migrateExecutorToPlugin<T>(
createNodes: CreateNodes<T>, createNodes: CreateNodes<T>,
specificProjectToMigrate?: string, specificProjectToMigrate?: string,
skipTargetFilter?: SkipTargetFilter skipTargetFilter?: SkipTargetFilter
): Promise<void> { ): Promise<number> {
const migrator = new ExecutorToPluginMigrator<T>( const migrator = new ExecutorToPluginMigrator<T>(
tree, tree,
projectGraph, projectGraph,
@ -324,5 +320,6 @@ export async function migrateExecutorToPlugin<T>(
specificProjectToMigrate, specificProjectToMigrate,
skipTargetFilter skipTargetFilter
); );
await migrator.run(); const migratedProjectsAndTargets = await migrator.run();
return migratedProjectsAndTargets.size;
} }

View File

@ -16,16 +16,21 @@ interface Schema {
export async function convertToInferred(tree: Tree, options: Schema) { export async function convertToInferred(tree: Tree, options: Schema) {
const projectGraph = await createProjectGraphAsync(); const projectGraph = await createProjectGraphAsync();
await migrateExecutorToPlugin<PlaywrightPluginOptions>( const migratedProjects =
tree, await migrateExecutorToPlugin<PlaywrightPluginOptions>(
projectGraph, tree,
'@nx/playwright:playwright', projectGraph,
'@nx/playwright/plugin', '@nx/playwright:playwright',
(targetName) => ({ targetName, ciTargetName: 'e2e-ci' }), '@nx/playwright/plugin',
postTargetTransformer, (targetName) => ({ targetName, ciTargetName: 'e2e-ci' }),
createNodes, postTargetTransformer,
options.project createNodes,
); options.project
);
if (migratedProjects === 0) {
throw new Error('Could not find any targets to migrate.');
}
if (!options.skipFormat) { if (!options.skipFormat) {
await formatFiles(tree); await formatFiles(tree);