Skip to content

Commit

Permalink
fix: resolve relative fetch urls against location (#499)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito authored Jan 25, 2024
1 parent df3500b commit f9193cd
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/interceptors/fetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { uuidv4 } from '../../utils/uuid'
import { toInteractiveRequest } from '../../utils/toInteractiveRequest'
import { emitAsync } from '../../utils/emitAsync'
import { isPropertyAccessible } from '../../utils/isPropertyAccessible'
import { canParseUrl } from '../../utils/canParseUrl'

export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
static symbol = Symbol('fetch')
Expand All @@ -32,7 +33,21 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {

globalThis.fetch = async (input, init) => {
const requestId = uuidv4()
const request = new Request(input, init)

/**
* @note Resolve potentially relative request URL
* against the present `location`. This is mainly
* for native `fetch` in JSDOM.
* @see https://github.com/mswjs/msw/issues/1625
*/
const resolvedInput =
typeof input === 'string' &&
typeof location !== 'undefined' &&
!canParseUrl(input)
? new URL(input, location.origin)
: input

const request = new Request(resolvedInput, init)

this.logger.info('[%s] %s', request.method, request.url)

Expand Down
13 changes: 13 additions & 0 deletions src/utils/canParseUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Returns a boolean indicating whether the given URL string
* can be parsed into a `URL` instance.
* A substitute for `URL.canParse()` for Node.js 18.
*/
export function canParseUrl(url: string): boolean {
try {
new URL(url)
return true
} catch (_error) {
return false
}
}
27 changes: 27 additions & 0 deletions test/modules/fetch/intercept/fetch-relative-url.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @vitest-environment jsdom
*/
import { it, expect, afterAll, beforeAll } from 'vitest'
import { FetchInterceptor } from '../../../../src/interceptors/fetch'

const interceptor = new FetchInterceptor()
interceptor.once('request', ({ request }) => {
if (request.url.endsWith('/numbers')) {
return request.respondWith(Response.json([1, 2, 3]))
}
})

beforeAll(() => {
interceptor.apply()
})

afterAll(() => {
interceptor.dispose()
})

it('intercepts a fetch request to a relative URL', async () => {
const response = await fetch('/numbers')

expect(response.status).toBe(200)
expect(await response.json()).toEqual([1, 2, 3])
})

0 comments on commit f9193cd

Please sign in to comment.