Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix params comparisons for post and put requests - Breaking Change #387

Merged
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,11 @@ mock
.onPost(
"/product",
{ id: 1 },
expect.objectContaining({
Authorization: expect.stringMatching(/^Basic /),
})
{
headers: expect.objectContaining({
Authorization: expect.stringMatching(/^Basic /),
})
}
)
.reply(204);
```
Expand Down
2 changes: 1 addition & 1 deletion src/handle_request.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function handleRequest(mockAdapter, resolve, reject, config) {
config.data,
config.params,
(config.headers && config.headers.constructor.name === 'AxiosHeaders')
? Object.assign({}, config.headers)
? Object.assign({}, config.headers.toJSON())
: config.headers,
config.baseURL
);
Expand Down
41 changes: 36 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,46 @@ MockAdapter.prototype.reset = reset;
MockAdapter.prototype.resetHandlers = resetHandlers;
MockAdapter.prototype.resetHistory = resetHistory;

var methodsWithConfigsAsSecondArg = ["any", "get", "delete", "head", "options"];
function convertDataAndConfigToConfig (method, data, config) {
if (methodsWithConfigsAsSecondArg.includes(method)) {
return validateconfig(method, data || {});
} else {
return validateconfig(method, Object.assign({}, config, { data: data }));
}
}

var allowedConfigProperties = ['headers', 'params', 'data'];
function validateconfig (method, config) {
for (var key in config) {
if (!allowedConfigProperties.includes(key)) {
throw new Error(
'Invalid config property ' +
JSON.stringify(key) +
' provided to ' +
toMethodName(method) +
'. Config: ' +
JSON.stringify(config)
);
}
}

return config;
}

function toMethodName (method) {
return "on" + method.charAt(0).toUpperCase() + method.slice(1);
}

VERBS.concat("any").forEach(function (method) {
var methodName = "on" + method.charAt(0).toUpperCase() + method.slice(1);
MockAdapter.prototype[methodName] = function (matcher, body, requestHeaders) {
MockAdapter.prototype[toMethodName(method)] = function (matcher, data, config) {
var _this = this;
var matcher = matcher === undefined ? /.*/ : matcher;
var delay;
var paramsAndBody = convertDataAndConfigToConfig(method, data, config);

function reply(code, response, headers) {
var handler = [matcher, body, requestHeaders, code, response, headers, false, delay];
var handler = [matcher, paramsAndBody, paramsAndBody.headers, code, response, headers, false, delay];
addHandler(method, _this.handlers, handler);
return _this;
}
Expand All @@ -100,7 +131,7 @@ VERBS.concat("any").forEach(function (method) {
}

function replyOnce(code, response, headers) {
var handler = [matcher, body, requestHeaders, code, response, headers, true, delay];
var handler = [matcher, paramsAndBody, paramsAndBody.headers, code, response, headers, true, delay];
addHandler(method, _this.handlers, handler);
return _this;
}
Expand All @@ -113,7 +144,7 @@ VERBS.concat("any").forEach(function (method) {
withDelayInMs: withDelayInMs,

passThrough: function passThrough() {
var handler = [matcher, body];
var handler = [matcher, paramsAndBody];
addHandler(method, _this.handlers, handler);
return _this;
},
Expand Down
39 changes: 18 additions & 21 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,18 @@ function findHandler(
baseURL
) {
return find(handlers[method.toLowerCase()], function (handler) {
var matchesUrl = false;
if (typeof handler[0] === "string") {
return (
(isUrlMatching(url, handler[0]) ||
isUrlMatching(combineUrls(baseURL, url), handler[0])) &&
isBodyOrParametersMatching(method, body, parameters, handler[1]) &&
isObjectMatching(headers, handler[2])
);
matchesUrl = isUrlMatching(url, handler[0]) ||
isUrlMatching(combineUrls(baseURL, url), handler[0]);
} else if (handler[0] instanceof RegExp) {
return (
(handler[0].test(url) || handler[0].test(combineUrls(baseURL, url))) &&
isBodyOrParametersMatching(method, body, parameters, handler[1]) &&
isObjectMatching(headers, handler[2])
);
matchesUrl = handler[0].test(url) ||
handler[0].test(combineUrls(baseURL, url));
}

return matchesUrl &&
isBodyOrParametersMatching(body, parameters, handler[1]) &&
isObjectMatching(headers, handler[2]);
});
}

Expand All @@ -71,15 +69,9 @@ function isUrlMatching(url, required) {
return noSlashUrl === noSlashRequired;
}

function isBodyOrParametersMatching(method, body, parameters, required) {
var allowedParamsMethods = ["delete", "get", "head", "options"];
if (allowedParamsMethods.indexOf(method.toLowerCase()) >= 0) {
var data = required ? required.data : undefined;
var params = required ? required.params : undefined;
return isObjectMatching(parameters, params) && isBodyMatching(body, data);
} else {
return isBodyMatching(body, required);
}
function isBodyOrParametersMatching(body, parameters, required) {
return isObjectMatching(parameters, required && required.params) &&
isBodyMatching(body, required && required.data);
}

function isObjectMatching(actual, expected) {
Expand Down Expand Up @@ -174,7 +166,12 @@ function createAxiosError(message, config, response, code) {
function createCouldNotFindMockError(config) {
var message =
"Could not find mock for: \n" +
JSON.stringify(config, ["method", "url"], 2);
JSON.stringify({
method: config.method,
url: config.url,
params: config.params,
headers: config.headers
}, null, 2);
var error = new Error(message);
error.isCouldNotFindMockError = true;
error.url = config.url;
Expand Down
70 changes: 38 additions & 32 deletions test/basics.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ describe("MockAdapter basics", function () {
.reply(200);

return instance
.get("/withParams", { params: { bar: "foo", foo: "bar" }, in: true })
.get("/withParams", { params: { bar: "foo", foo: "bar" } })
.then(function (response) {
expect(response.status).to.equal(200);
});
Expand All @@ -153,7 +153,7 @@ describe("MockAdapter basics", function () {
.reply(200);

return instance
.delete("/withParams", { params: { bar: "foo", foo: "bar" }, in: true })
.delete("/withParams", { params: { bar: "foo", foo: "bar" } })
.then(function (response) {
expect(response.status).to.equal(200);
});
Expand All @@ -177,33 +177,33 @@ describe("MockAdapter basics", function () {
.reply(200);

return instance
.head("/withParams", { params: { bar: "foo", foo: "bar" }, in: true })
.head("/withParams", { params: { bar: "foo", foo: "bar" } })
.then(function (response) {
expect(response.status).to.equal(200);
});
});

it("can't pass query params for post to match to a handler", function () {
it("can pass query params for post to match to a handler", function () {
mock
.onPost("/withParams", { params: { foo: "bar", bar: "foo" } })
.onPost("/withParams", undefined, { params: { foo: "bar", bar: "foo" } })
.reply(200);

return instance
.post("/withParams", { params: { foo: "bar", bar: "foo" }, in: true })
.catch(function (error) {
expect(error.response.status).to.equal(404);
.post("/withParams", { some: 'body' }, { params: { foo: "bar", bar: "foo" } })
.then(function (response) {
expect(response.status).to.equal(200);
});
});

it("can't pass query params for put to match to a handler", function () {
it("can pass query params for put to match to a handler", function () {
mock
.onPut("/withParams", { params: { foo: "bar", bar: "foo" } })
.onPut("/withParams", undefined, { params: { foo: "bar", bar: "foo" } })
.reply(200);

return instance
.put("/withParams", { params: { bar: "foo", foo: "bar" }, in: true })
.catch(function (error) {
expect(error.response.status).to.equal(404);
.put("/withParams", { some: 'body' }, { params: { bar: "foo", foo: "bar" } })
.then(function (response) {
expect(response.status).to.equal(200);
});
});

Expand All @@ -221,7 +221,7 @@ describe("MockAdapter basics", function () {
});
});

it("does not match when parameters are wrong", function () {
it("does not match when params are wrong", function () {
mock
.onGet("/withParams", { params: { foo: "bar", bar: "foo" } })
.reply(200);
Expand All @@ -232,7 +232,7 @@ describe("MockAdapter basics", function () {
});
});

it("does not match when parameters are missing", function () {
it("does not match when params are missing", function () {
mock
.onGet("/withParams", { params: { foo: "bar", bar: "foo" } })
.reply(200);
Expand All @@ -241,7 +241,7 @@ describe("MockAdapter basics", function () {
});
});

it("matches when parameters were not expected", function () {
it("matches when params were not expected", function () {
mock.onGet("/withParams").reply(200);
return instance
.get("/withParams", { params: { foo: "bar", bar: "foo" } })
Expand All @@ -251,18 +251,18 @@ describe("MockAdapter basics", function () {
});

it("can pass a body to match to a handler", function () {
mock.onPost("/withBody", { body: { is: "passed" }, in: true }).reply(200);
mock.onPost("/withBody", { somecontent: { is: "passed" } }).reply(200);

return instance
.post("/withBody", { body: { is: "passed" }, in: true })
.post("/withBody", { somecontent: { is: "passed" } })
.then(function (response) {
expect(response.status).to.equal(200);
});
});

it("does not match when body is wrong", function () {
var body = { body: { is: "passed" }, in: true };
mock.onPatch("/wrongObjBody", body).reply(200);
var matcher = { somecontent: { is: "passed" } };
mock.onPatch("/wrongObjBody", matcher).reply(200);

return instance
.patch("/wrongObjBody", { wrong: "body" })
Expand Down Expand Up @@ -294,18 +294,24 @@ describe("MockAdapter basics", function () {
"Header-test": "test-header",
};

mock.onPost("/withHeaders", undefined, headers).reply(200);
mock.onPost("/withHeaders", undefined, { headers: headers }).reply(200);

return instance
.post("/withHeaders", undefined, { headers: headers })
.then(function (response) {
expect(response.status).to.equal(200);

return instance
.post("/withHeaders", undefined, { headers: { Accept: 'no-match' } })
.catch(function (err) {
expect(err.response.status).to.equal(404);
});
});
});

it("does not match when request header is wrong", function () {
var headers = { "Header-test": "test-header" };
mock.onPatch("/wrongObjHeader", undefined, headers).reply(200);
mock.onPatch("/wrongObjHeader", undefined, { headers: headers }).reply(200);

return instance
.patch("/wrongObjHeader", undefined, {
Expand Down Expand Up @@ -558,7 +564,7 @@ describe("MockAdapter basics", function () {

it("allows delay in millsecond per request (legacy non-chaining)", function () {
mock = new MockAdapter(instance);
var start = new Date().getTime();
var start = Date.now();
var firstDelay = 100;
var secondDelay = 500;
var success = 200;
Expand All @@ -570,14 +576,14 @@ describe("MockAdapter basics", function () {

return Promise.all([
instance.get("/foo").then(function (response) {
var end = new Date().getTime();
var end = Date.now();
var totalTime = end - start;

expect(response.status).to.equal(success);
expect(totalTime).greaterThanOrEqual(firstDelay);
}),
instance.get("/bar").then(function (response) {
var end = new Date().getTime();
var end = Date.now();
var totalTime = end - start;

expect(response.status).to.equal(success);
Expand All @@ -588,7 +594,7 @@ describe("MockAdapter basics", function () {

it("allows delay in millsecond per request", function () {
mock = new MockAdapter(instance);
var start = new Date().getTime();
var start = Date.now();
var firstDelay = 100;
var secondDelay = 500;
var success = 200;
Expand All @@ -603,14 +609,14 @@ describe("MockAdapter basics", function () {

return Promise.all([
instance.get("/foo").then(function (response) {
var end = new Date().getTime();
var end = Date.now();
var totalTime = end - start;

expect(response.status).to.equal(success);
expect(totalTime).greaterThanOrEqual(firstDelay);
}),
instance.get("/bar").then(function (response) {
var end = new Date().getTime();
var end = Date.now();
var totalTime = end - start;

expect(response.status).to.equal(success);
Expand All @@ -620,7 +626,7 @@ describe("MockAdapter basics", function () {
});

it("overrides global delay if request per delay is provided and respects global delay if otherwise", function () {
var start = new Date().getTime();
var start = Date.now();
var requestDelay = 100;
var globalDelay = 500;
var success = 200;
Expand All @@ -632,7 +638,7 @@ describe("MockAdapter basics", function () {

return Promise.all([
instance.get("/foo").then(function (response) {
var end = new Date().getTime();
var end = Date.now();
var totalTime = end - start;

expect(response.status).to.equal(success);
Expand All @@ -641,7 +647,7 @@ describe("MockAdapter basics", function () {
expect(totalTime).lessThan(globalDelay);
}),
instance.get("/bar").then(function (response) {
var end = new Date().getTime();
var end = Date.now();
var totalTime = end - start;

expect(response.status).to.equal(success);
Expand Down Expand Up @@ -850,7 +856,7 @@ describe("MockAdapter basics", function () {
});
});

it("allows overwriting mocks with parameters", function () {
it("allows overwriting mocks with params", function () {
mock
.onGet("/users", { params: { searchText: "John" } })
.reply(500)
Expand Down
Loading
Loading