From 0779d34c99e1724dd95074a268bb8e630fbd86a6 Mon Sep 17 00:00:00 2001 From: Marc Bachmann Date: Sun, 4 Aug 2024 17:58:04 +0200 Subject: [PATCH] Support axios-like config object with params, headers and data attributes BREAKING CHANGE: Change the parameters of the methods to align it to the one of axios. The last parameter must be a config object with {params, headers} instead of just the headers. If you've always only used two parameters, you won't have to change anything. Methods with data param: - `mock.onPost(url, data, headers)` > `mock.onPost(url, data, {params, headers})` - `mock.onPut(url, data, headers)` > `mock.onPost(url, data, {params, headers})` - `mock.onPatch(url, data, headers)` > `mock.onPatch(url, data, {params, headers})` - `mock.onAny(url, data, headers)` > `mock.onAny(url, {data, params, headers})` Methods without data param: - `mock.onGet(url, {params}, headers)` > `mock.onGet(url, {params, headers})` - `mock.onDelete(url, {params}, headers)` > `mock.onDelete(url, {params, headers})` - `mock.onHead(url, {params}, headers)` > `mock.onHead(url, {params, headers})` - `mock.onOptions(url, {params}, headers)` > `mock.onOptions(url, {params, headers})` --- README.md | 8 +++++--- src/index.js | 16 +++++++++++++--- test/basics.spec.js | 18 ++++++++++++------ test/on_any.spec.js | 10 +++++++++- types/index.d.ts | 43 ++++++++++++++++++++++++++----------------- types/test.ts | 16 ++++++---------- 6 files changed, 71 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 20f6671..867bf34 100644 --- a/README.md +++ b/README.md @@ -226,9 +226,11 @@ mock .onPost( "/product", { id: 1 }, - expect.objectContaining({ - Authorization: expect.stringMatching(/^Basic /), - }) + { + headers: expect.objectContaining({ + Authorization: expect.stringMatching(/^Basic /), + }) + } ) .reply(204); ``` diff --git a/src/index.js b/src/index.js index babbc3d..74f956a 100644 --- a/src/index.js +++ b/src/index.js @@ -79,15 +79,25 @@ 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 data || {}; + } else { + return Object.assign({}, config || {}, { data: data }); + } +} + VERBS.concat("any").forEach(function (method) { var methodName = "on" + method.charAt(0).toUpperCase() + method.slice(1); - MockAdapter.prototype[methodName] = function (matcher, paramsAndBody, requestHeaders) { + MockAdapter.prototype[methodName] = 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, paramsAndBody, requestHeaders, code, response, headers, false, delay]; + var handler = [matcher, paramsAndBody, paramsAndBody.headers, code, response, headers, false, delay]; addHandler(method, _this.handlers, handler); return _this; } @@ -100,7 +110,7 @@ VERBS.concat("any").forEach(function (method) { } function replyOnce(code, response, headers) { - var handler = [matcher, paramsAndBody, requestHeaders, code, response, headers, true, delay]; + var handler = [matcher, paramsAndBody, paramsAndBody.headers, code, response, headers, true, delay]; addHandler(method, _this.handlers, handler); return _this; } diff --git a/test/basics.spec.js b/test/basics.spec.js index 285f0e6..735fbfc 100644 --- a/test/basics.spec.js +++ b/test/basics.spec.js @@ -185,7 +185,7 @@ describe("MockAdapter basics", 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 @@ -197,7 +197,7 @@ describe("MockAdapter basics", 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 @@ -251,17 +251,17 @@ describe("MockAdapter basics", function () { }); it("can pass a body to match to a handler", function () { - mock.onPost("/withBody", { body: { is: "passed" } }).reply(200); + mock.onPost("/withBody", { somecontent: { is: "passed" } }).reply(200); return instance - .post("/withBody", { body: { is: "passed" } }) + .post("/withBody", { somecontent: { is: "passed" } }) .then(function (response) { expect(response.status).to.equal(200); }); }); it("does not match when body is wrong", function () { - var matcher = { body: { is: "passed" } }; + var matcher = { somecontent: { is: "passed" } }; mock.onPatch("/wrongObjBody", matcher).reply(200); return instance @@ -294,12 +294,18 @@ 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); + }); }); }); diff --git a/test/on_any.spec.js b/test/on_any.spec.js index a91b194..f063624 100644 --- a/test/on_any.spec.js +++ b/test/on_any.spec.js @@ -45,7 +45,7 @@ describe("MockAdapter onAny", function () { { object: { with: { deep: "property" } }, array: ["1", "abc"] }, "a", ]; - mock.onAny("/anyWithBody", body).reply(200); + mock.onAny("/anyWithBody", { data: body }).reply(200); return instance .put("/anyWithBody", body) @@ -54,6 +54,14 @@ describe("MockAdapter onAny", function () { }) .then(function (response) { expect(response.status).to.equal(200); + + return instance.post("/anyWithBody") + .then(function () { + throw new Error("should not get here"); + }) + .catch(function (err) { + expect(err.response.status).to.equal(404); + }); }); }); diff --git a/types/index.d.ts b/types/index.d.ts index a5afa6b..3115908 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -33,25 +33,34 @@ interface AsymmetricMatcher { asymmetricMatch: Function; } -interface RequestDataMatcher { - [index: string]: any; - params?: { - [index: string]: any; - }; +interface ParamsMatcher { + [param: string]: any; } interface HeadersMatcher { [header: string]: string; } +type UrlMatcher = string | RegExp; +type AsymmetricParamsMatcher = AsymmetricMatcher | ParamsMatcher; type AsymmetricHeadersMatcher = AsymmetricMatcher | HeadersMatcher; +type AsymmetricRequestDataMatcher = AsymmetricMatcher | any; -type AsymmetricRequestDataMatcher = AsymmetricMatcher | RequestDataMatcher; +interface ConfigMatcher { + params?: AsymmetricParamsMatcher; + headers?: AsymmetricHeadersMatcher; + data?: AsymmetricRequestDataMatcher; +} type RequestMatcherFunc = ( - matcher?: string | RegExp, - body?: string | AsymmetricRequestDataMatcher, - headers?: AsymmetricHeadersMatcher + matcher?: UrlMatcher, + body?: AsymmetricRequestDataMatcher, + config?: ConfigMatcher +) => MockAdapter.RequestHandler; + +type NoBodyRequestMatcherFunc = ( + matcher?: UrlMatcher, + config?: ConfigMatcher ) => MockAdapter.RequestHandler; declare class MockAdapter { @@ -67,17 +76,17 @@ declare class MockAdapter { history: { [method: string]: AxiosRequestConfig[] }; - onGet: RequestMatcherFunc; + onList: NoBodyRequestMatcherFunc; + onOptions: NoBodyRequestMatcherFunc; + onAny: NoBodyRequestMatcherFunc; + onLink: NoBodyRequestMatcherFunc; + onUnlink: NoBodyRequestMatcherFunc; + onGet: NoBodyRequestMatcherFunc; + onHead: NoBodyRequestMatcherFunc; + onDelete: NoBodyRequestMatcherFunc; onPost: RequestMatcherFunc; onPut: RequestMatcherFunc; - onHead: RequestMatcherFunc; - onDelete: RequestMatcherFunc; onPatch: RequestMatcherFunc; - onList: RequestMatcherFunc; - onOptions: RequestMatcherFunc; - onAny: RequestMatcherFunc; - onLink: RequestMatcherFunc; - onUnlink: RequestMatcherFunc; } export = MockAdapter; diff --git a/types/test.ts b/types/test.ts index e17a164..da439b6 100644 --- a/types/test.ts +++ b/types/test.ts @@ -75,18 +75,14 @@ namespace AllowsStringBodyMatcher { } namespace AllowsBodyMatcher { - mock.onGet('/foo', { - id: 4, - name: 'foo' - }); + mock.onPost('/foo', {id: 4, name: 'foo'}); + mock.onPut('/foo', {id: 4, name: 'foo'}); + mock.onAny('/foo', {data: {id: 4, name: 'foo'}}); } -namespace AllowsParameterMatcher { - mock.onGet('/foo', { - params: { - searchText: 'John' - } - }); +namespace AllowsParamsMatcher { + mock.onGet('/foo', {params: {searchText: 'John'}}); + mock.onDelete('/foo', {params: {searchText: 'John'}}); } namespace AllowsReplyWithStatus {