@mojaloop/sdk-scheme-adapter 11.18.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/.env.example +140 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc.json +30 -0
  4. package/.nvmrc +1 -0
  5. package/.versionrc +15 -0
  6. package/CHANGELOG.md +118 -0
  7. package/InboundServer/api.yaml +3594 -0
  8. package/InboundServer/api_template.yaml +69 -0
  9. package/InboundServer/handlers.js +940 -0
  10. package/InboundServer/index.js +205 -0
  11. package/InboundServer/middlewares.js +426 -0
  12. package/OAuthTestServer/index.js +66 -0
  13. package/OAuthTestServer/model.js +70 -0
  14. package/OutboundServer/api.yaml +2732 -0
  15. package/OutboundServer/api_interfaces/index.d.ts +117 -0
  16. package/OutboundServer/api_interfaces/openapi.d.ts +1475 -0
  17. package/OutboundServer/api_template/components/parameters/bulkQuoteId.yaml +9 -0
  18. package/OutboundServer/api_template/components/parameters/bulkTransferId.yaml +9 -0
  19. package/OutboundServer/api_template/components/parameters/requestToPayTransactionId.yaml +9 -0
  20. package/OutboundServer/api_template/components/parameters/transferId.yaml +9 -0
  21. package/OutboundServer/api_template/components/responses/accountsCreationCompleted.yaml +5 -0
  22. package/OutboundServer/api_template/components/responses/accountsCreationError.yaml +5 -0
  23. package/OutboundServer/api_template/components/responses/accountsCreationTimeout.yaml +5 -0
  24. package/OutboundServer/api_template/components/responses/authorizationPostSuccess.yaml +5 -0
  25. package/OutboundServer/api_template/components/responses/authorizationsServerError.yaml +5 -0
  26. package/OutboundServer/api_template/components/responses/bulkQuoteBadRequest.yaml +5 -0
  27. package/OutboundServer/api_template/components/responses/bulkQuoteServerError.yaml +5 -0
  28. package/OutboundServer/api_template/components/responses/bulkQuoteSuccess.yaml +5 -0
  29. package/OutboundServer/api_template/components/responses/bulkQuoteTimeout.yaml +5 -0
  30. package/OutboundServer/api_template/components/responses/bulkTransferBadRequest.yaml +5 -0
  31. package/OutboundServer/api_template/components/responses/bulkTransferServerError.yaml +5 -0
  32. package/OutboundServer/api_template/components/responses/bulkTransferSuccess.yaml +5 -0
  33. package/OutboundServer/api_template/components/responses/bulkTransferTimeout.yaml +5 -0
  34. package/OutboundServer/api_template/components/responses/partiesByIdError404.yaml +9 -0
  35. package/OutboundServer/api_template/components/responses/partiesByIdSuccess.yaml +5 -0
  36. package/OutboundServer/api_template/components/responses/quotesPostSuccess.yaml +5 -0
  37. package/OutboundServer/api_template/components/responses/quotesServerError.yaml +5 -0
  38. package/OutboundServer/api_template/components/responses/requestToPaySuccess.yaml +5 -0
  39. package/OutboundServer/api_template/components/responses/requestToPayTransferBadRequest.yaml +5 -0
  40. package/OutboundServer/api_template/components/responses/requestToPayTransferSuccess.yaml +5 -0
  41. package/OutboundServer/api_template/components/responses/simpleTransfersPostSuccess.yaml +5 -0
  42. package/OutboundServer/api_template/components/responses/simpleTransfersServerError.yaml +5 -0
  43. package/OutboundServer/api_template/components/responses/transferBadRequest.yaml +5 -0
  44. package/OutboundServer/api_template/components/responses/transferServerError.yaml +5 -0
  45. package/OutboundServer/api_template/components/responses/transferSuccess.yaml +5 -0
  46. package/OutboundServer/api_template/components/responses/transferTimeout.yaml +5 -0
  47. package/OutboundServer/api_template/components/schemas/accountCreationStatus.yaml +18 -0
  48. package/OutboundServer/api_template/components/schemas/accountsCreationState.yaml +4 -0
  49. package/OutboundServer/api_template/components/schemas/accountsRequest.yaml +20 -0
  50. package/OutboundServer/api_template/components/schemas/accountsResponse.yaml +15 -0
  51. package/OutboundServer/api_template/components/schemas/async2SyncCurrentState.yaml +5 -0
  52. package/OutboundServer/api_template/components/schemas/authorizationsPostRequest.yaml +15 -0
  53. package/OutboundServer/api_template/components/schemas/authorizationsPostResponse.yaml +19 -0
  54. package/OutboundServer/api_template/components/schemas/bulkQuoteErrorResponse.yaml +8 -0
  55. package/OutboundServer/api_template/components/schemas/bulkQuoteRequest.yaml +26 -0
  56. package/OutboundServer/api_template/components/schemas/bulkQuoteResponse.yaml +21 -0
  57. package/OutboundServer/api_template/components/schemas/bulkQuoteStatus.yaml +4 -0
  58. package/OutboundServer/api_template/components/schemas/bulkQuoteStatusResponse.yaml +17 -0
  59. package/OutboundServer/api_template/components/schemas/bulkTransferErrorResponse.yaml +8 -0
  60. package/OutboundServer/api_template/components/schemas/bulkTransferRequest.yaml +26 -0
  61. package/OutboundServer/api_template/components/schemas/bulkTransferResponse.yaml +16 -0
  62. package/OutboundServer/api_template/components/schemas/bulkTransferStatus.yaml +4 -0
  63. package/OutboundServer/api_template/components/schemas/bulkTransferStatusResponse.yaml +17 -0
  64. package/OutboundServer/api_template/components/schemas/errorAccountsResponse.yaml +8 -0
  65. package/OutboundServer/api_template/components/schemas/errorAuthorizationsResponse.yaml +3 -0
  66. package/OutboundServer/api_template/components/schemas/errorQuotesResponse.yaml +9 -0
  67. package/OutboundServer/api_template/components/schemas/errorResponse.yaml +8 -0
  68. package/OutboundServer/api_template/components/schemas/errorSimpleTransfersResponse.yaml +3 -0
  69. package/OutboundServer/api_template/components/schemas/errorTransferResponse.yaml +8 -0
  70. package/OutboundServer/api_template/components/schemas/extensionListEmptiable.yaml +6 -0
  71. package/OutboundServer/api_template/components/schemas/individualQuote.yaml +32 -0
  72. package/OutboundServer/api_template/components/schemas/individualQuoteResult.yaml +28 -0
  73. package/OutboundServer/api_template/components/schemas/individualTransfer.yaml +32 -0
  74. package/OutboundServer/api_template/components/schemas/individualTransferFulfilment.yaml +13 -0
  75. package/OutboundServer/api_template/components/schemas/individualTransferResult.yaml +41 -0
  76. package/OutboundServer/api_template/components/schemas/mojaloopError.yaml +5 -0
  77. package/OutboundServer/api_template/components/schemas/mojaloopTransactionRequestState.yaml +2 -0
  78. package/OutboundServer/api_template/components/schemas/partiesByIdResponse.yaml +13 -0
  79. package/OutboundServer/api_template/components/schemas/quote.yaml +3 -0
  80. package/OutboundServer/api_template/components/schemas/quoteError.yaml +16 -0
  81. package/OutboundServer/api_template/components/schemas/quotesPostRequest.yaml +13 -0
  82. package/OutboundServer/api_template/components/schemas/quotesPostResponse.yaml +48 -0
  83. package/OutboundServer/api_template/components/schemas/requestToPayRequest.yaml +39 -0
  84. package/OutboundServer/api_template/components/schemas/requestToPayResponse.yaml +41 -0
  85. package/OutboundServer/api_template/components/schemas/requestToPayTransferRequest.yaml +42 -0
  86. package/OutboundServer/api_template/components/schemas/requestToPayTransferResponse.yaml +58 -0
  87. package/OutboundServer/api_template/components/schemas/simpleTransferServerError.yaml +5 -0
  88. package/OutboundServer/api_template/components/schemas/simpleTransfersPostRequest.yaml +12 -0
  89. package/OutboundServer/api_template/components/schemas/simpleTransfersPostResponse.yaml +11 -0
  90. package/OutboundServer/api_template/components/schemas/transactionType.yaml +4 -0
  91. package/OutboundServer/api_template/components/schemas/transferContinuationAcceptOTP.yaml +9 -0
  92. package/OutboundServer/api_template/components/schemas/transferContinuationAcceptParty.yaml +8 -0
  93. package/OutboundServer/api_template/components/schemas/transferContinuationAcceptQuote.yaml +9 -0
  94. package/OutboundServer/api_template/components/schemas/transferError.yaml +16 -0
  95. package/OutboundServer/api_template/components/schemas/transferFulfilment.yaml +3 -0
  96. package/OutboundServer/api_template/components/schemas/transferParty.yaml +40 -0
  97. package/OutboundServer/api_template/components/schemas/transferRequest.yaml +37 -0
  98. package/OutboundServer/api_template/components/schemas/transferResponse.yaml +58 -0
  99. package/OutboundServer/api_template/components/schemas/transferStatus.yaml +6 -0
  100. package/OutboundServer/api_template/components/schemas/transferStatusResponse.yaml +13 -0
  101. package/OutboundServer/api_template/health.yaml +12 -0
  102. package/OutboundServer/api_template/openapi.yaml +55 -0
  103. package/OutboundServer/api_template/paths/accounts.yaml +26 -0
  104. package/OutboundServer/api_template/paths/authorizations.yaml +19 -0
  105. package/OutboundServer/api_template/paths/bulkQuotes.yaml +23 -0
  106. package/OutboundServer/api_template/paths/bulkQuotes_bulkQuoteId.yaml +24 -0
  107. package/OutboundServer/api_template/paths/bulkTransfers.yaml +23 -0
  108. package/OutboundServer/api_template/paths/bulkTransfers_bulkTransferId.yaml +24 -0
  109. package/OutboundServer/api_template/paths/parties_Type_ID.yaml +20 -0
  110. package/OutboundServer/api_template/paths/parties_Type_ID_SubId.yaml +22 -0
  111. package/OutboundServer/api_template/paths/quotes.yaml +20 -0
  112. package/OutboundServer/api_template/paths/requestToPay.yaml +22 -0
  113. package/OutboundServer/api_template/paths/requestToPayTransfer.yaml +57 -0
  114. package/OutboundServer/api_template/paths/requestToPayTransfer_requestToPayTransactionId.yaml +34 -0
  115. package/OutboundServer/api_template/paths/simpleTransfers.yaml +19 -0
  116. package/OutboundServer/api_template/paths/transfers.yaml +55 -0
  117. package/OutboundServer/api_template/paths/transfers_transferId.yaml +58 -0
  118. package/OutboundServer/handlers.js +622 -0
  119. package/OutboundServer/index.js +137 -0
  120. package/OutboundServer/middlewares.js +67 -0
  121. package/TestServer/api.yaml +62 -0
  122. package/TestServer/handlers.js +63 -0
  123. package/TestServer/index.js +215 -0
  124. package/audit-resolve.json +65 -0
  125. package/babel.config.js +3 -0
  126. package/config.js +158 -0
  127. package/index.d.ts +1 -0
  128. package/index.js +149 -0
  129. package/jest.config.js +15 -0
  130. package/lib/api/index.js +12 -0
  131. package/lib/cache.js +352 -0
  132. package/lib/check.js +25 -0
  133. package/lib/model/AccountsModel.js +396 -0
  134. package/lib/model/Async2SyncModel.js +283 -0
  135. package/lib/model/AuthorizationsModel.js +86 -0
  136. package/lib/model/InboundTransfersModel.js +730 -0
  137. package/lib/model/OutboundBulkQuotesModel.js +485 -0
  138. package/lib/model/OutboundBulkTransfersModel.js +479 -0
  139. package/lib/model/OutboundRequestToPayModel.js +517 -0
  140. package/lib/model/OutboundRequestToPayTransferModel.js +893 -0
  141. package/lib/model/OutboundTransfersModel.js +823 -0
  142. package/lib/model/PartiesModel.js +70 -0
  143. package/lib/model/ProxyModel/MatchRules/Expression.js +48 -0
  144. package/lib/model/ProxyModel/MatchRules/Headers.js +65 -0
  145. package/lib/model/ProxyModel/MatchRules/MatchRule.js +27 -0
  146. package/lib/model/ProxyModel/MatchRules/Path.js +36 -0
  147. package/lib/model/ProxyModel/MatchRules/Query.js +65 -0
  148. package/lib/model/ProxyModel/MatchRules/index.js +19 -0
  149. package/lib/model/ProxyModel/Route.js +82 -0
  150. package/lib/model/ProxyModel/configSchema.json +118 -0
  151. package/lib/model/ProxyModel/index.js +138 -0
  152. package/lib/model/QuotesModel.js +94 -0
  153. package/lib/model/TransfersModel.js +81 -0
  154. package/lib/model/common/BackendError.js +26 -0
  155. package/lib/model/common/PersistentStateMachine.js +93 -0
  156. package/lib/model/common/index.js +18 -0
  157. package/lib/model/index.js +43 -0
  158. package/lib/model/lib/deferredJob.js +113 -0
  159. package/lib/model/lib/index.js +9 -0
  160. package/lib/model/lib/requests/backendRequests.js +227 -0
  161. package/lib/model/lib/requests/common.js +76 -0
  162. package/lib/model/lib/requests/index.js +19 -0
  163. package/lib/model/lib/shared.js +468 -0
  164. package/lib/randomphrase/index.js +21 -0
  165. package/lib/randomphrase/words.json +3397 -0
  166. package/lib/router.js +28 -0
  167. package/lib/validate.js +205 -0
  168. package/package.json +102 -0
  169. package/test/__mocks__/@mojaloop/sdk-standard-components.js +152 -0
  170. package/test/__mocks__/javascript-state-machine.js +21 -0
  171. package/test/__mocks__/redis.js +49 -0
  172. package/test/__mocks__/uuidv4.js +16 -0
  173. package/test/config/integration.env +136 -0
  174. package/test/integration/lib/Outbound/authorizations.test.js +58 -0
  175. package/test/integration/lib/Outbound/data/authorizationsPostRequest.json +43 -0
  176. package/test/integration/lib/Outbound/data/quotesPostRequest.json +52 -0
  177. package/test/integration/lib/Outbound/data/transfersPostRequest.json +24 -0
  178. package/test/integration/lib/Outbound/parties.test.js +28 -0
  179. package/test/integration/lib/Outbound/quotes.test.js +58 -0
  180. package/test/integration/lib/Outbound/simpleTransfers.test.js +67 -0
  181. package/test/integration/lib/cache.test.js +80 -0
  182. package/test/integration/testEnv.js +7 -0
  183. package/test/unit/InboundServer.test.js +443 -0
  184. package/test/unit/TestServer.test.js +394 -0
  185. package/test/unit/api/accounts/accounts.test.js +128 -0
  186. package/test/unit/api/accounts/data/postAccountsBody.json +7 -0
  187. package/test/unit/api/accounts/data/postAccountsErrorMojaloopResponse.json +25 -0
  188. package/test/unit/api/accounts/data/postAccountsErrorTimeoutResponse.json +19 -0
  189. package/test/unit/api/accounts/data/postAccountsSuccessResponse.json +17 -0
  190. package/test/unit/api/accounts/data/postAccountsSuccessResponseWithError1.json +21 -0
  191. package/test/unit/api/accounts/data/postAccountsSuccessResponseWithError2.json +21 -0
  192. package/test/unit/api/accounts/utils.js +65 -0
  193. package/test/unit/api/proxy/data/proxyConfig.yaml +82 -0
  194. package/test/unit/api/proxy/data/requestBody.json +22 -0
  195. package/test/unit/api/proxy/data/requestHeaders.json +5 -0
  196. package/test/unit/api/proxy/data/requestQuery.json +6 -0
  197. package/test/unit/api/proxy/data/responseBody.json +21 -0
  198. package/test/unit/api/proxy/data/responseHeaders.json +5 -0
  199. package/test/unit/api/proxy/proxy.test.js +220 -0
  200. package/test/unit/api/proxy/utils.js +79 -0
  201. package/test/unit/api/transfers/data/getTransfersCommittedResponse.json +21 -0
  202. package/test/unit/api/transfers/data/getTransfersErrorNotFound.json +17 -0
  203. package/test/unit/api/transfers/data/postQuotesBody.json +52 -0
  204. package/test/unit/api/transfers/data/postTransfersBadBody.json +17 -0
  205. package/test/unit/api/transfers/data/postTransfersBody.json +24 -0
  206. package/test/unit/api/transfers/data/postTransfersErrorMojaloopResponse.json +53 -0
  207. package/test/unit/api/transfers/data/postTransfersErrorTimeoutResponse.json +47 -0
  208. package/test/unit/api/transfers/data/postTransfersSimpleBody.json +26 -0
  209. package/test/unit/api/transfers/data/postTransfersSuccessResponse.json +101 -0
  210. package/test/unit/api/transfers/data/putPartiesBody.json +20 -0
  211. package/test/unit/api/transfers/data/putQuotesBody.json +37 -0
  212. package/test/unit/api/transfers/data/putTransfersBody.json +17 -0
  213. package/test/unit/api/transfers/transfers.test.js +191 -0
  214. package/test/unit/api/transfers/utils.js +183 -0
  215. package/test/unit/api/utils.js +75 -0
  216. package/test/unit/config.test.js +119 -0
  217. package/test/unit/data/commonHttpHeaders.json +6 -0
  218. package/test/unit/data/defaultConfig.json +58 -0
  219. package/test/unit/data/postQuotesBody.json +52 -0
  220. package/test/unit/data/putParticipantsBody.json +12 -0
  221. package/test/unit/data/putPartiesBody.json +20 -0
  222. package/test/unit/data/testFile.json +29 -0
  223. package/test/unit/data/testFile.yaml +14 -0
  224. package/test/unit/inboundApi/data/mockArguments.json +117 -0
  225. package/test/unit/inboundApi/data/mockTransactionRequest.json +42 -0
  226. package/test/unit/inboundApi/handlers.test.js +799 -0
  227. package/test/unit/index.test.js +55 -0
  228. package/test/unit/lib/cache.test.js +146 -0
  229. package/test/unit/lib/model/AccountsModel.test.js +121 -0
  230. package/test/unit/lib/model/AuthorizationsModel.test.js +460 -0
  231. package/test/unit/lib/model/InboundTransfersModel.test.js +628 -0
  232. package/test/unit/lib/model/OutboundBulkQuotesModel.test.js +249 -0
  233. package/test/unit/lib/model/OutboundBulkTransfersModel.test.js +244 -0
  234. package/test/unit/lib/model/OutboundRequestToPayModel.test.js +166 -0
  235. package/test/unit/lib/model/OutboundRequestToPayTransferModel.test.js +245 -0
  236. package/test/unit/lib/model/OutboundTransfersModel.test.js +836 -0
  237. package/test/unit/lib/model/PartiesModel.test.js +468 -0
  238. package/test/unit/lib/model/QuotesModel.test.js +470 -0
  239. package/test/unit/lib/model/TransfersModel.test.js +474 -0
  240. package/test/unit/lib/model/common/PersistentStateMachine.test.js +179 -0
  241. package/test/unit/lib/model/data/authorizationsResponse.json +13 -0
  242. package/test/unit/lib/model/data/bulkQuoteRequest.json +27 -0
  243. package/test/unit/lib/model/data/bulkQuoteResponse.json +35 -0
  244. package/test/unit/lib/model/data/bulkTransferFulfil.json +13 -0
  245. package/test/unit/lib/model/data/bulkTransferRequest.json +29 -0
  246. package/test/unit/lib/model/data/defaultConfig.json +47 -0
  247. package/test/unit/lib/model/data/getBulkTransfersBackendResponse.json +42 -0
  248. package/test/unit/lib/model/data/getBulkTransfersMojaloopResponse.json +22 -0
  249. package/test/unit/lib/model/data/getTransfersBackendResponse.json +34 -0
  250. package/test/unit/lib/model/data/getTransfersMojaloopResponse.json +17 -0
  251. package/test/unit/lib/model/data/mockArguments.json +131 -0
  252. package/test/unit/lib/model/data/mockTxnRequestsArguments.json +63 -0
  253. package/test/unit/lib/model/data/notificationToPayee.json +10 -0
  254. package/test/unit/lib/model/data/payeeParty.json +16 -0
  255. package/test/unit/lib/model/data/putAuthorizationsResponse.json +10 -0
  256. package/test/unit/lib/model/data/putQuotesResponse.json +33 -0
  257. package/test/unit/lib/model/data/putTransfersResponse.json +5 -0
  258. package/test/unit/lib/model/data/quoteResponse.json +31 -0
  259. package/test/unit/lib/model/data/requestToPayRequest.json +20 -0
  260. package/test/unit/lib/model/data/requestToPayTransferRequest.json +27 -0
  261. package/test/unit/lib/model/data/transactionRequestResponse.json +18 -0
  262. package/test/unit/lib/model/data/transferFulfil.json +8 -0
  263. package/test/unit/lib/model/data/transferRequest.json +26 -0
  264. package/test/unit/lib/model/mockedLibRequests.js +74 -0
  265. package/test/unit/mockLogger.js +39 -0
  266. package/test/unit/outboundApi/data/bulkQuoteRequest.json +28 -0
  267. package/test/unit/outboundApi/data/bulkTransferRequest.json +28 -0
  268. package/test/unit/outboundApi/data/mockBulkQuoteError.json +45 -0
  269. package/test/unit/outboundApi/data/mockBulkTransferError.json +48 -0
  270. package/test/unit/outboundApi/data/mockError.json +41 -0
  271. package/test/unit/outboundApi/data/mockGetPartiesError.json +4 -0
  272. package/test/unit/outboundApi/data/mockRequestToPayError.json +32 -0
  273. package/test/unit/outboundApi/data/mockRequestToPayTransferError.json +39 -0
  274. package/test/unit/outboundApi/data/requestToPay.json +21 -0
  275. package/test/unit/outboundApi/data/requestToPayTransferRequest.json +20 -0
  276. package/test/unit/outboundApi/data/transferRequest.json +21 -0
  277. package/test/unit/outboundApi/handlers.test.js +986 -0
@@ -0,0 +1,39 @@
1
+ /**************************************************************************
2
+ * (C) Copyright ModusBox Inc. 2020 - All rights reserved. *
3
+ * *
4
+ * This file is made available under the terms of the license agreement *
5
+ * specified in the corresponding source code repository. *
6
+ * *
7
+ * ORIGINAL AUTHOR: *
8
+ * Paweł Marzec - pawel.marzec@modusbox.com *
9
+ **************************************************************************/
10
+
11
+ const { Logger } = require('@mojaloop/sdk-standard-components');
12
+
13
+ function mockLogger(context, keepQuiet) {
14
+ // if keepQuite is undefined then be quiet
15
+ if (keepQuiet || typeof keepQuiet === 'undefined') {
16
+ const methods = {
17
+ // log methods
18
+ log: jest.fn(),
19
+
20
+ configure: jest.fn(),
21
+
22
+ // generated methods from default levels
23
+ verbose: jest.fn(),
24
+ debug: jest.fn(),
25
+ warn: jest.fn(),
26
+ error: jest.fn(),
27
+ trace: jest.fn(),
28
+ info: jest.fn(),
29
+ fatal: jest.fn()
30
+ };
31
+ return {
32
+ ...methods,
33
+ push: jest.fn(() => methods)
34
+ };
35
+ }
36
+ return new Logger.Logger();
37
+ }
38
+
39
+ module.exports = mockLogger;
@@ -0,0 +1,28 @@
1
+ {
2
+ "homeTransactionId": "123ABC",
3
+ "from": {
4
+ "displayName": "James Bush",
5
+ "idType": "MSISDN",
6
+ "idValue": "447710066017",
7
+ "extensionList": [
8
+ {
9
+ "key": "accountType",
10
+ "value": "Wallet"
11
+ }
12
+ ]
13
+ },
14
+ "individualQuotes": [
15
+ {
16
+ "quoteId": "12346789",
17
+ "to": {
18
+ "idType": "MSISDN",
19
+ "idValue": "1234567890"
20
+ },
21
+ "amountType": "SEND",
22
+ "currency": "USD",
23
+ "amount": "100",
24
+ "transactionType": "TRANSFER",
25
+ "note": "test payment"
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "homeTransactionId": "123ABC",
3
+ "from": {
4
+ "displayName": "James Bush",
5
+ "idType": "MSISDN",
6
+ "idValue": "447710066017",
7
+ "extensionList": [
8
+ {
9
+ "key": "accountType",
10
+ "value": "Wallet"
11
+ }
12
+ ]
13
+ },
14
+ "individualTransfers": [
15
+ {
16
+ "transferId": "132435",
17
+ "to": {
18
+ "idType": "MSISDN",
19
+ "idValue": "1234567890"
20
+ },
21
+ "amountType": "SEND",
22
+ "currency": "USD",
23
+ "amount": "100",
24
+ "transactionType": "TRANSFER",
25
+ "note": "test payment"
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "message": "Mock error",
3
+ "httpStatusCode": 500,
4
+ "bulkQuoteState": {
5
+ "from": {
6
+ "displayName": "James Bush",
7
+ "idType": "MSISDN",
8
+ "idValue": "447710066017"
9
+ },
10
+ "individualQuoteResults": [
11
+ {
12
+ "to": {
13
+ "idType": "MSISDN",
14
+ "idValue": "1234567890"
15
+ },
16
+ "amountType": "SEND",
17
+ "currency": "USD",
18
+ "amount": "100",
19
+ "transactionType": "TRANSFER",
20
+ "note": "test payment",
21
+ "homeTransactionId": "123ABC",
22
+ "transferId": "5a2ad5dc-4ab1-4a22-8c5b-62f75252a8d5",
23
+ "currentState": "ERROR_OCCURRED"
24
+ }
25
+ ],
26
+ "lastError": {
27
+ "httpStatusCode": 500,
28
+ "mojaloopError": {
29
+ "errorInformation": {
30
+ "errorCode": "3204",
31
+ "errorDescription": "Party not found",
32
+ "extensionList": {
33
+ "extension": [{
34
+ "key": "someKey",
35
+ "value": "someValue"
36
+ }, {
37
+ "key": "extErrorKey",
38
+ "value": "9999"
39
+ }]
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "message": "Mock error",
3
+ "statusCode": 500,
4
+ "bulkTransferState": {
5
+ "from": {
6
+ "displayName": "James Bush",
7
+ "idType": "MSISDN",
8
+ "idValue": "447710066017"
9
+ },
10
+ "to": {
11
+ "idType": "MSISDN",
12
+ "idValue": "1234567890"
13
+ },
14
+ "individualTransferResults": [
15
+ {
16
+ "transferId": "5a2ad5dc-4ab1-4a22-8c5b-62f75252a8d5",
17
+ "amountType": "SEND",
18
+ "currency": "USD",
19
+ "amount": "100",
20
+ "transactionType": "TRANSFER",
21
+ "note": "test payment",
22
+ "homeTransactionId": "123ABC",
23
+ "currentState": "ERROR_OCCURRED"
24
+ }
25
+ ],
26
+ "lastError": {
27
+ "httpStatusCode": 500,
28
+ "mojaloopError": {
29
+ "errorInformation": {
30
+ "errorCode": "3204",
31
+ "errorDescription": "Party not found",
32
+ "extensionList": {
33
+ "extension": [
34
+ {
35
+ "key": "someKey",
36
+ "value": "someValue"
37
+ },
38
+ {
39
+ "key": "extErrorKey",
40
+ "value": "9999"
41
+ }
42
+ ]
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "message": "Mock error",
3
+ "httpStatusCode": 500,
4
+ "transferState": {
5
+ "from": {
6
+ "displayName": "James Bush",
7
+ "idType": "MSISDN",
8
+ "idValue": "447710066017"
9
+ },
10
+ "to": {
11
+ "idType": "MSISDN",
12
+ "idValue": "1234567890"
13
+ },
14
+ "amountType": "SEND",
15
+ "currency": "USD",
16
+ "amount": "100",
17
+ "transactionType": "TRANSFER",
18
+ "note": "test payment",
19
+ "homeTransactionId": "123ABC",
20
+ "transferId": "5a2ad5dc-4ab1-4a22-8c5b-62f75252a8d5",
21
+ "currentState": "ERROR_OCCURRED",
22
+ "lastError": {
23
+ "httpStatusCode": 500,
24
+ "mojaloopError": {
25
+ "errorInformation": {
26
+ "errorCode": "3204",
27
+ "errorDescription": "Party not found",
28
+ "extensionList": {
29
+ "extension": [{
30
+ "key": "someKey",
31
+ "value": "someValue"
32
+ }, {
33
+ "key": "extErrorKey",
34
+ "value": "9999"
35
+ }]
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "message": "Mock error",
3
+ "httpStatusCode": 500
4
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "message": "Mock error",
3
+ "httpStatusCode": 500,
4
+ "requestToPayState": {
5
+ "from": {
6
+ "displayName": "James Bush",
7
+ "idType": "MSISDN",
8
+ "idValue": "447710066017"
9
+ },
10
+ "to": {
11
+ "idType": "MSISDN",
12
+ "idValue": "1234567890"
13
+ },
14
+ "amountType": "SEND",
15
+ "currency": "USD",
16
+ "amount": "100",
17
+ "transactionType": "TRANSFER",
18
+ "note": "test payment",
19
+ "homeTransactionId": "123ABC",
20
+ "transferId": "5a2ad5dc-4ab1-4a22-8c5b-62f75252a8d5",
21
+ "currentState": "ERROR_OCCURRED",
22
+ "lastError": {
23
+ "httpStatusCode": 500,
24
+ "mojaloopError": {
25
+ "errorInformation": {
26
+ "errorCode": "3204",
27
+ "errorDescription": "Party not found"
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "message": "Mock error",
3
+ "httpStatusCode": 500,
4
+ "requestToPayTransferState": {
5
+ "from": {
6
+ "displayName": "James Bush",
7
+ "idType": "MSISDN",
8
+ "idValue": "447710066017"
9
+ },
10
+ "to": {
11
+ "idType": "MSISDN",
12
+ "idValue": "1234567890"
13
+ },
14
+ "amountType": "SEND",
15
+ "currency": "USD",
16
+ "amount": "100",
17
+ "transactionType": "TRANSFER",
18
+ "note": "test payment",
19
+ "homeTransactionId": "123ABC",
20
+ "transferId": "5a2ad5dc-4ab1-4a22-8c5b-62f75252a8d5",
21
+ "currentState": "ERROR_OCCURRED",
22
+ "lastError": {
23
+ "httpStatusCode": 500,
24
+ "mojaloopError": {
25
+ "errorInformation": {
26
+ "errorCode": "3204",
27
+ "errorDescription": "Quote failed",
28
+ "extensionList": [{
29
+ "key": "someKey",
30
+ "value": "someValue"
31
+ }, {
32
+ "key": "extErrorKey",
33
+ "value": "9999"
34
+ }]
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "from": {
3
+ "displayName": "Murthy Kakarlamudi",
4
+ "idType": "MSISDN",
5
+ "idValue": "17855501914",
6
+ "extensionList": [
7
+ {"key": "accountType",
8
+ "value": "Wallet"}
9
+ ]
10
+ },
11
+ "to": {
12
+ "idType": "MSISDN",
13
+ "idValue": "1234567890"
14
+ },
15
+ "amountType": "SEND",
16
+ "currency": "USD",
17
+ "amount": "100",
18
+ "transactionType": "TRANSFER",
19
+ "note": "test payment",
20
+ "homeTransactionId": "123ABC"
21
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "requestToPayTransactionId": "c85e581e-fccf-4f55-8bea-96192ee2a32b",
3
+ "from": {
4
+ "displayName": "CustomerName",
5
+ "idType": "MSISDN",
6
+ "idValue": "17855501914"
7
+ },
8
+ "to": {
9
+ "idType": "BUSINESS",
10
+ "idValue": "Starbucks",
11
+ "fspId": "payeefsp"
12
+ },
13
+ "amountType": "SEND",
14
+ "currency": "USD",
15
+ "amount": "100",
16
+ "scenario":"PAYMENT",
17
+ "initiator":"PAYEE",
18
+ "initiatorType":"DEVICE",
19
+ "note": "test payment"
20
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "from": {
3
+ "displayName": "James Bush",
4
+ "idType": "MSISDN",
5
+ "idValue": "447710066017",
6
+ "extensionList": [
7
+ {"key": "accountType",
8
+ "value": "Wallet"}
9
+ ]
10
+ },
11
+ "to": {
12
+ "idType": "MSISDN",
13
+ "idValue": "1234567890"
14
+ },
15
+ "amountType": "SEND",
16
+ "currency": "USD",
17
+ "amount": "100",
18
+ "transactionType": "TRANSFER",
19
+ "note": "test payment",
20
+ "homeTransactionId": "123ABC"
21
+ }
@@ -0,0 +1,986 @@
1
+ /**************************************************************************
2
+ * (C) Copyright ModusBox Inc. 2019 - All rights reserved. *
3
+ * *
4
+ * This file is made available under the terms of the license agreement *
5
+ * specified in the corresponding source code repository. *
6
+ * *
7
+ * ORIGINAL AUTHOR: *
8
+ * James Bush - james.bush@modusbox.com *
9
+ **************************************************************************/
10
+
11
+ 'use strict';
12
+
13
+ const mockError = require('./data/mockError');
14
+ const mockBulkQuoteError = require('./data/mockBulkQuoteError');
15
+ const mockBulkTransferError = require('./data/mockBulkTransferError');
16
+ const mockRequestToPayError = require('./data/mockRequestToPayError');
17
+ const mockRequestToPayTransferError = require('./data/mockRequestToPayTransferError');
18
+ const mockGetPartiesError = require('./data/mockGetPartiesError');
19
+ const transferRequest = require('./data/transferRequest');
20
+ const bulkTransferRequest = require('./data/bulkTransferRequest');
21
+ const bulkQuoteRequest = require('./data/bulkQuoteRequest');
22
+ const requestToPayPayload = require('./data/requestToPay');
23
+ const requestToPayTransferRequest = require('./data/requestToPayTransferRequest');
24
+ const mockLogger = require('../mockLogger');
25
+ const { uuid } = require('uuidv4');
26
+
27
+ jest.mock('../../../lib/model');
28
+
29
+ const handlers = require('../../../OutboundServer/handlers');
30
+ const {
31
+ OutboundTransfersModel,
32
+ OutboundBulkTransfersModel,
33
+ OutboundBulkQuotesModel,
34
+ OutboundRequestToPayTransferModel,
35
+ OutboundRequestToPayModel,
36
+ PartiesModel,
37
+ QuotesModel,
38
+ TransfersModel,
39
+ AuthorizationsModel
40
+ } = require('../../../lib/model');
41
+
42
+ /**
43
+ * Mock the outbound transfer model to simulate throwing errors
44
+ */
45
+ OutboundTransfersModel.mockImplementation(() => {
46
+ return {
47
+ run: async () => {
48
+ // throw the mockError object when the model is run
49
+ throw mockError;
50
+ },
51
+ initialize: async () => {
52
+ // nothing needed here
53
+ return;
54
+ },
55
+ load: async () => {
56
+ // nothing needed here
57
+ return;
58
+ }
59
+ };
60
+ });
61
+
62
+ /**
63
+ * Mock the outbound bulk transfers model to simulate throwing errors
64
+ */
65
+ OutboundBulkTransfersModel.mockImplementation(() => {
66
+ return {
67
+ run: async () => {
68
+ throw mockBulkTransferError;
69
+ },
70
+ initialize: async () => {
71
+ return;
72
+ },
73
+ load: async () => {
74
+ return;
75
+ }
76
+ };
77
+ });
78
+
79
+ /**
80
+ * Mock the outbound bulk quotes model to simulate throwing errors
81
+ */
82
+ OutboundBulkQuotesModel.mockImplementation(() => {
83
+ return {
84
+ run: async () => {
85
+ throw mockBulkQuoteError;
86
+ },
87
+ initialize: async () => {
88
+ return;
89
+ },
90
+ load: async () => {
91
+ return;
92
+ }
93
+ };
94
+ });
95
+
96
+ /**
97
+ * Mock the outbound transfer model to simulate throwing errors
98
+ */
99
+ OutboundRequestToPayTransferModel.mockImplementation(() => {
100
+ return {
101
+ run: async () => {
102
+ // throw the mockError object when the model is run
103
+ throw mockRequestToPayTransferError;
104
+ },
105
+ initialize: async () => {
106
+ // nothing needed here
107
+ return;
108
+ },
109
+ load: async () => {
110
+ // nothing needed here
111
+ return;
112
+ }
113
+ };
114
+ });
115
+
116
+ /**
117
+ * Mock the outbound request to pay model to simulate throwing errors
118
+ */
119
+ OutboundRequestToPayModel.mockImplementation(() => {
120
+ return {
121
+ run: async () => {
122
+ // throw the mockError object when the model is run
123
+ throw mockRequestToPayError;
124
+ },
125
+ initialize: async () => {
126
+ // nothing needed here
127
+ return;
128
+ },
129
+ load: async () => {
130
+ // nothing needed here
131
+ return;
132
+ }
133
+ };
134
+ });
135
+
136
+
137
+ describe('Outbound API handlers:', () => {
138
+ describe('POST /transfers', () => {
139
+ test('returns correct error response body when model throws mojaloop error', async () => {
140
+ const mockContext = {
141
+ request: {
142
+ body: transferRequest,
143
+ headers: {
144
+ 'fspiop-source': 'foo'
145
+ }
146
+ },
147
+ response: {},
148
+ state: {
149
+ conf: {},
150
+ logger: { log: () => {} },
151
+ }
152
+ };
153
+
154
+ await handlers['/transfers'].post(mockContext);
155
+
156
+ // check response is correct
157
+ expect(mockContext.response.status).toEqual(500);
158
+ expect(mockContext.response.body).toBeTruthy();
159
+ expect(mockContext.response.body.message).toEqual('Mock error');
160
+ expect(mockContext.response.body.statusCode)
161
+ .toEqual(mockError.transferState.lastError.mojaloopError.errorInformation.errorCode);
162
+ expect(mockContext.response.body.transferState).toEqual(mockError.transferState);
163
+ });
164
+
165
+ test('uses correct extension list error code for response body statusCode when configured to do so', async () => {
166
+ const mockContext = {
167
+ request: {
168
+ body: transferRequest,
169
+ headers: {
170
+ 'fspiop-source': 'foo'
171
+ }
172
+ },
173
+ response: {},
174
+ state: {
175
+ conf: {
176
+ outboundErrorStatusCodeExtensionKey: 'extErrorKey' // <- tell the handler to use this extensionList item as source of statusCode
177
+ },
178
+ logger: { log: () => {} },
179
+ }
180
+ };
181
+
182
+ await handlers['/transfers'].post(mockContext);
183
+
184
+ // check response is correct
185
+ expect(mockContext.response.status).toEqual(500);
186
+ expect(mockContext.response.body).toBeTruthy();
187
+ expect(mockContext.response.body.message).toEqual('Mock error');
188
+
189
+ // in this case, where we have set outboundErrorExtensionKey config we expect the error body statusCode
190
+ // property to come from the extensionList item with the corresponding key 'extErrorKey'
191
+ expect(mockContext.response.body.statusCode).toEqual('9999');
192
+ expect(mockContext.response.body.transferState).toEqual(mockError.transferState);
193
+ });
194
+ });
195
+
196
+ describe('PUT /transfers', () => {
197
+ test('returns correct error response body when model throws mojaloop error', async () => {
198
+ const mockContext = {
199
+ request: {
200
+ body: {
201
+ acceptQuote: true
202
+ },
203
+ headers: {
204
+ 'fspiop-source': 'foo'
205
+ }
206
+ },
207
+ response: {},
208
+ state: {
209
+ conf: {},
210
+ logger: { log: () => {} },
211
+ path: {
212
+ params: {
213
+ transferId: '12345'
214
+ }
215
+ }
216
+ }
217
+ };
218
+
219
+ await handlers['/transfers/{transferId}'].put(mockContext);
220
+
221
+ // check response is correct
222
+ expect(mockContext.response.status).toEqual(500);
223
+ expect(mockContext.response.body).toBeTruthy();
224
+ expect(mockContext.response.body.message).toEqual('Mock error');
225
+ expect(mockContext.response.body.statusCode).toEqual('3204');
226
+ expect(mockContext.response.body.transferState).toEqual(mockError.transferState);
227
+ });
228
+ });
229
+
230
+ describe('POST /bulkTransfers', () => {
231
+ test('returns correct error response body when model throws mojaloop error', async () => {
232
+ const mockContext = {
233
+ request: {
234
+ body: bulkTransferRequest,
235
+ headers: {
236
+ 'fspiop-source': 'foo'
237
+ }
238
+ },
239
+ response: {},
240
+ state: {
241
+ conf: {},
242
+ logger: { log: () => {} },
243
+ }
244
+ };
245
+
246
+ await handlers['/bulkTransfers'].post(mockContext);
247
+
248
+ // check response is correct
249
+ expect(mockContext.response.status).toEqual(500);
250
+ expect(mockContext.response.body).toBeTruthy();
251
+ expect(mockContext.response.body.message).toEqual('Mock error');
252
+ expect(mockContext.response.body.statusCode)
253
+ .toEqual(mockBulkTransferError.bulkTransferState.lastError.mojaloopError.errorInformation.errorCode);
254
+ expect(mockContext.response.body.bulkTransferState).toEqual(mockBulkTransferError.bulkTransferState);
255
+ });
256
+
257
+ test('uses correct extension list error code for response body statusCode when configured to do so', async () => {
258
+ const mockContext = {
259
+ request: {
260
+ body: bulkTransferRequest,
261
+ headers: {
262
+ 'fspiop-source': 'foo'
263
+ }
264
+ },
265
+ response: {},
266
+ state: {
267
+ conf: {
268
+ outboundErrorStatusCodeExtensionKey: 'extErrorKey' // <- tell the handler to use this extensionList item as source of statusCode
269
+ },
270
+ logger: { log: () => {} },
271
+ }
272
+ };
273
+
274
+ await handlers['/bulkTransfers'].post(mockContext);
275
+
276
+ // check response is correct
277
+ expect(mockContext.response.status).toEqual(500);
278
+ expect(mockContext.response.body).toBeTruthy();
279
+ expect(mockContext.response.body.message).toEqual('Mock error');
280
+
281
+ // in this case, where we have set outboundErrorExtensionKey config we expect the error body statusCode
282
+ // property to come from the extensionList item with the corresponding key 'extErrorKey'
283
+ expect(mockContext.response.body.statusCode).toEqual('9999');
284
+ expect(mockContext.response.body.bulkTransferState).toEqual(mockBulkTransferError.bulkTransferState);
285
+ });
286
+ });
287
+
288
+ describe('POST /bulkQuotes', () => {
289
+ test('returns correct error response body when model throws mojaloop error', async () => {
290
+ const mockContext = {
291
+ request: {
292
+ body: bulkQuoteRequest,
293
+ headers: {
294
+ 'fspiop-source': 'foo'
295
+ }
296
+ },
297
+ response: {},
298
+ state: {
299
+ conf: {},
300
+ logger: { log: () => {} },
301
+ }
302
+ };
303
+
304
+ await handlers['/bulkQuotes'].post(mockContext);
305
+
306
+ // check response is correct
307
+ expect(mockContext.response.status).toEqual(500);
308
+ expect(mockContext.response.body).toBeTruthy();
309
+ expect(mockContext.response.body.message).toEqual('Mock error');
310
+ expect(mockContext.response.body.statusCode)
311
+ .toEqual(mockBulkQuoteError.bulkQuoteState.lastError.mojaloopError.errorInformation.errorCode);
312
+ expect(mockContext.response.body.bulkQuoteState).toEqual(mockBulkQuoteError.bulkQuoteState);
313
+ });
314
+
315
+ test('uses correct extension list error code for response body statusCode when configured to do so', async () => {
316
+ const mockContext = {
317
+ request: {
318
+ body: bulkQuoteRequest,
319
+ headers: {
320
+ 'fspiop-source': 'foo'
321
+ }
322
+ },
323
+ response: {},
324
+ state: {
325
+ conf: {
326
+ outboundErrorStatusCodeExtensionKey: 'extErrorKey' // <- tell the handler to use this extensionList item as source of statusCode
327
+ },
328
+ logger: { log: () => {} },
329
+ }
330
+ };
331
+
332
+ await handlers['/bulkQuotes'].post(mockContext);
333
+
334
+ // check response is correct
335
+ expect(mockContext.response.status).toEqual(500);
336
+ expect(mockContext.response.body).toBeTruthy();
337
+ expect(mockContext.response.body.message).toEqual('Mock error');
338
+
339
+ // in this case, where we have set outboundErrorExtensionKey config we expect the error body statusCode
340
+ // property to come from the extensionList item with the corresponding key 'extErrorKey'
341
+ expect(mockContext.response.body.statusCode).toEqual('9999');
342
+ expect(mockContext.response.body.bulkQuoteState).toEqual(mockBulkQuoteError.bulkQuoteState);
343
+ });
344
+ });
345
+
346
+ describe('POST /requestToPayTransfer', () => {
347
+ test('returns correct error response body when model throws mojaloop error', async () => {
348
+ const mockContext = {
349
+ request: {
350
+ body: requestToPayTransferRequest,
351
+ headers: {
352
+ 'fspiop-source': 'foo'
353
+ }
354
+ },
355
+ response: {},
356
+ state: {
357
+ conf: {},
358
+ logger: { log: () => {} },
359
+ }
360
+ };
361
+
362
+ await handlers['/requestToPayTransfer'].post(mockContext);
363
+ // check response is correct
364
+ expect(mockContext.response.status).toEqual(500);
365
+ expect(mockContext.response.body).toBeTruthy();
366
+ expect(mockContext.response.body.message).toEqual('Mock error');
367
+ expect(mockContext.response.body.statusCode)
368
+ .toEqual(mockRequestToPayTransferError.requestToPayTransferState.lastError.mojaloopError.errorInformation.errorCode);
369
+ expect(mockContext.response.body.requestToPayTransferState).toEqual(mockRequestToPayTransferError.requestToPayTransferState);
370
+ });
371
+ });
372
+
373
+ describe('POST /requestToPay', () => {
374
+ test('returns correct error response body when model throws mojaloop error', async () => {
375
+ const mockContext = {
376
+ request: {
377
+ body: requestToPayPayload,
378
+ headers: {
379
+ 'fspiop-source': 'foo'
380
+ }
381
+ },
382
+ response: {},
383
+ state: {
384
+ conf: {},
385
+ logger: { log: () => {} }
386
+ }
387
+ };
388
+
389
+ await handlers['/requestToPay'].post(mockContext);
390
+
391
+ // check response is correct
392
+ expect(mockContext.response.status).toEqual(500);
393
+ expect(mockContext.response.body).toBeTruthy();
394
+ expect(mockContext.response.body.message).toEqual('Mock error');
395
+ expect(mockContext.response.body.statusCode).toEqual('3204');
396
+ expect(mockContext.response.body.requestToPayState).toEqual(mockRequestToPayError.requestToPayState);
397
+ });
398
+ });
399
+
400
+ describe('GET /parties/{Type}/{ID}/{SubId}', () => {
401
+ test('happy flow', async() => {
402
+
403
+ const mockContext = {
404
+ request: {},
405
+ response: {},
406
+ state: {
407
+ conf: {},
408
+ wso2Auth: 'mocked wso2Auth',
409
+ logger: mockLogger({ app: 'outbound-api-handlers-test'}),
410
+ cache: { the: 'mocked cache' },
411
+ path: {
412
+ params: {
413
+ 'Type': 'MSISDN',
414
+ 'ID': '1234567890',
415
+ 'SubId': 'abcdefgh'
416
+ },
417
+ },
418
+ },
419
+ };
420
+
421
+ // mock state machine
422
+ const mockedPSM = {
423
+ run: jest.fn(async () => ({ the: 'run response' }))
424
+ };
425
+
426
+ const createSpy = jest.spyOn(PartiesModel, 'create')
427
+ .mockImplementationOnce(async () => mockedPSM);
428
+
429
+ // invoke handler
430
+ await handlers['/parties/{Type}/{ID}/{SubId}'].get(mockContext);
431
+
432
+ // PSM model creation
433
+ const state = mockContext.state;
434
+ const cacheKey = PartiesModel.channelName({
435
+ type: 'MSISDN',
436
+ id: '1234567890',
437
+ subId: 'abcdefgh'
438
+ });
439
+ const expectedConfig = {
440
+ cache: state.cache,
441
+ logger: state.logger,
442
+ wso2Auth: state.wso2Auth
443
+ };
444
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
445
+
446
+ // run workflow
447
+ expect(mockedPSM.run).toBeCalledWith({
448
+ type: 'MSISDN',
449
+ id: '1234567890',
450
+ subId: 'abcdefgh'
451
+ });
452
+
453
+ // response
454
+ expect(mockContext.response.status).toBe(200);
455
+ expect(mockContext.response.body).toEqual({ the: 'run response' });
456
+ });
457
+
458
+ test('error flow', async() => {
459
+ const mockContext = {
460
+ request: {},
461
+ response: {},
462
+ state: {
463
+ conf: {},
464
+ wso2Auth: 'mocked wso2Auth',
465
+ logger: mockLogger({ app: 'outbound-api-handlers-test'}),
466
+ cache: { the: 'mocked cache' },
467
+ path: {
468
+ params: {
469
+ 'Type': 'MSISDN',
470
+ 'ID': '1234567890',
471
+ 'SubId': 'abcdefgh'
472
+ },
473
+ },
474
+ },
475
+ };
476
+
477
+ // mock state machine
478
+ const mockedPSM = {
479
+ run: jest.fn(async () => ({ errorInformation: { Iam: 'the-error'} }))
480
+ };
481
+
482
+ const createSpy = jest.spyOn(PartiesModel, 'create')
483
+ .mockImplementationOnce(async () => mockedPSM);
484
+
485
+ // invoke handler
486
+ await handlers['/parties/{Type}/{ID}/{SubId}'].get(mockContext);
487
+
488
+ // PSM model creation
489
+ const state = mockContext.state;
490
+ const cacheKey = PartiesModel.channelName({
491
+ type: 'MSISDN',
492
+ id: '1234567890',
493
+ subId: 'abcdefgh'
494
+ });
495
+ const expectedConfig = {
496
+ cache: state.cache,
497
+ logger: state.logger,
498
+ wso2Auth: state.wso2Auth
499
+ };
500
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
501
+
502
+ // run workflow
503
+ expect(mockedPSM.run).toBeCalledWith({
504
+ type: 'MSISDN',
505
+ id: '1234567890',
506
+ subId: 'abcdefgh'
507
+ });
508
+
509
+ // response
510
+ expect(mockContext.response.status).toBe(404);
511
+ expect(mockContext.response.body).toEqual({ errorInformation: { Iam: 'the-error'} });
512
+ });
513
+ });
514
+ describe('GET /parties/{Type}/{ID}', () => {
515
+ const mockContext = {
516
+ request: {},
517
+ response: {},
518
+ state: {
519
+ conf: {},
520
+ wso2Auth: 'mocked wso2Auth',
521
+ logger: mockLogger({ app: 'outbound-api-handlers-test'}),
522
+ cache: {
523
+ subscribe: jest.fn(() => Promise.resolve())
524
+ },
525
+ path: {
526
+ params: {
527
+ 'Type': 'MSISDN',
528
+ 'ID': '1234567890'
529
+ },
530
+ },
531
+ },
532
+ };
533
+ test('happy flow', async() => {
534
+
535
+
536
+ // mock state machine
537
+ const mockedPSM = {
538
+ run: jest.fn(async () => ({ the: 'run response' }))
539
+ };
540
+
541
+ const createSpy = jest.spyOn(PartiesModel, 'create')
542
+ .mockImplementationOnce(async () => mockedPSM);
543
+
544
+ // invoke handler
545
+ await handlers['/parties/{Type}/{ID}'].get(mockContext);
546
+
547
+ // PSM model creation
548
+ const state = mockContext.state;
549
+ const cacheKey = PartiesModel.channelName({
550
+ type: 'MSISDN',
551
+ id: '1234567890'
552
+ });
553
+ const expectedConfig = {
554
+ cache: state.cache,
555
+ logger: state.logger,
556
+ wso2Auth: state.wso2Auth
557
+ };
558
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
559
+
560
+ // run workflow
561
+ expect(mockedPSM.run).toBeCalledWith({ type: 'MSISDN', id: '1234567890', subId: undefined });
562
+
563
+ // response
564
+ expect(mockContext.response.status).toBe(200);
565
+ expect(mockContext.response.body).toEqual({ the: 'run response' });
566
+ });
567
+
568
+ test('not found error flow', async() => {
569
+
570
+ // mock state machine
571
+ const mockedPSM = {
572
+ run: jest.fn(async () => ({ errorInformation: { Iam: 'the-error'} }))
573
+ };
574
+
575
+ const createSpy = jest.spyOn(PartiesModel, 'create')
576
+ .mockImplementationOnce(async () => mockedPSM);
577
+
578
+ // invoke handler
579
+ await handlers['/parties/{Type}/{ID}'].get(mockContext);
580
+
581
+ // PSM model creation
582
+ const state = mockContext.state;
583
+ const cacheKey = PartiesModel.channelName({
584
+ type: 'MSISDN',
585
+ id: '1234567890'
586
+ });
587
+ const expectedConfig = {
588
+ cache: state.cache,
589
+ logger: state.logger,
590
+ wso2Auth: state.wso2Auth
591
+ };
592
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
593
+
594
+ // run workflow
595
+ expect(mockedPSM.run).toBeCalledWith({
596
+ type: 'MSISDN',
597
+ id: '1234567890',
598
+ subId: undefined
599
+ });
600
+
601
+ // response
602
+ expect(mockContext.response.status).toBe(404);
603
+ expect(mockContext.response.body).toEqual({ errorInformation: { Iam: 'the-error'} });
604
+ });
605
+
606
+ test('mojaloop error propagation for /parties/{Type}/{ID}', async() => {
607
+
608
+ // mock state machine
609
+ const mockedPSM = {
610
+ run: jest.fn(async () => { throw mockGetPartiesError; })
611
+ };
612
+
613
+ const createSpy = jest.spyOn(PartiesModel, 'create')
614
+ .mockImplementationOnce(async () => mockedPSM);
615
+
616
+ // invoke handler
617
+ await handlers['/parties/{Type}/{ID}'].get(mockContext);
618
+
619
+ // PSM model creation
620
+ const state = mockContext.state;
621
+ const cacheKey = PartiesModel.channelName({
622
+ type: 'MSISDN',
623
+ id: '1234567890'
624
+ });
625
+ const expectedConfig = {
626
+ cache: state.cache,
627
+ logger: state.logger,
628
+ wso2Auth: state.wso2Auth
629
+ };
630
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
631
+
632
+ // run workflow
633
+ expect(mockedPSM.run).toBeCalledWith({
634
+ type: 'MSISDN',
635
+ id: '1234567890',
636
+ subId: undefined
637
+ });
638
+
639
+ // response
640
+ expect(mockContext.response.status).toBe(500);
641
+ expect(mockContext.response.body).toEqual({
642
+ message: 'Mock error',
643
+ statusCode: '500',
644
+ requestPartiesInformationState: {}
645
+ });
646
+ });
647
+ test('mojaloop error propagation for /parties/{Type}/{ID}/{SubId}', async() => {
648
+
649
+ // mock state machine
650
+ const mockedPSM = {
651
+ run: jest.fn(async () => { throw mockGetPartiesError; })
652
+ };
653
+
654
+ const createSpy = jest.spyOn(PartiesModel, 'create')
655
+ .mockImplementationOnce(async () => mockedPSM);
656
+
657
+ // invoke handler
658
+ await handlers['/parties/{Type}/{ID}/{SubId}'].get(mockContext);
659
+
660
+ // PSM model creation
661
+ const state = mockContext.state;
662
+ const cacheKey = PartiesModel.channelName({
663
+ type: 'MSISDN',
664
+ id: '1234567890'
665
+ });
666
+ const expectedConfig = {
667
+ cache: state.cache,
668
+ logger: state.logger,
669
+ wso2Auth: state.wso2Auth
670
+ };
671
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
672
+
673
+ // run workflow
674
+ expect(mockedPSM.run).toBeCalledWith({
675
+ type: 'MSISDN',
676
+ id: '1234567890',
677
+ subId: undefined
678
+ });
679
+
680
+ // response
681
+ expect(mockContext.response.status).toBe(500);
682
+ expect(mockContext.response.body).toEqual({
683
+ message: 'Mock error',
684
+ statusCode: '500',
685
+ requestPartiesInformationState: {}
686
+ });
687
+ });
688
+ });
689
+
690
+ describe('POST /quotes', () => {
691
+ const mockContext = {
692
+ request: {
693
+ body: {
694
+ fspId: uuid(),
695
+ quotesPostRequest: {
696
+ quoteId: uuid()
697
+ }
698
+ }
699
+ },
700
+ response: {},
701
+ state: {
702
+ conf: {},
703
+ wso2Auth: 'mocked wso2Auth',
704
+ logger: mockLogger({ app: 'outbound-api-handlers-test' }),
705
+ cache: {
706
+ subscribe: jest.fn(() => Promise.resolve())
707
+ }
708
+ },
709
+ };
710
+ test('happy flow', async () => {
711
+
712
+
713
+ // mock state machine
714
+ const mockedPSM = {
715
+ run: jest.fn(async () => ({ the: 'run response' }))
716
+ };
717
+
718
+ const createSpy = jest.spyOn(QuotesModel, 'create')
719
+ .mockImplementationOnce(async () => mockedPSM);
720
+
721
+ // invoke handler
722
+ await handlers['/quotes'].post(mockContext);
723
+
724
+ // PSM model creation
725
+ const state = mockContext.state;
726
+ const cacheKey = QuotesModel.channelName({
727
+ quoteId: mockContext.request.body.quotesPostRequest.quoteId
728
+ });
729
+ const expectedConfig = {
730
+ cache: state.cache,
731
+ logger: state.logger,
732
+ wso2Auth: state.wso2Auth
733
+ };
734
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
735
+
736
+ // run workflow
737
+ expect(mockedPSM.run).toBeCalledWith({
738
+ quoteId: mockContext.request.body.quotesPostRequest.quoteId,
739
+ fspId: mockContext.request.body.fspId,
740
+ quote: mockContext.request.body.quotesPostRequest
741
+ });
742
+
743
+ // response
744
+ expect(mockContext.response.status).toBe(200);
745
+ expect(mockContext.response.body).toEqual({ the: 'run response' });
746
+ });
747
+
748
+ test('mojaloop error propagation for /parties/{Type}/{ID}', async() => {
749
+
750
+ // mock state machine
751
+ const mockedPSM = {
752
+ run: jest.fn(async () => { throw { mocked: 'error' }; })
753
+ };
754
+
755
+ const createSpy = jest.spyOn(QuotesModel, 'create')
756
+ .mockImplementationOnce(async () => mockedPSM);
757
+
758
+ // invoke handler
759
+ await handlers['/quotes'].post(mockContext);
760
+
761
+ // PSM model creation
762
+ const state = mockContext.state;
763
+ const cacheKey = QuotesModel.channelName({
764
+ quoteId: mockContext.request.body.quotesPostRequest.quoteId
765
+ });
766
+ const expectedConfig = {
767
+ cache: state.cache,
768
+ logger: state.logger,
769
+ wso2Auth: state.wso2Auth
770
+ };
771
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
772
+
773
+ // run workflow
774
+ expect(mockedPSM.run).toBeCalledWith({
775
+ quoteId: mockContext.request.body.quotesPostRequest.quoteId,
776
+ fspId: mockContext.request.body.fspId,
777
+ quote: mockContext.request.body.quotesPostRequest
778
+ });
779
+
780
+ // response
781
+ expect(mockContext.response.status).toBe(500);
782
+ expect(mockContext.response.body).toEqual({
783
+ message: 'Unspecified error',
784
+ requestQuotesInformationState: {},
785
+ statusCode: '500',
786
+ });
787
+ });
788
+ });
789
+ describe('POST /simpleTransfers', () => {
790
+ const mockContext = {
791
+ request: {
792
+ body: {
793
+ fspId: uuid(),
794
+ transfersPostRequest: {
795
+ transferId: uuid()
796
+ }
797
+ }
798
+ },
799
+ response: {},
800
+ state: {
801
+ conf: {},
802
+ wso2Auth: 'mocked wso2Auth',
803
+ logger: mockLogger({ app: 'outbound-api-handlers-test' }),
804
+ cache: {
805
+ subscribe: jest.fn(() => Promise.resolve())
806
+ }
807
+ },
808
+ };
809
+ test('happy flow', async () => {
810
+
811
+
812
+ // mock state machine
813
+ const mockedPSM = {
814
+ run: jest.fn(async () => ({ the: 'run response' }))
815
+ };
816
+
817
+ const createSpy = jest.spyOn(TransfersModel, 'create')
818
+ .mockImplementationOnce(async () => mockedPSM);
819
+
820
+ // invoke handler
821
+ await handlers['/simpleTransfers'].post(mockContext);
822
+
823
+ // PSM model creation
824
+ const state = mockContext.state;
825
+ const cacheKey = TransfersModel.channelName({
826
+ transferId: mockContext.request.body.transfersPostRequest.transferId
827
+ });
828
+ const expectedConfig = {
829
+ cache: state.cache,
830
+ logger: state.logger,
831
+ wso2Auth: state.wso2Auth
832
+ };
833
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
834
+
835
+ // run workflow
836
+ expect(mockedPSM.run).toBeCalledWith({
837
+ transferId: mockContext.request.body.transfersPostRequest.transferId,
838
+ fspId: mockContext.request.body.fspId,
839
+ transfer: mockContext.request.body.transfersPostRequest
840
+ });
841
+
842
+ // response
843
+ expect(mockContext.response.status).toBe(200);
844
+ expect(mockContext.response.body).toEqual({ the: 'run response' });
845
+ });
846
+
847
+ test('mojaloop error propagation for /simpleTransfers', async() => {
848
+
849
+ // mock state machine
850
+ const mockedPSM = {
851
+ run: jest.fn(async () => { throw { mocked: 'error' }; })
852
+ };
853
+
854
+ const createSpy = jest.spyOn(TransfersModel, 'create')
855
+ .mockImplementationOnce(async () => mockedPSM);
856
+
857
+ // invoke handler
858
+ await handlers['/simpleTransfers'].post(mockContext);
859
+
860
+ // PSM model creation
861
+ const state = mockContext.state;
862
+ const cacheKey = TransfersModel.channelName({
863
+ transferId: mockContext.request.body.transfersPostRequest.transferId
864
+ });
865
+ const expectedConfig = {
866
+ cache: state.cache,
867
+ logger: state.logger,
868
+ wso2Auth: state.wso2Auth
869
+ };
870
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
871
+
872
+ // run workflow
873
+ expect(mockedPSM.run).toBeCalledWith({
874
+ transferId: mockContext.request.body.transfersPostRequest.transferId,
875
+ fspId: mockContext.request.body.fspId,
876
+ transfer: mockContext.request.body.transfersPostRequest
877
+ });
878
+
879
+ // response
880
+ expect(mockContext.response.status).toBe(500);
881
+ expect(mockContext.response.body).toEqual({
882
+ message: 'Unspecified error',
883
+ requestSimpleTransfersInformationState: {},
884
+ statusCode: '500',
885
+ });
886
+ });
887
+ });
888
+ describe('POST /authorizations', () => {
889
+ const mockContext = {
890
+ request: {
891
+ body: {
892
+ fspId: uuid(),
893
+ authorizationsPostRequest: {
894
+ transactionRequestId: uuid()
895
+ }
896
+ }
897
+ },
898
+ response: {},
899
+ state: {
900
+ conf: {},
901
+ wso2Auth: 'mocked wso2Auth',
902
+ logger: mockLogger({ app: 'outbound-api-handlers-test' }),
903
+ cache: {
904
+ subscribe: jest.fn(() => Promise.resolve())
905
+ }
906
+ },
907
+ };
908
+ test('happy flow', async () => {
909
+
910
+ // mock state machine
911
+ const mockedPSM = {
912
+ run: jest.fn(async () => ({ the: 'run response' }))
913
+ };
914
+
915
+ const createSpy = jest.spyOn(AuthorizationsModel, 'create')
916
+ .mockImplementationOnce(async () => mockedPSM);
917
+
918
+ // invoke handler
919
+ await handlers['/authorizations'].post(mockContext);
920
+
921
+ // PSM model creation
922
+ const state = mockContext.state;
923
+ const cacheKey = AuthorizationsModel.channelName({
924
+ transactionRequestId: mockContext.request.body.authorizationsPostRequest.transactionRequestId
925
+ });
926
+ const expectedConfig = {
927
+ cache: state.cache,
928
+ logger: state.logger,
929
+ wso2Auth: state.wso2Auth
930
+ };
931
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
932
+
933
+ // run workflow
934
+ expect(mockedPSM.run).toBeCalledWith({
935
+ transactionRequestId: mockContext.request.body.authorizationsPostRequest.transactionRequestId,
936
+ fspId: mockContext.request.body.fspId,
937
+ authorization: mockContext.request.body.authorizationsPostRequest
938
+ });
939
+
940
+ // response
941
+ expect(mockContext.response.status).toBe(200);
942
+ expect(mockContext.response.body).toEqual({ the: 'run response' });
943
+ });
944
+
945
+ test('mojaloop error propagation for /authorizations/{ID}', async() => {
946
+
947
+ // mock state machine
948
+ const mockedPSM = {
949
+ run: jest.fn(async () => { throw { mocked: 'error' }; })
950
+ };
951
+
952
+ const createSpy = jest.spyOn(AuthorizationsModel, 'create')
953
+ .mockImplementationOnce(async () => mockedPSM);
954
+
955
+ // invoke handler
956
+ await handlers['/authorizations'].post(mockContext);
957
+
958
+ // PSM model creation
959
+ const state = mockContext.state;
960
+ const cacheKey = AuthorizationsModel.channelName({
961
+ transactionRequestId: mockContext.request.body.authorizationsPostRequest.transactionRequestId
962
+ });
963
+ const expectedConfig = {
964
+ cache: state.cache,
965
+ logger: state.logger,
966
+ wso2Auth: state.wso2Auth
967
+ };
968
+ expect(createSpy).toBeCalledWith({}, cacheKey, expectedConfig);
969
+
970
+ // run workflow
971
+ expect(mockedPSM.run).toBeCalledWith({
972
+ transactionRequestId: mockContext.request.body.authorizationsPostRequest.transactionRequestId,
973
+ fspId: mockContext.request.body.fspId,
974
+ authorization: mockContext.request.body.authorizationsPostRequest
975
+ });
976
+
977
+ // response
978
+ expect(mockContext.response.status).toBe(500);
979
+ expect(mockContext.response.body).toEqual({
980
+ message: 'Unspecified error',
981
+ requestAuthorizationsInformationState: {},
982
+ statusCode: '500',
983
+ });
984
+ });
985
+ });
986
+ });