UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

163 lines (133 loc) 4.24 kB
import _ from 'lodash' import { CyHttpMessages, SERIALIZABLE_RES_PROPS, NetEventFrames, } from '@packages/net-stubbing/lib/types' import { validateStaticResponse, parseStaticResponseShorthand, STATIC_RESPONSE_KEYS, getBackendStaticResponse, } from '../static-response-utils' import $errUtils from '../../../cypress/error_utils' import { HandlerFn } from './' import Bluebird from 'bluebird' import { parseJsonBody } from './utils' export const onResponseReceived: HandlerFn<NetEventFrames.HttpResponseReceived> = (Cypress, frame, { getRoute, getRequest, emitNetEvent }) => { const { res, requestId, routeHandlerId } = frame const request = getRequest(frame.routeHandlerId, frame.requestId) parseJsonBody(res) let sendCalled = false let resolved = false if (request) { request.state = 'ResponseReceived' request.log.fireChangeEvent() if (!request.responseHandler) { // this is notification-only, update the request with the response attributes and end request.response = res return } } const continueFrame: NetEventFrames.HttpResponseContinue = { routeHandlerId, requestId, } const sendContinueFrame = () => { // copy changeable attributes of userRes to res in frame // if the user is setting a StaticResponse, use that instead // @ts-ignore continueFrame.res = { ..._.pick(continueFrame.staticResponse || userRes, SERIALIZABLE_RES_PROPS), } if (request) { request.response = _.clone(continueFrame.res) request.state = 'ResponseIntercepted' request.log.fireChangeEvent() } if (_.isObject(continueFrame.res!.body)) { continueFrame.res!.body = JSON.stringify(continueFrame.res!.body) } emitNetEvent('http:response:continue', continueFrame) } const userRes: CyHttpMessages.IncomingHttpResponse = { ...res, send (staticResponse?, maybeBody?, maybeHeaders?) { if (resolved) { return $errUtils.throwErrByPath('net_stubbing.response_handling.send_called_after_resolved', { args: { res } }) } if (sendCalled) { return $errUtils.throwErrByPath('net_stubbing.response_handling.multiple_send_calls', { args: { res } }) } sendCalled = true const shorthand = parseStaticResponseShorthand(staticResponse, maybeBody, maybeHeaders) if (shorthand) { staticResponse = shorthand } if (staticResponse) { validateStaticResponse('res.send', staticResponse) // arguments to res.send() are merged with the existing response const _staticResponse = _.defaults({}, staticResponse, _.pick(res, STATIC_RESPONSE_KEYS)) _.defaults(_staticResponse.headers, res.headers) continueFrame.staticResponse = getBackendStaticResponse(_staticResponse) } return sendContinueFrame() }, delay (delay) { continueFrame.delay = delay return this }, throttle (throttleKbps) { continueFrame.throttleKbps = throttleKbps return this }, } if (!request) { return sendContinueFrame() } const timeout = Cypress.config('defaultCommandTimeout') const curTest = Cypress.state('test') return Bluebird.try(() => { return request.responseHandler!(userRes) }) .catch((err) => { $errUtils.throwErrByPath('net_stubbing.response_handling.cb_failed', { args: { err, req: request.request, route: _.get(getRoute(routeHandlerId), 'options'), res, }, errProps: { appendToStack: { title: 'From response callback', content: err.stack, }, }, }) }) .timeout(timeout) .catch(Bluebird.TimeoutError, (err) => { if (Cypress.state('test') !== curTest) { // active test has changed, ignore the timeout return } $errUtils.throwErrByPath('net_stubbing.response_handling.cb_timeout', { args: { timeout, req: request.request, route: _.get(getRoute(routeHandlerId), 'options'), res, }, }) }) .then(() => { if (!sendCalled) { // user did not call send, send response userRes.send() } }) .finally(() => { resolved = true }) }