Skip to content

Commit c8cd29d

Browse files
authored
test: add http unix socket test cases (#751)
1 parent f169e01 commit c8cd29d

File tree

1 file changed

+110
-42
lines changed

1 file changed

+110
-42
lines changed
Lines changed: 110 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,137 @@
1+
// @vitest-environment node
12
/**
2-
* @vitest-environment node
3+
* @see https://github.com/mswjs/interceptors/pull/722
34
*/
5+
import { afterAll, afterEach, beforeAll, beforeEach, expect, it } from 'vitest'
6+
import path from 'node:path'
47
import http from 'node:http'
5-
import { tmpdir } from 'node:os';
6-
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
7-
import { DeferredPromise } from '@open-draft/deferred-promise'
8+
import { promisify } from 'node:util'
89
import { ClientRequestInterceptor } from '../../../../src/interceptors/ClientRequest'
910
import { waitForClientRequest } from '../../../helpers'
10-
import exp from 'node:constants';
1111

12-
const interceptor = new ClientRequestInterceptor()
12+
// const HTTP_SOCKET_PATH = mockFs.resolve('./test.sock')
13+
const HTTP_SOCKET_PATH = path.join(__dirname, './test-http.sock')
14+
15+
const httpServer = http.createServer((req, res) => {
16+
res.writeHead(200, req.headers)
1317

14-
const socketPath = tmpdir() + '/socket.sock'
15-
const httpServer = new http.Server((req, res) => {
16-
res.end('hello world')
18+
if (req.method === 'POST') {
19+
req.pipe(res)
20+
} else {
21+
res.end()
22+
}
1723
})
1824

25+
const interceptor = new ClientRequestInterceptor()
26+
1927
beforeAll(async () => {
20-
interceptor.apply()
21-
const serverListenPromise = new DeferredPromise<void>()
22-
httpServer.listen(socketPath, () => {
23-
serverListenPromise.resolve()
28+
await new Promise<void>((resolve) => {
29+
httpServer.listen(HTTP_SOCKET_PATH, resolve)
2430
})
25-
await serverListenPromise
31+
32+
interceptor.apply()
33+
})
34+
35+
afterEach(() => {
36+
interceptor.removeAllListeners()
2637
})
2738

2839
afterAll(async () => {
2940
interceptor.dispose()
30-
const serverClosePromise = new DeferredPromise<void>()
31-
httpServer.close((error) => {
32-
if (error) {
33-
serverClosePromise.reject(error)
34-
}
35-
serverClosePromise.resolve()
41+
await promisify(httpServer.close.bind(httpServer))()
42+
})
43+
44+
it('supports passthrough HTTP GET requests over a unix socket', async () => {
45+
const request = http.get({
46+
socketPath: HTTP_SOCKET_PATH,
47+
path: '/irrelevant',
48+
headers: {
49+
'X-Custom-Header': 'custom-value',
50+
},
3651
})
37-
await serverClosePromise
52+
const { res } = await waitForClientRequest(request)
53+
54+
expect.soft(res.statusCode).toBe(200)
55+
expect.soft(res.headers['x-custom-header']).toBe('custom-value')
3856
})
3957

40-
describe('Unix socket', () => {
41-
it('dispatches a GET request to a Unix socket', async () => {
42-
const request = http.get({
43-
socketPath,
44-
path: '/test-get',
45-
})
58+
it('supports passthrough HTTP POST requests over a unix socket', async () => {
59+
const request = http.request({
60+
method: 'POST',
61+
socketPath: HTTP_SOCKET_PATH,
62+
path: '/irrelevant',
63+
headers: {
64+
'Content-Type': 'application/json',
65+
'Content-Length': 11,
66+
},
67+
})
68+
request.end('hello world')
4669

47-
const { text } = await waitForClientRequest(request)
70+
const { res, text } = await waitForClientRequest(request)
4871

49-
expect(await text()).toBe('hello world')
72+
expect.soft(res.statusCode).toBe(200)
73+
expect.soft(res.headers).toMatchObject({
74+
'content-type': 'application/json',
75+
'content-length': '11',
5076
})
77+
await expect.soft(text()).resolves.toBe('hello world')
78+
})
5179

52-
it('intercepts a GET request to a Unix socket', async () => {
53-
const requestListenerPromise = new DeferredPromise<string>()
54-
interceptor.on('request', ({ controller, request }) => {
55-
requestListenerPromise.resolve(request.url)
56-
controller.respondWith(new Response('hello world', { status: 200 }))
57-
})
80+
it('supports passthrough HTTP GET requests to a non-existing unix socket', async () => {
81+
const request = http.get({
82+
socketPath: path.join('non-existing.sock'),
83+
path: '/irrelevant',
84+
})
5885

59-
const request = http.get({
60-
socketPath,
61-
path: '/test-get',
86+
await expect(waitForClientRequest(request)).rejects.toThrow(
87+
expect.objectContaining({
88+
code: 'ENOENT',
89+
message: 'connect ENOENT non-existing.sock',
6290
})
91+
)
92+
})
93+
94+
it('mocks a response to HTTP GET requests over a unix socket', async () => {
95+
interceptor.on('request', ({ request, controller }) => {
96+
controller.respondWith(new Response('hello world', request))
97+
})
98+
99+
const request = http.get({
100+
socketPath: HTTP_SOCKET_PATH,
101+
path: '/irrelevant',
102+
headers: {
103+
'X-Custom-Header': 'custom-value',
104+
},
105+
})
106+
const { res, text } = await waitForClientRequest(request)
107+
108+
expect.soft(res.statusCode).toBe(200)
109+
expect.soft(res.headers['x-custom-header']).toBe('custom-value')
110+
await expect.soft(text()).resolves.toBe('hello world')
111+
})
63112

64-
const { text } = await waitForClientRequest(request)
113+
it('mocks a response to HTTP POST requests over a unix socket', async () => {
114+
interceptor.on('request', ({ request, controller }) => {
115+
controller.respondWith(
116+
new Response(request.body, {
117+
headers: request.headers,
118+
})
119+
)
120+
})
65121

66-
expect(await text()).toBe('hello world')
67-
await expect(requestListenerPromise).resolves.toStrictEqual('http://localhost/test-get')
122+
const request = http.request({
123+
method: 'POST',
124+
socketPath: HTTP_SOCKET_PATH,
125+
path: '/irrelevant',
126+
headers: {
127+
'X-Custom-Header': 'custom-value',
128+
},
68129
})
69-
})
130+
request.end('request-payload')
131+
132+
const { res, text } = await waitForClientRequest(request)
133+
134+
expect.soft(res.statusCode).toBe(200)
135+
expect.soft(res.headers['x-custom-header']).toBe('custom-value')
136+
await expect.soft(text()).resolves.toBe('request-payload')
137+
})

0 commit comments

Comments
 (0)