Skip to content

Commit 5fc5951

Browse files
clydinjkrems
authored andcommitted
fix(@schematics/angular): generate guards with a dash type separator
To align with the updated style guide, Angular v20 will generate guards with file extension `guard` 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 guard 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.guard.ts` will now be named `example-guard.ts`. The TypeScript declaration will continue to contain `Guard` such as with `ExampleGuard`.
1 parent bb3c027 commit 5fc5951

9 files changed

+54
-30
lines changed

packages/schematics/angular/guard/implements-files/__name@dasherize__.guard.spec.ts.template renamed to packages/schematics/angular/guard/implements-files/__name@dasherize____typeSeparator__guard.spec.ts.template

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TestBed } from '@angular/core/testing';
22

3-
import { <%= classify(name) %>Guard } from './<%= dasherize(name) %>.guard';
3+
import { <%= classify(name) %>Guard } from './<%= dasherize(name) %><%= typeSeparator %>guard';
44

55
describe('<%= classify(name) %>Guard', () => {
66
let guard: <%= classify(name) %>Guard;

packages/schematics/angular/guard/index_spec.ts

+37-15
Original file line numberDiff line numberDiff line change
@@ -51,40 +51,62 @@ describe('Guard Schematic', () => {
5151
);
5252

5353
const files = tree.files;
54-
expect(files).toContain('/projects/bar/src/app/foo.guard.spec.ts');
55-
expect(files).toContain('/projects/bar/src/app/foo.guard.ts');
54+
expect(files).toContain('/projects/bar/src/app/foo-guard.spec.ts');
55+
expect(files).toContain('/projects/bar/src/app/foo-guard.ts');
5656
});
5757

5858
it('should respect the skipTests flag', async () => {
5959
const options = { ...defaultOptions, skipTests: true };
6060

6161
const tree = await schematicRunner.runSchematic('guard', options, appTree);
6262
const files = tree.files;
63-
expect(files).not.toContain('/projects/bar/src/app/foo.guard.spec.ts');
63+
expect(files).not.toContain('/projects/bar/src/app/foo-guard.spec.ts');
64+
expect(files).toContain('/projects/bar/src/app/foo-guard.ts');
65+
});
66+
67+
it('should use a `.` type separator when specified', async () => {
68+
const options = { ...defaultOptions, typeSeparator: '.' };
69+
70+
const tree = await schematicRunner.runSchematic('guard', options, appTree);
71+
const files = tree.files;
72+
expect(files).toContain('/projects/bar/src/app/foo.guard.spec.ts');
6473
expect(files).toContain('/projects/bar/src/app/foo.guard.ts');
74+
const specContent = tree.readContent('/projects/bar/src/app/foo.guard.spec.ts');
75+
expect(specContent).toContain(`'./foo.guard'`);
76+
});
77+
78+
it('should use a `-` type separator when specified', async () => {
79+
const options = { ...defaultOptions, typeSeparator: '-' };
80+
81+
const tree = await schematicRunner.runSchematic('guard', options, appTree);
82+
const files = tree.files;
83+
expect(files).toContain('/projects/bar/src/app/foo-guard.spec.ts');
84+
expect(files).toContain('/projects/bar/src/app/foo-guard.ts');
85+
const specContent = tree.readContent('/projects/bar/src/app/foo-guard.spec.ts');
86+
expect(specContent).toContain(`'./foo-guard'`);
6587
});
6688

6789
it('should respect the flat flag', async () => {
6890
const options = { ...defaultOptions, flat: false };
6991

7092
const tree = await schematicRunner.runSchematic('guard', options, appTree);
7193
const files = tree.files;
72-
expect(files).toContain('/projects/bar/src/app/foo/foo.guard.spec.ts');
73-
expect(files).toContain('/projects/bar/src/app/foo/foo.guard.ts');
94+
expect(files).toContain('/projects/bar/src/app/foo/foo-guard.spec.ts');
95+
expect(files).toContain('/projects/bar/src/app/foo/foo-guard.ts');
7496
});
7597

7698
it('should respect the sourceRoot value', async () => {
7799
const config = JSON.parse(appTree.readContent('/angular.json'));
78100
config.projects.bar.sourceRoot = 'projects/bar/custom';
79101
appTree.overwrite('/angular.json', JSON.stringify(config, null, 2));
80102
appTree = await schematicRunner.runSchematic('guard', defaultOptions, appTree);
81-
expect(appTree.files).toContain('/projects/bar/custom/app/foo.guard.ts');
103+
expect(appTree.files).toContain('/projects/bar/custom/app/foo-guard.ts');
82104
});
83105

84106
it('should respect the implements value', async () => {
85107
const options = { ...defaultOptions, implements: ['CanActivate'], functional: false };
86108
const tree = await schematicRunner.runSchematic('guard', options, appTree);
87-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
109+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
88110
expect(fileString).toContain('CanActivate');
89111
expect(fileString).toContain('canActivate');
90112
expect(fileString).not.toContain('CanActivateChild');
@@ -96,7 +118,7 @@ describe('Guard Schematic', () => {
96118
it('should generate a functional guard by default', async () => {
97119
const options = { ...defaultOptions, implements: ['CanActivate'] };
98120
const tree = await schematicRunner.runSchematic('guard', options, appTree);
99-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
121+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
100122
expect(fileString).toContain('export const fooGuard: CanActivateFn = (route, state) => {');
101123
expect(fileString).not.toContain('CanActivateChild');
102124
expect(fileString).not.toContain('canActivateChild');
@@ -107,7 +129,7 @@ describe('Guard Schematic', () => {
107129
it('should generate a helper function to execute the guard in a test', async () => {
108130
const options = { ...defaultOptions, implements: ['CanActivate'] };
109131
const tree = await schematicRunner.runSchematic('guard', options, appTree);
110-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.spec.ts');
132+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.spec.ts');
111133
expect(fileString).toContain('const executeGuard: CanActivateFn = (...guardParameters) => ');
112134
expect(fileString).toContain(
113135
'TestBed.runInInjectionContext(() => fooGuard(...guardParameters));',
@@ -117,7 +139,7 @@ describe('Guard Schematic', () => {
117139
it('should generate CanDeactivateFn with unknown functional guard', async () => {
118140
const options = { ...defaultOptions, implements: ['CanDeactivate'] };
119141
const tree = await schematicRunner.runSchematic('guard', options, appTree);
120-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
142+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
121143
expect(fileString).toContain(
122144
'export const fooGuard: CanDeactivateFn<unknown> = ' +
123145
'(component, currentRoute, currentState, nextState) => {',
@@ -128,7 +150,7 @@ describe('Guard Schematic', () => {
128150
const implementationOptions = ['CanActivate', 'CanDeactivate', 'CanActivateChild'];
129151
const options = { ...defaultOptions, implements: implementationOptions, functional: false };
130152
const tree = await schematicRunner.runSchematic('guard', options, appTree);
131-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
153+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
132154

133155
// Should contain all implementations
134156
implementationOptions.forEach((implementation: string) => {
@@ -142,7 +164,7 @@ describe('Guard Schematic', () => {
142164
const implementationOptions = ['CanMatch'];
143165
const options = { ...defaultOptions, implements: implementationOptions, functional: false };
144166
const tree = await schematicRunner.runSchematic('guard', options, appTree);
145-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
167+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
146168
const expectedImports = `import { CanMatch, GuardResult, MaybeAsync, Route, subPath } from '@angular/router';`;
147169

148170
expect(fileString).toContain(expectedImports);
@@ -152,7 +174,7 @@ describe('Guard Schematic', () => {
152174
const implementationOptions = ['CanActivate'];
153175
const options = { ...defaultOptions, implements: implementationOptions, functional: false };
154176
const tree = await schematicRunner.runSchematic('guard', options, appTree);
155-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
177+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
156178
const expectedImports =
157179
`import { ActivatedRouteSnapshot, CanActivate, GuardResult, ` +
158180
`MaybeAsync, RouterStateSnapshot } from '@angular/router';`;
@@ -163,7 +185,7 @@ describe('Guard Schematic', () => {
163185
it('should add correct imports based on canActivate functional guard', async () => {
164186
const options = { ...defaultOptions, implements: ['CanActivate'] };
165187
const tree = await schematicRunner.runSchematic('guard', options, appTree);
166-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
188+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
167189
const expectedImports = `import { CanActivateFn } from '@angular/router';`;
168190

169191
expect(fileString).toContain(expectedImports);
@@ -173,7 +195,7 @@ describe('Guard Schematic', () => {
173195
const implementationOptions = ['CanActivate', 'CanMatch', 'CanActivateChild'];
174196
const options = { ...defaultOptions, implements: implementationOptions, functional: false };
175197
const tree = await schematicRunner.runSchematic('guard', options, appTree);
176-
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
198+
const fileString = tree.readContent('/projects/bar/src/app/foo-guard.ts');
177199
const expectedImports =
178200
`import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanMatch, GuardResult, ` +
179201
`MaybeAsync, Route, RouterStateSnapshot, subPath } from '@angular/router';`;

packages/schematics/angular/guard/schema.json

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
},
5959
"default": ["CanActivate"],
6060
"x-prompt": "Which type of guard would you like to create?"
61+
},
62+
"typeSeparator": {
63+
"type": "string",
64+
"default": "-",
65+
"enum": ["-", "."]
6166
}
6267
},
6368
"required": ["name", "project"]

packages/schematics/angular/guard/type-files/__name@dasherize__.guard.spec.ts.template renamed to packages/schematics/angular/guard/type-files/__name@dasherize____typeSeparator__guard.spec.ts.template

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { TestBed } from '@angular/core/testing';
22
import { <%= guardType %> } from '@angular/router';
33

4-
import { <%= camelize(name) %>Guard } from './<%= dasherize(name) %>.guard';
4+
import { <%= camelize(name) %>Guard } from './<%= dasherize(name) %><%= typeSeparator %>guard';
55

66
describe('<%= camelize(name) %>Guard', () => {
77
const executeGuard: <%= guardType %><% if (guardType === 'CanDeactivateFn') { %><unknown><% } %> = (...guardParameters) =>

tests/legacy-cli/e2e/tests/generate/guard/guard-basic.ts

+4-7
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@ export default async function () {
66
// Does not create a sub directory.
77
const guardDir = join('src', 'app');
88

9-
await ng('generate', 'guard', 'test-guard');
9+
await ng('generate', 'guard', 'test');
1010
await expectFileToExist(guardDir);
11-
await expectFileToExist(join(guardDir, 'test-guard.guard.ts'));
12-
await expectFileToMatch(
13-
join(guardDir, 'test-guard.guard.ts'),
14-
/export const testGuardGuard: CanActivateFn/,
15-
);
16-
await expectFileToExist(join(guardDir, 'test-guard.guard.spec.ts'));
11+
await expectFileToExist(join(guardDir, 'test-guard.ts'));
12+
await expectFileToMatch(join(guardDir, 'test-guard.ts'), /export const testGuard: CanActivateFn/);
13+
await expectFileToExist(join(guardDir, 'test-guard.spec.ts'));
1714
await ng('test', '--watch=false');
1815
}

tests/legacy-cli/e2e/tests/generate/guard/guard-implements.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export default async function () {
88

99
await ng('generate', 'guard', 'match', '--implements=CanMatch');
1010
await expectFileToExist(guardDir);
11-
await expectFileToExist(join(guardDir, 'match.guard.ts'));
12-
await expectFileToMatch(join(guardDir, 'match.guard.ts'), /export const matchGuard: CanMatch/);
13-
await expectFileToExist(join(guardDir, 'match.guard.spec.ts'));
11+
await expectFileToExist(join(guardDir, 'match-guard.ts'));
12+
await expectFileToMatch(join(guardDir, 'match-guard.ts'), /export const matchGuard: CanMatch/);
13+
await expectFileToExist(join(guardDir, 'match-guard.spec.ts'));
1414
await ng('test', '--watch=false');
1515
}

tests/legacy-cli/e2e/tests/generate/guard/guard-multiple-implements.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ export default async function () {
1616
'--no-functional',
1717
);
1818
await expectFileToExist(guardDir);
19-
await expectFileToExist(join(guardDir, 'multiple.guard.ts'));
19+
await expectFileToExist(join(guardDir, 'multiple-guard.ts'));
2020
await expectFileToMatch(
21-
join(guardDir, 'multiple.guard.ts'),
21+
join(guardDir, 'multiple-guard.ts'),
2222
/implements CanActivate, CanDeactivate<unknown>/,
2323
);
24-
await expectFileToExist(join(guardDir, 'multiple.guard.spec.ts'));
24+
await expectFileToExist(join(guardDir, 'multiple-guard.spec.ts'));
2525
await ng('test', '--watch=false');
2626
}

0 commit comments

Comments
 (0)