This repository has been archived by the owner on Nov 21, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
/
fakeresponse.js
118 lines (100 loc) · 4.27 KB
/
fakeresponse.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
* Copyright (c) 2014, Yahoo! Inc. All rights reserved.
* Copyrights licensed under the New BSD License.
* See the accompanying LICENSE file for terms.
*/
/*jshint node:true */
'use strict';
var fs = require('fs');
var glob = require('glob');
var path = require('path');
var when = require('when');
var url = require('url');
var _ = require('lodash');
var FakeResponse = {
_items: [],
preload: function(pathToConfiguration) {
return when.promise(function(resolve, reject) {
var configDir = pathToConfiguration || path.join(__dirname, 'default_routes');
console.log('loading config from: ',configDir);
glob.sync('*.json', {cwd:configDir})
.forEach(function eachFile(file) {
var contents = fs.readFileSync(path.join(configDir,file), 'utf8');
try {
var allRoutes = JSON.parse(contents);
allRoutes.routes.forEach(function(configLine) {
FakeResponse.add(configLine);
});
} catch(e) {
console.log('Wrong configuration format');
reject(e);
}
});
return resolve(FakeResponse.getAll());
});
},
getAll: function () {
return FakeResponse._items;
},
add: function (item) {
item.numCalls = 0;
FakeResponse._items.push(item);
},
flush: function () {
FakeResponse._items = [];
},
/*Lexicographic comparison based on: (at, num query + payload params matched, num headers matched)*/
compareMatches: function(matchA, matchB) {
/*First rank on 'at' match*/
if (!matchA.hasOwnProperty('at') && matchB.hasOwnProperty('at')) {
return 1;
}
if (matchA.hasOwnProperty('at') && !matchB.hasOwnProperty('at')) {
return -1;
}
/*Second rank on quality of 'params' match*/
var numParamsMatchedB = Object.keys(matchB.queryParams || {}).length +
Object.keys(matchB.payload || {}).length;
var numParamsMatchedA = Object.keys(matchA.queryParams || {}).length +
Object.keys(matchA.payload || {}).length;
var queryCmp = numParamsMatchedB - numParamsMatchedA;
if (queryCmp !== 0) {
return queryCmp;
}
/*If still tied, rank on quality of 'headers' match*/
return Object.keys(matchB.requiredHeaders || {}).length - Object.keys(matchA.requiredHeaders || {}).length;
},
/* Filters all items that match the URL and then tries to check if there is a specific behavior for the Nth call on the same endpoint */
match: function (uri, payload, headers) {
uri = url.parse(uri, true);
return FakeResponse._items.filter(function (item) {
var doPathsMatch = uri.pathname.match(new RegExp(item.route));
if (doPathsMatch !== null) {
item.numCalls += 1;
if(item.queryParams && !FakeResponse.matchRegex(item.queryParams, uri.query)) return false;
if(item.payload && !FakeResponse.matchRegex(item.payload, payload)) return false;
if(item.requiredHeaders && !FakeResponse.matchRegex(item.requiredHeaders, headers)) return false;
if (item.at) return (item.numCalls === item.at);
return true;
}
return false;
}).sort(FakeResponse.compareMatches)[0] || null;
},
/*
* Match objB's values against regular expressions stored in objA. Key equality determines values to test.
* @param {objA} An object whose string values represent regular expressions
* @param {objB} An object whose values will be matched against objA's values
* @return {boolean} If objB matches all regular expressions
*/
matchRegex: function(objA, objB) {
if (typeof(objB) !== "object" || typeof(objA) !== "object") return false;
return Object.keys(objA).every(function(path) {
var value = _.get(objB, path);
if (!value) return false;
// Evalute regex match
var matches = String(value).match(new RegExp(objA[path]));
return matches;
});
}
};
module.exports = FakeResponse;