Skip to content

Commit

Permalink
refactor: Replace several more uses of lodash with native, and relate…
Browse files Browse the repository at this point in the history
…d refactors (#1754)

This renames `Interceptor.matchAddress` to `Interceptor.matchOrigin` which I think better fits what is being done in that method.

The terminology comes from e.g. [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin) and what is sent for an [Origin header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin).

In Nock v12 we will stop checking for strings using the String constructor (i.e. `new String`).

Ref #1285
  • Loading branch information
paulmelnikow committed Oct 31, 2019
1 parent e01a67d commit 3fbc69d
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 50 deletions.
7 changes: 4 additions & 3 deletions lib/back.js
Expand Up @@ -61,6 +61,7 @@ function Back(fixtureName, options, nockedFn) {
)
}

// TODO-12.x: Replace with `typeof fixtureName === 'string'`.
if (!_.isString(fixtureName)) {
throw new Error('Parameter fixtureName must be a string')
}
Expand All @@ -70,7 +71,7 @@ function Back(fixtureName, options, nockedFn) {
} else if (arguments.length === 2) {
// If 2nd parameter is a function then `options` has been omitted
// otherwise `options` haven't been omitted but `nockedFn` was.
if (_.isFunction(options)) {
if (options instanceof Function) {
nockedFn = options
options = {}
}
Expand All @@ -88,7 +89,7 @@ function Back(fixtureName, options, nockedFn) {
debug('context:', context)

// If nockedFn is a function then invoke it, otherwise return a promise resolving to nockDone.
if (_.isFunction(nockedFn)) {
if (nockedFn instanceof Function) {
nockedFn.call(context, nockDone)
} else {
return Promise.resolve({ nockDone, context })
Expand Down Expand Up @@ -169,7 +170,7 @@ const record = {
if (context.isRecording) {
let outputs = recorder.outputs()

if (typeof options.afterRecord === 'function') {
if (options.afterRecord instanceof Function) {
outputs = options.afterRecord(outputs)
}

Expand Down
11 changes: 7 additions & 4 deletions lib/common.js
Expand Up @@ -170,6 +170,7 @@ function stringifyRequest(options, body) {

function isContentEncoded(headers) {
const contentEncoding = headers['content-encoding']
// TODO-12.x: Replace with `typeof contentEncoding === 'string'`.
return _.isString(contentEncoding) && contentEncoding !== ''
}

Expand Down Expand Up @@ -314,7 +315,7 @@ const noDuplicatesHeaders = new Set([
*/
function addHeaderLine(headers, name, value) {
let values // code below expects `values` to be an array of strings
if (typeof value === 'function') {
if (value instanceof Function) {
// Function values are evaluated towards the end of the response, before that we use a placeholder
// string just to designate that the header exists. Useful when `Content-Type` is set with a function.
values = [value.name]
Expand Down Expand Up @@ -359,6 +360,7 @@ function deleteHeadersField(headers, fieldNameToDelete) {
throw Error('headers must be an object')
}

// TODO-12.x: Replace with `typeof fieldNameToDelete !== 'string'`.
if (!_.isString(fieldNameToDelete)) {
throw Error('field name must be a string')
}
Expand Down Expand Up @@ -440,6 +442,7 @@ function formatQueryValue(key, value, stringFormattingFn) {
case value === undefined:
value = ''
break
// TODO-12.x: Replace with `typeof value === 'string'`.
case _.isString(value):
if (stringFormattingFn) {
value = stringFormattingFn(value)
Expand All @@ -453,7 +456,7 @@ function formatQueryValue(key, value, stringFormattingFn) {
})
break
}
case _.isObject(value): {
case typeof value === 'object': {
value = Object.entries(value).reduce(function(acc, [subKey, subVal]) {
const subPair = formatQueryValue(subKey, subVal, stringFormattingFn)
acc[subPair[0]] = subPair[1]
Expand All @@ -473,7 +476,7 @@ function isStream(obj) {
obj &&
typeof obj !== 'string' &&
!Buffer.isBuffer(obj) &&
_.isFunction(obj.setEncoding)
obj.setEncoding instanceof Function
)
}

Expand All @@ -497,7 +500,7 @@ function normalizeClientRequestArgs(input, options, cb) {
input = null
}

if (typeof options === 'function') {
if (options instanceof Function) {
cb = options
options = input || {}
} else {
Expand Down
18 changes: 9 additions & 9 deletions lib/intercept.js
Expand Up @@ -52,9 +52,10 @@ let allowNetConnect
* nock.enableNetConnect(/(google|amazon)/);
*/
function enableNetConnect(matcher) {
// TODO-12.x: Replace with `typeof matcher === 'string'`.
if (_.isString(matcher)) {
allowNetConnect = new RegExp(matcher)
} else if (_.isObject(matcher) && _.isFunction(matcher.test)) {
} else if (matcher instanceof RegExp) {
allowNetConnect = matcher
} else {
allowNetConnect = /.*/
Expand Down Expand Up @@ -170,7 +171,7 @@ function interceptorsFor(options) {
return [
{
options: { allowUnmocked: true },
matchAddress() {
matchOrigin() {
return false
},
},
Expand Down Expand Up @@ -389,13 +390,12 @@ function activate() {
const interceptors = interceptorsFor(options)

if (isOn() && interceptors) {
const matches = !!_.find(interceptors, function(interceptor) {
return interceptor.matchAddress(options)
})

const allowUnmocked = !!_.find(interceptors, function(interceptor) {
return interceptor.options.allowUnmocked
})
const matches = interceptors.some(interceptor =>
interceptor.matchOrigin(options)
)
const allowUnmocked = interceptors.some(
interceptor => interceptor.options.allowUnmocked
)

if (!matches && allowUnmocked) {
let req
Expand Down
8 changes: 4 additions & 4 deletions lib/intercepted_request_router.js
Expand Up @@ -113,7 +113,7 @@ class InterceptedRequestRouter {
}
this.requestBodyBuffers.push(buffer)
}
if (typeof callback === 'function') {
if (callback instanceof Function) {
callback()
}
} else {
Expand All @@ -131,17 +131,17 @@ class InterceptedRequestRouter {
debug('req.end')
const { req } = this

if (typeof chunk === 'function') {
if (chunk instanceof Function) {
callback = chunk
chunk = null
} else if (typeof encoding === 'function') {
} else if (encoding instanceof Function) {
callback = encoding
encoding = null
}

if (!req.aborted && !this.playbackStarted) {
req.write(chunk, encoding, () => {
if (typeof callback === 'function') {
if (callback instanceof Function) {
callback()
}
this.startPlayback()
Expand Down
22 changes: 11 additions & 11 deletions lib/interceptor.js
Expand Up @@ -110,7 +110,7 @@ module.exports = class Interceptor {

reply(statusCode, body, rawHeaders) {
// support the format of only passing in a callback
if (_.isFunction(statusCode)) {
if (statusCode instanceof Function) {
if (arguments.length > 1) {
// It's not very Javascript-y to throw an error for extra args to a function, but because
// of legacy behavior, this error was added to reduce confusion for those migrating.
Expand All @@ -126,7 +126,7 @@ module.exports = class Interceptor {
}

this.statusCode = statusCode || 200
if (_.isFunction(body)) {
if (body instanceof Function) {
this.replyFunction = body
body = null
}
Expand Down Expand Up @@ -213,7 +213,7 @@ module.exports = class Interceptor {
}

if (reqHeader !== undefined && header !== undefined) {
if (_.isFunction(reqHeader)) {
if (reqHeader instanceof Function) {
return reqHeader(header)
} else if (common.matchStringOrRegexp(header, reqHeader)) {
return true
Expand Down Expand Up @@ -248,7 +248,7 @@ module.exports = class Interceptor {

const requestMatchesFilter = ({ name, value: predicate }) => {
const headerValue = req.getHeader(name)
if (typeof predicate === 'function') {
if (predicate instanceof Function) {
return predicate(headerValue)
} else {
return common.matchStringOrRegexp(headerValue, predicate)
Expand Down Expand Up @@ -315,7 +315,7 @@ module.exports = class Interceptor {
matchKey = common.normalizeOrigin(proto, options.host, options.port)
}

if (typeof this.uri === 'function') {
if (this.uri instanceof Function) {
matches =
common.matchStringOrRegexp(matchKey, this.basePath) &&
// This is a false positive, as `uri` is not bound to `this`.
Expand Down Expand Up @@ -352,9 +352,9 @@ module.exports = class Interceptor {
* Return true when the interceptor's method, protocol, host, port, and path
* match the provided options.
*/
matchAddress(options) {
const isRegex = _.isRegExp(this.path)
const isRegexBasePath = _.isRegExp(this.scope.basePath)
matchOrigin(options) {
const isRegex = this.path instanceof RegExp
const isRegexBasePath = this.scope.basePath instanceof RegExp

const method = (options.method || 'GET').toUpperCase()
let { path } = options
Expand Down Expand Up @@ -395,7 +395,7 @@ module.exports = class Interceptor {
debug('Interceptor queries: %j', this.queries)
debug(' Request queries: %j', reqQueries)

if (_.isFunction(this.queries)) {
if (this.queries instanceof Function) {
return this.queries(reqQueries)
}

Expand Down Expand Up @@ -456,7 +456,7 @@ module.exports = class Interceptor {
return this
}

if (_.isFunction(queries)) {
if (queries instanceof Function) {
this.queries = queries
return this
}
Expand Down Expand Up @@ -553,7 +553,7 @@ module.exports = class Interceptor {
if (_.isNumber(opts)) {
headDelay = opts
bodyDelay = 0
} else if (_.isObject(opts)) {
} else if (typeof opts === 'object') {
headDelay = opts.head || 0
bodyDelay = opts.body || 0
} else {
Expand Down
19 changes: 5 additions & 14 deletions lib/match_body.js
Expand Up @@ -26,7 +26,7 @@ module.exports = function matchBody(options, spec, body) {

// try to transform body to json
let json
if (typeof spec === 'object' || typeof spec === 'function') {
if (typeof spec === 'object' || spec instanceof Function) {
try {
json = JSON.parse(body)
} catch (err) {
Expand All @@ -39,7 +39,7 @@ module.exports = function matchBody(options, spec, body) {
}
}

if (typeof spec === 'function') {
if (spec instanceof Function) {
return spec.call(options, body)
}

Expand All @@ -56,12 +56,7 @@ module.exports = function matchBody(options, spec, body) {
// Because the nature of URL encoding, all the values in the body have been cast to strings.
// dataEqual does strict checking so we we have to cast the non-regexp values in the spec too.
if (isUrlencoded) {
spec = mapValuesDeep(spec, function(val) {
if (_.isRegExp(val)) {
return val
}
return `${val}`
})
spec = mapValuesDeep(spec, val => (val instanceof RegExp ? val : `${val}`))
}

return common.dataEqual(spec, body)
Expand All @@ -73,14 +68,10 @@ module.exports = function matchBody(options, spec, body) {
*/
function mapValuesDeep(obj, cb) {
if (Array.isArray(obj)) {
return obj.map(function(v) {
return mapValuesDeep(v, cb)
})
return obj.map(v => mapValuesDeep(v, cb))
}
if (_.isPlainObject(obj)) {
return _.mapValues(obj, function(v) {
return mapValuesDeep(v, cb)
})
return _.mapValues(obj, v => mapValuesDeep(v, cb))
}
return cb(obj)
}
5 changes: 2 additions & 3 deletions lib/playback_interceptor.js
Expand Up @@ -3,7 +3,6 @@
const util = require('util')
const zlib = require('zlib')
const debug = require('debug')('nock.playback_interceptor')
const _ = require('lodash')
const common = require('./common')
const DelayedBody = require('./delayed_body')

Expand Down Expand Up @@ -100,7 +99,7 @@ function playbackInterceptor({
interceptor.markConsumed()

let error
if (_.isObject(interceptor.errorMessage)) {
if (typeof interceptor.errorMessage === 'object') {
error = interceptor.errorMessage
} else {
error = new Error(interceptor.errorMessage)
Expand Down Expand Up @@ -271,7 +270,7 @@ function playbackInterceptor({

// Evaluate functional headers.
common.forEachHeader(response.rawHeaders, (value, fieldName, i) => {
if (typeof value === 'function') {
if (value instanceof Function) {
response.rawHeaders[i + 1] = value(req, response, responseBody)
}
})
Expand Down
4 changes: 2 additions & 2 deletions lib/recorder.js
Expand Up @@ -344,10 +344,10 @@ function record(recOptions) {
const oldEnd = req.end
req.end = function(chunk, encoding, callback) {
debug('req.end')
if (typeof chunk === 'function') {
if (chunk instanceof Function) {
callback = chunk
chunk = null
} else if (typeof encoding === 'function') {
} else if (encoding instanceof Function) {
callback = encoding
encoding = null
}
Expand Down

0 comments on commit 3fbc69d

Please sign in to comment.