115 lines
3.1 KiB
TypeScript
115 lines
3.1 KiB
TypeScript
import {
|
|
ensurePackage,
|
|
generateFiles,
|
|
joinPathFragments,
|
|
readProjectConfiguration,
|
|
Tree,
|
|
} from '@nrwl/devkit';
|
|
import { basename, dirname, extname, relative } from 'path';
|
|
import {
|
|
findExportDeclarationsForJsx,
|
|
getComponentNode,
|
|
} from '../../utils/ast-utils';
|
|
import { getDefaultsForComponent } from '../../utils/component-props';
|
|
import { nxVersion } from '../../utils/versions';
|
|
import { ComponentTestSchema } from './schema';
|
|
import { ensureTypescript } from '@nrwl/js/src/utils/typescript/ensure-typescript';
|
|
|
|
let tsModule: typeof import('typescript');
|
|
|
|
export async function componentTestGenerator(
|
|
tree: Tree,
|
|
options: ComponentTestSchema
|
|
) {
|
|
ensurePackage('@nrwl/cypress', nxVersion);
|
|
const { assertMinimumCypressVersion } = await import(
|
|
'@nrwl/cypress/src/utils/cypress-version'
|
|
);
|
|
assertMinimumCypressVersion(10);
|
|
|
|
const projectConfig = readProjectConfiguration(tree, options.project);
|
|
|
|
const normalizedPath = options.componentPath.startsWith(
|
|
projectConfig.sourceRoot
|
|
)
|
|
? relative(projectConfig.sourceRoot, options.componentPath)
|
|
: options.componentPath;
|
|
|
|
const componentPath = joinPathFragments(
|
|
projectConfig.sourceRoot,
|
|
normalizedPath
|
|
);
|
|
|
|
if (tree.exists(componentPath)) {
|
|
generateSpecsForComponents(tree, componentPath);
|
|
}
|
|
}
|
|
|
|
function generateSpecsForComponents(tree: Tree, filePath: string) {
|
|
if (!tsModule) {
|
|
tsModule = ensureTypescript();
|
|
}
|
|
|
|
const sourceFile = tsModule.createSourceFile(
|
|
filePath,
|
|
tree.read(filePath, 'utf-8'),
|
|
tsModule.ScriptTarget.Latest,
|
|
true
|
|
);
|
|
|
|
const cmpNodes = findExportDeclarationsForJsx(sourceFile);
|
|
const componentDir = dirname(filePath);
|
|
const ext = extname(filePath);
|
|
const fileName = basename(filePath, ext);
|
|
|
|
if (tree.exists(joinPathFragments(componentDir, `${fileName}.cy${ext}`))) {
|
|
return;
|
|
}
|
|
|
|
const defaultExport = getComponentNode(sourceFile);
|
|
|
|
if (cmpNodes?.length) {
|
|
const components = cmpNodes.map((cmp) => {
|
|
const defaults = getDefaultsForComponent(sourceFile, cmp);
|
|
const isDefaultExport = defaultExport
|
|
? (defaultExport as any).name.text === (cmp as any).name.text
|
|
: false;
|
|
return {
|
|
isDefaultExport,
|
|
props: [...defaults.props, ...defaults.argTypes],
|
|
name: (cmp as any).name.text as string,
|
|
typeName: defaults.propsTypeName,
|
|
};
|
|
});
|
|
const namedImports = components
|
|
.reduce((imports, cmp) => {
|
|
if (cmp.typeName) {
|
|
imports.push(cmp.typeName);
|
|
}
|
|
if (cmp.isDefaultExport) {
|
|
return imports;
|
|
}
|
|
|
|
imports.push(cmp.name);
|
|
return imports;
|
|
}, [])
|
|
.join(', ');
|
|
|
|
const namedImportStatement =
|
|
namedImports.length > 0 ? `, { ${namedImports} }` : '';
|
|
|
|
generateFiles(tree, joinPathFragments(__dirname, 'files'), componentDir, {
|
|
fileName,
|
|
components,
|
|
importStatement: defaultExport
|
|
? `import ${
|
|
(defaultExport as any).name.text
|
|
}${namedImportStatement} from './${fileName}'`
|
|
: `import { ${namedImports} } from './${fileName}'`,
|
|
ext,
|
|
});
|
|
}
|
|
}
|
|
|
|
export default componentTestGenerator;
|