nx/packages/angular/src/generators/cypress-component-configuration/cypress-component-configuration.ts

180 lines
4.9 KiB
TypeScript

import { componentConfigurationGenerator as baseCyCTConfig } from '@nx/cypress';
import { NxComponentTestingOptions } from '@nx/cypress/plugins/cypress-preset';
import {
addDefaultCTConfig,
addMountDefinition,
getProjectCypressConfigPath,
} from '@nx/cypress/src/utils/config';
import {
findBuildConfig,
FoundTarget,
} from '@nx/cypress/src/utils/find-target-options';
import {
formatFiles,
glob,
joinPathFragments,
ProjectConfiguration,
readProjectConfiguration,
Tree,
updateProjectConfiguration,
} from '@nx/devkit';
import { relative } from 'path';
import { componentTestGenerator } from '../component-test/component-test';
import {
getComponentsInfo,
getStandaloneComponentsInfo,
} from '../utils/storybook-ast/component-info';
import { getProjectEntryPoints } from '../utils/storybook-ast/entry-point';
import { getModuleFilePaths } from '../utils/storybook-ast/module-info';
import { CypressComponentConfigSchema } from './schema';
export function cypressComponentConfiguration(
tree: Tree,
options: CypressComponentConfigSchema
) {
return cypressComponentConfigurationInternal(tree, {
...options,
});
}
/**
* This is for cypress built in component testing, if you want to test with
* storybook + cypress then use the componentCypressGenerator instead.
*/
export async function cypressComponentConfigurationInternal(
tree: Tree,
options: CypressComponentConfigSchema
) {
const projectConfig = readProjectConfiguration(tree, options.project);
const installTask = await baseCyCTConfig(tree, {
project: options.project,
skipFormat: true,
addPlugin: false,
addExplicitTargets: true,
});
await configureCypressCT(tree, options);
await addFiles(tree, projectConfig, options);
if (!options.skipFormat) {
await formatFiles(tree);
}
return installTask;
}
async function addFiles(
tree: Tree,
projectConfig: ProjectConfiguration,
options: CypressComponentConfigSchema
) {
const componentFile = joinPathFragments(
projectConfig.root,
'cypress',
'support',
'component.ts'
);
const updatedCmpContents = await addMountDefinition(
tree.read(componentFile, 'utf-8')
);
tree.write(
componentFile,
`import { mount } from 'cypress/angular';\n${updatedCmpContents}`
);
if (options.generateTests) {
const entryPoints = getProjectEntryPoints(tree, options.project);
const componentInfo = [];
for (const entryPoint of entryPoints) {
const moduleFilePaths = getModuleFilePaths(tree, entryPoint);
componentInfo.push(
...getComponentsInfo(
tree,
entryPoint,
moduleFilePaths,
options.project
),
...getStandaloneComponentsInfo(tree, entryPoint)
);
}
for (const info of componentInfo) {
if (info === undefined) {
continue;
}
const componentDirFromProjectRoot = relative(
projectConfig.root,
joinPathFragments(info.moduleFolderPath, info.path)
);
await componentTestGenerator(tree, {
project: options.project,
componentName: info.name,
componentDir: componentDirFromProjectRoot,
componentFileName: info.componentFileName,
skipFormat: true,
});
}
}
}
async function configureCypressCT(
tree: Tree,
options: CypressComponentConfigSchema
) {
let found: FoundTarget = { target: options.buildTarget, config: undefined };
if (!options.buildTarget) {
found = await findBuildConfig(tree, {
project: options.project,
buildTarget: options.buildTarget,
validExecutorNames: new Set<string>([
'@nx/angular:webpack-browser',
'@nrwl/angular:webpack-browser',
'@angular-devkit/build-angular:browser',
]),
});
assertValidConfig(found?.config);
}
const ctConfigOptions: NxComponentTestingOptions = {};
const projectConfig = readProjectConfiguration(tree, options.project);
if (
projectConfig.targets?.['component-test']?.executor ===
'@nx/cypress:cypress'
) {
projectConfig.targets['component-test'].options = {
...projectConfig.targets['component-test'].options,
skipServe: true,
devServerTarget: found.target,
};
updateProjectConfiguration(tree, options.project, projectConfig);
} else {
ctConfigOptions.buildTarget = found.target;
}
const cypressConfigPath = getProjectCypressConfigPath(
tree,
projectConfig.root
);
const updatedCyConfig = await addDefaultCTConfig(
tree.read(cypressConfigPath, 'utf-8'),
ctConfigOptions
);
tree.write(
cypressConfigPath,
`import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing';\n${updatedCyConfig}`
);
}
function assertValidConfig(config: unknown) {
if (!config) {
throw new Error(
'Unable to find a valid build configuration. Try passing in a target for an Angular app. --build-target=<project>:<target>[:<configuration>]'
);
}
}
export default cypressComponentConfiguration;