Skip to content

Commit

Permalink
fix(fetch): await response listener before resolving the response pro…
Browse files Browse the repository at this point in the history
…mise (#658)

Co-authored-by: Artem Zakharchenko <[email protected]>
  • Loading branch information
Michael Solomon and kettanaito authored Oct 7, 2024
1 parent 343cc5a commit 261f581
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/interceptors/fetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,15 @@ export class FetchInterceptor extends Interceptor<HttpRequestEventMap> {
'no mocked response received, performing request as-is...'
)

return pureFetch(request).then((response) => {
return pureFetch(request).then(async (response) => {
this.logger.info('original fetch performed', response)

if (this.emitter.listenerCount('response') > 0) {
this.logger.info('emitting the "response" event...')

const responseClone = response.clone()

this.emitter.emit('response', {
await emitAsync(this.emitter, 'response', {
response: responseClone,
isMockedResponse: false,
request,
Expand Down
68 changes: 68 additions & 0 deletions test/modules/fetch/response/fetch-await-response-event.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// @vitest-environment node
import { vi, it, expect, beforeAll, afterAll, afterEach } from 'vitest'
import { HttpServer } from '@open-draft/test-server/http'
import { FetchInterceptor } from '../../../../src/interceptors/fetch'

const httpServer = new HttpServer((app) => {
app.get('/resource', (req, res) => {
res.send('original response')
})
})

const interceptor = new FetchInterceptor()

beforeAll(async () => {
interceptor.apply()
await httpServer.listen()
})

afterEach(() => {
interceptor.removeAllListeners()
})

afterAll(async () => {
interceptor.dispose()
await httpServer.close()
})

it('awaits response listener promise before resolving the mocked response promise', async () => {
const markStep = vi.fn<[number]>()

interceptor.on('request', ({ controller }) => {
controller.respondWith(new Response('hello world'))
})

interceptor.on('response', async ({ response }) => {
markStep(2)
await response.text()
markStep(3)
})

markStep(1)
await fetch('http://localhost/')
markStep(4)

expect(markStep).toHaveBeenNthCalledWith(1, 1)
expect(markStep).toHaveBeenNthCalledWith(2, 2)
expect(markStep).toHaveBeenNthCalledWith(3, 3)
expect(markStep).toHaveBeenNthCalledWith(4, 4)
})

it('awaits response listener promise before resolving the original response promise', async () => {
const markStep = vi.fn<[number]>()

interceptor.on('response', async ({ response }) => {
markStep(2)
await response.text()
markStep(3)
})

markStep(1)
await fetch(httpServer.http.url('/resource'))
markStep(4)

expect(markStep).toHaveBeenNthCalledWith(1, 1)
expect(markStep).toHaveBeenNthCalledWith(2, 2)
expect(markStep).toHaveBeenNthCalledWith(3, 3)
expect(markStep).toHaveBeenNthCalledWith(4, 4)
})
36 changes: 25 additions & 11 deletions test/modules/http/response/http-await-response-event.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { vi, it, expect, beforeAll, afterAll, afterEach } from 'vitest'
import http from 'node:http'
import { HttpServer } from '@open-draft/test-server/http'
import { ClientRequestInterceptor } from '../../../../src/interceptors/ClientRequest'
import { sleep, waitForClientRequest } from '../../../helpers'
import { waitForClientRequest } from '../../../helpers'

const httpServer = new HttpServer((app) => {
app.get('/resource', (req, res) => {
Expand All @@ -27,35 +27,49 @@ afterAll(async () => {
})

it('awaits asynchronous response event listener for a mocked response', async () => {
const markStep = vi.fn<[number]>()

interceptor.on('request', ({ controller }) => {
controller.respondWith(new Response('hello world'))
})

const responseDone = vi.fn()
interceptor.on('response', async ({ response }) => {
await sleep(200)
const text = await response.text()
responseDone(text)
markStep(2)
await response.text()
markStep(3)
})

markStep(1)
const request = http.get('http://localhost/')
const { text } = await waitForClientRequest(request)
markStep(4)

expect(await text()).toBe('hello world')
expect(responseDone).toHaveBeenCalledWith('hello world')

expect(markStep).toHaveBeenNthCalledWith(1, 1)
expect(markStep).toHaveBeenNthCalledWith(2, 2)
expect(markStep).toHaveBeenNthCalledWith(3, 3)
expect(markStep).toHaveBeenNthCalledWith(4, 4)
})

it('awaits asynchronous response event listener for the original response', async () => {
const responseDone = vi.fn()
const markStep = vi.fn<[number]>()

interceptor.on('response', async ({ response }) => {
await sleep(200)
const text = await response.text()
responseDone(text)
markStep(2)
await response.text()
markStep(3)
})

markStep(1)
const request = http.get(httpServer.http.url('/resource'))
const { text } = await waitForClientRequest(request)
markStep(4)

expect(await text()).toBe('original response')
expect(responseDone).toHaveBeenCalledWith('original response')

expect(markStep).toHaveBeenNthCalledWith(1, 1)
expect(markStep).toHaveBeenNthCalledWith(2, 2)
expect(markStep).toHaveBeenNthCalledWith(3, 3)
expect(markStep).toHaveBeenNthCalledWith(4, 4)
})

0 comments on commit 261f581

Please sign in to comment.