1import type { IncomingMessage, ServerResponse } from 'http'; 2import type { Socket } from 'net'; 3import { URL } from 'url'; 4 5import { METRO_INSPECTOR_RESPONSE_FIXTURE } from './fixtures/metroInspectorResponse'; 6import * as JsInspector from '../JsInspector'; 7import createJsInspectorMiddleware from '../createJsInspectorMiddleware'; 8 9jest.mock('../JsInspector'); 10 11describe('createJsInspectorMiddleware', () => { 12 it('should return specific app entity for GET request with given applicationId', async () => { 13 const app = METRO_INSPECTOR_RESPONSE_FIXTURE[0]; 14 const req = createRequest(`http://localhost:8081/inspector?applicationId=${app.description}`); 15 const res = createMockedResponse(); 16 const next = jest.fn(); 17 ( 18 JsInspector.queryInspectorAppAsync as jest.MockedFunction< 19 typeof JsInspector.queryInspectorAppAsync 20 > 21 ).mockReturnValue(Promise.resolve(app)); 22 23 const middlewareAsync = createJsInspectorMiddleware(); 24 await middlewareAsync(req, res as ServerResponse, next); 25 26 expectMockedResponse(res, 200, JSON.stringify(app)); 27 }); 28 29 it('should handle ipv6 address', async () => { 30 const app = METRO_INSPECTOR_RESPONSE_FIXTURE[0]; 31 const req = createRequest( 32 `http://[::ffff:127.0.0.1]/inspector?applicationId=${app.description}` 33 ); 34 const res = createMockedResponse(); 35 const next = jest.fn(); 36 ( 37 JsInspector.queryInspectorAppAsync as jest.MockedFunction< 38 typeof JsInspector.queryInspectorAppAsync 39 > 40 ).mockReturnValue(Promise.resolve(app)); 41 42 const middlewareAsync = createJsInspectorMiddleware(); 43 await middlewareAsync(req, res as ServerResponse, next); 44 45 expectMockedResponse(res, 200, JSON.stringify(app)); 46 }); 47 48 it('should return 404 for GET request with nonexistent applicationId', async () => { 49 const req = createRequest('http://localhost:8081/inspector?applicationId=nonExistentApp'); 50 const res = createMockedResponse(); 51 const next = jest.fn(); 52 ( 53 JsInspector.queryInspectorAppAsync as jest.MockedFunction< 54 typeof JsInspector.queryInspectorAppAsync 55 > 56 ).mockReturnValue(Promise.resolve(null)); 57 58 const middlewareAsync = createJsInspectorMiddleware(); 59 await middlewareAsync(req, res as ServerResponse, next); 60 61 expectMockedResponse(res, 404); 62 }); 63 64 it('should return 400 for GET request without parameters', async () => { 65 const req = createRequest('http://localhost:8081/inspector'); 66 const res = createMockedResponse(); 67 const next = jest.fn(); 68 69 const middlewareAsync = createJsInspectorMiddleware(); 70 await middlewareAsync(req, res as ServerResponse, next); 71 72 expectMockedResponse(res, 400); 73 }); 74 75 it('should open browser for PUT request with given applicationId', async () => { 76 const app = METRO_INSPECTOR_RESPONSE_FIXTURE[0]; 77 const req = createRequest( 78 `http://localhost:8081/inspector?applicationId=${app.description}`, 79 'PUT' 80 ); 81 const res = createMockedResponse(); 82 const next = jest.fn(); 83 ( 84 JsInspector.queryInspectorAppAsync as jest.MockedFunction< 85 typeof JsInspector.queryInspectorAppAsync 86 > 87 ).mockReturnValue(Promise.resolve(app)); 88 89 const middlewareAsync = createJsInspectorMiddleware(); 90 await middlewareAsync(req, res as ServerResponse, next); 91 92 expectMockedResponse(res, 200); 93 expect(JsInspector.openJsInspector).toHaveBeenCalledTimes(1); 94 }); 95}); 96 97function createRequest(requestUrl: string, method?: 'GET' | 'POST' | 'PUT'): IncomingMessage { 98 const url = new URL(requestUrl); 99 const req: Partial<IncomingMessage> = { 100 method: method || 'GET', 101 headers: { 102 host: url.host, 103 }, 104 socket: { 105 localAddress: url.hostname, 106 localPort: Number(url.port || 80), 107 } as Socket, 108 url: `${url.pathname}${url.search}`, 109 }; 110 return req as IncomingMessage; 111} 112 113interface MockedResponse extends Partial<ServerResponse> { 114 end: jest.Mock; 115 writeHead: jest.Mock; 116 write: jest.Mock; 117} 118 119function createMockedResponse(): MockedResponse { 120 return { 121 end: jest.fn(), 122 writeHead: jest.fn().mockReturnThis(), 123 write: jest.fn().mockReturnThis(), 124 }; 125} 126 127function expectMockedResponse(res: MockedResponse, status: number, body?: string) { 128 if (status !== 200) { 129 expect(res.writeHead.mock.calls[0][0]).toBe(status); 130 } 131 if (body) { 132 expect(res.end.mock.calls[0][0]).toBe(body); 133 } 134} 135