11import { jest , describe , it , beforeEach , expect } from '@jest/globals' ;
22import { h , render } from 'preact' ;
33import { html } from 'htm/preact' ;
4- import { LocationProvider , Router , useLocation } from '../router.js' ;
4+ import { LocationProvider , Router , useLocation , Route , useRoute } from '../router.js' ;
55import lazy , { ErrorBoundary } from '../lazy.js' ;
66
77Object . defineProperty ( window , 'scrollTo' , { value ( ) { } } ) ;
@@ -47,7 +47,7 @@ describe('Router', () => {
4747 ) ;
4848
4949 expect ( scratch ) . toHaveProperty ( 'textContent' , 'Home' ) ;
50- expect ( Home ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } } , expect . anything ( ) ) ;
50+ expect ( Home ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
5151 expect ( Profiles ) . not . toHaveBeenCalled ( ) ;
5252 expect ( Profile ) . not . toHaveBeenCalled ( ) ;
5353 expect ( Fallback ) . not . toHaveBeenCalled ( ) ;
@@ -64,7 +64,7 @@ describe('Router', () => {
6464
6565 expect ( scratch ) . toHaveProperty ( 'textContent' , 'Profiles' ) ;
6666 expect ( Home ) . not . toHaveBeenCalled ( ) ;
67- expect ( Profiles ) . toHaveBeenCalledWith ( { path : '/profiles' , query : { } , params : { } } , expect . anything ( ) ) ;
67+ expect ( Profiles ) . toHaveBeenCalledWith ( { path : '/profiles' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
6868 expect ( Profile ) . not . toHaveBeenCalled ( ) ;
6969 expect ( Fallback ) . not . toHaveBeenCalled ( ) ;
7070
@@ -82,7 +82,7 @@ describe('Router', () => {
8282 expect ( Home ) . not . toHaveBeenCalled ( ) ;
8383 expect ( Profiles ) . not . toHaveBeenCalled ( ) ;
8484 expect ( Profile ) . toHaveBeenCalledWith (
85- { path : '/profiles/bob' , query : { } , params : { id : 'bob' } , id : 'bob' } ,
85+ { path : '/profiles/bob' , query : { } , params : { id : 'bob' } , id : 'bob' , rest : '' } ,
8686 expect . anything ( )
8787 ) ;
8888 expect ( Fallback ) . not . toHaveBeenCalled ( ) ;
@@ -102,7 +102,7 @@ describe('Router', () => {
102102 expect ( Profiles ) . not . toHaveBeenCalled ( ) ;
103103 expect ( Profile ) . not . toHaveBeenCalled ( ) ;
104104 expect ( Fallback ) . toHaveBeenCalledWith (
105- { default : true , path : '/other' , query : { a : 'b' , c : 'd' } , params : { } } ,
105+ { default : true , path : '/other' , query : { a : 'b' , c : 'd' } , params : { } , rest : '' } ,
106106 expect . anything ( )
107107 ) ;
108108
@@ -141,13 +141,13 @@ describe('Router', () => {
141141 ) ;
142142
143143 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '' ) ;
144- expect ( A ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } } , expect . anything ( ) ) ;
144+ expect ( A ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
145145
146146 A . mockClear ( ) ;
147147 await sleep ( 10 ) ;
148148
149149 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>A</h1><p>hello</p>' ) ;
150- expect ( A ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } } , expect . anything ( ) ) ;
150+ expect ( A ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
151151
152152 A . mockClear ( ) ;
153153 loc . route ( '/b' ) ;
@@ -160,14 +160,14 @@ describe('Router', () => {
160160 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>A</h1><p>hello</p>' ) ;
161161 // We should never re-invoke <A /> while loading <B /> (that would be a remount of the old route):
162162 expect ( A ) . not . toHaveBeenCalled ( ) ;
163- expect ( B ) . toHaveBeenCalledWith ( { path : '/b' , query : { } , params : { } } , expect . anything ( ) ) ;
163+ expect ( B ) . toHaveBeenCalledWith ( { path : '/b' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
164164
165165 B . mockClear ( ) ;
166166 await sleep ( 10 ) ;
167167
168168 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>B</h1><p>hello</p>' ) ;
169169 expect ( A ) . not . toHaveBeenCalled ( ) ;
170- expect ( B ) . toHaveBeenCalledWith ( { path : '/b' , query : { } , params : { } } , expect . anything ( ) ) ;
170+ expect ( B ) . toHaveBeenCalledWith ( { path : '/b' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
171171
172172 B . mockClear ( ) ;
173173 loc . route ( '/c' ) ;
@@ -186,14 +186,14 @@ describe('Router', () => {
186186 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>B</h1><p>hello</p>' ) ;
187187 // We should never re-invoke <A /> while loading <B /> (that would be a remount of the old route):
188188 expect ( B ) . not . toHaveBeenCalled ( ) ;
189- expect ( C ) . toHaveBeenCalledWith ( { path : '/c' , query : { } , params : { } } , expect . anything ( ) ) ;
189+ expect ( C ) . toHaveBeenCalledWith ( { path : '/c' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
190190
191191 C . mockClear ( ) ;
192192 await sleep ( 10 ) ;
193193
194194 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>C</h1>' ) ;
195195 expect ( B ) . not . toHaveBeenCalled ( ) ;
196- expect ( C ) . toHaveBeenCalledWith ( { path : '/c' , query : { } , params : { } } , expect . anything ( ) ) ;
196+ expect ( C ) . toHaveBeenCalledWith ( { path : '/c' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
197197
198198 // "instant" routing to already-loaded routes
199199
@@ -205,7 +205,7 @@ describe('Router', () => {
205205 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>B</h1><p>hello</p>' ) ;
206206 expect ( C ) . not . toHaveBeenCalled ( ) ;
207207 // expect(B).toHaveBeenCalledTimes(1);
208- expect ( B ) . toHaveBeenCalledWith ( { path : '/b' , query : { } , params : { } } , expect . anything ( ) ) ;
208+ expect ( B ) . toHaveBeenCalledWith ( { path : '/b' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
209209
210210 B . mockClear ( ) ;
211211 loc . route ( '/' ) ;
@@ -214,7 +214,7 @@ describe('Router', () => {
214214 expect ( scratch ) . toHaveProperty ( 'innerHTML' , '<h1>A</h1><p>hello</p>' ) ;
215215 expect ( B ) . not . toHaveBeenCalled ( ) ;
216216 // expect(A).toHaveBeenCalledTimes(1);
217- expect ( A ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } } , expect . anything ( ) ) ;
217+ expect ( A ) . toHaveBeenCalledWith ( { path : '/' , query : { } , params : { } , rest : '' } , expect . anything ( ) ) ;
218218 } ) ;
219219
220220 describe ( 'intercepted VS external links' , ( ) => {
@@ -436,4 +436,66 @@ describe('Router', () => {
436436
437437 pushState . mockRestore ( ) ;
438438 } ) ;
439+
440+ it ( 'should match nested routes' , async ( ) => {
441+ let route ;
442+ const Inner = ( ) => html `
443+ < ${ Router } >
444+ < ${ Route }
445+ path="/bob"
446+ component=${ ( ) => {
447+ route = useRoute ( ) ;
448+ return null ;
449+ } }
450+ />
451+ </ />
452+ ` ;
453+
454+ render (
455+ html `
456+ < ${ LocationProvider } >
457+ < ${ Router } >
458+ < ${ Route } path="/foo/:id/*" component=${ Inner } />
459+ </ />
460+ < a href="/foo/bar/bob"> </ a>
461+ </ />
462+ ` ,
463+ scratch
464+ ) ;
465+
466+ scratch . querySelector ( 'a[href="/foo/bar/bob"]' ) . click ( ) ;
467+ await sleep ( 20 ) ;
468+ expect ( route ) . toMatchObject ( { path : '/bob' , params : { id : 'bar' } } ) ;
469+ } ) ;
470+
471+ it ( 'should append params in nested routes' , async ( ) => {
472+ let params ;
473+ const Inner = ( ) => html `
474+ < ${ Router } >
475+ < ${ Route }
476+ path="/bob"
477+ component=${ ( ) => {
478+ params = useRoute ( ) . params ;
479+ return null ;
480+ } }
481+ />
482+ </ />
483+ ` ;
484+
485+ render (
486+ html `
487+ < ${ LocationProvider } >
488+ < ${ Router } >
489+ < ${ Route } path="/foo/:id/*" component=${ Inner } />
490+ </ />
491+ < a href="/foo/bar/bob"> </ a>
492+ </ />
493+ ` ,
494+ scratch
495+ ) ;
496+
497+ scratch . querySelector ( 'a[href="/foo/bar/bob"]' ) . click ( ) ;
498+ await sleep ( 20 ) ;
499+ expect ( params ) . toMatchObject ( { id : 'bar' } ) ;
500+ } ) ;
439501} ) ;
0 commit comments