@@ -498,4 +498,382 @@ describe('routeUtils', () => {
498498 expect ( ( ) => processRoutes ( { router : doubleSlashRouter } ) ) . not . toThrow ( ) ;
499499 } ) ;
500500 } ) ;
501+
502+ describe ( 'processRoutes with hashRoute' , ( ) => {
503+ it ( 'should create a hash history when hashRoute is true' , ( ) => {
504+ const routes = createNestedRoutes ( ) ;
505+ const router = createRouter ( {
506+ history : createWebHistory ( ) ,
507+ routes,
508+ } ) ;
509+
510+ const result = processRoutes ( {
511+ router,
512+ hashRoute : true ,
513+ } ) ;
514+
515+ expect ( result . history ) . toBeDefined ( ) ;
516+ // Hash history base includes the '#' prefix
517+ expect ( result . history . base ) . toBe ( '/#' ) ;
518+ } ) ;
519+
520+ it ( 'should prefix routes with basename when hashRoute is true and basename is provided' , ( ) => {
521+ const routes = createNestedRoutes ( ) ;
522+ const router = createRouter ( {
523+ history : createWebHistory ( ) ,
524+ routes,
525+ } ) ;
526+
527+ const result = processRoutes ( {
528+ router,
529+ basename : '/app' ,
530+ hashRoute : true ,
531+ } ) ;
532+
533+ expect ( result . history ) . toBeDefined ( ) ;
534+ expect ( result . routes . length ) . toBeGreaterThan ( 0 ) ;
535+
536+ // Top-level routes should be prefixed with basename
537+ // Home route path '/' + basename '/app' normalizes to '/app'
538+ const homeRoute = result . routes . find ( ( r ) => r . name === 'Home' ) ;
539+ expect ( homeRoute ?. path ) . toBe ( '/app' ) ;
540+
541+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
542+ // Paths are joined with '/' and normalized (no double slashes)
543+ expect ( dashboardRoute ?. path ) . toBe ( '/app/dashboard' ) ;
544+ } ) ;
545+
546+ it ( 'should prefix nested children with basename when hashRoute is true' , ( ) => {
547+ const routes = createNestedRoutes ( ) ;
548+ const router = createRouter ( {
549+ history : createWebHistory ( ) ,
550+ routes,
551+ } ) ;
552+
553+ const result = processRoutes ( {
554+ router,
555+ basename : '/app' ,
556+ hashRoute : true ,
557+ } ) ;
558+
559+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
560+ expect ( dashboardRoute ) . toBeDefined ( ) ;
561+
562+ if ( dashboardRoute ?. children ) {
563+ const profileRoute = dashboardRoute . children . find (
564+ ( child ) => child . name === 'Profile' ,
565+ ) ;
566+ // Paths are now properly joined with '/' separator
567+ expect ( profileRoute ?. path ) . toBe ( '/app/profile' ) ;
568+
569+ const settingsRoute = dashboardRoute . children . find (
570+ ( child ) => child . name === 'Settings' ,
571+ ) ;
572+ expect ( settingsRoute ?. path ) . toBe ( '/app/settings' ) ;
573+
574+ if ( settingsRoute ?. children ) {
575+ const accountRoute = settingsRoute . children . find (
576+ ( child ) => child . name === 'Account' ,
577+ ) ;
578+ expect ( accountRoute ?. path ) . toBe ( '/app/account' ) ;
579+ }
580+ }
581+ } ) ;
582+
583+ it ( 'should not prefix routes when hashRoute is true but no basename' , ( ) => {
584+ const routes = createNestedRoutes ( ) ;
585+ const router = createRouter ( {
586+ history : createWebHistory ( ) ,
587+ routes,
588+ } ) ;
589+
590+ const result = processRoutes ( {
591+ router,
592+ hashRoute : true ,
593+ } ) ;
594+
595+ const homeRoute = result . routes . find ( ( r ) => r . name === 'Home' ) ;
596+ expect ( homeRoute ?. path ) . toBe ( '/' ) ;
597+
598+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
599+ expect ( dashboardRoute ?. path ) . toBe ( '/dashboard' ) ;
600+ } ) ;
601+
602+ it ( 'should prefer memoryRoute over hashRoute when both are set' , ( ) => {
603+ const routes = createNestedRoutes ( ) ;
604+ const router = createRouter ( {
605+ history : createWebHistory ( ) ,
606+ routes,
607+ } ) ;
608+
609+ const result = processRoutes ( {
610+ router,
611+ basename : '/app' ,
612+ memoryRoute : true ,
613+ hashRoute : true ,
614+ } ) ;
615+
616+ // memoryRoute takes priority (checked first in processRoutes)
617+ // Memory history uses basename as the base
618+ expect ( result . history . base ) . toBe ( '/app' ) ;
619+ } ) ;
620+
621+ it ( 'should preserve trailing slashes in paths when prefixing with basename' , ( ) => {
622+ const trailingSlashRoutes = [
623+ {
624+ path : '/dashboard/' ,
625+ name : 'Dashboard' ,
626+ component : { template : '<div>Dashboard</div>' } ,
627+ } ,
628+ {
629+ path : '/settings' ,
630+ name : 'Settings' ,
631+ component : { template : '<div>Settings</div>' } ,
632+ } ,
633+ ] ;
634+
635+ const router = createRouter ( {
636+ history : createWebHistory ( ) ,
637+ routes : trailingSlashRoutes ,
638+ } ) ;
639+
640+ const result = processRoutes ( {
641+ router,
642+ basename : '/app' ,
643+ hashRoute : true ,
644+ } ) ;
645+
646+ // Trailing slash should be preserved for /dashboard/
647+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
648+ expect ( dashboardRoute ?. path ) . toBe ( '/app/dashboard/' ) ;
649+
650+ // No trailing slash should remain absent for /settings
651+ const settingsRoute = result . routes . find ( ( r ) => r . name === 'Settings' ) ;
652+ expect ( settingsRoute ?. path ) . toBe ( '/app/settings' ) ;
653+ } ) ;
654+
655+ it ( 'should preserve trailing slashes in string redirects' , ( ) => {
656+ const redirectRoutes = [
657+ {
658+ path : '/' ,
659+ redirect : '/dashboard/' ,
660+ } ,
661+ {
662+ path : '/dashboard/' ,
663+ name : 'Dashboard' ,
664+ component : { template : '<div>Dashboard</div>' } ,
665+ } ,
666+ ] ;
667+
668+ const router = createRouter ( {
669+ history : createWebHistory ( ) ,
670+ routes : redirectRoutes ,
671+ } ) ;
672+
673+ const result = processRoutes ( {
674+ router,
675+ basename : '/app' ,
676+ hashRoute : true ,
677+ } ) ;
678+
679+ const rootRoute = result . routes . find ( ( r ) => r . path === '/app' ) ;
680+ expect ( rootRoute ?. redirect ) . toBe ( '/app/dashboard/' ) ;
681+ } ) ;
682+ } ) ;
683+
684+ describe ( 'processRoutes with memoryRoute' , ( ) => {
685+ it ( 'should create a memory history when memoryRoute is true' , ( ) => {
686+ const routes = createNestedRoutes ( ) ;
687+ const router = createRouter ( {
688+ history : createWebHistory ( ) ,
689+ routes,
690+ } ) ;
691+
692+ const result = processRoutes ( {
693+ router,
694+ memoryRoute : true ,
695+ } ) ;
696+
697+ expect ( result . history ) . toBeDefined ( ) ;
698+ expect ( result . routes . length ) . toBeGreaterThan ( 0 ) ;
699+ } ) ;
700+
701+ it ( 'should pass basename to memory history' , ( ) => {
702+ const routes = createNestedRoutes ( ) ;
703+ const router = createRouter ( {
704+ history : createWebHistory ( ) ,
705+ routes,
706+ } ) ;
707+
708+ const result = processRoutes ( {
709+ router,
710+ basename : '/app' ,
711+ memoryRoute : true ,
712+ } ) ;
713+
714+ expect ( result . history ) . toBeDefined ( ) ;
715+ expect ( result . history . base ) . toBe ( '/app' ) ;
716+ } ) ;
717+
718+ it ( 'should not prefix route paths when using memoryRoute' , ( ) => {
719+ const routes = createNestedRoutes ( ) ;
720+ const router = createRouter ( {
721+ history : createWebHistory ( ) ,
722+ routes,
723+ } ) ;
724+
725+ const result = processRoutes ( {
726+ router,
727+ basename : '/app' ,
728+ memoryRoute : true ,
729+ } ) ;
730+
731+ // Unlike hashRoute, memoryRoute does NOT prefix routes — it passes basename to createMemoryHistory
732+ const homeRoute = result . routes . find ( ( r ) => r . name === 'Home' ) ;
733+ expect ( homeRoute ?. path ) . toBe ( '/' ) ;
734+
735+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
736+ expect ( dashboardRoute ?. path ) . toBe ( '/dashboard' ) ;
737+ } ) ;
738+ } ) ;
739+
740+ describe ( 'processRoutes default (web history)' , ( ) => {
741+ it ( 'should create web history with basename by default' , ( ) => {
742+ const routes = createNestedRoutes ( ) ;
743+ const router = createRouter ( {
744+ history : createWebHistory ( ) ,
745+ routes,
746+ } ) ;
747+
748+ const result = processRoutes ( {
749+ router,
750+ basename : '/app' ,
751+ } ) ;
752+
753+ expect ( result . history ) . toBeDefined ( ) ;
754+ expect ( result . history . base ) . toBe ( '/app' ) ;
755+ } ) ;
756+
757+ it ( 'should not prefix route paths in default mode' , ( ) => {
758+ const routes = createNestedRoutes ( ) ;
759+ const router = createRouter ( {
760+ history : createWebHistory ( ) ,
761+ routes,
762+ } ) ;
763+
764+ const result = processRoutes ( {
765+ router,
766+ basename : '/app' ,
767+ } ) ;
768+
769+ const homeRoute = result . routes . find ( ( r ) => r . name === 'Home' ) ;
770+ expect ( homeRoute ?. path ) . toBe ( '/' ) ;
771+
772+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
773+ expect ( dashboardRoute ?. path ) . toBe ( '/dashboard' ) ;
774+ } ) ;
775+ } ) ;
776+
777+ describe ( 'processRoutes hashRoute with redirects' , ( ) => {
778+ it ( 'should prefix string redirects with basename' , ( ) => {
779+ const redirectRoutes = [
780+ {
781+ path : '/' ,
782+ redirect : '/dashboard' ,
783+ } ,
784+ {
785+ path : '/dashboard' ,
786+ name : 'Dashboard' ,
787+ component : { template : '<div>Dashboard</div>' } ,
788+ } ,
789+ {
790+ path : '/about' ,
791+ name : 'About' ,
792+ component : { template : '<div>About</div>' } ,
793+ } ,
794+ ] ;
795+
796+ const router = createRouter ( {
797+ history : createWebHistory ( ) ,
798+ routes : redirectRoutes ,
799+ } ) ;
800+
801+ const result = processRoutes ( {
802+ router,
803+ basename : '/barber' ,
804+ hashRoute : true ,
805+ } ) ;
806+
807+ // The redirect route should have its redirect target prefixed
808+ const rootRoute = result . routes . find ( ( r ) => r . path === '/barber' ) ;
809+ expect ( rootRoute ) . toBeDefined ( ) ;
810+ expect ( rootRoute ?. redirect ) . toBe ( '/barber/dashboard' ) ;
811+
812+ // Other routes should be prefixed normally
813+ const dashboardRoute = result . routes . find ( ( r ) => r . name === 'Dashboard' ) ;
814+ expect ( dashboardRoute ?. path ) . toBe ( '/barber/dashboard' ) ;
815+
816+ const aboutRoute = result . routes . find ( ( r ) => r . name === 'About' ) ;
817+ expect ( aboutRoute ?. path ) . toBe ( '/barber/about' ) ;
818+ } ) ;
819+
820+ it ( 'should prefix object redirects with path property' , ( ) => {
821+ const redirectRoutes = [
822+ {
823+ path : '/' ,
824+ redirect : { path : '/dashboard' } ,
825+ } ,
826+ {
827+ path : '/dashboard' ,
828+ name : 'Dashboard' ,
829+ component : { template : '<div>Dashboard</div>' } ,
830+ } ,
831+ ] ;
832+
833+ const router = createRouter ( {
834+ history : createWebHistory ( ) ,
835+ routes : redirectRoutes ,
836+ } ) ;
837+
838+ const result = processRoutes ( {
839+ router,
840+ basename : '/app' ,
841+ hashRoute : true ,
842+ } ) ;
843+
844+ const rootRoute = result . routes . find ( ( r ) => r . path === '/app' ) ;
845+ expect ( rootRoute ) . toBeDefined ( ) ;
846+ expect ( rootRoute ?. redirect ) . toEqual ( { path : '/app/dashboard' } ) ;
847+ } ) ;
848+
849+ it ( 'should not modify named redirects (no path property)' , ( ) => {
850+ const redirectRoutes = [
851+ {
852+ path : '/' ,
853+ redirect : { name : 'Dashboard' } ,
854+ } ,
855+ {
856+ path : '/dashboard' ,
857+ name : 'Dashboard' ,
858+ component : { template : '<div>Dashboard</div>' } ,
859+ } ,
860+ ] ;
861+
862+ const router = createRouter ( {
863+ history : createWebHistory ( ) ,
864+ routes : redirectRoutes ,
865+ } ) ;
866+
867+ const result = processRoutes ( {
868+ router,
869+ basename : '/app' ,
870+ hashRoute : true ,
871+ } ) ;
872+
873+ const rootRoute = result . routes . find ( ( r ) => r . path === '/app' ) ;
874+ expect ( rootRoute ) . toBeDefined ( ) ;
875+ // Named redirects should be untouched — Vue Router resolves by name, not path
876+ expect ( rootRoute ?. redirect ) . toEqual ( { name : 'Dashboard' } ) ;
877+ } ) ;
878+ } ) ;
501879} ) ;
0 commit comments