Skip to content

Commit

Permalink
feat(@schematics/angular): remove deprecated CanLoad option for guards
Browse files Browse the repository at this point in the history
Angular v15.1 deprecated the `CanLoad` guard in favor of `CanMatch`.
This commit removes the support for `CanLoad` when generating a guard with the CLI, to encourage developers to use `CanMatch` instead.

BREAKING CHANGE:
The CLI no longer allows to generate `CanLoad` guards. Use `CanMatch` instead.
  • Loading branch information
cexbrayat authored and angular-robot[bot] committed Feb 15, 2023
1 parent 6d9b157 commit 5ceedcb
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,5 @@ export class <%= classify(name) %>Guard implements <%= implementations %> {
route: Route,
segments: UrlSegment[]): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return true;
}<% } %><% if (implements.includes('CanLoad')) { %>canLoad(
route: Route,
segments: UrlSegment[]): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return true;
}<% } %>
}
5 changes: 1 addition & 4 deletions packages/schematics/angular/guard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ export default function (options: GuardOptions): Rule {
const commonRouterNameImports = ['ActivatedRouteSnapshot', 'RouterStateSnapshot'];
const routerNamedImports: string[] = [...options.implements, 'UrlTree'];

if (
options.implements.includes(GuardInterface.CanLoad) ||
options.implements.includes(GuardInterface.CanMatch)
) {
if (options.implements.includes(GuardInterface.CanMatch)) {
routerNamedImports.push('Route', 'UrlSegment');

if (options.implements.length > 1) {
Expand Down
33 changes: 7 additions & 26 deletions packages/schematics/angular/guard/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ describe('Guard Schematic', () => {
expect(fileString).toContain('canActivate');
expect(fileString).not.toContain('CanActivateChild');
expect(fileString).not.toContain('canActivateChild');
expect(fileString).not.toContain('CanLoad');
expect(fileString).not.toContain('canLoad');
expect(fileString).not.toContain('CanMatch');
expect(fileString).not.toContain('canMatch');
});

it('should respect the functional guard value', async () => {
Expand All @@ -96,8 +96,8 @@ describe('Guard Schematic', () => {
expect(fileString).toContain('export const fooGuard: CanActivateFn = (route, state) => {');
expect(fileString).not.toContain('CanActivateChild');
expect(fileString).not.toContain('canActivateChild');
expect(fileString).not.toContain('CanLoad');
expect(fileString).not.toContain('canLoad');
expect(fileString).not.toContain('CanMatch');
expect(fileString).not.toContain('canMatch');
});

it('should generate a helper function to execute the guard in a test', async () => {
Expand All @@ -121,7 +121,7 @@ describe('Guard Schematic', () => {
});

it('should respect the implements values', async () => {
const implementationOptions = ['CanActivate', 'CanLoad', 'CanActivateChild'];
const implementationOptions = ['CanActivate', 'CanDeactivate', 'CanActivateChild'];
const options = { ...defaultOptions, implements: implementationOptions };
const tree = await schematicRunner.runSchematic('guard', options, appTree);
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
Expand All @@ -134,16 +134,6 @@ describe('Guard Schematic', () => {
});
});

it('should add correct imports based on CanLoad implementation', async () => {
const implementationOptions = ['CanLoad'];
const options = { ...defaultOptions, implements: implementationOptions };
const tree = await schematicRunner.runSchematic('guard', options, appTree);
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
const expectedImports = `import { CanLoad, Route, UrlSegment, UrlTree } from '@angular/router';`;

expect(fileString).toContain(expectedImports);
});

it('should add correct imports based on CanMatch implementation', async () => {
const implementationOptions = ['CanMatch'];
const options = { ...defaultOptions, implements: implementationOptions };
Expand All @@ -154,15 +144,6 @@ describe('Guard Schematic', () => {
expect(fileString).toContain(expectedImports);
});

it('should add correct imports based on canLoad functional guard', async () => {
const options = { ...defaultOptions, implements: ['CanLoad'], functional: true };
const tree = await schematicRunner.runSchematic('guard', options, appTree);
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
const expectedImports = `import { CanLoadFn } from '@angular/router';`;

expect(fileString).toContain(expectedImports);
});

it('should add correct imports based on CanActivate implementation', async () => {
const implementationOptions = ['CanActivate'];
const options = { ...defaultOptions, implements: implementationOptions };
Expand All @@ -183,13 +164,13 @@ describe('Guard Schematic', () => {
});

it('should add correct imports if multiple implementations was selected', async () => {
const implementationOptions = ['CanActivate', 'CanLoad', 'CanActivateChild'];
const implementationOptions = ['CanActivate', 'CanMatch', 'CanActivateChild'];
const options = { ...defaultOptions, implements: implementationOptions };
const tree = await schematicRunner.runSchematic('guard', options, appTree);
const fileString = tree.readContent('/projects/bar/src/app/foo.guard.ts');
const expectedImports =
`import ` +
`{ ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanLoad, Route, RouterStateSnapshot, UrlSegment, UrlTree } ` +
`{ ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanMatch, Route, RouterStateSnapshot, UrlSegment, UrlTree } ` +
`from '@angular/router';`;

expect(fileString).toContain(expectedImports);
Expand Down
2 changes: 1 addition & 1 deletion packages/schematics/angular/guard/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"uniqueItems": true,
"minItems": 1,
"items": {
"enum": ["CanActivate", "CanActivateChild", "CanDeactivate", "CanLoad", "CanMatch"],
"enum": ["CanActivate", "CanActivateChild", "CanDeactivate", "CanMatch"],
"type": "string"
},
"default": ["CanActivate"],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { <%= guardType %> } from '@angular/router';

export const <%= camelize(name) %>Guard: <%= guardType %><% if (guardType === 'CanDeactivateFn') { %><unknown><% } %> = <%
if (guardType === 'CanMatchFn' || guardType === 'CanLoadFn') { %>(route, segments)<% }
if (guardType === 'CanMatchFn') { %>(route, segments)<% }
%><% if (guardType === 'CanActivateFn') { %>(route, state)<% }
%><% if (guardType === 'CanActivateChildFn') { %>(childRoute, state)<% }
%><% if (guardType === 'CanDeactivateFn') { %>(component, currentRoute, currentState, nextState)<% } %> => {
Expand Down
4 changes: 2 additions & 2 deletions packages/schematics/angular/utility/ast-utils_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ describe('ast utils', () => {
import { AppComponent } from './app.component';
const routes = [
{ path: 'foo', component: FooComponent, canLoad: [Guard] }
{ path: 'foo', component: FooComponent, canMatch: [Guard] }
];
@NgModule({
Expand All @@ -527,7 +527,7 @@ describe('ast utils', () => {
const output = applyChanges(modulePath, moduleContent, [changes]);
/* eslint-disable max-len */
expect(output).toMatch(
/const routes = \[\r?\n?\s*{ path: 'foo', component: FooComponent, canLoad: \[Guard\] },\r?\n?\s*{ path: 'bar', component: BarComponent }\r?\n?\s*\]/,
/const routes = \[\r?\n?\s*{ path: 'foo', component: FooComponent, canMatch: \[Guard\] },\r?\n?\s*{ path: 'bar', component: BarComponent }\r?\n?\s*\]/,
);
/* eslint-enable max-len */
});
Expand Down
8 changes: 4 additions & 4 deletions tests/legacy-cli/e2e/tests/generate/guard/guard-implements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ export default async function () {
// Does not create a sub directory.
const guardDir = join('src', 'app');

await ng('generate', 'guard', 'load', '--implements=CanLoad');
await ng('generate', 'guard', 'match', '--implements=CanMatch');
await expectFileToExist(guardDir);
await expectFileToExist(join(guardDir, 'load.guard.ts'));
await expectFileToMatch(join(guardDir, 'load.guard.ts'), /implements CanLoad/);
await expectFileToExist(join(guardDir, 'load.guard.spec.ts'));
await expectFileToExist(join(guardDir, 'match.guard.ts'));
await expectFileToMatch(join(guardDir, 'match.guard.ts'), /implements CanMatch/);
await expectFileToExist(join(guardDir, 'match.guard.spec.ts'));
await ng('test', '--watch=false');
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ export default async function () {
// Does not create a sub directory.
const guardDir = join('src', 'app');

await ng('generate', 'guard', 'load', '--implements=CanLoad', '--implements=CanDeactivate');
await ng(
'generate',
'guard',
'multiple',
'--implements=CanActivate',
'--implements=CanDeactivate',
);
await expectFileToExist(guardDir);
await expectFileToExist(join(guardDir, 'load.guard.ts'));
await expectFileToExist(join(guardDir, 'multiple.guard.ts'));
await expectFileToMatch(
join(guardDir, 'load.guard.ts'),
/implements CanLoad, CanDeactivate<unknown>/,
join(guardDir, 'multiple.guard.ts'),
/implements CanActivate, CanDeactivate<unknown>/,
);
await expectFileToExist(join(guardDir, 'load.guard.spec.ts'));
await expectFileToExist(join(guardDir, 'multiple.guard.spec.ts'));
await ng('test', '--watch=false');
}

0 comments on commit 5ceedcb

Please sign in to comment.