@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,468 @@
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
+ * Paweł Marzec - pawel.marzec@modusbox.com *
9
+ **************************************************************************/
10
+
11
+ 'use strict';
12
+
13
+ // we use a mock standard components lib to intercept and mock certain funcs
14
+ jest.mock('@mojaloop/sdk-standard-components');
15
+
16
+ const { uuid } = require('uuidv4');
17
+ const Model = require('../../../../lib/model').PartiesModel;
18
+ const PSM = require('../../../../lib/model/common').PersistentStateMachine;
19
+ const { MojaloopRequests } = require('@mojaloop/sdk-standard-components');
20
+ const defaultConfig = require('./data/defaultConfig');
21
+ const mockLogger = require('../../mockLogger');
22
+ const deferredJob = require('../../../../lib/model/lib').deferredJob;
23
+ const pt = require('promise-timeout');
24
+
25
+ describe('PartiesModel', () => {
26
+ let cacheKey;
27
+ let data;
28
+ let modelConfig;
29
+
30
+ const subId = 123;
31
+ let handler = null;
32
+ beforeEach(async () => {
33
+
34
+ modelConfig = {
35
+ logger: mockLogger({app: 'PartiesModel-test'}),
36
+
37
+ // there is no need to mock redis but only Cache
38
+ cache: {
39
+ get: jest.fn(() => Promise.resolve(data)),
40
+ set: jest.fn(() => Promise.resolve),
41
+
42
+ // mock subscription and store handler
43
+ subscribe: jest.fn(async (channel, h) => {
44
+ handler = jest.fn(h);
45
+ return subId;
46
+ }),
47
+
48
+ // mock publish and call stored handler
49
+ publish: jest.fn(async (channel, message) => await handler(channel, message, subId)),
50
+
51
+ unsubscribe: jest.fn(() => Promise.resolve())
52
+ },
53
+ ...defaultConfig
54
+ };
55
+ data = { the: 'mocked data' };
56
+
57
+ cacheKey = 'cache-key';
58
+ });
59
+
60
+ describe('create', () => {
61
+ test('proper creation of model', async () => {
62
+ const model = await Model.create(data, cacheKey, modelConfig);
63
+
64
+ expect(model.state).toBe('start');
65
+
66
+ // model's methods layout
67
+ const methods = [
68
+ 'run',
69
+ 'getResponse',
70
+ 'onRequestAction'
71
+ ];
72
+
73
+ methods.forEach((method) => expect(typeof model[method]).toEqual('function'));
74
+ });
75
+ });
76
+
77
+ describe('getResponse', () => {
78
+
79
+ it('should remap currentState', async () => {
80
+ const model = await Model.create(data, cacheKey, modelConfig);
81
+ const states = model.allStates();
82
+ // should remap for all states except 'init' and 'none'
83
+ states.filter((s) => s !== 'init' && s !== 'none').forEach((state) => {
84
+ model.context.data.currentState = state;
85
+ const result = model.getResponse();
86
+ expect(result.currentState).toEqual(Model.mapCurrentState[state]);
87
+ });
88
+
89
+ });
90
+
91
+ it('should handle unexpected state', async() => {
92
+ const model = await Model.create(data, cacheKey, modelConfig);
93
+
94
+ // simulate lack of state by undefined property
95
+ delete model.context.data.currentState;
96
+
97
+ const resp = model.getResponse();
98
+ expect(resp.currentState).toEqual(Model.mapCurrentState.errored);
99
+
100
+ // ensure that we log the problem properly
101
+ expect(modelConfig.logger.error).toHaveBeenCalledWith(`PartiesModel model response being returned from an unexpected state: ${undefined}. Returning ERROR_OCCURRED state`);
102
+ });
103
+ });
104
+
105
+ describe('channelName', () => {
106
+ it('should validate input', () => {
107
+ expect(Model.channelName({})).toEqual('parties-undefined-undefined-undefined');
108
+ });
109
+
110
+ it('should generate proper channel name', () => {
111
+ const type = uuid();
112
+ const id = uuid();
113
+ expect(Model.channelName({ type, id })).toEqual(`parties-${type}-${id}-undefined`);
114
+ });
115
+
116
+ it('should generate proper channel name when all params specified', () => {
117
+ const type = uuid();
118
+ const id = uuid();
119
+ const subId = uuid();
120
+ expect(Model.channelName({ type, id, subId })).toEqual(`parties-${type}-${id}-${subId}`);
121
+ });
122
+ });
123
+
124
+ describe('generateKey', () => {
125
+ it('should generate proper cache key', () => {
126
+ const type = uuid();
127
+ const id = uuid();
128
+ expect(Model.generateKey({ type, id })).toEqual(`key-${Model.channelName({ type, id })}`);
129
+ });
130
+
131
+ it('should handle lack of id param', () => {
132
+ const type = uuid();
133
+ expect(() => Model.generateKey({ type })).toThrowError(new Error('PartiesModel args required at least two string arguments: \'type\' and \'id\''));
134
+ });
135
+
136
+ it('should handle all params', () => {
137
+ const type = uuid();
138
+ const id = uuid();
139
+ const subId = uuid();
140
+ expect(Model.generateKey({ type, id, subId })).toEqual(`key-${Model.channelName({ type, id, subId })}`);
141
+ });
142
+ });
143
+
144
+ describe('onRequestAction', () => {
145
+
146
+ it('should implement happy flow', async () => {
147
+ const type = uuid();
148
+ const id = uuid();
149
+ const subIdValue = uuid();
150
+
151
+ const channel = Model.channelName({ type, id, subId: subIdValue });
152
+ const model = await Model.create(data, cacheKey, modelConfig);
153
+ const { cache } = model.context;
154
+ // mock workflow execution which is tested in separate case
155
+ model.run = jest.fn(() => Promise.resolve());
156
+
157
+ const message = {
158
+ party: {
159
+ Iam: 'the-body'
160
+ }
161
+ };
162
+
163
+ const onRequestActionPromise = new Promise((resolve, reject) => {
164
+ // manually invoke transition handler
165
+ model.onRequestAction(model.fsm, { type, id, subId: subIdValue })
166
+ .then(() => {
167
+ // subscribe should be called only once
168
+ expect(cache.subscribe).toBeCalledTimes(1);
169
+
170
+ // subscribe should be done to proper notificationChannel
171
+ expect(cache.subscribe.mock.calls[0][0]).toEqual(channel);
172
+
173
+ // check invocation of request.getParties
174
+ expect(MojaloopRequests.__getParties).toBeCalledWith(type, id, subIdValue);
175
+
176
+ // check that this.context.data is updated
177
+ expect(model.context.data).toEqual({
178
+ ...message,
179
+ // current state will be updated by onAfterTransition which isn't called
180
+ // when manual invocation of transition handler happens
181
+ currentState: 'start'
182
+ });
183
+ // handler should be called only once
184
+ expect(handler).toBeCalledTimes(1);
185
+
186
+ // handler should unsubscribe from notification channel
187
+ expect(cache.unsubscribe).toBeCalledTimes(1);
188
+ expect(cache.unsubscribe).toBeCalledWith(channel, subId);
189
+ resolve();
190
+ }).catch((err) => { reject(err); } );
191
+ });
192
+
193
+ // ensure handler wasn't called before publishing the message
194
+ expect(handler).not.toBeCalled();
195
+
196
+ // ensure that cache.unsubscribe does not happened before fire the message
197
+ expect(cache.unsubscribe).not.toBeCalled();
198
+
199
+ // fire publication with given message
200
+ const df = deferredJob(cache, channel);
201
+ setImmediate(() => df.trigger(message));
202
+
203
+ // wait for onRequestAction
204
+ await onRequestActionPromise;
205
+ });
206
+
207
+ it('should handle timeouts', async () => {
208
+ const type = uuid();
209
+ const id = uuid();
210
+ const subIdValue = uuid();
211
+
212
+ const channel = Model.channelName({ type, id, subId: subIdValue });
213
+ const model = await Model.create(data, cacheKey, modelConfig);
214
+ const { cache } = model.context;
215
+ // mock workflow execution which is tested in separate case
216
+ model.run = jest.fn(() => Promise.resolve());
217
+
218
+ const message = {
219
+ party: {
220
+ Iam: 'the-body'
221
+ }
222
+ };
223
+
224
+ const onRequestActionPromise = new Promise((resolve, reject) => {
225
+ // manually invoke transition handler
226
+ model.onRequestAction(model.fsm, { type, id, subId: subIdValue })
227
+ .then(() => reject())
228
+ .catch((err) => {
229
+ // subscribe should be called only once
230
+ expect(err instanceof pt.TimeoutError).toBeTruthy();
231
+
232
+ // subscribe should be done to proper notificationChannel
233
+ expect(cache.subscribe.mock.calls[0][0]).toEqual(channel);
234
+
235
+ // check invocation of request.getParties
236
+ expect(MojaloopRequests.__getParties).toBeCalledWith(type, id, subIdValue);
237
+
238
+ // handler should be called only once
239
+ expect(handler).toBeCalledTimes(0);
240
+
241
+ // handler should unsubscribe from notification channel
242
+ expect(cache.unsubscribe).toBeCalledTimes(1);
243
+ expect(cache.unsubscribe).toBeCalledWith(channel, subId);
244
+ resolve();
245
+ });
246
+ });
247
+
248
+ // ensure handler wasn't called before publishing the message
249
+ expect(handler).not.toBeCalled();
250
+
251
+ // ensure that cache.unsubscribe does not happened before fire the message
252
+ expect(cache.unsubscribe).not.toBeCalled();
253
+
254
+ // fire publication with given message
255
+ const df = deferredJob(cache, channel);
256
+
257
+ setTimeout(
258
+ () => { df.trigger(message); },
259
+ // ensure that publication will be far long after timeout should be auto triggered
260
+ (modelConfig.requestProcessingTimeoutSeconds+1)*1000
261
+ );
262
+
263
+ // wait for onRequestAction
264
+ await onRequestActionPromise;
265
+ });
266
+
267
+ it('should unsubscribe from cache in case when error happens in workflow run', async () => {
268
+ const type = uuid();
269
+ const id = uuid();
270
+ const subIdValue = uuid();
271
+
272
+ const channel = Model.channelName({ type, id, subId: subIdValue });
273
+ const model = await Model.create(data, cacheKey, modelConfig);
274
+ const { cache } = model.context;
275
+
276
+ const onRequestActionPromise = new Promise((resolve, reject) => {
277
+ // invoke transition handler
278
+ model.onRequestAction(model.fsm, { type, id, subId: subIdValue })
279
+ .then(() => reject())
280
+ .catch((err) => {
281
+ expect(err.message).toEqual('Unexpected token u in JSON at position 0');
282
+ expect(cache.unsubscribe).toBeCalledTimes(1);
283
+ expect(cache.unsubscribe).toBeCalledWith(channel, subId);
284
+ resolve();
285
+ });
286
+ });
287
+
288
+ // fire publication to channel with invalid message
289
+ // should throw the exception from JSON.parse
290
+ const df = deferredJob(cache, channel);
291
+ setImmediate(() => df.trigger(undefined));
292
+
293
+ // wait for onRequestAction
294
+ await onRequestActionPromise;
295
+ });
296
+
297
+ it('should unsubscribe from cache in case when error happens Mojaloop requests', async () => {
298
+ // simulate error
299
+ MojaloopRequests.__getParties = jest.fn(() => Promise.reject('getParties failed'));
300
+ const type = uuid();
301
+ const id = uuid();
302
+ const subIdValue = uuid();
303
+
304
+ const channel = Model.channelName({ type, id, subId: subIdValue });
305
+ const model = await Model.create(data, cacheKey, modelConfig);
306
+ const { cache } = model.context;
307
+
308
+ let theError = null;
309
+ // invoke transition handler
310
+ try {
311
+ await model.onRequestAction(model.fsm, { type, id, subId: subIdValue });
312
+ throw new Error('this point should not be reached');
313
+ } catch (error) {
314
+ theError = error;
315
+ expect(theError).toEqual('getParties failed');
316
+ // handler should unsubscribe from notification channel
317
+ expect(cache.unsubscribe).toBeCalledTimes(1);
318
+ expect(cache.unsubscribe).toBeCalledWith(channel, subId);
319
+ }
320
+ });
321
+
322
+ });
323
+
324
+ describe('run workflow', () => {
325
+ it('start', async () => {
326
+ const type = uuid();
327
+ const id = uuid();
328
+ const subIdValue = uuid();
329
+
330
+ const model = await Model.create(data, cacheKey, modelConfig);
331
+
332
+ model.requestAction = jest.fn();
333
+ model.getResponse = jest.fn(() => Promise.resolve({the: 'response'}));
334
+
335
+ model.context.data.currentState = 'start';
336
+ const result = await model.run({ type, id, subId: subIdValue });
337
+ expect(result).toEqual({the: 'response'});
338
+ expect(model.requestAction).toBeCalledTimes(1);
339
+ expect(model.getResponse).toBeCalledTimes(1);
340
+ expect(model.context.logger.log.mock.calls).toEqual([
341
+ ['State machine transitioned \'init\': none -> start'],
342
+ ['Action called successfully'],
343
+ [`Persisted model in cache: ${cacheKey}`],
344
+ ]);
345
+ });
346
+ it('succeeded', async () => {
347
+ const type = uuid();
348
+ const id = uuid();
349
+ const subIdValue = uuid();
350
+
351
+ const model = await Model.create(data, cacheKey, modelConfig);
352
+
353
+ model.getResponse = jest.fn(() => Promise.resolve({the: 'response'}));
354
+
355
+ model.context.data.currentState = 'succeeded';
356
+ const result = await model.run({ type, id, subId: subIdValue });
357
+
358
+ expect(result).toEqual({the: 'response'});
359
+ expect(model.getResponse).toBeCalledTimes(1);
360
+ expect(model.context.logger.log).toBeCalledWith('Action called successfully');
361
+ });
362
+
363
+ it('errored', async () => {
364
+ const type = uuid();
365
+ const id = uuid();
366
+ const subIdValue = uuid();
367
+
368
+ const model = await Model.create(data, cacheKey, modelConfig);
369
+
370
+ model.getResponse = jest.fn(() => Promise.resolve({the: 'response'}));
371
+
372
+ model.context.data.currentState = 'errored';
373
+ const result = await model.run({ type, id, subId: subIdValue });
374
+
375
+ expect(result).toBeFalsy();
376
+ expect(model.getResponse).not.toBeCalled();
377
+ expect(model.context.logger.log).toBeCalledWith('State machine in errored state');
378
+ });
379
+
380
+ it('handling errors', async () => {
381
+ const type = uuid();
382
+ const id = uuid();
383
+ const subIdValue = uuid();
384
+
385
+ const model = await Model.create(data, cacheKey, modelConfig);
386
+
387
+ model.requestAction = jest.fn(() => { throw new Error('mocked error'); });
388
+
389
+ model.context.data.currentState = 'start';
390
+ try {
391
+ await model.run({ type, id, subId: subIdValue });
392
+ throw new Error('this point should not be reached');
393
+ } catch (err) {
394
+ expect(model.context.data.currentState).toEqual('errored');
395
+ expect(err.requestActionState).toEqual( {
396
+ ...data,
397
+ currentState: 'ERROR_OCCURRED',
398
+ });
399
+ }
400
+ });
401
+
402
+ it('should handle errors', async () => {
403
+ const type = uuid();
404
+ const id = uuid();
405
+ const subIdValue = uuid();
406
+
407
+ const model = await Model.create(data, cacheKey, modelConfig);
408
+
409
+ model.requestAction = jest.fn(() => {
410
+ const err = new Error('requestAction failed');
411
+ err.requestActionState = 'some';
412
+ return Promise.reject(err);
413
+ });
414
+ model.error = jest.fn();
415
+ model.context.data.currentState = 'start';
416
+
417
+ let theError = null;
418
+ try {
419
+ await model.run({ type, id, subId: subIdValue });
420
+ throw new Error('this point should not be reached');
421
+ } catch(error) {
422
+ theError = error;
423
+ }
424
+ // check propagation of original error
425
+ expect(theError.message).toEqual('requestAction failed');
426
+
427
+ // ensure we start transition to errored state
428
+ expect(model.error).toBeCalledTimes(1);
429
+ });
430
+
431
+ it('should handle input validation for id/subId params', async () => {
432
+ const type = uuid();
433
+ const model = await Model.create(data, cacheKey, modelConfig);
434
+
435
+ expect(() => model.run(type))
436
+ .rejects.toEqual(
437
+ new Error('PartiesModel args required at least two string arguments: \'type\' and \'id\'')
438
+ );
439
+ });
440
+ });
441
+
442
+ describe('loadFromCache', () => {
443
+ test('should use PSM.loadFromCache properly', async () => {
444
+ const spyLoadFromCache = jest.spyOn(PSM, 'loadFromCache');
445
+ const key = uuid();
446
+
447
+ // act
448
+ const model = await Model.loadFromCache(key, modelConfig);
449
+
450
+ // assert
451
+ // check does model is proper
452
+ expect(typeof model.requestAction).toEqual('function');
453
+
454
+ // check how cache.get has been called
455
+ expect(modelConfig.cache.get).toBeCalledWith(key);
456
+
457
+ // check how loadFromCache from parent PSM module was used
458
+ expect(spyLoadFromCache).toBeCalledTimes(1);
459
+ expect(spyLoadFromCache).toBeCalledWith(
460
+ modelConfig.cache,
461
+ key,
462
+ modelConfig.logger,
463
+ expect.anything(),
464
+ expect.anything()
465
+ );
466
+ });
467
+ });
468
+ });