diff --git a/packages/api/features/getRequests.feature b/packages/api/features/getRequests.feature deleted file mode 100644 index 1ba5cf7..0000000 --- a/packages/api/features/getRequests.feature +++ /dev/null @@ -1,18 +0,0 @@ -Feature: API - GET Requests - - Tesing GET requests to different apis and endpoints - - Scenario: GET request to a single resource - When perform api request: - """ - { - "url": "http://google.com", - "api": "/maps", - "method": "GET", - "headers": { - "Accept": "application/json", - "Content-Type": "application/x-www-form-urlencoded" - } - } - """ - Then the status is 200 \ No newline at end of file diff --git a/packages/api/features/requests.feature b/packages/api/features/requests.feature new file mode 100644 index 0000000..bd5b137 --- /dev/null +++ b/packages/api/features/requests.feature @@ -0,0 +1,55 @@ +Feature: API - Requests + + Tesing GET requests to different apis and endpoints + + Scenario: GET request to a single resource + When perform api request: + """ + { + "url": "https://httpbin.org", + "api": "/get", + "method": "GET", + "headers": { + "Accept": "application/json", + "Content-Type": "application/x-www-form-urlencoded" + } + } + """ + Then the status is 200 + + Scenario: POST request to a single resource + When perform api request: + """ + { + "url": "http://httpbin.org", + "api": "/post", + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/x-www-form-urlencoded" + }, + "body": { + "name": "John Doe", + "age": 30 + } + } + """ + Then the status is 200 + + Scenario: POST - urlEncodedBody + When perform api request: + """ + { + "url": "http://httpbin.org", + "api": "/post", + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/x-www-form-urlencoded" + }, + "urlEncodedBody": { + "hello": "THERE" + } + } + """ + Then the status is 200 \ No newline at end of file diff --git a/packages/api/stepDefinitions/api.js b/packages/api/stepDefinitions/api.js index 670c796..988b3fa 100644 --- a/packages/api/stepDefinitions/api.js +++ b/packages/api/stepDefinitions/api.js @@ -9,6 +9,56 @@ const { fetchToCurl } = require('fetch-to-curl') setDefaultTimeout(15 * 1000) +/** + * @deprecated Set the item 'url' instead + */ +MAFWhen('url {string}', function (url) { + filltemplate(url, this.results) + // Remove trailing slash + url = url.replace(/\/$/, '') + MAFSave.call(this, 'url', url) +}) + +/** + * @deprecated Set the item 'api' instead + */ +MAFWhen('api {string}', function (api) { + filltemplate(api, this.results) + // Remove leading slash + api = api.replace(/^\//, '') + MAFSave.call(this, 'api', api) +}) + +/** + * @deprecated Set the item 'body' instead + */ +MAFWhen('body {string}', function (body) { + filltemplate(body, this.results) + MAFSave.call(this, 'body', body) +}) + +/** + * @deprecated Set the item 'headers' instead + */ +MAFWhen('headers {string}', function (headers) { + filltemplate(headers, this.results) + MAFSave.call(this, 'headers', headers) +}) + +/** + * @deprecated Set the item 'method' instead + */ +MAFWhen('method post', async function () { + MAFSave.call(this, 'method', 'POST') +}) + +/** + * @deprecated Set the item 'method' instead + */ +MAFWhen('method get', async function () { + MAFSave.call(this, 'method', 'GET') +}) + // Builds a request object from the given request, populating any missing fields using the results object async function requestBuilder(request) { if (!request.url && this.results && this.results.url) { @@ -17,6 +67,7 @@ async function requestBuilder(request) { if (!request.url) { throw new Error('A url must be provided either in the request or in the results object') } + request.url = request.url.replace(/\/$/, '') if (!request.headers && this.results && this.results.headers) { request.headers = this.results.headers @@ -38,14 +89,14 @@ async function requestBuilder(request) { request.urlEncodedBody = this.results.urlEncodedBody } if (request.urlEncodedBody) { - const formBody = [] + const urlEncodedBody = [] const details = request.urlEncodedBody for (const property in details) { const encodedKey = encodeURIComponent(property) const encodedValue = encodeURIComponent(details[property]) - formBody.push(encodedKey + '=' + encodedValue) + urlEncodedBody.push(encodedKey + '=' + encodedValue) } - request.formBody = formBody.join('&') + request.api = request.api + '?' + urlEncodedBody.join('&') } const formBodyMap = function (item) { switch (item.type) { @@ -69,7 +120,7 @@ async function requestBuilder(request) { data.append(property, formBodyMap.call(this, details[property])) } } - this.request.body = data + request.body = data } if (!request.method && this.results && this.results.method) { @@ -79,6 +130,9 @@ async function requestBuilder(request) { if (!request.api && this.results && this.results.api) { request.api = this.results.api } + if (request.api) { + request.api = request.api.replace(/^\//, '') + } if (!request.apiParams && this.results && this.results.apiParams) { request.apiParams = this.results.apiParams } @@ -91,8 +145,7 @@ async function requestBuilder(request) { formBody.push(encodedKey + '=' + encodedValue) } formBody = formBody.join('&') - const api = this.request.api ? this.request.api : '' - MAFSave.call(this, 'api', api + '?' + formBody) + request.api = request.api + '?' + formBody } let additionalParams = {} if (this.results && this.results.api) { @@ -114,13 +167,13 @@ async function performRequest(request, additionalParams = {}) { url.push(request.api) } const absoluteUrl = url.join('/') - const req = await fetch(absoluteUrl, params) + const response = await fetch(absoluteUrl, params) const curlCommand = fetchToCurl(absoluteUrl, params) let text if (this.results.apiRetrieveType) { - text = await (req[this.results.apiRetrieveType])() - } else if (req.headers.get('content-type') && req.headers.get('content-type').includes('image')) { - text = await req.blob() + text = await (response[this.results.apiRetrieveType])() + } else if (response.headers.get('content-type') && response.headers.get('content-type').includes('image')) { + text = await response.blob() try { if (canAttach.call(this)) { const tmpBlob = Buffer.from(await text.arrayBuffer()) @@ -129,78 +182,28 @@ async function performRequest(request, additionalParams = {}) { } catch (err) { } } else { try { - text = await req.text() + text = await response.text() text = JSON.parse(text) } catch (err) { } } - const headers = await req.headers.raw() + const headers = await response.headers.raw() Object.keys(headers).forEach(header => { headers[header] = headers[header][0] }) - const res = { + const results = { request: { absoluteUrl, ...params }, curlCommand, - ok: req.ok, - status: req.status, + ok: response.ok, + status: response.status, response: text, headers } - return res + return results } -/** - * @deprecated Set the item 'url' instead - */ -MAFWhen('url {string}', function (url) { - filltemplate(url, this.results) - // Remove trailing slash - url = url.replace(/\/$/, '') - MAFSave.call(this, 'url', url) -}) - -/** - * @deprecated Set the item 'api' instead - */ -MAFWhen('api {string}', function (api) { - filltemplate(api, this.results) - // Remove leading slash - api = api.replace(/^\//, '') - MAFSave.call(this, 'api', api) -}) - -/** - * @deprecated Set the item 'body' instead - */ -MAFWhen('body {string}', function (body) { - filltemplate(body, this.results) - MAFSave.call(this, 'body', body) -}) - -/** - * @deprecated Set the item 'headers' instead - */ -MAFWhen('headers {string}', function (headers) { - filltemplate(headers, this.results) - MAFSave.call(this, 'headers', headers) -}) - -/** - * @deprecated Set the item 'method' instead - */ -MAFWhen('method post', async function () { - MAFSave.call(this, 'method', 'POST') -}) - -/** - * @deprecated Set the item 'method' instead - */ -MAFWhen('method get', async function () { - MAFSave.call(this, 'method', 'GET') -}) - MAFWhen('api request from {jsonObject} is performed', async function (request) { request = performJSONObjectTransform.call(this, request) const results = await requestBuilder.call(this, request)