UNPKG

2.08 kBJavaScriptView Raw
1'use strict'
2
3const _ = require('lodash')
4const querystring = require('querystring')
5
6const common = require('./common')
7
8module.exports = function matchBody(options, spec, body) {
9 if (spec instanceof RegExp) {
10 return spec.test(body)
11 }
12
13 if (Buffer.isBuffer(spec)) {
14 const encoding = common.isUtf8Representable(spec) ? 'utf8' : 'hex'
15 spec = spec.toString(encoding)
16 }
17
18 const contentType = (
19 (options.headers &&
20 (options.headers['Content-Type'] || options.headers['content-type'])) ||
21 ''
22 ).toString()
23
24 const isMultipart = contentType.includes('multipart')
25 const isUrlencoded = contentType.includes('application/x-www-form-urlencoded')
26
27 // try to transform body to json
28 let json
29 if (typeof spec === 'object' || typeof spec === 'function') {
30 try {
31 json = JSON.parse(body)
32 } catch (err) {
33 // not a valid JSON string
34 }
35 if (json !== undefined) {
36 body = json
37 } else if (isUrlencoded) {
38 body = querystring.parse(body)
39 }
40 }
41
42 if (typeof spec === 'function') {
43 return spec.call(options, body)
44 }
45
46 // strip line endings from both so that we get a match no matter what OS we are running on
47 // if Content-Type does not contains 'multipart'
48 if (!isMultipart && typeof body === 'string') {
49 body = body.replace(/\r?\n|\r/g, '')
50 }
51
52 if (!isMultipart && typeof spec === 'string') {
53 spec = spec.replace(/\r?\n|\r/g, '')
54 }
55
56 // Because the nature of URL encoding, all the values in the body have been cast to strings.
57 // dataEqual does strict checking so we we have to cast the non-regexp values in the spec too.
58 if (isUrlencoded) {
59 spec = mapValuesDeep(spec, val => (val instanceof RegExp ? val : `${val}`))
60 }
61
62 return common.dataEqual(spec, body)
63}
64
65/**
66 * Based on lodash issue discussion
67 * https://github.com/lodash/lodash/issues/1244
68 */
69function mapValuesDeep(obj, cb) {
70 if (Array.isArray(obj)) {
71 return obj.map(v => mapValuesDeep(v, cb))
72 }
73 if (_.isPlainObject(obj)) {
74 return _.mapValues(obj, v => mapValuesDeep(v, cb))
75 }
76 return cb(obj)
77}