Skip to content

Commit

Permalink
cleanup(angular): consolidate name and path normalization for compone…
Browse files Browse the repository at this point in the history
…nt, directive and pipe generators (#16108)
  • Loading branch information
leosvelperez committed Apr 5, 2023
1 parent 18c016b commit a0fb3c7
Show file tree
Hide file tree
Showing 51 changed files with 806 additions and 823 deletions.
6 changes: 6 additions & 0 deletions docs/generated/packages/angular/generators/scam.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
"description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.",
"default": true,
"x-priority": "important"
},
"skipFormat": {
"type": "boolean",
"description": "Skip formatting files.",
"default": false,
"x-priority": "internal"
}
},
"required": ["name", "project"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,55 @@ export * from './lib/example/example.component';
"
`;

exports[`component Generator should create component files correctly: component 1`] = `
"import { Component } from '@angular/core';
@Component({
selector: 'proj-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css'],
})
export class ExampleComponent {}
"
`;

exports[`component Generator should create component files correctly: component test file 1`] = `
"import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ExampleComponent } from './example.component';
describe('ExampleComponent', () => {
let component: ExampleComponent;
let fixture: ComponentFixture<ExampleComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ExampleComponent],
}).compileComponents();
fixture = TestBed.createComponent(ExampleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
"
`;
exports[`component Generator should create component files correctly: entry point file 1`] = `
"export * from './lib/lib.module';
"
`;
exports[`component Generator should create component files correctly: stylesheet 1`] = `""`;
exports[`component Generator should create component files correctly: template 1`] = `
"<p>example works!</p>
"
`;
exports[`component Generator should create the component correctly and export it in the entry point when "export=true" 1`] = `
"import { Component } from '@angular/core';
Expand Down Expand Up @@ -137,3 +186,27 @@ exports[`component Generator should create the component correctly but not expor
export class ExampleComponent {}
"
`;
exports[`component Generator should inline styles when --inline-style=true 1`] = `
"import { Component } from '@angular/core';
@Component({
selector: 'proj-example',
templateUrl: './example.component.html',
styles: [],
})
export class ExampleComponent {}
"
`;
exports[`component Generator should inline template when --inline-template=true 1`] = `
"import { Component } from '@angular/core';
@Component({
selector: 'proj-example',
template: \`<p>example works!</p>\`,
styleUrls: ['./example.component.css'],
})
export class ExampleComponent {}
"
`;
153 changes: 153 additions & 0 deletions packages/angular/src/generators/component/component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,159 @@ import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { componentGenerator } from './component';

describe('component Generator', () => {
it('should create component files correctly', async () => {
// ARRANGE
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
addProjectConfiguration(tree, 'lib1', {
projectType: 'library',
sourceRoot: 'libs/lib1/src',
root: 'libs/lib1',
});
tree.write(
'libs/lib1/src/lib/lib.module.ts',
`
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
exports: []
})
export class LibModule {}`
);
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";');

// ACT
await componentGenerator(tree, {
name: 'example',
project: 'lib1',
});

// ASSERT
expect(
tree.read('libs/lib1/src/lib/example/example.component.ts', 'utf-8')
).toMatchSnapshot('component');
expect(
tree.read('libs/lib1/src/lib/example/example.component.html', 'utf-8')
).toMatchSnapshot('template');
expect(
tree.read('libs/lib1/src/lib/example/example.component.css', 'utf-8')
).toMatchSnapshot('stylesheet');
expect(
tree.read('libs/lib1/src/lib/example/example.component.spec.ts', 'utf-8')
).toMatchSnapshot('component test file');
expect(tree.read('libs/lib1/src/index.ts', 'utf-8')).toMatchSnapshot(
'entry point file'
);
});

it('should not generate test file when --skip-tests=true', async () => {
// ARRANGE
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
addProjectConfiguration(tree, 'lib1', {
projectType: 'library',
sourceRoot: 'libs/lib1/src',
root: 'libs/lib1',
});
tree.write(
'libs/lib1/src/lib/lib.module.ts',
`
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
exports: []
})
export class LibModule {}`
);
tree.write('libs/lib1/src/index.ts', '');

// ACT
await componentGenerator(tree, {
name: 'example',
project: 'lib1',
skipTests: true,
});

// ASSERT
expect(
tree.exists('libs/lib1/src/lib/example/example.component.spec.ts')
).toBe(false);
});

it('should inline template when --inline-template=true', async () => {
// ARRANGE
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
addProjectConfiguration(tree, 'lib1', {
projectType: 'library',
sourceRoot: 'libs/lib1/src',
root: 'libs/lib1',
});
tree.write(
'libs/lib1/src/lib/lib.module.ts',
`
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
exports: []
})
export class LibModule {}`
);
tree.write('libs/lib1/src/index.ts', '');

// ACT
await componentGenerator(tree, {
name: 'example',
project: 'lib1',
inlineTemplate: true,
});

// ASSERT
expect(
tree.read('libs/lib1/src/lib/example/example.component.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.exists('libs/lib1/src/lib/example/example.component.html')
).toBe(false);
});

it('should inline styles when --inline-style=true', async () => {
// ARRANGE
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
addProjectConfiguration(tree, 'lib1', {
projectType: 'library',
sourceRoot: 'libs/lib1/src',
root: 'libs/lib1',
});
tree.write(
'libs/lib1/src/lib/lib.module.ts',
`
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
exports: []
})
export class LibModule {}`
);
tree.write('libs/lib1/src/index.ts', '');

// ACT
await componentGenerator(tree, {
name: 'example',
project: 'lib1',
inlineStyle: true,
});

// ASSERT
expect(
tree.read('libs/lib1/src/lib/example/example.component.ts', 'utf-8')
).toMatchSnapshot();
expect(tree.exists('libs/lib1/src/lib/example/example.component.css')).toBe(
false
);
});

it('should create the component correctly and export it in the entry point when "export=true"', async () => {
// ARRANGE
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
Expand Down
59 changes: 27 additions & 32 deletions packages/angular/src/generators/component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,53 @@ export async function componentGenerator(tree: Tree, rawOptions: Schema) {
validateOptions(tree, rawOptions);
const options = normalizeOptions(tree, rawOptions);

const pathToGenerate = options.flat
? joinPathFragments(__dirname, './files/__fileName__')
: joinPathFragments(__dirname, './files');

const componentNames = names(options.name);
const typeNames = names(options.type);

generateFiles(tree, pathToGenerate, options.path, {
fileName: componentNames.fileName,
className: componentNames.className,
type: typeNames.fileName,
typeClassName: typeNames.className,
style: options.style,
inlineStyle: options.inlineStyle,
inlineTemplate: options.inlineTemplate,
standalone: options.standalone,
skipSelector: options.skipSelector,
changeDetection: options.changeDetection,
viewEncapsulation: options.viewEncapsulation,
displayBlock: options.displayBlock,
selector: options.selector,
tpl: '',
});
generateFiles(
tree,
joinPathFragments(__dirname, 'files'),
options.directory,
{
fileName: componentNames.fileName,
className: componentNames.className,
type: typeNames.fileName,
typeClassName: typeNames.className,
style: options.style,
inlineStyle: options.inlineStyle,
inlineTemplate: options.inlineTemplate,
standalone: options.standalone,
skipSelector: options.skipSelector,
changeDetection: options.changeDetection,
viewEncapsulation: options.viewEncapsulation,
displayBlock: options.displayBlock,
selector: options.selector,
tpl: '',
}
);

if (options.skipTests) {
const pathToSpecFile = joinPathFragments(
options.path,
`${!options.flat ? `${componentNames.fileName}/` : ``}${
componentNames.fileName
}.${typeNames.fileName}.spec.ts`
options.directory,
`${componentNames.fileName}.${typeNames.fileName}.spec.ts`
);

tree.delete(pathToSpecFile);
}

if (options.inlineTemplate) {
const pathToTemplateFile = joinPathFragments(
options.path,
`${!options.flat ? `${componentNames.fileName}/` : ``}${
componentNames.fileName
}.${typeNames.fileName}.html`
options.directory,
`${componentNames.fileName}.${typeNames.fileName}.html`
);

tree.delete(pathToTemplateFile);
}

if (options.inlineStyle) {
const pathToStyleFile = joinPathFragments(
options.path,
`${!options.flat ? `${componentNames.fileName}/` : ``}${
componentNames.fileName
}.${typeNames.fileName}.${options.style}`
options.directory,
`${componentNames.fileName}.${typeNames.fileName}.${options.style}`
);

tree.delete(pathToStyleFile);
Expand Down
7 changes: 2 additions & 5 deletions packages/angular/src/generators/component/lib/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { logger, readProjectConfiguration, stripIndents } from '@nrwl/devkit';
import { ensureTypescript } from '@nrwl/js/src/utils/typescript/ensure-typescript';
import type { StringLiteral } from 'typescript';
import { locateLibraryEntryPointFromDirectory } from '../../utils/entry-point';
import { getComponentFileInfo } from '../../utils/file-info';
import { getRelativeImportToFile } from '../../utils/path';
import type { NormalizedSchema } from '../schema';
import { findModuleFromOptions } from './module';
Expand All @@ -22,11 +21,9 @@ export function exportComponentInEntryPoint(
return;
}

const { directory, filePath } = getComponentFileInfo(tree, schema);

const entryPointPath = locateLibraryEntryPointFromDirectory(
tree,
directory,
schema.directory,
root,
schema.projectSourceRoot
);
Expand All @@ -48,7 +45,7 @@ export function exportComponentInEntryPoint(

const relativePathFromEntryPoint = getRelativeImportToFile(
entryPointPath,
filePath
schema.filePath
);
const updateEntryPointContent = stripIndents`${tree.read(
entryPointPath,
Expand Down
6 changes: 2 additions & 4 deletions packages/angular/src/generators/component/lib/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ export function findModuleFromOptions(
projectRoot: string
): string | null {
if (!options.module) {
const pathToCheck = joinPathFragments(options.path, options.name);

return normalizePath(findModule(tree, pathToCheck, projectRoot));
return normalizePath(findModule(tree, options.directory, projectRoot));
} else {
const modulePath = joinPathFragments(options.path, options.module);
const componentPath = joinPathFragments(options.path, options.name);
const componentPath = options.directory;
const moduleBaseName = basename(modulePath);

const candidateSet = new Set<string>([options.path]);
Expand Down
Loading

1 comment on commit a0fb3c7

@vercel
Copy link

@vercel vercel bot commented on a0fb3c7 Apr 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx.dev

Please sign in to comment.