UNPKG

@mojaloop/central-services-shared

Version:
367 lines (336 loc) 13.5 kB
'use strict' const EventSdk = require('@mojaloop/event-sdk') const Test = require('tapes')(require('tape')) const Sinon = require('sinon') const Config = require('../../util/config') const Mustache = require('mustache') const proxyquire = require('proxyquire') const Enum = require('../../../src/enums') const Helper = require('../../util/helper') const Metrics = require('@mojaloop/central-services-metrics') const Uuid = require('uuid4') const JwsSigner = require('@mojaloop/sdk-standard-components').Jws.signer const signingKey = `-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA0eJEh3Op5p6x137lRkAsvmEBbd32dbRChrCUItZbtxjf/qfB yD5k8Hn4n4vbqzP8XSGS0f6KmNC+iRaP74HVgzAqc4Uid4J8dtSBq3VmucYQYzLc 101QjuvD+SKmZwlw/q0PtulmqlASI2SbMfwcAraMi6ab7v5W4EGNeIPLEIo3BXsQ DTCWqiZb7aXkHkcY7sOjAzK/2bNGYFmAthdYrHzvCkqnJ7LAHX3Oj7rJea5MqtuN B9POZYaD10n9JuYWdwPqLrw6/hVgPSFEy+ulrVbXf54ZH0dfMThAYRvFrT81yulk H95JhXWGdi6cTp6t8LVOKFhnNfxjWw0Jayj9xwIDAQABAoIBADB2u/Y/CgNbr5sg DRccqHhJdAgHkep59kadrYch0knEL6zg1clERxCUSYmlxNKSjXp/zyQ4T46b3PNQ x2m5pDDHxXWpT10jP1Q9G7gYwuCw0IXnb8EzdB+cZ0M28g+myXW1RoSo/nDjTlzn 1UJEgb9Kocd5cFZOWocr+9vRKumlZULMsA8yiNwlAfJHcMBM7acsa3myCqVhLyWt 4BQylVuLFa+A6QzpMXEwFCq8EOXf07gl1XVzC6LJ1fTa9gVM3N+YE+oEXKrsHCxG /ACgKsjepL27QjJ7qvecWPP0F2LxEZYOm5tbXaKJTobzQUJHgUokanZMhjYprDsZ zumLw9kCgYEA/DUWcnLeImlfq/EYdhejkl3J+WX3vhS23OqVgY1amu7CZzaai6vt H0TRc8Zsbi4jgmFDU8PFzytP6qz6Tgom4R736z6oBi7bjnGyN17/NSbf+DaRVcM6 vnZr7jNC2FJlECmIN+dkwUA/YCr2SA7hxZXM9mIYSc+6+glDiIO5Cf0CgYEA1Qo/ uQbVHhW+Cp8H0kdMuhwUbkBquRrxRZlXS1Vrf3f9me9JLUy9UPWb3y3sKVurG5+O SIlr4hDcZyXdE198MtDMhBIGqU9ORSjppJDNDVvtt+n2FD4XmWIU70vKBJBivX0+ Bow6yduis+p12fuvpvpnKCz8UjOgOQJhLZ4GQBMCgYBP6gpozVjxkm4ML2LO2IKt +CXtbo/nnOysZ3BkEoQpH4pd5gFmTF3gUJAFnVPyPZBm2abZvejJ0jGKbLELVVAo eQWZdssK2oIbSo9r2CAJmX3SSogWorvUafWdDoUZwlHfoylUfW+BhHgQYsyS3JRR ZTwCveZwTPA0FgdeFE7niQKBgQCHaD8+ZFhbCejDqXb4MXdUJ3rY5Lqwsq491YwF huKPn32iNNQnJcqCxclv3iln1Cr6oLx34Fig1KSyLv/IS32OcuY635Y6UPznumxe u+aJIjADIILXNOwdAplZy6s4oWkRFaSx1rmbCa3tew2zImTv1eJxR76MpOGmupt3 uiQw3wKBgFjBT/aVKdBeHeP1rIHHldQV5QQxZNkc6D3qn/oAFcwpj9vcGfRjQWjO ARzXM2vUWEet4OVn3DXyOdaWFR1ppehz7rAWBiPgsMg4fjAusYb9Mft1GMxMzuwT Oyqsp6pzAWFrCD3JAoTLxClV+j5m+SXZ/ItD6ziGpl/h7DyayrFZ -----END RSA PRIVATE KEY-----` Test('ParticipantEndpoint Model Test', modelTest => { let sandbox let request let Model const hubName = 'Hub' const hubNameRegex = /^Hub$/i Metrics.setup({ INSTRUMENTATION: { METRICS: { DISABLED: false, config: { timeout: 5000, prefix: 'moja_ml_', defaultLabels: { serviceName: 'ml-service' } } } } }) modelTest.beforeEach(test => { sandbox = Sinon.createSandbox() test.end() }) modelTest.afterEach(test => { sandbox.restore() test.end() }) modelTest.test('sendRequest should', async (getEndpointTest) => { getEndpointTest.test('return the object of endpoints', async (test) => { const fsp = 'fsp' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }), method: 'get' } request = sandbox.stub().returns(Helper.getEndPointsResponse) Model = proxyquire('../../../src/util/request', { axios: request }) try { const result = await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, hubNameRegex }) test.deepEqual(result, Helper.getEndPointsResponse, 'The results match') test.end() } catch (err) { test.fail('Error thrown', err) test.end() } }) getEndpointTest.test('handle a span and add traceparent header', async (test) => { const fsp = 'fsp' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }), method: 'get' } const requestFunction = (request) => { test.ok(request.headers.traceparent) return Helper.getEndPointsResponse } const span = EventSdk.Tracer.createSpan('test-span') Model = proxyquire('../../../src/util/request', { axios: requestFunction }) try { const result = await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, method: Enum.Http.RestMethods.GET, responseType: Enum.Http.ResponseTypes.JSON, span, hubNameRegex }) test.deepEqual(result, Helper.getEndPointsResponse, 'The results match') test.end() } catch (err) { test.fail('Error thrown', err) test.end() } }) getEndpointTest.test('handle protocolVersions for config injection', async (test) => { const protocolVersions = { content: '2.1', accept: '2' } const fsp = 'fsp' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }), method: 'get' } const requestFunction = (request) => { test.equal(request.headers['content-type'], Helper.generateProtocolHeader('participants', protocolVersions.content)) test.equal(request.headers.accept, Helper.generateProtocolHeader('participants', protocolVersions.accept)) return Helper.getEndPointsResponse } const span = EventSdk.Tracer.createSpan('test-span') Model = proxyquire('../../../src/util/request', { axios: requestFunction }) try { const result = await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, method: Enum.Http.RestMethods.GET, responseType: Enum.Http.ResponseTypes.JSON, span, jwsSigner: null, protocolVersions, hubNameRegex }) test.deepEqual(result, Helper.getEndPointsResponse, 'The results match') test.end() } catch (err) { test.fail('Error thrown', err) test.end() } }) getEndpointTest.test('handle protocolVersions without config injection', async (test) => { const protocolVersions = null const fsp = 'fsp' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }), method: 'get' } const requestFunction = (request) => { test.equal(request.headers['content-type'], Helper.generateProtocolHeader('participants', '1.0')) test.equal(request.headers.accept, Helper.generateProtocolHeader('participants', '1')) return Helper.getEndPointsResponse } const span = EventSdk.Tracer.createSpan('test-span') Model = proxyquire('../../../src/util/request', { axios: requestFunction }) try { const result = await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, method: Enum.Http.RestMethods.GET, responseType: Enum.Http.ResponseTypes.JSON, span, jwsSigner: null, protocolVersions, hubNameRegex }) test.deepEqual(result, Helper.getEndPointsResponse, 'The results match') test.end() } catch (err) { test.fail('Error thrown', err) test.end() } }) getEndpointTest.test('throw error', async (test) => { const fsp = 'fsp1' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }), method: 'get' } request = sandbox.stub().throws(new Error()) Model = proxyquire('../../../src/util/request', { axios: request }) try { await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, hubNameRegex }) test.fail('should throw error') test.end() } catch (e) { test.ok(e instanceof Error) test.ok(request.defaults.httpAgent.toJSON()) test.end() } }) getEndpointTest.test('throw error when error contains response property', async (test) => { const fsp = 'fsp1' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }), method: 'get' } const customError = new Error() customError.response = { status: 'status', data: 'data' } request = sandbox.stub().throws(customError) Model = proxyquire('../../../src/util/request', { axios: request }) try { await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, hubNameRegex }) test.fail('should throw error') test.end() } catch (e) { test.ok(e instanceof Error) test.end() } }) getEndpointTest.test('throw error when required parameter is missing', async (test) => { const fsp = 'fsp1' const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.TRANSACTION_REQUEST_POST, { fsp }), method: 'post' } request = sandbox.stub().throws(new Error()) Model = proxyquire('../../../src/util/request', { axios: request }) try { await Model.sendRequest({ url: requestOptions.url, headers: Helper.defaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName), source: hubName, destination: hubName, method: Enum.Http.RestMethods.POST, hubNameRegex }) test.fail('should throw error') test.end() } catch (e) { test.ok(e instanceof Error) test.end() } }) getEndpointTest.test('sign with JWS signature when JwsSigner object is passed', async (test) => { const fsp = 'payerfsp' const payeefsp = 'payeefsp' const ID = Uuid() const body = { errorInformation: { errorCode: 3106, errorDescription: 'Modified request' } } const payload = JSON.stringify(body) const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.TRANSFERS_PUT_ERROR, { fsp, ID }), method: 'post', headers: Helper.defaultHeaders(fsp, Enum.Http.HeaderResources.PARTICIPANTS, payeefsp) } const jwsSigner = new JwsSigner({ logger: null, signingKey }) request = sandbox.stub().returns({ status: 200 }) Model = proxyquire('../../../src/util/request', { axios: request }) const signSpy = Sinon.spy(jwsSigner, 'getSignature') await Model.sendRequest({ url: requestOptions.url, headers: requestOptions.headers, source: hubName, destination: fsp, method: requestOptions.method, payload, responseType: Enum.Http.ResponseTypes.JSON, jwsSigner, hubNameRegex }) test.ok(signSpy.calledOnce, 'JwsSigner.sign is called once') test.ok('fspiop-signature' in signSpy.getCall(0).firstArg.headers, 'The header has fspiop-signature') test.end() }) getEndpointTest.test('NOT sign with JWS signature when JwsSigner object is NOT passed', async (test) => { const fsp = 'payerfsp' const payeefsp = 'payeefsp' const ID = Uuid() const body = { errorInformation: { errorCode: 3106, errorDescription: 'Modified request' } } const payload = JSON.stringify(body) const requestOptions = { url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.TRANSFERS_PUT_ERROR, { fsp, ID }), method: 'post', headers: Helper.defaultHeaders(fsp, Enum.Http.HeaderResources.PARTICIPANTS, payeefsp) } const jwsSigner = new JwsSigner({ logger: null, signingKey }) request = sandbox.stub().returns({ status: 200 }) Model = proxyquire('../../../src/util/request', { axios: request }) const signSpy = Sinon.spy(jwsSigner, 'getSignature') await Model.sendRequest({ url: requestOptions.url, headers: requestOptions.headers, source: hubName, destination: fsp, method: requestOptions.method, payload, responseType: Enum.Http.ResponseTypes.JSON, hubNameRegex }) test.equal(signSpy.callCount, 0, 'JwsSigner.sign is NOT called') test.end() }) getEndpointTest.end() }) modelTest.end() })