11import { describe , expect , it } from 'vitest' ;
22import type { RouteManifest } from '../../../src/config/manifest/types' ;
3- import type { SentryBuildOptions } from '../../../src/config/types' ;
4-
5- type RouteManifestInjectionOptions = Exclude < SentryBuildOptions [ 'routeManifestInjection' ] , false | undefined > ;
6- type ExcludeFilter = RouteManifestInjectionOptions [ 'exclude' ] ;
7-
8- // Inline the filtering logic for unit testing
9- // This mirrors what maybeCreateRouteManifest does internally
10- function filterManifest ( manifest : RouteManifest , excludeFilter : ExcludeFilter ) : RouteManifest {
11- if ( ! excludeFilter ) {
12- return manifest ;
13- }
14-
15- const shouldExclude = ( route : string ) : boolean => {
16- if ( typeof excludeFilter === 'function' ) {
17- return excludeFilter ( route ) ;
18- }
19-
20- return excludeFilter . some ( ( pattern : string | RegExp ) => {
21- if ( typeof pattern === 'string' ) {
22- return route === pattern ;
23- }
24- return pattern . test ( route ) ;
25- } ) ;
26- } ;
27-
28- return {
29- staticRoutes : manifest . staticRoutes . filter ( r => ! shouldExclude ( r . path ) ) ,
30- dynamicRoutes : manifest . dynamicRoutes . filter ( r => ! shouldExclude ( r . path ) ) ,
31- isrRoutes : manifest . isrRoutes . filter ( r => ! shouldExclude ( r ) ) ,
32- } ;
33- }
3+ import { filterRouteManifest } from '../../../src/config/withSentryConfig/getFinalConfigObjectUtils' ;
344
355describe ( 'routeManifestInjection.exclude' , ( ) => {
366 const mockManifest : RouteManifest = {
@@ -52,14 +22,14 @@ describe('routeManifestInjection.exclude', () => {
5222
5323 describe ( 'with no filter' , ( ) => {
5424 it ( 'should return manifest unchanged' , ( ) => {
55- const result = filterManifest ( mockManifest , undefined ) ;
25+ const result = filterRouteManifest ( mockManifest , undefined ) ;
5626 expect ( result ) . toEqual ( mockManifest ) ;
5727 } ) ;
5828 } ) ;
5929
6030 describe ( 'with string patterns' , ( ) => {
6131 it ( 'should exclude exact string matches' , ( ) => {
62- const result = filterManifest ( mockManifest , [ '/admin' ] ) ;
32+ const result = filterRouteManifest ( mockManifest , [ '/admin' ] ) ;
6333
6434 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [
6535 '/' ,
@@ -71,7 +41,7 @@ describe('routeManifestInjection.exclude', () => {
7141 } ) ;
7242
7343 it ( 'should exclude multiple exact matches' , ( ) => {
74- const result = filterManifest ( mockManifest , [ '/admin' , '/about' , '/blog' ] ) ;
44+ const result = filterRouteManifest ( mockManifest , [ '/admin' , '/about' , '/blog' ] ) ;
7545
7646 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [
7747 '/' ,
@@ -85,22 +55,22 @@ describe('routeManifestInjection.exclude', () => {
8555
8656 describe ( 'with regex patterns' , ( ) => {
8757 it ( 'should exclude routes matching regex' , ( ) => {
88- const result = filterManifest ( mockManifest , [ / ^ \/ a d m i n / ] ) ;
58+ const result = filterRouteManifest ( mockManifest , [ / ^ \/ a d m i n / ] ) ;
8959
9060 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [ '/' , '/about' , '/internal/secret' , '/public/page' ] ) ;
9161 expect ( result . dynamicRoutes . map ( r => r . path ) ) . toEqual ( [ '/users/:id' , '/secret-feature/:id' ] ) ;
9262 expect ( result . isrRoutes ) . toEqual ( [ '/blog' , '/internal/stats' ] ) ;
9363 } ) ;
9464
9565 it ( 'should support multiple regex patterns' , ( ) => {
96- const result = filterManifest ( mockManifest , [ / ^ \/ a d m i n / , / ^ \/ i n t e r n a l / ] ) ;
66+ const result = filterRouteManifest ( mockManifest , [ / ^ \/ a d m i n / , / ^ \/ i n t e r n a l / ] ) ;
9767
9868 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [ '/' , '/about' , '/public/page' ] ) ;
9969 expect ( result . isrRoutes ) . toEqual ( [ '/blog' ] ) ;
10070 } ) ;
10171
10272 it ( 'should support partial regex matches' , ( ) => {
103- const result = filterManifest ( mockManifest , [ / s e c r e t / ] ) ;
73+ const result = filterRouteManifest ( mockManifest , [ / s e c r e t / ] ) ;
10474
10575 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [
10676 '/' ,
@@ -111,27 +81,45 @@ describe('routeManifestInjection.exclude', () => {
11181 ] ) ;
11282 expect ( result . dynamicRoutes . map ( r => r . path ) ) . toEqual ( [ '/users/:id' , '/admin/users/:id' ] ) ;
11383 } ) ;
84+
85+ it ( 'should handle regex with global flag consistently across multiple routes' , ( ) => {
86+ // Regex with `g` flag has stateful lastIndex - ensure it works correctly
87+ const globalRegex = / a d m i n / g;
88+ const result = filterRouteManifest ( mockManifest , [ globalRegex ] ) ;
89+
90+ // All admin routes should be excluded, not just every other one
91+ expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [ '/' , '/about' , '/internal/secret' , '/public/page' ] ) ;
92+ expect ( result . dynamicRoutes . map ( r => r . path ) ) . toEqual ( [ '/users/:id' , '/secret-feature/:id' ] ) ;
93+ expect ( result . isrRoutes ) . toEqual ( [ '/blog' , '/internal/stats' ] ) ;
94+ } ) ;
95+
96+ it ( 'should handle regex with global and case-insensitive flags' , ( ) => {
97+ const result = filterRouteManifest ( mockManifest , [ / A D M I N / gi] ) ;
98+
99+ expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [ '/' , '/about' , '/internal/secret' , '/public/page' ] ) ;
100+ expect ( result . dynamicRoutes . map ( r => r . path ) ) . toEqual ( [ '/users/:id' , '/secret-feature/:id' ] ) ;
101+ } ) ;
114102 } ) ;
115103
116104 describe ( 'with mixed patterns' , ( ) => {
117105 it ( 'should support both strings and regex' , ( ) => {
118- const result = filterManifest ( mockManifest , [ '/about' , / ^ \/ a d m i n / ] ) ;
106+ const result = filterRouteManifest ( mockManifest , [ '/about' , / ^ \/ a d m i n / ] ) ;
119107
120108 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [ '/' , '/internal/secret' , '/public/page' ] ) ;
121109 } ) ;
122110 } ) ;
123111
124112 describe ( 'with function filter' , ( ) => {
125113 it ( 'should exclude routes where function returns true' , ( ) => {
126- const result = filterManifest ( mockManifest , ( route : string ) => route . includes ( 'admin' ) ) ;
114+ const result = filterRouteManifest ( mockManifest , ( route : string ) => route . includes ( 'admin' ) ) ;
127115
128116 expect ( result . staticRoutes . map ( r => r . path ) ) . toEqual ( [ '/' , '/about' , '/internal/secret' , '/public/page' ] ) ;
129117 expect ( result . dynamicRoutes . map ( r => r . path ) ) . toEqual ( [ '/users/:id' , '/secret-feature/:id' ] ) ;
130118 expect ( result . isrRoutes ) . toEqual ( [ '/blog' , '/internal/stats' ] ) ;
131119 } ) ;
132120
133121 it ( 'should support complex filter logic' , ( ) => {
134- const result = filterManifest ( mockManifest , ( route : string ) => {
122+ const result = filterRouteManifest ( mockManifest , ( route : string ) => {
135123 // Exclude anything with "secret" or "internal" or admin routes
136124 return route . includes ( 'secret' ) || route . includes ( 'internal' ) || route . startsWith ( '/admin' ) ;
137125 } ) ;
@@ -150,25 +138,25 @@ describe('routeManifestInjection.exclude', () => {
150138 isrRoutes : [ ] ,
151139 } ;
152140
153- const result = filterManifest ( emptyManifest , [ / a d m i n / ] ) ;
141+ const result = filterRouteManifest ( emptyManifest , [ / a d m i n / ] ) ;
154142 expect ( result ) . toEqual ( emptyManifest ) ;
155143 } ) ;
156144
157145 it ( 'should handle filter that excludes everything' , ( ) => {
158- const result = filterManifest ( mockManifest , ( ) => true ) ;
146+ const result = filterRouteManifest ( mockManifest , ( ) => true ) ;
159147
160148 expect ( result . staticRoutes ) . toEqual ( [ ] ) ;
161149 expect ( result . dynamicRoutes ) . toEqual ( [ ] ) ;
162150 expect ( result . isrRoutes ) . toEqual ( [ ] ) ;
163151 } ) ;
164152
165153 it ( 'should handle filter that excludes nothing' , ( ) => {
166- const result = filterManifest ( mockManifest , ( ) => false ) ;
154+ const result = filterRouteManifest ( mockManifest , ( ) => false ) ;
167155 expect ( result ) . toEqual ( mockManifest ) ;
168156 } ) ;
169157
170158 it ( 'should handle empty filter array' , ( ) => {
171- const result = filterManifest ( mockManifest , [ ] ) ;
159+ const result = filterRouteManifest ( mockManifest , [ ] ) ;
172160 expect ( result ) . toEqual ( mockManifest ) ;
173161 } ) ;
174162 } ) ;
0 commit comments