mswjs / interceptors

Low-level network interception library.
https://npm.im/@mswjs/interceptors
MIT License
527 stars 119 forks source link

XMLHttpRequestController creates bad URL when location exists but href not set #517

Closed jlissner closed 4 months ago

jlissner commented 4 months ago

https://github.com/mswjs/interceptors/blob/ac4f22b1319401d946746d5ca34f6f98846465f1/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts#L610

if location.href is an empty string, you get an "Invalid baseURL" error.

image

I believe this could easily be fixed by updating to return new URL(url.toString(), location.href || undefined)

kettanaito commented 4 months ago

Hi, @jlissner. Thanks for reporting this!

What would be the use case when the location object exists but doesn't have the href property set?

That sounds a lot like a broken environment then. In that case, the environment has to be fixed. The interceptor is correctly relying on the existing global location object, which must have the href property.

return new URL(url.toString(), location.href || undefined)

This won't work, sadly, because if url is relative and location.href is missing, like in your case, the URL constructor will throw anyway.

I will close this for now but would like to hear from you regarding my question above.

jlissner commented 4 months ago

For my example, it was a simple test of react component. The request was made to a fully qualified URL, so no base url had been set. I can try to set up a repo to reproduce, but it seems that you could repeat it fairly easily. The app was created with create-react-app, using axios to fetch the data (which if I set the adapter to http doesn't have this problem, but introduces other problems). Then, just create a simple test, having msw try to mock a response from say, http://example.com, and when you do const data = await axios({ url: 'http://example.com', method: 'GET' }); in your code, it will break.

kettanaito commented 4 months ago

I can try to set up a repo to reproduce

Please do! I'd be happy to iterate on this together once the reproduction is here. Thanks.

jlissner commented 4 months ago

In working to reproduce, I found where the root of the issue was coming from :)

We needed to mock some window location methods, such as described in articles like https://remarkablemark.org/blog/2018/11/17/mock-window-location/

So, we ended up with a piece of code in our setup file that looked like this:

Object.defineProperty(global, 'location', {
  value: {
    assign: jest.fn(),
    reload: jest.fn(),
    href: '', // this was the problem
  },
  writable: true,
});

I agree that this SHOULDN'T happen, and I will have to dig further to understand why it happened in the first place as no including it at all works just fine, but still took hours to understand the error being given: Invalid base URL, considering now base URL was given.