From 0dec6f651727ae20fe449a0687fea2a136d9bf8d Mon Sep 17 00:00:00 2001 From: Alan Date: Tue, 9 Jul 2019 10:03:01 +0200 Subject: [PATCH] fix(@schematics/angular): ignore nested arrays in route declarations `findNodes` will continue looking for arrays recursively unless we specify that we specify that we want only the first array. Routes array can contain nested arrays such as when specifying guards. Fixes #15016 --- .../schematics/angular/utility/ast-utils.ts | 8 ++--- .../angular/utility/ast-utils_spec.ts | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packages/schematics/angular/utility/ast-utils.ts b/packages/schematics/angular/utility/ast-utils.ts index 906246e2f860..4f6dc3565aab 100644 --- a/packages/schematics/angular/utility/ast-utils.ts +++ b/packages/schematics/angular/utility/ast-utils.ts @@ -622,8 +622,8 @@ export function addRouteDeclarationToModule( // Check if the route declarations array is // an inlined argument of RouterModule or a standalone variable - if (routesArg.kind === ts.SyntaxKind.ArrayLiteralExpression) { - routesArr = routesArg as ts.ArrayLiteralExpression; + if (ts.isArrayLiteralExpression(routesArg)) { + routesArr = routesArg; } else { const routesVarName = routesArg.getText(); let routesVar; @@ -642,8 +642,8 @@ export function addRouteDeclarationToModule( `to router module at line ${line} in ${fileToAdd}`, ); } - const arrExpr = findNodes(routesVar, ts.SyntaxKind.ArrayLiteralExpression).pop(); - routesArr = arrExpr as ts.ArrayLiteralExpression; + + routesArr = findNodes(routesVar, ts.SyntaxKind.ArrayLiteralExpression, 1)[0] as ts.ArrayLiteralExpression; } const occurencesCount = routesArr.elements.length; diff --git a/packages/schematics/angular/utility/ast-utils_spec.ts b/packages/schematics/angular/utility/ast-utils_spec.ts index 60a4958aa12f..0f82e4acf2d4 100644 --- a/packages/schematics/angular/utility/ast-utils_spec.ts +++ b/packages/schematics/angular/utility/ast-utils_spec.ts @@ -444,6 +444,41 @@ describe('ast utils', () => { ); }); + it('should add a route to the routes to the correct array when having guards', () => { + const moduleContent = ` + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import { AppComponent } from './app.component'; + + const routes = [ + { path: 'foo', component: FooComponent, canLoad: [Guard] } + ]; + + @NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + RouterModule.forRoot(routes) + ], + bootstrap: [AppComponent] + }) + export class AppModule { } + `; + + const source = getTsSource(modulePath, moduleContent); + const changes = addRouteDeclarationToModule( + source, + './src/app', `{ path: 'bar', component: BarComponent }`, + ); + const output = applyChanges(modulePath, moduleContent, [changes]); + expect(output).toMatch( + // tslint:disable-next-line:max-line-length + /const routes = \[\r?\n?\s*{ path: 'foo', component: FooComponent, canLoad: \[Guard\] },\r?\n?\s*{ path: 'bar', component: BarComponent }\r?\n?\s*\]/, + ); + }); + it('should add a route to the routes argument of RouteModule', () => { const moduleContent = ` import { BrowserModule } from '@angular/platform-browser';