From 91b7c1209e9323a3eb52148dd9e74527a4564f87 Mon Sep 17 00:00:00 2001 From: David Grayston Date: Fri, 27 Sep 2019 15:25:51 +0100 Subject: [PATCH 1/6] SDK-1203: Allow empty response body --- src/request/request.handler.js | 5 +- tests/request/request.handler.spec.js | 112 ++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 tests/request/request.handler.spec.js diff --git a/src/request/request.handler.js b/src/request/request.handler.js index d18140c0..c466a14c 100644 --- a/src/request/request.handler.js +++ b/src/request/request.handler.js @@ -23,8 +23,9 @@ module.exports.execute = yotiRequest => new Promise((resolve, reject) => { request .then((response) => { try { - const parsedResponse = JSON.parse(response.text); - const receipt = parsedResponse.receipt || null; + const parsedResponse = response.text !== '' ? JSON.parse(response.text) : null; + const receipt = parsedResponse !== null ? parsedResponse.receipt : null; + return resolve(new YotiResponse(parsedResponse, response.statusCode, receipt)); } catch (err) { return reject(err); diff --git a/tests/request/request.handler.spec.js b/tests/request/request.handler.spec.js new file mode 100644 index 00000000..be0b4aae --- /dev/null +++ b/tests/request/request.handler.spec.js @@ -0,0 +1,112 @@ +const nock = require('nock'); +const fs = require('fs'); +const yotiRequestHandler = require('../../src/request/request.handler'); +const { RequestBuilder } = require('../../src/request/request.builder'); +const { Payload } = require('../../src/request/payload'); + +const SOME_BASE_URL = 'https://someapi.yoti.com'; +const SOME_ENDPOINT = '/some/endpoint'; +const SOME_ENDPOINT_REG_EXP = new RegExp(`^${SOME_ENDPOINT}`); +const SOME_PEM_STRING = fs.readFileSync('./tests/sample-data/keys/node-sdk-test.pem', 'utf8'); +const ALLOWED_METHODS = ['POST', 'PUT', 'PATCH', 'GET', 'DELETE']; +const SOME_JSON_DATA = { some: 'json' }; +const SOME_JSON_RECEIPT_DATA = { receipt: 'some receipt' }; + +/** + * @param {string} method + * @param {string} uri + * @param {integer} responseCode + * @param {string} body + */ +const mockResponse = (method, uri, responseCode, body) => { + const scope = nock(SOME_BASE_URL); + const interceptor = scope[method.toLowerCase()](uri); + interceptor.reply(responseCode, body); +}; + +describe('yotiRequest', () => { + afterEach((done) => { + nock.cleanAll(); + done(); + }); + + ALLOWED_METHODS.forEach((ALLOWED_METHOD) => { + describe(`when empty response is returned for ${ALLOWED_METHOD} method`, () => { + beforeEach((done) => { + mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, ''); + done(); + }); + + it('should return YotiResponse', (done) => { + const request = new RequestBuilder() + .withBaseUrl(SOME_BASE_URL) + .withEndpoint(SOME_ENDPOINT) + .withMethod(ALLOWED_METHOD) + .withPayload(new Payload('')) + .withPemString(SOME_PEM_STRING) + .build(); + + yotiRequestHandler + .execute(request) + .then((response) => { + expect(response.getParsedResponse()).toBeNull(); + done(); + }) + .catch(done); + }); + }); + describe(`when JSON response is returned for ${ALLOWED_METHOD} method`, () => { + beforeEach((done) => { + mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, JSON.stringify(SOME_JSON_DATA)); + done(); + }); + + it('should return YotiResponse', (done) => { + const request = new RequestBuilder() + .withBaseUrl(SOME_BASE_URL) + .withEndpoint(SOME_ENDPOINT) + .withMethod(ALLOWED_METHOD) + .withPayload(new Payload('')) + .withPemString(SOME_PEM_STRING) + .build(); + + yotiRequestHandler + .execute(request) + .then((response) => { + expect(response.getParsedResponse()) + .toStrictEqual(SOME_JSON_DATA); + expect(response.getReceipt()) + .toBeNull(); + done(); + }) + .catch(done); + }); + }); + }); + describe('when receipt is returned', () => { + beforeEach((done) => { + mockResponse('GET', SOME_ENDPOINT_REG_EXP, 200, JSON.stringify(SOME_JSON_RECEIPT_DATA)); + done(); + }); + + it('should return YotiResponse', (done) => { + const request = new RequestBuilder() + .withBaseUrl(SOME_BASE_URL) + .withEndpoint(SOME_ENDPOINT) + .withMethod('GET') + .withPemString(SOME_PEM_STRING) + .build(); + + yotiRequestHandler + .execute(request) + .then((response) => { + expect(response.getParsedResponse()) + .toStrictEqual(SOME_JSON_RECEIPT_DATA); + expect(response.getReceipt()) + .toStrictEqual(SOME_JSON_RECEIPT_DATA.receipt); + done(); + }) + .catch(done); + }); + }); +}); From 45eff497fc2c338e2a087cb60ac8b646e8745949 Mon Sep 17 00:00:00 2001 From: David Grayston Date: Fri, 27 Sep 2019 15:39:40 +0100 Subject: [PATCH 2/6] SDK-1203: Prepare release version --- package-lock.json | 2 +- package.json | 2 +- sonar-project.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d14bd290..94d57d8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "yoti", - "version": "3.7.1", + "version": "3.7.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a834f247..fec1134e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yoti", - "version": "3.7.1", + "version": "3.7.2", "description": "Yoti NodeJS SDK for back-end integration", "author": "Yoti LTD (https://www.yoti.com/developers)", "license": "MIT", diff --git a/sonar-project.properties b/sonar-project.properties index 8e6c3934..8698c507 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,6 +1,6 @@ sonar.projectKey = yoti-web-sdk:node sonar.projectName = node-sdk -sonar.projectVersion = 3.7.1 +sonar.projectVersion = 3.7.2 sonar.exclusions=tests/**,examples/**,node_modules/**,coverage/** sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.verbose = true \ No newline at end of file From d64b936507a3f02b22bc5472e1f39ef8f936b538 Mon Sep 17 00:00:00 2001 From: David Grayston Date: Sun, 29 Sep 2019 01:06:28 +0100 Subject: [PATCH 3/6] SDK-1203: Allow response to be parsed based on content-type --- src/request/request.handler.js | 22 +++++++++++--- tests/request/request.handler.spec.js | 43 +++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/request/request.handler.js b/src/request/request.handler.js index c466a14c..c1f28cd4 100644 --- a/src/request/request.handler.js +++ b/src/request/request.handler.js @@ -22,11 +22,25 @@ module.exports.execute = yotiRequest => new Promise((resolve, reject) => { request .then((response) => { - try { - const parsedResponse = response.text !== '' ? JSON.parse(response.text) : null; - const receipt = parsedResponse !== null ? parsedResponse.receipt : null; + let parsedResponse = null; + if (typeof response.text !== 'undefined') { + try { + parsedResponse = JSON.parse(response.text); + } catch (e) { + parsedResponse = response.text; + } + } else { + parsedResponse = response.body; + } - return resolve(new YotiResponse(parsedResponse, response.statusCode, receipt)); + const receipt = parsedResponse !== null ? parsedResponse.receipt : null; + + try { + return resolve(new YotiResponse( + parsedResponse, + response.statusCode, + receipt + )); } catch (err) { return reject(err); } diff --git a/tests/request/request.handler.spec.js b/tests/request/request.handler.spec.js index be0b4aae..269d2af5 100644 --- a/tests/request/request.handler.spec.js +++ b/tests/request/request.handler.spec.js @@ -10,7 +10,10 @@ const SOME_ENDPOINT_REG_EXP = new RegExp(`^${SOME_ENDPOINT}`); const SOME_PEM_STRING = fs.readFileSync('./tests/sample-data/keys/node-sdk-test.pem', 'utf8'); const ALLOWED_METHODS = ['POST', 'PUT', 'PATCH', 'GET', 'DELETE']; const SOME_JSON_DATA = { some: 'json' }; +const SOME_JSON_DATA_STRING = JSON.stringify(SOME_JSON_DATA); const SOME_JSON_RECEIPT_DATA = { receipt: 'some receipt' }; +const SOME_JSON_RECEIPT_DATA_STRING = JSON.stringify(SOME_JSON_RECEIPT_DATA); +const SOME_DATA = 'someData'; /** * @param {string} method @@ -49,7 +52,7 @@ describe('yotiRequest', () => { yotiRequestHandler .execute(request) .then((response) => { - expect(response.getParsedResponse()).toBeNull(); + expect(response.getParsedResponse()).toBe(''); done(); }) .catch(done); @@ -57,7 +60,7 @@ describe('yotiRequest', () => { }); describe(`when JSON response is returned for ${ALLOWED_METHOD} method`, () => { beforeEach((done) => { - mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, JSON.stringify(SOME_JSON_DATA)); + mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, SOME_JSON_DATA_STRING); done(); }); @@ -85,7 +88,7 @@ describe('yotiRequest', () => { }); describe('when receipt is returned', () => { beforeEach((done) => { - mockResponse('GET', SOME_ENDPOINT_REG_EXP, 200, JSON.stringify(SOME_JSON_RECEIPT_DATA)); + mockResponse('GET', SOME_ENDPOINT_REG_EXP, 200, SOME_JSON_RECEIPT_DATA_STRING); done(); }); @@ -109,4 +112,38 @@ describe('yotiRequest', () => { .catch(done); }); }); + [ + 'image/jpeg', + 'image/png', + ].forEach((mimeType) => { + describe(`when ${mimeType} content is returned`, () => { + beforeEach((done) => { + nock(SOME_BASE_URL) + .get(SOME_ENDPOINT_REG_EXP) + .reply(200, SOME_DATA, { + 'Content-Type': mimeType, + }); + done(); + }); + it('should return YotiResponse', (done) => { + const request = new RequestBuilder() + .withBaseUrl(SOME_BASE_URL) + .withEndpoint(SOME_ENDPOINT) + .withMethod('GET') + .withPemString(SOME_PEM_STRING) + .build(); + + yotiRequestHandler + .execute(request) + .then((response) => { + expect(response.getParsedResponse()) + .toBeInstanceOf(Buffer); + expect(response.getParsedResponse().toString()) + .toBe(SOME_DATA); + done(); + }) + .catch(done); + }); + }); + }); }); From 9cb645d345a30ee687357065df18395896d33086 Mon Sep 17 00:00:00 2001 From: David Grayston Date: Sun, 29 Sep 2019 23:30:56 +0100 Subject: [PATCH 4/6] SDK-1203: Allow Buffer response --- src/request/request.handler.js | 22 ++++++++++++---------- src/request/request.js | 6 ++++-- tests/request/request.handler.spec.js | 9 ++++++--- tests/request/request.spec.js | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/request/request.handler.js b/src/request/request.handler.js index c1f28cd4..4592cc7e 100644 --- a/src/request/request.handler.js +++ b/src/request/request.handler.js @@ -6,16 +6,21 @@ const yotiCommon = require('../yoti_common'); * Default HTTP request handler. * * @param {YotiRequest} yotiRequest + * @param {boolean} buffer Return the response as a Buffer. * * @returns {Promise} Resolves {YotiResponse} */ -module.exports.execute = yotiRequest => new Promise((resolve, reject) => { +module.exports.execute = (yotiRequest, buffer = false) => new Promise((resolve, reject) => { const request = superagent(yotiRequest.getMethod(), yotiRequest.getUrl()); if (yotiCommon.requestCanSendPayload(yotiRequest.getMethod())) { request.send(yotiRequest.getPayload().getPayloadJSON()); } + if (buffer === true) { + request.buffer(buffer); + } + if (yotiRequest.getHeaders()) { request.set(yotiRequest.getHeaders()); } @@ -23,18 +28,15 @@ module.exports.execute = yotiRequest => new Promise((resolve, reject) => { request .then((response) => { let parsedResponse = null; - if (typeof response.text !== 'undefined') { - try { - parsedResponse = JSON.parse(response.text); - } catch (e) { - parsedResponse = response.text; - } - } else { + let receipt = null; + + if (response.body instanceof Buffer) { parsedResponse = response.body; + } else if (response.text) { + parsedResponse = response.headers['content-type'] ? response.body : JSON.parse(response.text); + receipt = parsedResponse.receipt || null; } - const receipt = parsedResponse !== null ? parsedResponse.receipt : null; - try { return resolve(new YotiResponse( parsedResponse, diff --git a/src/request/request.js b/src/request/request.js index 6ff9361c..6a4421b0 100644 --- a/src/request/request.js +++ b/src/request/request.js @@ -62,10 +62,12 @@ class YotiRequest { /** * Executes the request. * + * @param {boolean} buffer Return the response as a Buffer. + * * @returns {Promise} Resolves {YotiResponse} */ - execute() { - return requestHandler.execute(this); + execute(buffer = false) { + return requestHandler.execute(this, buffer); } } diff --git a/tests/request/request.handler.spec.js b/tests/request/request.handler.spec.js index 269d2af5..72e13deb 100644 --- a/tests/request/request.handler.spec.js +++ b/tests/request/request.handler.spec.js @@ -24,7 +24,9 @@ const SOME_DATA = 'someData'; const mockResponse = (method, uri, responseCode, body) => { const scope = nock(SOME_BASE_URL); const interceptor = scope[method.toLowerCase()](uri); - interceptor.reply(responseCode, body); + interceptor.reply(responseCode, body, { + 'content-type': 'application/json', + }); }; describe('yotiRequest', () => { @@ -52,7 +54,7 @@ describe('yotiRequest', () => { yotiRequestHandler .execute(request) .then((response) => { - expect(response.getParsedResponse()).toBe(''); + expect(response.getParsedResponse()).toBeNull(); done(); }) .catch(done); @@ -113,6 +115,7 @@ describe('yotiRequest', () => { }); }); [ + 'application/octet-stream', 'image/jpeg', 'image/png', ].forEach((mimeType) => { @@ -134,7 +137,7 @@ describe('yotiRequest', () => { .build(); yotiRequestHandler - .execute(request) + .execute(request, true) .then((response) => { expect(response.getParsedResponse()) .toBeInstanceOf(Buffer); diff --git a/tests/request/request.spec.js b/tests/request/request.spec.js index 7b58631b..939f32fd 100644 --- a/tests/request/request.spec.js +++ b/tests/request/request.spec.js @@ -1,6 +1,9 @@ const { YotiRequest } = require('../../src/request/request'); +const requestHandler = require('../../src/request/request.handler'); const { Payload } = require('../../src/request/payload'); +jest.mock('../../src/request/request.handler'); + const SOME_URL = 'https://api.example.com/some-endpoint'; const SOME_METHOD = 'POST'; const SOME_PAYLOAD = new Payload('some payload'); @@ -10,6 +13,20 @@ const SOME_HEADERS = { const SOME_REQUEST = new YotiRequest(SOME_METHOD, SOME_URL, SOME_HEADERS, SOME_PAYLOAD); describe('YotiRequest', () => { + describe('#execute', () => { + it('should execute the request handler', () => { + SOME_REQUEST.execute(); + expect(requestHandler.execute).toHaveBeenCalledWith(SOME_REQUEST, false); + }); + it('should execute the request handler with buffer disabled', () => { + SOME_REQUEST.execute(false); + expect(requestHandler.execute).toHaveBeenCalledWith(SOME_REQUEST, false); + }); + it('should execute the request handler with buffer enabled', () => { + SOME_REQUEST.execute(true); + expect(requestHandler.execute).toHaveBeenCalledWith(SOME_REQUEST, true); + }); + }); describe('#getUrl', () => { it('should return the URL', () => { expect(SOME_REQUEST.getUrl()).toBe(SOME_URL); From 24833de0f5aa44783b1237067f7156c5c6bcc65f Mon Sep 17 00:00:00 2001 From: David Grayston Date: Mon, 30 Sep 2019 11:14:49 +0100 Subject: [PATCH 5/6] SDK-1203: Remove unneeded try/catch --- src/request/request.handler.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/request/request.handler.js b/src/request/request.handler.js index 4592cc7e..f01bc37a 100644 --- a/src/request/request.handler.js +++ b/src/request/request.handler.js @@ -37,15 +37,11 @@ module.exports.execute = (yotiRequest, buffer = false) => new Promise((resolve, receipt = parsedResponse.receipt || null; } - try { - return resolve(new YotiResponse( - parsedResponse, - response.statusCode, - receipt - )); - } catch (err) { - return reject(err); - } + return resolve(new YotiResponse( + parsedResponse, + response.statusCode, + receipt + )); }) .catch((err) => { console.log(`Error getting data from Connect API: ${err.message}`); From b804e55e164d267e9d532eabf127c59654eeda7a Mon Sep 17 00:00:00 2001 From: David Grayston Date: Mon, 30 Sep 2019 13:59:10 +0100 Subject: [PATCH 6/6] SDK-1203: Add YotiResponse.getBody() and allow plain text responses --- src/request/request.builder.js | 2 +- src/request/request.handler.js | 6 +- src/request/response.js | 11 +++- tests/request/request.builder.spec.js | 24 +++++++ tests/request/request.handler.spec.js | 94 +++++++++++++++++---------- tests/request/response.spec.js | 51 +++++++++++++++ 6 files changed, 150 insertions(+), 38 deletions(-) create mode 100644 tests/request/response.spec.js diff --git a/src/request/request.builder.js b/src/request/request.builder.js index fe978b8b..ef043bb7 100644 --- a/src/request/request.builder.js +++ b/src/request/request.builder.js @@ -162,7 +162,7 @@ class RequestBuilder { // Merge provided query params with nonce and timestamp. const queryString = buildQueryString(Object.assign( - this.queryParams || {}, + this.queryParams, { nonce: uuid.v4(), timestamp: Date.now(), diff --git a/src/request/request.handler.js b/src/request/request.handler.js index f01bc37a..6dd43b63 100644 --- a/src/request/request.handler.js +++ b/src/request/request.handler.js @@ -28,11 +28,14 @@ module.exports.execute = (yotiRequest, buffer = false) => new Promise((resolve, request .then((response) => { let parsedResponse = null; + let body = null; let receipt = null; if (response.body instanceof Buffer) { + body = response.body; parsedResponse = response.body; } else if (response.text) { + body = response.text; parsedResponse = response.headers['content-type'] ? response.body : JSON.parse(response.text); receipt = parsedResponse.receipt || null; } @@ -40,7 +43,8 @@ module.exports.execute = (yotiRequest, buffer = false) => new Promise((resolve, return resolve(new YotiResponse( parsedResponse, response.statusCode, - receipt + receipt, + body )); }) .catch((err) => { diff --git a/src/request/response.js b/src/request/response.js index c06337c0..027aedca 100644 --- a/src/request/response.js +++ b/src/request/response.js @@ -8,11 +8,13 @@ class YotiResponse { * @param {*} parsedResponse * @param {int} statusCode * @param {Object|null} receipt + * @param {Buffer|string|null} body */ - constructor(parsedResponse, statusCode, receipt = null) { + constructor(parsedResponse, statusCode, receipt = null, body = null) { this.parsedResponse = parsedResponse; this.statusCode = statusCode; this.receipt = receipt; + this.body = body; } /** @@ -29,6 +31,13 @@ class YotiResponse { return this.parsedResponse; } + /** + * @returns {Buffer|string|null} The response body. + */ + getBody() { + return this.body; + } + /** * @returns {int} Response status code. */ diff --git a/tests/request/request.builder.spec.js b/tests/request/request.builder.spec.js index 61c55a2b..a6803ed3 100644 --- a/tests/request/request.builder.spec.js +++ b/tests/request/request.builder.spec.js @@ -148,6 +148,30 @@ describe('RequestBuilder', () => { assertExpectedRequest(request, done); }); }); + describe('#withGet', () => { + it('should set method to GET', () => { + const request = new RequestBuilder() + .withBaseUrl(API_BASE_URL) + .withPemFilePath(PEM_FILE_PATH) + .withEndpoint(API_ENDPOINT) + .withGet() + .build(); + + expect(request.getMethod()).toBe('GET'); + }); + }); + describe('#withPost', () => { + it('should set method to POST', () => { + const request = new RequestBuilder() + .withBaseUrl(API_BASE_URL) + .withPemFilePath(PEM_FILE_PATH) + .withEndpoint(API_ENDPOINT) + .withPost() + .build(); + + expect(request.getMethod()).toBe('POST'); + }); + }); describe('#withHeader', () => { it('should only accept string header value', () => { expect(() => { diff --git a/tests/request/request.handler.spec.js b/tests/request/request.handler.spec.js index 72e13deb..176c6868 100644 --- a/tests/request/request.handler.spec.js +++ b/tests/request/request.handler.spec.js @@ -14,6 +14,12 @@ const SOME_JSON_DATA_STRING = JSON.stringify(SOME_JSON_DATA); const SOME_JSON_RECEIPT_DATA = { receipt: 'some receipt' }; const SOME_JSON_RECEIPT_DATA_STRING = JSON.stringify(SOME_JSON_RECEIPT_DATA); const SOME_DATA = 'someData'; +const SOME_REQUEST = new RequestBuilder() + .withBaseUrl(SOME_BASE_URL) + .withEndpoint(SOME_ENDPOINT) + .withMethod('GET') + .withPemString(SOME_PEM_STRING) + .build(); /** * @param {string} method @@ -21,12 +27,10 @@ const SOME_DATA = 'someData'; * @param {integer} responseCode * @param {string} body */ -const mockResponse = (method, uri, responseCode, body) => { +const mockResponse = (method, uri, responseCode, body, headers) => { const scope = nock(SOME_BASE_URL); const interceptor = scope[method.toLowerCase()](uri); - interceptor.reply(responseCode, body, { - 'content-type': 'application/json', - }); + interceptor.reply(responseCode, body, headers); }; describe('yotiRequest', () => { @@ -38,7 +42,9 @@ describe('yotiRequest', () => { ALLOWED_METHODS.forEach((ALLOWED_METHOD) => { describe(`when empty response is returned for ${ALLOWED_METHOD} method`, () => { beforeEach((done) => { - mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, ''); + mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, '', { + 'content-type': 'application/json', + }); done(); }); @@ -55,6 +61,8 @@ describe('yotiRequest', () => { .execute(request) .then((response) => { expect(response.getParsedResponse()).toBeNull(); + expect(response.getBody()).toBeNull(); + expect(response.getStatusCode()).toBe(200); done(); }) .catch(done); @@ -62,7 +70,9 @@ describe('yotiRequest', () => { }); describe(`when JSON response is returned for ${ALLOWED_METHOD} method`, () => { beforeEach((done) => { - mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, SOME_JSON_DATA_STRING); + mockResponse(ALLOWED_METHOD, SOME_ENDPOINT_REG_EXP, 200, SOME_JSON_DATA_STRING, { + 'content-type': 'application/json', + }); done(); }); @@ -78,10 +88,10 @@ describe('yotiRequest', () => { yotiRequestHandler .execute(request) .then((response) => { - expect(response.getParsedResponse()) - .toStrictEqual(SOME_JSON_DATA); - expect(response.getReceipt()) - .toBeNull(); + expect(response.getParsedResponse()).toStrictEqual(SOME_JSON_DATA); + expect(response.getBody()).toBe(SOME_JSON_DATA_STRING); + expect(response.getReceipt()).toBeNull(); + expect(response.getStatusCode()).toBe(200); done(); }) .catch(done); @@ -90,25 +100,22 @@ describe('yotiRequest', () => { }); describe('when receipt is returned', () => { beforeEach((done) => { - mockResponse('GET', SOME_ENDPOINT_REG_EXP, 200, SOME_JSON_RECEIPT_DATA_STRING); + nock(SOME_BASE_URL) + .get(SOME_ENDPOINT_REG_EXP) + .reply(200, SOME_JSON_RECEIPT_DATA_STRING, { + 'content-type': 'application/json', + }); done(); }); it('should return YotiResponse', (done) => { - const request = new RequestBuilder() - .withBaseUrl(SOME_BASE_URL) - .withEndpoint(SOME_ENDPOINT) - .withMethod('GET') - .withPemString(SOME_PEM_STRING) - .build(); - yotiRequestHandler - .execute(request) + .execute(SOME_REQUEST) .then((response) => { - expect(response.getParsedResponse()) - .toStrictEqual(SOME_JSON_RECEIPT_DATA); - expect(response.getReceipt()) - .toStrictEqual(SOME_JSON_RECEIPT_DATA.receipt); + expect(response.getParsedResponse()).toStrictEqual(SOME_JSON_RECEIPT_DATA); + expect(response.getBody()).toBe(SOME_JSON_RECEIPT_DATA_STRING); + expect(response.getReceipt()).toStrictEqual(SOME_JSON_RECEIPT_DATA.receipt); + expect(response.getStatusCode()).toBe(200); done(); }) .catch(done); @@ -116,6 +123,7 @@ describe('yotiRequest', () => { }); [ 'application/octet-stream', + 'application/pdf', 'image/jpeg', 'image/png', ].forEach((mimeType) => { @@ -129,20 +137,36 @@ describe('yotiRequest', () => { done(); }); it('should return YotiResponse', (done) => { - const request = new RequestBuilder() - .withBaseUrl(SOME_BASE_URL) - .withEndpoint(SOME_ENDPOINT) - .withMethod('GET') - .withPemString(SOME_PEM_STRING) - .build(); - yotiRequestHandler - .execute(request, true) + .execute(SOME_REQUEST, true) + .then((response) => { + expect(response.getParsedResponse()).toBeInstanceOf(Buffer); + expect(response.getParsedResponse().toString()).toBe(SOME_DATA); + expect(response.getBody().toString()).toBe(SOME_DATA); + expect(response.getStatusCode()).toBe(200); + done(); + }) + .catch(done); + }); + }); + }); + [ + 'text/plain', + ].forEach((mimeType) => { + describe(`when ${mimeType} content is returned`, () => { + beforeEach((done) => { + nock(SOME_BASE_URL) + .get(SOME_ENDPOINT_REG_EXP) + .reply(200, SOME_DATA, { + 'Content-Type': mimeType, + }); + done(); + }); + it('should return YotiResponse', (done) => { + yotiRequestHandler + .execute(SOME_REQUEST) .then((response) => { - expect(response.getParsedResponse()) - .toBeInstanceOf(Buffer); - expect(response.getParsedResponse().toString()) - .toBe(SOME_DATA); + expect(response.getBody()).toBe(SOME_DATA); done(); }) .catch(done); diff --git a/tests/request/response.spec.js b/tests/request/response.spec.js new file mode 100644 index 00000000..f3aa18ce --- /dev/null +++ b/tests/request/response.spec.js @@ -0,0 +1,51 @@ +const { YotiResponse } = require('../../src/request/response'); + +const SOME_BODY = '{"some":"response"}'; +const SOME_RECEIPT = { some: 'receipt' }; +const SOME_PARSED_RESPONSE = JSON.parse(SOME_BODY); +const SOME_RESPONSE = new YotiResponse( + SOME_PARSED_RESPONSE, + 200, + SOME_RECEIPT, + SOME_BODY +); + +describe('YotiResponse', () => { + describe('#getBody', () => { + it('should return the body', () => { + expect(SOME_RESPONSE.getBody()).toBe(SOME_BODY); + }); + }); + describe('#getParsedResponse', () => { + it('should return the parsed response', () => { + expect(SOME_RESPONSE.getParsedResponse()).toBe(SOME_PARSED_RESPONSE); + }); + }); + describe('#getReceipt', () => { + it('should return the receipt', () => { + expect(SOME_RESPONSE.getReceipt()).toBe(SOME_RECEIPT); + }); + }); + describe('#getStatusCode', () => { + it('should return the status code', () => { + expect(SOME_RESPONSE.getStatusCode()).toBe(200); + }); + }); + describe('#constructor', () => { + it('should not require receipt', () => { + const SOME_RESPONSE_WITHOUT_RECEIPT = new YotiResponse( + SOME_PARSED_RESPONSE, + 200 + ); + expect(SOME_RESPONSE_WITHOUT_RECEIPT.getReceipt()).toBeNull(); + }); + it('should not require body', () => { + const SOME_RESPONSE_WITHOUT_BODY = new YotiResponse( + SOME_PARSED_RESPONSE, + 200, + SOME_RECEIPT + ); + expect(SOME_RESPONSE_WITHOUT_BODY.getBody()).toBeNull(); + }); + }); +});