From 83964c63ad2318928c2c6384ffd9e6deceb402e6 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:52:56 -0400 Subject: [PATCH] fix(@schematics/angular): generate interceptors with a dash type separator To align with the updated style guide, Angular v20 will generate interceptors with file extension `interceptor` type prefixed with a `-` separator instead of a `.` by default. Projects will automatically use this naming convention. Projects can however opt-out by setting the `typeSeparator` option to `.` for the interceptor schematic. This can be done as a default in the `angular.json` or directly on the commandline via `--type-separator=.` when executing `ng generate`. As an example, `example.interceptor.ts` will now be named `example-interceptor.ts`. The TypeScript declaration will continue to contain `Interceptor` such as with `ExampleInterceptor`. --- ...peSeparator__interceptor.spec.ts.template} | 2 +- ...___typeSeparator__interceptor.ts.template} | 0 ...peSeparator__interceptor.spec.ts.template} | 2 +- ...___typeSeparator__interceptor.ts.template} | 0 .../angular/interceptor/index_spec.ts | 32 ++++++++++++++++--- .../angular/interceptor/schema.json | 6 ++++ .../generate/interceptor/interceptor-basic.ts | 6 ++-- 7 files changed, 38 insertions(+), 10 deletions(-) rename packages/schematics/angular/interceptor/class-files/{__name@dasherize__.interceptor.spec.ts.template => __name@dasherize____typeSeparator__interceptor.spec.ts.template} (91%) rename packages/schematics/angular/interceptor/class-files/{__name@dasherize__.interceptor.ts.template => __name@dasherize____typeSeparator__interceptor.ts.template} (100%) rename packages/schematics/angular/interceptor/functional-files/{__name@dasherize__.interceptor.spec.ts.template => __name@dasherize____typeSeparator__interceptor.spec.ts.template} (92%) rename packages/schematics/angular/interceptor/functional-files/{__name@dasherize__.interceptor.ts.template => __name@dasherize____typeSeparator__interceptor.ts.template} (100%) diff --git a/packages/schematics/angular/interceptor/class-files/__name@dasherize__.interceptor.spec.ts.template b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template similarity index 91% rename from packages/schematics/angular/interceptor/class-files/__name@dasherize__.interceptor.spec.ts.template rename to packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template index d136abd5f7dc..9af595489571 100755 --- a/packages/schematics/angular/interceptor/class-files/__name@dasherize__.interceptor.spec.ts.template +++ b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template @@ -1,6 +1,6 @@ import { TestBed } from '@angular/core/testing'; -import { <%= classify(name) %>Interceptor } from './<%= dasherize(name) %>.interceptor'; +import { <%= classify(name) %>Interceptor } from './<%= dasherize(name) %><%= typeSeparator %>interceptor'; describe('<%= classify(name) %>Interceptor', () => { beforeEach(() => TestBed.configureTestingModule({ diff --git a/packages/schematics/angular/interceptor/class-files/__name@dasherize__.interceptor.ts.template b/packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template similarity index 100% rename from packages/schematics/angular/interceptor/class-files/__name@dasherize__.interceptor.ts.template rename to packages/schematics/angular/interceptor/class-files/__name@dasherize____typeSeparator__interceptor.ts.template diff --git a/packages/schematics/angular/interceptor/functional-files/__name@dasherize__.interceptor.spec.ts.template b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template similarity index 92% rename from packages/schematics/angular/interceptor/functional-files/__name@dasherize__.interceptor.spec.ts.template rename to packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template index 58b6b7e709b8..ee1662c6530f 100755 --- a/packages/schematics/angular/interceptor/functional-files/__name@dasherize__.interceptor.spec.ts.template +++ b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.spec.ts.template @@ -1,7 +1,7 @@ import { TestBed } from '@angular/core/testing'; import { HttpInterceptorFn } from '@angular/common/http'; -import { <%= camelize(name) %>Interceptor } from './<%= dasherize(name) %>.interceptor'; +import { <%= camelize(name) %>Interceptor } from './<%= dasherize(name) %><%= typeSeparator %>interceptor'; describe('<%= camelize(name) %>Interceptor', () => { const interceptor: HttpInterceptorFn = (req, next) => diff --git a/packages/schematics/angular/interceptor/functional-files/__name@dasherize__.interceptor.ts.template b/packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.ts.template similarity index 100% rename from packages/schematics/angular/interceptor/functional-files/__name@dasherize__.interceptor.ts.template rename to packages/schematics/angular/interceptor/functional-files/__name@dasherize____typeSeparator__interceptor.ts.template diff --git a/packages/schematics/angular/interceptor/index_spec.ts b/packages/schematics/angular/interceptor/index_spec.ts index 8a9286f76fff..a657ee7e4225 100755 --- a/packages/schematics/angular/interceptor/index_spec.ts +++ b/packages/schematics/angular/interceptor/index_spec.ts @@ -46,9 +46,31 @@ describe('Interceptor Schematic', () => { const tree = await schematicRunner.runSchematic('interceptor', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.ts'); + }); + + it('should use a `.` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '.' }; + + const tree = await schematicRunner.runSchematic('interceptor', options, appTree); const files = tree.files; expect(files).toContain('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); expect(files).toContain('/projects/bar/src/app/foo/foo.interceptor.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); + expect(specContent).toContain(`'./foo.interceptor'`); + }); + + it('should use a `-` type separator when specified', async () => { + const options = { ...defaultOptions, typeSeparator: '-' }; + + const tree = await schematicRunner.runSchematic('interceptor', options, appTree); + const files = tree.files; + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.ts'); + const specContent = tree.readContent('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); + expect(specContent).toContain(`'./foo-interceptor'`); }); it('should respect the skipTests flag', async () => { @@ -57,8 +79,8 @@ describe('Interceptor Schematic', () => { const tree = await schematicRunner.runSchematic('interceptor', options, appTree); const files = tree.files; - expect(files).toContain('/projects/bar/src/app/foo/foo.interceptor.ts'); - expect(files).not.toContain('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); + expect(files).toContain('/projects/bar/src/app/foo/foo-interceptor.ts'); + expect(files).not.toContain('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); }); it('should respect the sourceRoot value', async () => { @@ -67,7 +89,7 @@ describe('Interceptor Schematic', () => { appTree.overwrite('/angular.json', JSON.stringify(config, null, 2)); appTree = await schematicRunner.runSchematic('interceptor', defaultOptions, appTree); - expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo.interceptor.ts'); + expect(appTree.files).toContain('/projects/bar/custom/app/foo/foo-interceptor.ts'); }); it('should create a functional interceptor', async () => { @@ -77,7 +99,7 @@ describe('Interceptor Schematic', () => { appTree, ); - const fileString = tree.readContent('/projects/bar/src/app/foo/foo.interceptor.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo/foo-interceptor.ts'); expect(fileString).toContain( 'export const fooInterceptor: HttpInterceptorFn = (req, next) => {', ); @@ -90,7 +112,7 @@ describe('Interceptor Schematic', () => { appTree, ); - const fileString = tree.readContent('/projects/bar/src/app/foo/foo.interceptor.spec.ts'); + const fileString = tree.readContent('/projects/bar/src/app/foo/foo-interceptor.spec.ts'); expect(fileString).toContain('const interceptor: HttpInterceptorFn = (req, next) => '); expect(fileString).toContain('TestBed.runInInjectionContext(() => fooInterceptor(req, next));'); }); diff --git a/packages/schematics/angular/interceptor/schema.json b/packages/schematics/angular/interceptor/schema.json index ff072a5557d2..e42e0c675e8e 100755 --- a/packages/schematics/angular/interceptor/schema.json +++ b/packages/schematics/angular/interceptor/schema.json @@ -45,6 +45,12 @@ "type": "boolean", "description": "Creates the interceptor as a function `HttpInterceptorFn` instead of a class. Functional interceptors can be simpler for basic scenarios.", "default": true + }, + "typeSeparator": { + "type": "string", + "default": "-", + "enum": ["-", "."], + "description": "The separator character to use before the type within the generated file's name. For example, if you set the option to `.`, the file will be named `example.interceptor.ts`." } }, "required": ["name", "project"] diff --git a/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts b/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts index 5046f2603da6..7dd0b48c439b 100755 --- a/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts +++ b/tests/legacy-cli/e2e/tests/generate/interceptor/interceptor-basic.ts @@ -7,10 +7,10 @@ export default function () { const interceptorDir = join('src', 'app'); return ( - ng('generate', 'interceptor', 'test-interceptor') + ng('generate', 'interceptor', 'test') .then(() => expectFileToExist(interceptorDir)) - .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.interceptor.ts'))) - .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.interceptor.spec.ts'))) + .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.ts'))) + .then(() => expectFileToExist(join(interceptorDir, 'test-interceptor.spec.ts'))) // Try to run the unit tests. .then(() => ng('test', '--watch=false'))