From ded3fb42218fe96dfa8a13ede01a1dce88a4f43c Mon Sep 17 00:00:00 2001 From: Andrey Ovcharov Date: Tue, 23 Jul 2019 16:04:46 +0200 Subject: [PATCH] fix: correct handling of parameters in URI templates * Resolve #165 - incorrect handling of parameters in URL * Added sorting of resourceURLs for better matching --- src/mock.js | 20 ++++++++++++-- test/fixtures/apib-url-parameters.apib | 37 ++++++++++++++++++++++++++ test/mock-apib-url-parameters.js | 32 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/apib-url-parameters.apib create mode 100644 test/mock-apib-url-parameters.js diff --git a/src/mock.js b/src/mock.js index 176804e..395a755 100644 --- a/src/mock.js +++ b/src/mock.js @@ -13,7 +13,7 @@ apiDescription(_); // Extend lodash const mock = (refract, options) => { return new Promise((resolve, reject) => { - let mocks = []; + let routes = {}; const resourceGroups = _.filter(refract.content, { 'element': 'category' @@ -77,7 +77,12 @@ const mock = (refract, options) => { responseBody, responseHeaders }; - mocks.push(mockRoute(nockOptions)); + + if(!routes.hasOwnProperty(resourceUrl)) { + routes[resourceUrl] = []; + } + + routes[resourceUrl].push(nockOptions); }); }); }); @@ -85,6 +90,17 @@ const mock = (refract, options) => { }); }); + // sort URLs by length + const urls = Object.keys(routes); + urls.sort((a, b) => b.length - a.length); + + // collect mocks + const mocks = []; + urls.forEach(url => { + const resources = routes[url]; + resources.forEach(resource => mocks.push(mockRoute(resource))) + }); + const restore = () => { mocks.forEach((mock) => { mock.interceptors.forEach((interceptor) => nock.removeInterceptor(interceptor)); diff --git a/test/fixtures/apib-url-parameters.apib b/test/fixtures/apib-url-parameters.apib new file mode 100644 index 0000000..7266d3f --- /dev/null +++ b/test/fixtures/apib-url-parameters.apib @@ -0,0 +1,37 @@ +FORMAT: 1A +HOST: http://example.com + +# API blueprint + +# Data Structures + +## User (object) + + id: `1` (number) + + username: `example` (string) + +## Post (object) + + id: `1` (number) + + user_id: `1` (number) + + text: `Post text` (string) + +# Group User + +## User details [/users/{user}/] + +### Get user details [GET] + ++ Parameters + + user: `example` (string) + ++ Response 200 (application/json) + + Attributes (User) + +## User posts [/users/{user}/posts/] + +### Get user's posts [GET] + ++ Parameters + + user: `example` (string) + ++ Response 200 (application/json) + + Attributes (array[Post]) diff --git a/test/mock-apib-url-parameters.js b/test/mock-apib-url-parameters.js new file mode 100644 index 0000000..50890d3 --- /dev/null +++ b/test/mock-apib-url-parameters.js @@ -0,0 +1,32 @@ +import fs from 'fs'; +import hippie from 'hippie'; +import apish from '../dist/apish.js'; + +describe('Mock APIB with parameters in URL', () => { + let mockResult = {}; + before(() => { + const apib = fs.readFileSync(__dirname + '/fixtures/apib-url-parameters.apib'); + return mockResult = apish(apib.toString()); + }); + + after(() => { + mockResult.value().restore(); + }); + + it('should mock the GET /users/example/posts/ request including body', (done) => { + hippie() + .json() + .base('http://example.com') + .get('/users/example/posts/') + .expectStatus(200) + .expectHeader('Content-Type', 'application/json') + .expectBody([ + { + id: 1, + user_id: 1, + text: 'Post text' + } + ]) + .end(done); + }); +});