Skip to content
This repository was archived by the owner on Nov 21, 2018. It is now read-only.

Commit c16323e

Browse files
committed
Merge pull request #10 from mglezer/matching-improvements
Matching improvements
2 parents 91563dd + 9450198 commit c16323e

File tree

4 files changed

+70
-17
lines changed

4 files changed

+70
-17
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ This will match http://localhost:3012/news/007 as well as http://localhost:3012/
7070
> responseCode: 200,
7171
> responseBody: 'whatever you want' }
7272
73-
##### Fake-server supports "POST" calls and uses payload for matching. Regexs are supported for payload matching:
73+
##### Fake-server supports "POST" calls and uses payload for matching. Regexs are supported for payload matching, and paths can be used to specify inner properties of JSON payloads:
7474

7575
> { route: '/news'
7676
> payload: {
7777
> id: [\\d+],
78+
> requests[1].user.login: 'jdoe',
7879
> month: "february"
7980
> },
8081
> responseCode: 200,

fakeresponse.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var glob = require('glob');
1212
var path = require('path');
1313
var when = require('when');
1414
var url = require('url');
15+
var _ = require('lodash');
1516

1617
var FakeResponse = {
1718
_items: [],
@@ -50,7 +51,7 @@ var FakeResponse = {
5051
FakeResponse._items = [];
5152
},
5253

53-
/*Lexicographic comparison based on: (at, num params matched, num headers matched)*/
54+
/*Lexicographic comparison based on: (at, num query + payload params matched, num headers matched)*/
5455
compareMatches: function(matchA, matchB) {
5556
/*First rank on 'at' match*/
5657
if (!matchA.hasOwnProperty('at') && matchB.hasOwnProperty('at')) {
@@ -61,7 +62,11 @@ var FakeResponse = {
6162
}
6263

6364
/*Second rank on quality of 'params' match*/
64-
var queryCmp = Object.keys(matchB.queryParams || {}).length - Object.keys(matchA.queryParams || {}).length;
65+
var numParamsMatchedB = Object.keys(matchB.queryParams || {}).length +
66+
Object.keys(matchB.payload || {}).length;
67+
var numParamsMatchedA = Object.keys(matchA.queryParams || {}).length +
68+
Object.keys(matchA.payload || {}).length;
69+
var queryCmp = numParamsMatchedB - numParamsMatchedA;
6570
if (queryCmp !== 0) {
6671
return queryCmp;
6772
}
@@ -81,9 +86,9 @@ var FakeResponse = {
8186
if (doPathsMatch !== null) {
8287
item.numCalls += 1;
8388
if(item.queryParams && !FakeResponse.matchRegex(item.queryParams, uri.query)) return false;
84-
if(item.payload && !FakeResponse.matchRegex(item.payload, payload)) return false;
89+
if(item.payload && !FakeResponse.matchRegex(item.payload, payload)) return false;
8590
if(item.requiredHeaders && !FakeResponse.matchRegex(item.requiredHeaders, headers)) return false;
86-
if (item.at) return (item.numCalls === item.at);
91+
if (item.at) return (item.numCalls === item.at);
8792
return true;
8893
}
8994
return false;
@@ -99,14 +104,14 @@ var FakeResponse = {
99104
matchRegex: function(objA, objB) {
100105
if (typeof(objB) !== "object" || typeof(objA) !== "object") return false;
101106

102-
for (var ppty in objA) {
103-
if (!objA.hasOwnProperty(ppty) || !objB.hasOwnProperty(ppty)) return false;
107+
return Object.keys(objA).every(function(path) {
108+
var value = _.get(objB, path);
109+
if (!value) return false;
104110

105111
// Evalute regex match
106-
var matches = String(objB[ppty]).match(new RegExp(objA[ppty]));
107-
if (matches === null) return false;
108-
}
109-
return true;
112+
var matches = String(value).match(new RegExp(objA[path]));
113+
return matches;
114+
});
110115
}
111116
};
112117

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
},
2727
"dependencies": {
2828
"glob": "~5.0.14",
29+
"lodash": "~3.10.1",
2930
"merge": "^1.2.0",
3031
"restify": "=2.6.2",
3132
"rewire": "~2.3.4",

test/fakeresponse.js

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ describe('FakeResponse model tests', function () {
134134
});
135135

136136
/* POST request tests */
137-
it('should use payload to match against for POST requests', function() {
137+
it('should not match route if payload doesn\'t match', function() {
138138
model.add({
139139
route: '/match/me',
140140
payload: {
@@ -171,6 +171,46 @@ describe('FakeResponse model tests', function () {
171171
assert.deepEqual(response.responseCode, 200);
172172
});
173173

174+
it('should support paths in payload', function() {
175+
model.add({
176+
route: '/match/me',
177+
payload: {
178+
'outer[0].inner': 1
179+
},
180+
responseCode: 200,
181+
responseBody: 'weba'
182+
});
183+
model.add({
184+
route: '/match/me',
185+
payload: {
186+
'id': 2
187+
},
188+
responseCode: 403,
189+
responseBody: 'buuu'
190+
});
191+
192+
var response = model.match('/match/me', { outer: [{inner: 1 }]});
193+
assert.deepEqual(response.responseBody, 'weba');
194+
assert.deepEqual(response.responseCode, 200);
195+
});
196+
197+
it('paths should not break query param matching', function() {
198+
model.add({
199+
route: '/match/me',
200+
queryParams: {
201+
'outer[0].inner': 1
202+
},
203+
responseCode: 200,
204+
responseBody: 'weba'
205+
});
206+
207+
var response = model.match('/match/me?outer[0].inner=1');
208+
assert.deepEqual(response.responseBody, 'weba');
209+
assert.deepEqual(response.responseCode, 200);
210+
211+
response = model.match('/match/me?param=1');
212+
assert.deepEqual(response, null);
213+
});
174214
it('should match POST request payloads using explicit regular expressions', function() {
175215
model.add({
176216
route: '/match/me',
@@ -285,33 +325,39 @@ describe('FakeResponse model tests', function () {
285325
assert.deepEqual(response.responseBody, 'Regex success');
286326
});
287327

288-
it('should use number of query params matched to break ties (not order added)', function() {
328+
it('should use number of params (query and payload) matched to break ties (not order added)', function() {
289329
var route1 = {
290330
route: '/match/me',
291331
queryParams: {
292332
a: '[0-9]+'
293333
},
334+
payload: {
335+
b: '^[a-z]+$'
336+
},
294337
responseCode: 200
295338
};
296339
var route2 = {
297340
route: '/match/me',
341+
queryParams: {
342+
a: '[0-9]+'
343+
},
298344
responseCode: 400
299345
};
300346
model.add(route1);
301347
model.add(route2);
302348

303-
var response = model.match('/match/me?a=1234');
349+
var response = model.match('/match/me?a=1234', {b: 'abcd'});
304350
assert.equal(response.responseCode, 200);
305-
response = model.match('/match/me');
351+
response = model.match('/match/me?a=1234', {b: 'abc123'});
306352
assert.equal(response.responseCode, 400);
307353

308354
model.flush();
309355
model.add(route2);
310356
model.add(route1);
311357

312-
response = model.match('/match/me?a=1234');
358+
response = model.match('/match/me?a=1234', {b: 'abcd'});
313359
assert.equal(response.responseCode, 200);
314-
response = model.match('/match/me');
360+
response = model.match('/match/me?a=1234', {b: 'abc123'});
315361
assert.equal(response.responseCode, 400);
316362
});
317363

0 commit comments

Comments
 (0)