Skip to content

Commit

Permalink
Merge pull request #32 from Xyedo/feature/sophisticated-query-param-m…
Browse files Browse the repository at this point in the history
…atcher

chore(enhancement): query param value matches on decodedURI value set
  • Loading branch information
jordanwalsh23 authored Jul 22, 2024
2 parents 99cb56f + 4148e59 commit 3f6aeef
Show file tree
Hide file tree
Showing 3 changed files with 846 additions and 465 deletions.
91 changes: 68 additions & 23 deletions lib/responses.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const _ = require('lodash')
const distance = require('fastest-levenshtein').distance

function getMatchedResponse(req, responses, debug) {
function getMatchedResponse(req, responses, debug) {
var bestMatchedResponse = null;
var bestMatchedResponseScore = 0;

Expand All @@ -15,7 +15,7 @@ function getMatchedResponse(req, responses, debug) {
if (responsesToProcess.length == 0) {
return;
}

//2. Filter on Custom Mock Server Headers
//Check and see if any of the mock response selectors were used
let postmanHeaders = [
Expand Down Expand Up @@ -60,7 +60,7 @@ function getMatchedResponse(req, responses, debug) {
return matchedPostmanHeadersResponse;
}
}

//3. Filter by URL
debug && console.log('scoring responses by URL match...')

Expand Down Expand Up @@ -183,37 +183,80 @@ function getMatchedResponse(req, responses, debug) {
//iterate through the results array as these are the only potential matches.
Object.keys(results).forEach((id) => {

let response = responsesToProcess.find(response => response.id == id);
debug && console.log('Scoring query parameters')
let response = responsesToProcess.find(
(response) => response.id == id
);
debug && console.log("Scoring query parameters");
let fullMatches = 0;
let partialMatches = 0;
let missingMatches = 0;
let totalQueryParams = Object.keys(req.query).length;

let kv = new Map();
const responseHasQueryMember =
response.originalRequest &&
response.originalRequest.url &&
response.originalRequest.url.query &&
response.originalRequest.url.query.members &&
Array.isArray(response.originalRequest.url.query.members);

if (responseHasQueryMember) {
const decodeAndSplit = (value) =>
value.split(",").map(decodeURI);

/**
* Iterate through the query parameters and check the following:
*
* 1. if param is disabled, skip it
* 2. If we have already processed a query param with this key - retrieve the value, else return an empty array.
* 3. Evaluate the current param value
* 3.1. If the param value is an array, flatten each item of the array and return the decoded version.
* 3.2. If the param value is not an array, return the decoded version.
* 4. Update the value in the Key/Value Map.
*/

for (const param of response.originalRequest.url.query
.members) {
if (param.disabled) {
continue;
}

const existingValues = kv.get(param.key) || [];
const thisParamValues = Array.isArray(param.value)
? param.value.flatMap(decodeAndSplit)
: decodeAndSplit(param.value);
kv.set(param.key, existingValues.concat(thisParamValues));
}
}

Object.keys(req.query).every((key) => {
if (responseHasQueryMember) {
const queryValueSet = new Set();
if (Array.isArray(req.query[key])) {
for (const value of req.query[key]) {
queryValueSet.add(decodeURI(value));
}
} else {
queryValueSet.add(decodeURI(req.query[key]));
}

if (
response.originalRequest &&
response.originalRequest.url &&
response.originalRequest.url.query &&
response.originalRequest.url.query.members &&
Array.isArray(response.originalRequest.url.query.members)
) {
let matchKeyAndValue =
response.originalRequest.url.query.find(param => {
return key == param.key && req.query[key] == param.value
})
const matchKeyAndValue = kv
.get(key)
?.every((value) => queryValueSet.has(value)) ?? false;

if (matchKeyAndValue) {
debug && console.log("key and value match");
//We found a matched query and value so increase the score.
fullMatches++;
return true;
}

let match = response.originalRequest.url.query.find(param => {
debug && console.log("key:" + key.toLowerCase(), "param key: ", param.key.toLowerCase())
return key.toLowerCase() == param.key.toLowerCase()
})
let match = response.originalRequest.url.query.members.find(
(param) => {
debug && console.log("key:" + key.toLowerCase(),"param key: ",param.key.toLowerCase());
return key.toLowerCase() == param.key.toLowerCase();
}
);

if (match) {
//We found a matched query key so increase the score.
Expand All @@ -223,15 +266,17 @@ function getMatchedResponse(req, responses, debug) {
missingMatches++;
return true;
}

} else {
debug && console.log('No query parameters on this response example.')
debug &&
console.log(
"No query parameters on this response example."
);
}
});

let matchingPct = parseFloat(fullMatches / (fullMatches + partialMatches + missingMatches));
debug && console.log(`matchingpct: ${matchingPct}.`, fullMatches, partialMatches, missingMatches, totalQueryParams);
debug && console.log(fullMatches == totalQueryParams)
debug && console.log(`isallMatch`,fullMatches == totalQueryParams)

debug && console.log("results score before: ", results[id].score)

Expand Down
Loading

0 comments on commit 3f6aeef

Please sign in to comment.