UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

125 lines (95 loc) 4.11 kB
import _ from 'lodash' import { StaticResponse, BackendStaticResponse, FixtureOpts, } from '@packages/net-stubbing/lib/types' import $errUtils from '../../cypress/error_utils' // user-facing StaticResponse only export const STATIC_RESPONSE_KEYS: (keyof StaticResponse)[] = ['body', 'fixture', 'statusCode', 'headers', 'forceNetworkError', 'throttleKbps', 'delay', 'delayMs'] export function validateStaticResponse (cmd: string, staticResponse: StaticResponse): void { const err = (message) => { $errUtils.throwErrByPath('net_stubbing.invalid_static_response', { args: { cmd, message, staticResponse } }) } const { body, fixture, statusCode, headers, forceNetworkError, throttleKbps, delay, delayMs } = staticResponse if (forceNetworkError && (body || statusCode || headers)) { err('`forceNetworkError`, if passed, must be the only option in the StaticResponse.') } if (body && fixture) { err('`body` and `fixture` cannot both be set, pick one.') } if (fixture && !_.isString(fixture)) { err('`fixture` must be a string containing a path and, optionally, an encoding separated by a comma (for example, "foo.txt,ascii").') } // statusCode must be a three-digit integer // @see https://tools.ietf.org/html/rfc2616#section-6.1.1 if (statusCode && !(_.isNumber(statusCode) && _.inRange(statusCode, 100, 999))) { err('`statusCode` must be a number between 100 and 999 (inclusive).') } if (headers && _.keys(_.omitBy(headers, _.isString)).length) { err('`headers` must be a map of strings to strings.') } if (!_.isUndefined(throttleKbps) && (!_.isNumber(throttleKbps) || (throttleKbps < 0 || !_.isFinite(throttleKbps)))) { err('`throttleKbps` must be a finite, positive number.') } if (delayMs && delay) { err('`delayMs` and `delay` cannot both be set.') } if (delayMs && (!_.isFinite(delayMs) || delayMs < 0)) { err('`delayMs` must be a finite, positive number.') } if (delay && (!_.isFinite(delay) || delay < 0)) { err('`delay` must be a finite, positive number.') } } export function parseStaticResponseShorthand (statusCodeOrBody: number | string | any, bodyOrHeaders: string | { [key: string]: string }, maybeHeaders?: { [key: string]: string }) { if (_.isNumber(statusCodeOrBody)) { // statusCodeOrBody is a status code const staticResponse: StaticResponse = { statusCode: statusCodeOrBody, } if (!_.isUndefined(bodyOrHeaders)) { staticResponse.body = bodyOrHeaders as string } if (_.isObject(maybeHeaders)) { staticResponse.headers = maybeHeaders as { [key: string]: string } } return staticResponse } if ((_.isString(statusCodeOrBody) || !hasStaticResponseKeys(statusCodeOrBody)) && !maybeHeaders) { const staticResponse: StaticResponse = { body: statusCodeOrBody, } if (_.isObject(bodyOrHeaders)) { staticResponse.headers = bodyOrHeaders as { [key: string]: string } } return staticResponse } return } function getFixtureOpts (fixture: string): FixtureOpts { const [filePath, encoding] = fixture.split(',') return { filePath, encoding } } export function getBackendStaticResponse (staticResponse: Readonly<StaticResponse>): BackendStaticResponse { const backendStaticResponse: BackendStaticResponse = _.omit(staticResponse, 'body', 'fixture', 'delayMs') if (staticResponse.delayMs) { // support deprecated `delayMs` usage backendStaticResponse.delay = staticResponse.delayMs } if (staticResponse.fixture) { backendStaticResponse.fixture = getFixtureOpts(staticResponse.fixture) } if (staticResponse.body) { if (_.isString(staticResponse.body)) { backendStaticResponse.body = staticResponse.body } else { backendStaticResponse.body = JSON.stringify(staticResponse.body) _.set(backendStaticResponse, 'headers.content-type', 'application/json') } } return backendStaticResponse } export function hasStaticResponseKeys (obj: any) { return !_.isArray(obj) && (_.intersection(_.keys(obj), STATIC_RESPONSE_KEYS).length || _.isEmpty(obj)) }