@@ -521,6 +521,103 @@ describe('extractRoutesAndCreateRouteTree', () => {
521521 { route : '/profile/*' , renderMode : RenderMode . Server } ,
522522 ] ) ;
523523 } ) ;
524+
525+ it ( 'should error when a parameter value is not a valid path segment' , async ( ) => {
526+ const invalidValues : [ path : string , value : string ] [ ] = [
527+ [ 'users/:id' , 'a/b' ] ,
528+ [ 'users/:id' , 'a%2Fb' ] ,
529+ [ 'users/:id' , '\\..\\evil.test' ] ,
530+ [ 'users/:id' , '%5Cevil.test' ] ,
531+ [ 'users/:id' , '%255Cevil.test' ] ,
532+ [ 'users/:id' , '50%-off' ] ,
533+ [ 'users/:id' , '.' ] ,
534+ [ 'users/:id' , '..' ] ,
535+ [ 'users/:id' , '..?' ] ,
536+ [ 'users/:id' , 'a#b' ] ,
537+ [ 'users/:id' , 'a;b' ] ,
538+ [ 'users/:id' , '*' ] ,
539+ [ 'users/:id' , ':id' ] ,
540+ [ 'users/:id' , '' ] ,
541+ [ 'docs/**' , '//evil.test' ] ,
542+ [ 'docs/**' , 'a/\t/b' ] ,
543+ ] ;
544+
545+ for ( const [ path , value ] of invalidValues ) {
546+ const paramName = path . endsWith ( '**' ) ? '**' : 'id' ;
547+ setAngularAppTestingManifest (
548+ [ { path, component : DummyComponent } ] ,
549+ [
550+ {
551+ path,
552+ renderMode : RenderMode . Prerender ,
553+ async getPrerenderParams ( ) {
554+ return [ { [ paramName ] : value } ] ;
555+ } ,
556+ } ,
557+ ] ,
558+ ) ;
559+
560+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree ( {
561+ url,
562+ invokeGetPrerenderParams : true ,
563+ } ) ;
564+ expect ( errors ) . toEqual ( [
565+ jasmine . stringContaining (
566+ `The 'getPrerenderParams' function defined for the '${ path } ' route ` +
567+ `returned an invalid value '${ value } ' for parameter '${ paramName } '.` ,
568+ ) ,
569+ ] ) ;
570+ expect ( routeTree . toObject ( ) ) . toEqual ( [ ] ) ;
571+ }
572+ } ) ;
573+
574+ it ( 'should not error when a parameter value contains characters allowed in a path segment' , async ( ) => {
575+ setAngularAppTestingManifest (
576+ [
577+ { path : 'user/:id' , component : DummyComponent } ,
578+ { path : 'docs/**' , component : DummyComponent } ,
579+ ] ,
580+ [
581+ {
582+ path : 'user/:id' ,
583+ renderMode : RenderMode . Prerender ,
584+ fallback : PrerenderFallback . None ,
585+ async getPrerenderParams ( ) {
586+ return [
587+ { id : "customer's-choice" } ,
588+ { id : 'café' } ,
589+ { id : 'a b' } ,
590+ { id : 'a%20c' } ,
591+ { id : 'a:b' } ,
592+ ] ;
593+ } ,
594+ } ,
595+ {
596+ path : 'docs/**' ,
597+ renderMode : RenderMode . Prerender ,
598+ fallback : PrerenderFallback . None ,
599+ async getPrerenderParams ( ) {
600+ return [ { '**' : '' } , { '**' : 'a/b' } ] ;
601+ } ,
602+ } ,
603+ ] ,
604+ ) ;
605+
606+ const { routeTree, errors } = await extractRoutesAndCreateRouteTree ( {
607+ url,
608+ invokeGetPrerenderParams : true ,
609+ } ) ;
610+ expect ( errors ) . toHaveSize ( 0 ) ;
611+ expect ( routeTree . toObject ( ) ) . toEqual ( [
612+ { route : "/user/customer's-choice" , renderMode : RenderMode . Prerender } ,
613+ { route : '/user/café' , renderMode : RenderMode . Prerender } ,
614+ { route : '/user/a b' , renderMode : RenderMode . Prerender } ,
615+ { route : '/user/a c' , renderMode : RenderMode . Prerender } ,
616+ { route : '/user/a:b' , renderMode : RenderMode . Prerender } ,
617+ { route : '/docs' , renderMode : RenderMode . Prerender } ,
618+ { route : '/docs/a/b' , renderMode : RenderMode . Prerender } ,
619+ ] ) ;
620+ } ) ;
524621 } ) ;
525622
526623 it ( 'should extract routes with a route level matcher' , async ( ) => {
0 commit comments