import * as Log from '../../../../log'; import { ExpoMiddleware } from '../ExpoMiddleware'; import { ServerNext, ServerRequest, ServerResponse } from '../server.types'; jest.mock('../../../../log'); const asReq = (req: Partial) => req as ServerRequest; class MockExpoMiddleware extends ExpoMiddleware { handleRequestAsync(req: ServerRequest, res: ServerResponse, next: ServerNext): Promise { throw new Error('Method not implemented.'); } } describe('_shouldHandleRequest', () => { const middleware = new MockExpoMiddleware('/', ['/', '/index.html']); it('returns false when the request url is not defined', () => { expect(middleware._shouldHandleRequest(asReq({}))).toBe(false); }); it('returns false when the request url is not provided', () => { expect(middleware._shouldHandleRequest(asReq({ url: '/foo' }))).toBe(false); }); it('returns true when the request url is `/`, or `/index.html`', () => { expect(middleware._shouldHandleRequest(asReq({ url: '/' }))).toBe(true); expect(middleware._shouldHandleRequest(asReq({ url: '/index.html' }))).toBe(true); }); }); describe('getHandler', () => { it(`resolves successfully`, async () => { const middleware = new MockExpoMiddleware('/', ['/']); middleware.handleRequestAsync = jest.fn(); const handleAsync = middleware.getHandler(); const next = jest.fn(); const res = { setHeader: jest.fn(), end: jest.fn(), statusCode: 200, }; await handleAsync( asReq({ url: '/', headers: { 'expo-dev-client-id': 'client-id', }, }), // @ts-expect-error res, next ); // Internals are invoked. expect(middleware.handleRequestAsync).toBeCalled(); // Generally tests that the server I/O works as expected so we don't need to test this in subclasses. expect(res.statusCode).toEqual(200); }); it(`returns error info in the response`, async () => { const middleware = new MockExpoMiddleware('/', ['/']); middleware.handleRequestAsync = jest.fn(async () => { throw new Error('demo'); }); const handleAsync = middleware.getHandler(); const next = jest.fn(); const res = { setHeader: jest.fn(), end: jest.fn(), statusCode: 200, }; await handleAsync( asReq({ url: '/', headers: { 'expo-dev-client-id': 'client-id', }, }), // @ts-expect-error res, next ); // Internals are invoked. expect(middleware.handleRequestAsync).toBeCalled(); // Generally tests that the server I/O works as expected so we don't need to test this in subclasses. expect(res.statusCode).toEqual(500); expect(next).not.toBeCalled(); // Returns error info. expect(res.end).toBeCalledWith(JSON.stringify({ error: 'Error: demo' })); // Ensure the user sees the error in the terminal. expect(Log.exception).toBeCalled(); }); it(`continues`, async () => { const middleware = new MockExpoMiddleware('/', ['/']); middleware.handleRequestAsync = jest.fn(); const handleAsync = middleware.getHandler(); const next = jest.fn(); const res = { setHeader: jest.fn(), end: jest.fn(), statusCode: 200, }; await handleAsync( asReq({ url: '/foobar', headers: {} }), // @ts-expect-error res, next ); // Generally tests that the server I/O works as expected so we don't need to test this in subclasses. expect(res.statusCode).toEqual(200); expect(next).toBeCalled(); expect(middleware.handleRequestAsync).not.toBeCalled(); }); });