diff --git a/packages/schematics/angular/utility/ast-utils.ts b/packages/schematics/angular/utility/ast-utils.ts index f00160fb8119..833979609609 100644 --- a/packages/schematics/angular/utility/ast-utils.ts +++ b/packages/schematics/angular/utility/ast-utils.ts @@ -649,20 +649,38 @@ export function addRouteDeclarationToModule( routesArr = findNodes(routesVar, ts.SyntaxKind.ArrayLiteralExpression, 1)[0] as ts.ArrayLiteralExpression; } - const occurencesCount = routesArr.elements.length; + const occurrencesCount = routesArr.elements.length; const text = routesArr.getFullText(source); let route: string = routeLiteral; - if (occurencesCount > 0) { - const identation = text.match(/\r?\n(\r?)\s*/) || []; - route = `,${identation[0] || ' '}${routeLiteral}`; + let insertPos = routesArr.elements.pos; + + if (occurrencesCount > 0) { + const lastRouteLiteral = [...routesArr.elements].pop() as ts.Expression; + const lastRouteIsWildcard = ts.isObjectLiteralExpression(lastRouteLiteral) + && lastRouteLiteral + .properties + .some(n => ( + ts.isPropertyAssignment(n) + && ts.isIdentifier(n.name) + && n.name.text === 'path' + && ts.isStringLiteral(n.initializer) + && n.initializer.text === '**' + )); + + const indentation = text.match(/\r?\n(\r?)\s*/) || []; + const routeText = `${indentation[0] || ' '}${routeLiteral}`; + + // Add the new route before the wildcard route + // otherwise we'll always redirect to the wildcard route + if (lastRouteIsWildcard) { + insertPos = lastRouteLiteral.pos; + route = `${routeText},`; + } else { + insertPos = lastRouteLiteral.end; + route = `,${routeText}`; + } } - return insertAfterLastOccurrence( - routesArr.elements as unknown as ts.Node[], - route, - fileToAdd, - routesArr.elements.pos, - ts.SyntaxKind.ObjectLiteralExpression, - ); + return new InsertChange(fileToAdd, insertPos, route); } diff --git a/packages/schematics/angular/utility/ast-utils_spec.ts b/packages/schematics/angular/utility/ast-utils_spec.ts index 6a03de30e2fe..2ff1db8cb801 100644 --- a/packages/schematics/angular/utility/ast-utils_spec.ts +++ b/packages/schematics/angular/utility/ast-utils_spec.ts @@ -440,6 +440,40 @@ describe('ast utils', () => { ); }); + it('should add a route before the last wildcard path', () => { + const moduleContent = ` + import { BrowserModule } from '@angular/platform-browser'; + import { NgModule } from '@angular/core'; + import { AppComponent } from './app.component'; + const routes = [ + { path: '**', component: FooComponent } + ]; + @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( + /const routes = \[\r?\n?\s*{ path: 'bar', component: BarComponent },\r?\n?\s*{ path: '\*\*', component: FooComponent }\r?\n?\s*\]/, + ); + }); + it('should add a route to the routes to the correct array when having guards', () => { const moduleContent = ` import { BrowserModule } from '@angular/platform-browser';