fix(storybook): find any module file

This commit is contained in:
Isaac Mann 2020-02-28 16:12:19 -05:00 committed by Victor Savkin
parent e2b8406692
commit c2bac02420
2 changed files with 128 additions and 105 deletions

View File

@ -32,6 +32,11 @@ describe('schematic:stories', () => {
'libs/test-ui-lib/src/lib/test-other/test-other.component.stories.ts' 'libs/test-ui-lib/src/lib/test-other/test-other.component.stories.ts'
) )
).toBeTruthy(); ).toBeTruthy();
expect(
tree.exists(
'libs/test-ui-lib/src/lib/nested/nested-button/nested-button.component.stories.ts'
)
).toBeTruthy();
const propLines = [ const propLines = [
`buttonType: text('buttonType', 'button'),`, `buttonType: text('buttonType', 'button'),`,
`style: text('style', 'default'),`, `style: text('style', 'default'),`,
@ -137,6 +142,23 @@ export async function createTestUILib(libName: string): Promise<Tree> {
`import * as ButtonExports from './test-button/test-button.component'; `import * as ButtonExports from './test-button/test-button.component';
${appTree.read(modulePath)}` ${appTree.read(modulePath)}`
); );
appTree = await callRule(
externalSchematic('@schematics/angular', 'module', {
name: 'nested',
project: libName,
path: `libs/${libName}/src/lib`
}),
appTree
);
appTree = await callRule(
externalSchematic('@schematics/angular', 'component', {
name: 'nested-button',
project: libName,
module: 'nested',
path: `libs/${libName}/src/lib/nested`
}),
appTree
);
appTree.overwrite( appTree.overwrite(
`libs/${libName}/src/lib/test-button/test-button.component.ts`, `libs/${libName}/src/lib/test-button/test-button.component.ts`,
` `

View File

@ -29,120 +29,121 @@ export function createAllStories(
context.logger.debug('adding .storybook folder to lib'); context.logger.debug('adding .storybook folder to lib');
const libPath = getProjectConfig(tree, projectName).sourceRoot + '/lib'; const libPath = getProjectConfig(tree, projectName).sourceRoot + '/lib';
let moduleFilePaths = [] as string[];
tree.getDir(libPath).visit(filePath => {
if (!filePath.endsWith('.module.ts')) {
return;
}
moduleFilePaths.push(filePath);
});
return chain( return chain(
tree moduleFilePaths.map(filePath => {
.getDir(libPath) const file = getTsSourceFile(tree, filePath);
.subfiles.filter(fileName => fileName.endsWith('.module.ts'))
.map(fileName => {
const filePath = libPath + '/' + fileName;
const file = getTsSourceFile(tree, filePath);
const ngModuleDecorators = getDecoratorMetadata( const ngModuleDecorators = getDecoratorMetadata(
file, file,
'NgModule', 'NgModule',
'@angular/core' '@angular/core'
);
if (ngModuleDecorators.length === 0) {
throw new SchematicsException(
`No @NgModule decorator in ${filePath}`
); );
if (ngModuleDecorators.length === 0) { }
throw new SchematicsException( const ngModuleDecorator = ngModuleDecorators[0];
`No @NgModule decorator in ${filePath}` const syntaxList = ngModuleDecorator.getChildren().find(node => {
return node.kind === SyntaxKind.SyntaxList;
});
const declarationsPropertyAssignment = syntaxList
.getChildren()
.find(node => {
return (
node.kind === SyntaxKind.PropertyAssignment &&
node.getChildren()[0].getText() === 'declarations'
); );
}
const ngModuleDecorator = ngModuleDecorators[0];
const syntaxList = ngModuleDecorator.getChildren().find(node => {
return node.kind === SyntaxKind.SyntaxList;
}); });
const declarationsPropertyAssignment = syntaxList if (!declarationsPropertyAssignment) {
.getChildren() throw new SchematicsException(
.find(node => { `No declarations array in the @NgModule decorator in ${filePath}`
return (
node.kind === SyntaxKind.PropertyAssignment &&
node.getChildren()[0].getText() === 'declarations'
);
});
if (!declarationsPropertyAssignment) {
throw new SchematicsException(
`No declarations array in the @NgModule decorator in ${filePath}`
);
}
const declaredComponents = declarationsPropertyAssignment
.getChildren()
.find(node => node.kind === SyntaxKind.ArrayLiteralExpression)
.getChildren()
.find(node => node.kind === SyntaxKind.SyntaxList)
.getChildren()
.filter(node => node.kind === SyntaxKind.Identifier)
.map(node => node.getText())
.filter(name => name.endsWith('Component'));
const imports = file.statements.filter(
statement => statement.kind === SyntaxKind.ImportDeclaration
); );
const componentInfo = declaredComponents.map(componentName => { }
try { const declaredComponents = declarationsPropertyAssignment
const importStatement = imports.find(statement => { .getChildren()
const namedImports = statement .find(node => node.kind === SyntaxKind.ArrayLiteralExpression)
.getChildren() .getChildren()
.find(node => node.kind === SyntaxKind.ImportClause) .find(node => node.kind === SyntaxKind.SyntaxList)
.getChildren() .getChildren()
.find(node => node.kind === SyntaxKind.NamedImports); .filter(node => node.kind === SyntaxKind.Identifier)
if (namedImports === undefined) return false; .map(node => node.getText())
.filter(name => name.endsWith('Component'));
const importedIdentifiers = namedImports const imports = file.statements.filter(
.getChildren() statement => statement.kind === SyntaxKind.ImportDeclaration
.find(node => node.kind === SyntaxKind.SyntaxList) );
.getChildren() const componentInfo = declaredComponents.map(componentName => {
.filter(node => node.kind === SyntaxKind.ImportSpecifier) try {
.map(node => node.getText()); const importStatement = imports.find(statement => {
return importedIdentifiers.includes(componentName); const namedImports = statement
});
const fullPath = importStatement
.getChildren() .getChildren()
.find(node => node.kind === SyntaxKind.StringLiteral) .find(node => node.kind === SyntaxKind.ImportClause)
.getText() .getChildren()
.slice(1, -1); .find(node => node.kind === SyntaxKind.NamedImports);
const path = fullPath.slice(0, fullPath.lastIndexOf('/')); if (namedImports === undefined) return false;
const componentFileName = fullPath.slice(
fullPath.lastIndexOf('/') + 1
);
return { name: componentName, path, componentFileName };
} catch (ex) {
context.logger.warn(
`Could not generate a story for ${componentName}. Error: ${ex}`
);
return undefined;
}
});
return chain( const importedIdentifiers = namedImports
componentInfo .getChildren()
.filter(info => info !== undefined) .find(node => node.kind === SyntaxKind.SyntaxList)
.map(info => .getChildren()
chain([ .filter(node => node.kind === SyntaxKind.ImportSpecifier)
schematic<CreateComponentStoriesFileSchema>( .map(node => node.getText());
'component-story', return importedIdentifiers.includes(componentName);
{ });
libPath, const fullPath = importStatement
componentName: info.name, .getChildren()
componentPath: info.path, .find(node => node.kind === SyntaxKind.StringLiteral)
componentFileName: info.componentFileName .getText()
} .slice(1, -1);
), const path = fullPath.slice(0, fullPath.lastIndexOf('/'));
generateCypressSpecs const componentFileName = fullPath.slice(
? schematic<CreateComponentSpecFileSchema>( fullPath.lastIndexOf('/') + 1
'component-cypress-spec', );
{ return { name: componentName, path, componentFileName };
projectName, } catch (ex) {
libPath, context.logger.warn(
componentName: info.name, `Could not generate a story for ${componentName}. Error: ${ex}`
componentPath: info.path, );
componentFileName: info.componentFileName return undefined;
} }
) });
: () => {}
]) const modulePath = filePath.substr(0, filePath.lastIndexOf('/'));
) return chain(
); componentInfo
}) .filter(info => info !== undefined)
.map(info =>
chain([
schematic<CreateComponentStoriesFileSchema>('component-story', {
libPath: modulePath,
componentName: info.name,
componentPath: info.path,
componentFileName: info.componentFileName
}),
generateCypressSpecs
? schematic<CreateComponentSpecFileSchema>(
'component-cypress-spec',
{
projectName,
libPath: modulePath,
componentName: info.name,
componentPath: info.path,
componentFileName: info.componentFileName
}
)
: () => {}
])
)
);
})
); );
}; };
} }