/** * Slightly modified from Shopify/quilt/jest-koa-mock: * https://github.com/Shopify/quilt/blob/master/packages/jest-koa-mocks/src/create-mock-context/create-mock-context.ts * * License: https://github.com/Shopify/quilt/blob/master/LICENSE.md */ import { URL } from 'url'; import * as stream from 'stream'; import * as httpMocks from 'node-mocks-http'; import * as sinon from 'sinon'; import { IncomingMessage } from 'http'; import { NowRequest } from '@now/node'; import { ApiContext } from 'src/server'; export interface Dictionary { [key: string]: T; } export interface Options< CustomProperties extends object, RequestBody = undefined > { url?: string; method?: httpMocks.RequestMethod; statusCode?: number; headers?: Dictionary; cookies?: Dictionary; state?: ApiContext['state']; encrypted?: boolean; host?: string; requestBody?: RequestBody; } export function createContext< CustomProperties extends object, RequestBody = undefined >(options: Options = {}): ApiContext { const { method, statusCode, requestBody, url = '', host = 'test.com', encrypted = false, headers = {}, state = {}, } = options; const protocolFallback = encrypted ? 'https' : 'http'; const urlObject = new URL(url, `${protocolFallback}://${host}`); const socket = new stream.Duplex() as any; const request = new IncomingMessage(socket) as NowRequest; // Some functions we call in the implementations will perform checks for `req.encrypted`, which delegates to the socket. Object.defineProperty(request.socket, 'encrypted', { writable: false, value: urlObject.protocol === 'https:', }); request.url = urlObject.toString(); request.method = method; request.statusCode = statusCode; request.headers = headers; request.body = requestBody; const context: ApiContext = { request, state, }; return context; }