From b522002fff763cda2ae1c746efcb2638d0099184 Mon Sep 17 00:00:00 2001 From: harshlakhara Date: Fri, 4 Oct 2024 07:35:49 +0530 Subject: [PATCH] fix(@schematics/angular): add validation for component and directive class name (cherry picked from commit 6dbfc770b2d2f72dbc73e39e763f0773435825c6) --- packages/schematics/angular/component/index.ts | 3 ++- packages/schematics/angular/component/index_spec.ts | 8 ++++++++ packages/schematics/angular/directive/index.ts | 3 ++- packages/schematics/angular/directive/index_spec.ts | 8 ++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/schematics/angular/component/index.ts b/packages/schematics/angular/component/index.ts index bb07a85cab1d..ef1fcd856a00 100644 --- a/packages/schematics/angular/component/index.ts +++ b/packages/schematics/angular/component/index.ts @@ -25,7 +25,7 @@ import { import { addDeclarationToNgModule } from '../utility/add-declaration-to-ng-module'; import { findModuleFromOptions } from '../utility/find-module'; import { parseName } from '../utility/parse-name'; -import { validateHtmlSelector } from '../utility/validation'; +import { validateClassName, validateHtmlSelector } from '../utility/validation'; import { buildDefaultPath, getWorkspace } from '../utility/workspace'; import { Schema as ComponentOptions, Style } from './schema'; @@ -62,6 +62,7 @@ export default function (options: ComponentOptions): Rule { options.selector || buildSelector(options, (project && project.prefix) || ''); validateHtmlSelector(options.selector); + validateClassName(strings.classify(options.name)); const skipStyleFile = options.inlineStyle || options.style === Style.None; const templateSource = apply(url('./files'), [ diff --git a/packages/schematics/angular/component/index_spec.ts b/packages/schematics/angular/component/index_spec.ts index ee1d51c3c1a0..d6f5af8dc6df 100644 --- a/packages/schematics/angular/component/index_spec.ts +++ b/packages/schematics/angular/component/index_spec.ts @@ -157,6 +157,14 @@ describe('Component Schematic', () => { ).toBeRejectedWithError('Selector "app-1-one" is invalid.'); }); + it('should error when class name contains invalid characters', async () => { + const options = { ...defaultOptions, name: '404' }; + + await expectAsync( + schematicRunner.runSchematic('component', options, appTree), + ).toBeRejectedWithError('Class name "404" is invalid.'); + }); + it('should allow dash in selector before a number', async () => { const options = { ...defaultOptions, name: 'one-1' }; diff --git a/packages/schematics/angular/directive/index.ts b/packages/schematics/angular/directive/index.ts index b6e89eacf0e1..97e6a9deaa18 100644 --- a/packages/schematics/angular/directive/index.ts +++ b/packages/schematics/angular/directive/index.ts @@ -23,7 +23,7 @@ import { import { addDeclarationToNgModule } from '../utility/add-declaration-to-ng-module'; import { findModuleFromOptions } from '../utility/find-module'; import { parseName } from '../utility/parse-name'; -import { validateHtmlSelector } from '../utility/validation'; +import { validateClassName, validateHtmlSelector } from '../utility/validation'; import { buildDefaultPath, getWorkspace } from '../utility/workspace'; import { Schema as DirectiveOptions } from './schema'; @@ -58,6 +58,7 @@ export default function (options: DirectiveOptions): Rule { options.selector = options.selector || buildSelector(options, project.prefix || ''); validateHtmlSelector(options.selector); + validateClassName(strings.classify(options.name)); const templateSource = apply(url('./files'), [ options.skipTests ? filter((path) => !path.endsWith('.spec.ts.template')) : noop(), diff --git a/packages/schematics/angular/directive/index_spec.ts b/packages/schematics/angular/directive/index_spec.ts index e636830bf93c..afa845d29f65 100644 --- a/packages/schematics/angular/directive/index_spec.ts +++ b/packages/schematics/angular/directive/index_spec.ts @@ -111,6 +111,14 @@ describe('Directive Schematic', () => { expect(directiveContent).toContain('class FooDirective'); }); + it('should error when class name contains invalid characters', async () => { + const options = { ...defaultOptions, name: '404' }; + + await expectAsync( + schematicRunner.runSchematic('component', options, appTree), + ).toBeRejectedWithError('Class name "404" is invalid.'); + }); + describe('standalone=false', () => { const defaultNonStandaloneOptions: DirectiveOptions = { ...defaultOptions,