@@ -121,4 +121,49 @@ describe('instrument > addFetchInstrumentationHandler', () => {
121121
122122 expect ( error . message ) . toBe ( 'Failed to fetch (example.com)' ) ;
123123 } ) ;
124+
125+ describe ( 'relative URLs' , ( ) => {
126+ const globalWithLocation = GLOBAL_OBJ as typeof GLOBAL_OBJ & { location ?: { origin : string } } ;
127+
128+ afterEach ( ( ) => {
129+ Reflect . deleteProperty ( globalWithLocation , 'location' ) ;
130+ } ) ;
131+
132+ async function failWith ( target : string ) : Promise < TypeError > {
133+ const error = new TypeError ( 'Failed to fetch' ) ;
134+ globalThis . fetch = vi . fn < typeof fetch > ( ) . mockRejectedValue ( error ) ;
135+ addFetchInstrumentationHandler ( ( ) => undefined ) ;
136+ await expect ( globalThis . fetch ( target ) ) . rejects . toBe ( error ) ;
137+ return error ;
138+ }
139+
140+ it ( 'resolves a relative URL against the current origin' , async ( ) => {
141+ globalWithLocation . location = { origin : 'https://app.example.com/some/page?x=1' } ;
142+ expect ( ( await failWith ( '/api/users' ) ) . message ) . toBe ( 'Failed to fetch (app.example.com)' ) ;
143+ } ) ;
144+
145+ it ( 'resolves an empty URL (`fetch("")`) against the current page' , async ( ) => {
146+ globalWithLocation . location = { origin : 'https://app.example.com/some/page?x=1' } ;
147+ expect ( ( await failWith ( '' ) ) . message ) . toBe ( 'Failed to fetch (app.example.com)' ) ;
148+ } ) ;
149+
150+ it ( 'does not change the message for a relative URL if there is no current page' , async ( ) => {
151+ expect ( ( await failWith ( '/api/users' ) ) . message ) . toBe ( 'Failed to fetch' ) ;
152+ } ) ;
153+
154+ it ( 'does not append an empty host (e.g. pages served from file://)' , async ( ) => {
155+ globalWithLocation . location = { origin : 'file:///C:/app/index.html' } ;
156+ expect ( ( await failWith ( '/api/users' ) ) . message ) . toBe ( 'Failed to fetch' ) ;
157+ } ) ;
158+
159+ it ( 'does not change the message if the origin is opaque ("null")' , async ( ) => {
160+ globalWithLocation . location = { origin : 'null' } ;
161+ expect ( ( await failWith ( '/api/users' ) ) . message ) . toBe ( 'Failed to fetch' ) ;
162+ } ) ;
163+
164+ it ( 'still uses the host of an absolute URL, ignoring the current page' , async ( ) => {
165+ globalWithLocation . location = { origin : 'https://app.example.com/some/page' } ;
166+ expect ( ( await failWith ( 'https://other.example.org/x' ) ) . message ) . toBe ( 'Failed to fetch (other.example.org)' ) ;
167+ } ) ;
168+ } ) ;
124169} ) ;
0 commit comments