Skip to content

Commit

Permalink
fix: apply response delay conditionally (#1300)
Browse files Browse the repository at this point in the history
* fix(handleRequest): apply response delay conditionally

* test: add integration test for delay in node
  • Loading branch information
kettanaito committed Jun 22, 2022
1 parent e05157c commit 496154d
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 34 deletions.
36 changes: 21 additions & 15 deletions src/node/createSetupServer.ts
Expand Up @@ -67,24 +67,30 @@ export function createSetupServer(

interceptor.on('request', async function setupServerListener(request) {
const mockedRequest = parseIsomorphicRequest(request)
const response = await handleRequest<MockedInterceptedResponse>(
mockedRequest,
currentHandlers,
resolvedOptions,
emitter,
{
transformResponse(response) {
return {
status: response.status,
statusText: response.statusText,
headers: response.headers.all(),
body: response.body,
}
},
const response = await handleRequest<
MockedInterceptedResponse & { delay?: number }
>(mockedRequest, currentHandlers, resolvedOptions, emitter, {
transformResponse(response) {
return {
status: response.status,
statusText: response.statusText,
headers: response.headers.all(),
body: response.body,
delay: response.delay,
}
},
)
})

if (response) {
// Delay Node.js responses in the listener so that
// the response lookup logic is not concerned with responding
// in any way. The same delay is implemented in the worker.
if (response.delay) {
await new Promise((resolve) => {
setTimeout(resolve, response.delay)
})
}

request.respondWith(response)
}

Expand Down
34 changes: 15 additions & 19 deletions src/utils/handleRequest.ts
Expand Up @@ -125,27 +125,23 @@ Expected response resolver to return a mocked response Object, but got %s. The o

emitter.emit('request:match', request)

return new Promise((resolve) => {
const requiredLookupResult =
lookupResult as RequiredDeep<ResponseLookupResult>
const requiredLookupResult =
lookupResult as RequiredDeep<ResponseLookupResult>

const transformedResponse =
handleRequestOptions?.transformResponse?.(response) ||
(response as any as ResponseType)
const transformedResponse =
handleRequestOptions?.transformResponse?.(response) ||
(response as any as ResponseType)

handleRequestOptions?.onMockedResponse?.(
transformedResponse,
requiredLookupResult,
)
handleRequestOptions?.onMockedResponse?.(
transformedResponse,
requiredLookupResult,
)

setTimeout(() => {
handleRequestOptions?.onMockedResponseSent?.(
transformedResponse,
requiredLookupResult,
)
emitter.emit('request:end', request)
handleRequestOptions?.onMockedResponseSent?.(
transformedResponse,
requiredLookupResult,
)
emitter.emit('request:end', request)

resolve(transformedResponse as ResponseType)
}, response.delay ?? 0)
})
return transformedResponse
}
72 changes: 72 additions & 0 deletions test/msw-api/context/delay.node.test.ts
@@ -0,0 +1,72 @@
/**
* @jest-environment node
*/
import fetch from 'node-fetch'
import { rest } from 'msw'
import { setupServer } from 'msw/node'
import { performance } from 'perf_hooks'

const server = setupServer()

beforeAll(() => {
server.listen()
})

afterEach(() => {
server.resetHandlers()
})

afterAll(() => {
server.close()
})

async function makeRequest(url: string) {
const requestStart = performance.now()
const res = await fetch(url)
const requestEnd = performance.now()
const responseTime = requestEnd - requestStart

return { res, responseTime }
}

test('uses explicit server response time', async () => {
server.use(
rest.get('http://localhost/user', (req, res, ctx) => {
return res(ctx.delay(500), ctx.text('john'))
}),
)

const { res, responseTime } = await makeRequest('http://localhost/user')

expect(responseTime).toBeGreaterThanOrEqual(500)
expect(await res.text()).toBe('john')
})

test('uses realistic server response time when no duration is provided', async () => {
server.use(
rest.get('http://localhost/user', (req, res, ctx) => {
return res(ctx.delay(), ctx.text('john'))
}),
)

const { res, responseTime } = await makeRequest('http://localhost/user')

// Realistic server response time in Node.js is set to 5ms.
expect(responseTime).toBeGreaterThan(5)
expect(responseTime).toBeLessThan(100)
expect(await res.text()).toBe('john')
})

test('uses realistic server response time when "real" mode is provided', async () => {
server.use(
rest.get('http://localhost/user', (req, res, ctx) => {
return res(ctx.delay('real'), ctx.text('john'))
}),
)

const { res, responseTime } = await makeRequest('http://localhost/user')

// Realistic server response time in Node.js is set to 5ms.
expect(responseTime).toBeGreaterThan(5)
expect(await res.text()).toBe('john')
})

0 comments on commit 496154d

Please sign in to comment.