@mojaloop/sdk-scheme-adapter 17.0.2-snapshot.6 → 18.0.1

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 (120) hide show
  1. package/.circleci/config.yml +0 -4
  2. package/.dockerignore +18 -0
  3. package/.eslintignore +2 -0
  4. package/CHANGELOG.md +20 -0
  5. package/Dockerfile +8 -5
  6. package/audit-resolve.json +10 -0
  7. package/docker-compose.yml +3 -2
  8. package/package.json +4 -3
  9. package/src/lib/model/InboundTransfersModel.js +2 -2
  10. package/test/__mocks__/@mojaloop/sdk-standard-components.js +0 -151
  11. package/test/__mocks__/javascript-state-machine.js +0 -21
  12. package/test/__mocks__/redis.js +0 -78
  13. package/test/__mocks__/uuidv4.js +0 -16
  14. package/test/config/integration.env +0 -146
  15. package/test/integration/lib/Outbound/data/quotesPostRequest.json +0 -52
  16. package/test/integration/lib/Outbound/data/transfersPostRequest.json +0 -24
  17. package/test/integration/lib/Outbound/parties.test.js +0 -31
  18. package/test/integration/lib/Outbound/quotes.test.js +0 -62
  19. package/test/integration/lib/Outbound/simpleTransfers.test.js +0 -70
  20. package/test/integration/lib/cache.test.js +0 -79
  21. package/test/integration/testEnv.js +0 -4
  22. package/test/unit/ControlClient.test.js +0 -69
  23. package/test/unit/ControlServer/events.js +0 -41
  24. package/test/unit/ControlServer/index.js +0 -227
  25. package/test/unit/ControlServer.test.js +0 -66
  26. package/test/unit/InboundServer.test.js +0 -443
  27. package/test/unit/TestServer.test.js +0 -392
  28. package/test/unit/api/accounts/accounts.test.js +0 -128
  29. package/test/unit/api/accounts/data/postAccountsBody.json +0 -7
  30. package/test/unit/api/accounts/data/postAccountsErrorMojaloopResponse.json +0 -33
  31. package/test/unit/api/accounts/data/postAccountsErrorTimeoutResponse.json +0 -19
  32. package/test/unit/api/accounts/data/postAccountsSuccessResponse.json +0 -31
  33. package/test/unit/api/accounts/data/postAccountsSuccessResponseWithError1.json +0 -34
  34. package/test/unit/api/accounts/data/postAccountsSuccessResponseWithError2.json +0 -39
  35. package/test/unit/api/accounts/utils.js +0 -79
  36. package/test/unit/api/proxy/data/proxyConfig.yaml +0 -82
  37. package/test/unit/api/proxy/data/requestBody.json +0 -22
  38. package/test/unit/api/proxy/data/requestHeaders.json +0 -5
  39. package/test/unit/api/proxy/data/requestQuery.json +0 -6
  40. package/test/unit/api/proxy/data/responseBody.json +0 -21
  41. package/test/unit/api/proxy/data/responseHeaders.json +0 -5
  42. package/test/unit/api/proxy/proxy.test.js +0 -220
  43. package/test/unit/api/proxy/utils.js +0 -79
  44. package/test/unit/api/transfers/data/getTransfersCommittedResponse.json +0 -24
  45. package/test/unit/api/transfers/data/getTransfersErrorNotFound.json +0 -18
  46. package/test/unit/api/transfers/data/postQuotesBody.json +0 -52
  47. package/test/unit/api/transfers/data/postTransfersBadBody.json +0 -17
  48. package/test/unit/api/transfers/data/postTransfersBody.json +0 -24
  49. package/test/unit/api/transfers/data/postTransfersErrorMojaloopResponse.json +0 -62
  50. package/test/unit/api/transfers/data/postTransfersErrorTimeoutResponse.json +0 -48
  51. package/test/unit/api/transfers/data/postTransfersSimpleBody.json +0 -26
  52. package/test/unit/api/transfers/data/postTransfersSuccessResponse.json +0 -128
  53. package/test/unit/api/transfers/data/putPartiesBody.json +0 -20
  54. package/test/unit/api/transfers/data/putQuotesBody.json +0 -37
  55. package/test/unit/api/transfers/data/putTransfersBody.json +0 -17
  56. package/test/unit/api/transfers/transfers.test.js +0 -191
  57. package/test/unit/api/transfers/utils.js +0 -264
  58. package/test/unit/api/utils.js +0 -86
  59. package/test/unit/config.test.js +0 -119
  60. package/test/unit/data/commonHttpHeaders.json +0 -7
  61. package/test/unit/data/defaultConfig.json +0 -70
  62. package/test/unit/data/postQuotesBody.json +0 -52
  63. package/test/unit/data/putParticipantsBody.json +0 -12
  64. package/test/unit/data/putPartiesBody.json +0 -20
  65. package/test/unit/data/testFile.json +0 -29
  66. package/test/unit/data/testFile.yaml +0 -14
  67. package/test/unit/inboundApi/data/mockArguments.json +0 -117
  68. package/test/unit/inboundApi/data/mockTransactionRequest.json +0 -42
  69. package/test/unit/inboundApi/handlers.test.js +0 -786
  70. package/test/unit/index.test.js +0 -88
  71. package/test/unit/lib/cache.test.js +0 -145
  72. package/test/unit/lib/model/AccountsModel.test.js +0 -124
  73. package/test/unit/lib/model/InboundTransfersModel.test.js +0 -889
  74. package/test/unit/lib/model/OutboundBulkQuotesModel.test.js +0 -253
  75. package/test/unit/lib/model/OutboundBulkTransfersModel.test.js +0 -247
  76. package/test/unit/lib/model/OutboundRequestToPayModel.test.js +0 -166
  77. package/test/unit/lib/model/OutboundRequestToPayTransferModel.test.js +0 -245
  78. package/test/unit/lib/model/OutboundTransfersModel.test.js +0 -1579
  79. package/test/unit/lib/model/PartiesModel.test.js +0 -478
  80. package/test/unit/lib/model/QuotesModel.test.js +0 -477
  81. package/test/unit/lib/model/TransfersModel.test.js +0 -481
  82. package/test/unit/lib/model/common/PersistentStateMachine.test.js +0 -178
  83. package/test/unit/lib/model/data/authorizationsResponse.json +0 -13
  84. package/test/unit/lib/model/data/bulkQuoteRequest.json +0 -27
  85. package/test/unit/lib/model/data/bulkQuoteResponse.json +0 -35
  86. package/test/unit/lib/model/data/bulkTransferFulfil.json +0 -13
  87. package/test/unit/lib/model/data/bulkTransferRequest.json +0 -29
  88. package/test/unit/lib/model/data/defaultConfig.json +0 -59
  89. package/test/unit/lib/model/data/getBulkTransfersBackendResponse.json +0 -42
  90. package/test/unit/lib/model/data/getBulkTransfersMojaloopResponse.json +0 -22
  91. package/test/unit/lib/model/data/getTransfersBackendResponse.json +0 -34
  92. package/test/unit/lib/model/data/getTransfersMojaloopResponse.json +0 -17
  93. package/test/unit/lib/model/data/mockArguments.json +0 -188
  94. package/test/unit/lib/model/data/mockTxnRequestsArguments.json +0 -63
  95. package/test/unit/lib/model/data/notificationAbortedToPayee.json +0 -10
  96. package/test/unit/lib/model/data/notificationReservedToPayee.json +0 -10
  97. package/test/unit/lib/model/data/notificationToPayee.json +0 -10
  98. package/test/unit/lib/model/data/payeeParty.json +0 -18
  99. package/test/unit/lib/model/data/putQuotesResponse.json +0 -33
  100. package/test/unit/lib/model/data/putTransfersResponse.json +0 -5
  101. package/test/unit/lib/model/data/quoteResponse.json +0 -42
  102. package/test/unit/lib/model/data/requestToPayRequest.json +0 -20
  103. package/test/unit/lib/model/data/requestToPayTransferRequest.json +0 -27
  104. package/test/unit/lib/model/data/transactionRequestResponse.json +0 -18
  105. package/test/unit/lib/model/data/transferFulfil.json +0 -10
  106. package/test/unit/lib/model/data/transferRequest.json +0 -26
  107. package/test/unit/lib/model/mockedLibRequests.js +0 -74
  108. package/test/unit/mockLogger.js +0 -39
  109. package/test/unit/outboundApi/data/bulkQuoteRequest.json +0 -28
  110. package/test/unit/outboundApi/data/bulkTransferRequest.json +0 -28
  111. package/test/unit/outboundApi/data/mockBulkQuoteError.json +0 -45
  112. package/test/unit/outboundApi/data/mockBulkTransferError.json +0 -48
  113. package/test/unit/outboundApi/data/mockError.json +0 -41
  114. package/test/unit/outboundApi/data/mockGetPartiesError.json +0 -4
  115. package/test/unit/outboundApi/data/mockRequestToPayError.json +0 -32
  116. package/test/unit/outboundApi/data/mockRequestToPayTransferError.json +0 -39
  117. package/test/unit/outboundApi/data/requestToPay.json +0 -21
  118. package/test/unit/outboundApi/data/requestToPayTransferRequest.json +0 -20
  119. package/test/unit/outboundApi/data/transferRequest.json +0 -21
  120. package/test/unit/outboundApi/handlers.test.js +0 -887
@@ -1,253 +0,0 @@
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
- * Steven Oderayi - steven.oderayi@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
- jest.mock('redis');
16
-
17
- const Cache = require('~/lib/cache');
18
- const Model = require('~/lib/model').OutboundBulkQuotesModel;
19
-
20
- const { MojaloopRequests, Logger } = require('@mojaloop/sdk-standard-components');
21
- const StateMachine = require('javascript-state-machine');
22
-
23
- const { SDKStateEnum } = require('../../../../src/lib/model/common');
24
-
25
- const defaultConfig = require('./data/defaultConfig');
26
- const bulkQuoteRequest = require('./data/bulkQuoteRequest');
27
- const bulkQuoteResponseTemplate = require('./data/bulkQuoteResponse');
28
-
29
- // util function to simulate a quote response subscription message on a cache client
30
- const emitBulkQuoteResponseCacheMessage = (cache, bulkQuoteId, bulkQuoteResponse) => {
31
- cache.publish(`bulkQuote_${bulkQuoteId}`, JSON.stringify(bulkQuoteResponse));
32
- };
33
-
34
- describe('OutboundBulkQuotesModel', () => {
35
- let bulkQuoteResponse;
36
- let config;
37
- let logger;
38
- let cache;
39
-
40
- /**
41
- *
42
- * @param {Object} opts
43
- * @param {Number} opts.expirySeconds
44
- * @param {Object} opts.delays
45
- * @param {Number} delays.requestBulkQuotes
46
- * @param {Object} opts.rejects
47
- * @param {boolean} rejects.bulkQuoteResponse
48
- */
49
- async function testBulkQuoteWithDelay({expirySeconds, delays, rejects}) {
50
- const config = JSON.parse(JSON.stringify(defaultConfig));
51
- config.expirySeconds = expirySeconds;
52
- config.rejectExpiredQuoteResponses = rejects.bulkQuoteResponse;
53
-
54
- // simulate a delayed callback with the bulk quote response
55
- MojaloopRequests.__postBulkQuotes = jest.fn((postBulkQuotesBody) => {
56
- setTimeout(() => {
57
- emitBulkQuoteResponseCacheMessage(cache, postBulkQuotesBody.bulkQuoteId, bulkQuoteResponse);
58
- }, delays.requestBulkQuotes ? delays.requestBulkQuotes * 1000 : 0);
59
- });
60
-
61
- const model = new Model({
62
- ...config,
63
- cache,
64
- logger,
65
- });
66
-
67
- await model.initialize(JSON.parse(JSON.stringify(bulkQuoteRequest)));
68
-
69
- let expectError;
70
-
71
- if (rejects.bulkQuoteResponse && delays.requestBulkQuotes && expirySeconds < delays.requestBulkQuotes) {
72
- expectError = 'Bulk quote response missed expiry deadline';
73
- }
74
-
75
- if (expectError) {
76
- await expect(model.run()).rejects.toThrowError(expectError);
77
- } else {
78
- const result = await model.run();
79
- await expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
80
- }
81
- }
82
-
83
- beforeAll(async () => {
84
- logger = new Logger.Logger({ context: { app: 'outbound-model-unit-tests-cache' }, stringify: () => '' });
85
- bulkQuoteResponse = JSON.parse(JSON.stringify(bulkQuoteResponseTemplate));
86
- });
87
-
88
- beforeEach(async () => {
89
- config = JSON.parse(JSON.stringify(defaultConfig));
90
-
91
- MojaloopRequests.__postBulkQuotes = jest.fn(() => Promise.resolve());
92
- MojaloopRequests.__putBulkQuotes = jest.fn(() => Promise.resolve());
93
- MojaloopRequests.__putBulkQuotesError = jest.fn(() => Promise.resolve());
94
-
95
- cache = new Cache({
96
- cacheUrl: 'redis://dummy:1234',
97
- logger,
98
- });
99
- await cache.connect();
100
- });
101
-
102
- afterEach(async () => {
103
- await cache.disconnect();
104
- });
105
-
106
- test('initializes to starting state', async () => {
107
- const model = new Model({
108
- cache,
109
- logger,
110
- ...config,
111
- });
112
-
113
- await model.initialize(JSON.parse(JSON.stringify(bulkQuoteRequest)));
114
- expect(StateMachine.__instance.state).toBe('start');
115
- });
116
-
117
- test('test get bulk quote', async () => {
118
- MojaloopRequests.__getBulkQuotes = jest.fn((bulkQuoteId) => {
119
- emitBulkQuoteResponseCacheMessage(cache, bulkQuoteId, bulkQuoteResponse);
120
- return Promise.resolve();
121
- });
122
-
123
- const model = new Model({
124
- cache,
125
- logger,
126
- ...config,
127
- });
128
-
129
- const BULK_QUOTE_ID = 'bq-id000011';
130
-
131
- await model.initialize(JSON.parse(JSON.stringify({
132
- currentState: 'getBulkQuote',
133
- bulkQuoteId: BULK_QUOTE_ID,
134
- })));
135
-
136
- expect(StateMachine.__instance.state).toBe('getBulkQuote');
137
-
138
- // start the model running
139
- const result = await model.run();
140
-
141
- expect(MojaloopRequests.__getBulkQuotes).toHaveBeenCalledTimes(1);
142
-
143
- // check we stopped at succeeded state
144
- expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
145
- expect(StateMachine.__instance.state).toBe('succeeded');
146
- });
147
-
148
- test('sends bulk quotes request with correct payload', async () => {
149
- MojaloopRequests.__postBulkQuotes = jest.fn((postBulkQuotesBody) => {
150
- // ensure that the `MojaloopRequests.postBulkQuotes` method has been called with correct arguments
151
- // including extension list
152
- const extensionList = postBulkQuotesBody.extensionList.extension;
153
- expect(extensionList).toBeTruthy();
154
- expect(extensionList.length).toBe(2);
155
- expect(extensionList[0]).toEqual({ key: 'qkey1', value: 'qvalue1' });
156
- expect(extensionList[1]).toEqual({ key: 'qkey2', value: 'qvalue2' });
157
-
158
- // simulate a callback with the bulk quote response
159
- emitBulkQuoteResponseCacheMessage(cache, postBulkQuotesBody.bulkQuoteId, bulkQuoteResponse);
160
- return Promise.resolve();
161
- });
162
-
163
- const model = new Model({
164
- cache,
165
- logger,
166
- ...config,
167
- });
168
-
169
- await model.initialize(JSON.parse(JSON.stringify(bulkQuoteRequest)));
170
-
171
- expect(StateMachine.__instance.state).toBe('start');
172
-
173
- // start the model running
174
- const result = await model.run();
175
-
176
- expect(MojaloopRequests.__postBulkQuotes).toHaveBeenCalledTimes(1);
177
-
178
- // check we stopped at 'succeeded' state
179
- expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
180
- expect(StateMachine.__instance.state).toBe('succeeded');
181
- });
182
-
183
- test('pass quote response `expiration` deadline', () =>
184
- testBulkQuoteWithDelay({
185
- expirySeconds: 2,
186
- delays: {
187
- requestBulkQuotes: 1,
188
- },
189
- rejects: {
190
- bulkQuoteResponse: true,
191
- }
192
- })
193
- );
194
-
195
- test('fail on quote response `expiration` deadline', () =>
196
- testBulkQuoteWithDelay({
197
- expirySeconds: 1,
198
- delays: {
199
- requestBulkQuotes: 2,
200
- },
201
- rejects: {
202
- bulkQuoteResponse: true,
203
- }
204
- })
205
- );
206
-
207
- test('Throws with mojaloop error in response body when quote request error callback occurs', async () => {
208
- const expectError = {
209
- type: 'bulkQuoteResponseError',
210
- data: {
211
- body: {
212
- errorInformation: {
213
- errorCode: '3205',
214
- errorDescription: 'Bulk quote ID not found'
215
- }
216
- },
217
- headers: {}
218
- }
219
- };
220
-
221
- MojaloopRequests.__postBulkQuotes = jest.fn((postBulkQuotesBody) => {
222
- // simulate a callback with the bulk quote response
223
- cache.publish(`bulkQuote_${postBulkQuotesBody.bulkQuoteId}`, JSON.stringify(expectError));
224
- return Promise.resolve();
225
- });
226
-
227
- const model = new Model({
228
- cache,
229
- logger,
230
- ...config,
231
- });
232
-
233
- await model.initialize(JSON.parse(JSON.stringify(bulkQuoteRequest)));
234
-
235
- expect(StateMachine.__instance.state).toBe('start');
236
-
237
- const errMsg = 'Got an error response requesting bulk quote: { errorInformation:\n { errorCode: \'3205\', errorDescription: \'Bulk quote ID not found\' } }';
238
-
239
- try {
240
- await model.run();
241
- }
242
- catch(err) {
243
- expect(err.message.replace(/[ \n]/g,'')).toEqual(errMsg.replace(/[ \n]/g,''));
244
- expect(err.bulkQuoteState).toBeTruthy();
245
- expect(err.bulkQuoteState.lastError).toBeTruthy();
246
- expect(err.bulkQuoteState.lastError.mojaloopError).toEqual(expectError.data.body);
247
- expect(err.bulkQuoteState.lastError.bulkQuoteState).toBe(undefined);
248
- return;
249
- }
250
-
251
- throw new Error('Outbound bulk quotes model should have thrown');
252
- });
253
- });
@@ -1,247 +0,0 @@
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
- * Steven Oderayi - steven.oderayi@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
- jest.mock('redis');
16
-
17
- const Cache = require('~/lib/cache');
18
- const Model = require('~/lib/model').OutboundBulkTransfersModel;
19
-
20
- const { MojaloopRequests, Logger } = require('@mojaloop/sdk-standard-components');
21
- const StateMachine = require('javascript-state-machine');
22
- const { SDKStateEnum } = require('../../../../src/lib/model/common');
23
-
24
- const defaultConfig = require('./data/defaultConfig');
25
- const bulkTransferRequest = require('./data/bulkTransferRequest');
26
- const bulkTransferFulfil = require('./data/bulkTransferFulfil');
27
-
28
- // util function to simulate a bulk transfer fulfilment subscription message on a cache client
29
- const emitBulkTransferFulfilCacheMessage = (cache, bulkTransferId, fulfils) => cache.publish(`bulkTransfer_${bulkTransferId}`, JSON.stringify(fulfils));
30
-
31
- describe('outboundBulkTransferModel', () => {
32
- let config;
33
- let logger;
34
- let cache;
35
-
36
- /**
37
- *
38
- * @param {Object} opts
39
- * @param {Number} opts.expirySeconds
40
- * @param {Object} opts.delays
41
- * @param {Number} delays.prepareTransfer
42
- * @param {Object} opts.rejects
43
- * @param {boolean} rejects.transferFulfils
44
- */
45
- async function testBulkTransferWithDelay({expirySeconds, delays, rejects}) {
46
- const config = JSON.parse(JSON.stringify(defaultConfig));
47
- config.expirySeconds = expirySeconds;
48
- config.rejectExpiredTransferFulfils = rejects.transferFulfils;
49
-
50
- // simulate a delayed callback with the bulk transfer fulfilments
51
- MojaloopRequests.__postBulkTransfers = jest.fn((postBulkTransfersBody) => {
52
- setTimeout(() => {
53
- emitBulkTransferFulfilCacheMessage(cache, postBulkTransfersBody.bulkTransferId, bulkTransferFulfil);
54
- }, delays.prepareTransfer ? delays.prepareTransfer * 1000 : 0);
55
- });
56
-
57
- const model = new Model({
58
- ...config,
59
- cache,
60
- logger,
61
- });
62
-
63
- await model.initialize(JSON.parse(JSON.stringify(bulkTransferRequest)));
64
-
65
- let expectError;
66
-
67
- if (rejects.transferFulfils && delays.prepareTransfer && expirySeconds < delays.prepareTransfer) {
68
- expectError = 'Bulk transfer fulfils missed expiry deadline';
69
- }
70
- if (expectError) {
71
- await expect(model.run()).rejects.toThrowError(expectError);
72
- } else {
73
- const result = await model.run();
74
- await expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
75
- }
76
- }
77
-
78
- beforeAll(async () => {
79
- logger = new Logger.Logger({ context: { app: 'outbound-model-unit-tests-cache' }, stringify: () => '' });
80
- });
81
-
82
- beforeEach(async () => {
83
- config = JSON.parse(JSON.stringify(defaultConfig));
84
- MojaloopRequests.__postBulkTransfers = jest.fn(() => Promise.resolve());
85
-
86
- cache = new Cache({
87
- cacheUrl: 'redis://dummy:1234',
88
- logger,
89
- });
90
- await cache.connect();
91
- });
92
-
93
- afterEach(async () => {
94
- await cache.disconnect();
95
- });
96
-
97
- test('initializes to starting state', async () => {
98
- const model = new Model({
99
- cache,
100
- logger,
101
- ...config,
102
- });
103
-
104
- await model.initialize(JSON.parse(JSON.stringify(bulkTransferRequest)));
105
- expect(StateMachine.__instance.state).toBe('start');
106
- });
107
-
108
-
109
- test('executes bulk transfer', async () => {
110
- MojaloopRequests.__postBulkTransfers = jest.fn((postBulkTransfersBody) => {
111
- //ensure that the `MojaloopRequests.postBulkTransfers` method has been called with the correct arguments
112
- // set as the destination FSPID
113
- const extensionList = postBulkTransfersBody.extensionList.extension;
114
- expect(extensionList).toBeTruthy();
115
- expect(extensionList.length).toBe(2);
116
- expect(extensionList[0]).toEqual({ key: 'tkey1', value: 'tvalue1' });
117
- expect(extensionList[1]).toEqual({ key: 'tkey2', value: 'tvalue2' });
118
-
119
- // simulate a callback with the transfer fulfilment
120
- emitBulkTransferFulfilCacheMessage(cache, postBulkTransfersBody.bulkTransferId, bulkTransferFulfil);
121
- return Promise.resolve();
122
- });
123
-
124
- const model = new Model({
125
- cache,
126
- logger,
127
- ...config,
128
- });
129
-
130
- await model.initialize(JSON.parse(JSON.stringify(bulkTransferRequest)));
131
-
132
- expect(StateMachine.__instance.state).toBe('start');
133
-
134
- // start the model running
135
- const result = await model.run();
136
-
137
- expect(MojaloopRequests.__postBulkTransfers).toHaveBeenCalledTimes(1);
138
-
139
- // check we stopped at succeeded state
140
- expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
141
- expect(StateMachine.__instance.state).toBe('succeeded');
142
- });
143
-
144
- test('test get bulk transfer', async () => {
145
- MojaloopRequests.__getBulkTransfers = jest.fn((bulkTransferId) => {
146
- emitBulkTransferFulfilCacheMessage(cache, bulkTransferId, bulkTransferFulfil);
147
- return Promise.resolve();
148
- });
149
-
150
- const model = new Model({
151
- cache,
152
- logger,
153
- ...config,
154
- });
155
-
156
- const BULK_TRANSFER_ID = 'btx-id000011';
157
-
158
- await model.initialize(JSON.parse(JSON.stringify({
159
- ...bulkTransferRequest,
160
- currentState: 'getBulkTransfer',
161
- bulkTransferId: BULK_TRANSFER_ID,
162
- })));
163
-
164
- expect(StateMachine.__instance.state).toBe('getBulkTransfer');
165
-
166
- // start the model running
167
- const result = await model.run();
168
-
169
- expect(MojaloopRequests.__getBulkTransfers).toHaveBeenCalledTimes(1);
170
-
171
- // check we stopped at succeeded state
172
- expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
173
- expect(StateMachine.__instance.state).toBe('succeeded');
174
- });
175
-
176
- test('pass transfer fulfills `expiration` deadline', () =>
177
- testBulkTransferWithDelay({
178
- expirySeconds: 2,
179
- delays: {
180
- prepareTransfer: 1,
181
- },
182
- rejects: {
183
- transferFulfils: true,
184
- }
185
- })
186
- );
187
-
188
- test('fail on transfer fulfills `expiration` deadline', () =>
189
- testBulkTransferWithDelay({
190
- expirySeconds: 1,
191
- delays: {
192
- prepareTransfer: 2,
193
- },
194
- rejects: {
195
- transferFulfils: true,
196
- }
197
- })
198
- );
199
-
200
-
201
- test('Throws with mojaloop error in response body when transfer request error callback occurs', async () => {
202
- const expectError = {
203
- type: 'bulkTransferError',
204
- data: {
205
- body: {
206
- errorInformation: {
207
- errorCode: '4001',
208
- errorDescription: 'Payer FSP insufficient liquidity'
209
- }
210
- },
211
- headers: {}
212
- }
213
- };
214
-
215
- MojaloopRequests.__postBulkTransfers = jest.fn((postBulkTransfersBody) => {
216
- // simulate an error callback with the transfer fulfilments
217
- cache.publish(`bulkTransfer_${postBulkTransfersBody.bulkTransferId}`, JSON.stringify(expectError));
218
- return Promise.resolve();
219
- });
220
-
221
- const model = new Model({
222
- cache,
223
- logger,
224
- ...config,
225
- });
226
-
227
- await model.initialize(JSON.parse(JSON.stringify(bulkTransferRequest)));
228
-
229
- expect(StateMachine.__instance.state).toBe('start');
230
-
231
- const errMsg = 'Got an error response preparing bulk transfer: { errorInformation:\n { errorCode: \'4001\',\n errorDescription: \'Payer FSP insufficient liquidity\' } }';
232
-
233
- try {
234
- await model.run();
235
- }
236
- catch(err) {
237
- expect(err.message.replace(/[ \n]/g,'')).toEqual(errMsg.replace(/[ \n]/g,''));
238
- expect(err.bulkTransferState).toBeTruthy();
239
- expect(err.bulkTransferState.lastError).toBeTruthy();
240
- expect(err.bulkTransferState.lastError.mojaloopError).toEqual(expectError.data.body);
241
- expect(err.bulkTransferState.lastError.bulkTransferState).toBe(undefined);
242
- return;
243
- }
244
-
245
- throw new Error('Outbound model should have thrown');
246
- });
247
- });
@@ -1,166 +0,0 @@
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
- * Murthy Kakarlamudi - murthy@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
- jest.mock('redis');
16
-
17
- const Cache = require('~/lib/cache');
18
- const Model = require('~/lib/model').OutboundRequestToPayModel;
19
- const PartiesModel = require('~/lib/model').PartiesModel;
20
-
21
- const { MojaloopRequests, Logger } = require('@mojaloop/sdk-standard-components');
22
- const StateMachine = require('javascript-state-machine');
23
- const { SDKStateEnum } = require('../../../../src/lib/model/common');
24
-
25
- const defaultConfig = require('./data/defaultConfig');
26
- const requestToPayRequest = require('./data/requestToPayRequest');
27
- const payeeParty = require('./data/payeeParty');
28
- const transactionRequestResponseTemplate = require('./data/transactionRequestResponse');
29
-
30
- const genPartyId = (party) => {
31
- const { partyIdType, partyIdentifier, partySubIdOrType } = party.body.party.partyIdInfo;
32
- return PartiesModel.channelName({
33
- type: partyIdType,
34
- id: partyIdentifier,
35
- subId: partySubIdOrType
36
- });
37
- };
38
-
39
- // util function to simulate a party resolution subscription message on a cache client
40
- const emitPartyCacheMessage = (cache, party) => cache.publish(genPartyId(party), JSON.stringify(party));
41
-
42
- // util function to simulate a quote response subscription message on a cache client
43
- const emitTransactionRequestResponseCacheMessage = (cache, transactionRequestId, transactionRequestResponse) => cache.publish(`txnreq_${transactionRequestId}`, JSON.stringify(transactionRequestResponse));
44
-
45
- describe('outboundModel', () => {
46
- let transactionRequestResponse;
47
- let config;
48
- let logger;
49
- let cache;
50
-
51
- /**
52
- *
53
- * @param {Object} opts
54
- * @param {Number} opts.expirySeconds
55
- * @param {Object} opts.delays
56
- * @param {Number} delays.requestQuotes
57
- * @param {Number} delays.prepareTransfer
58
- * @param {Object} opts.rejects
59
- * @param {boolean} rejects.quoteResponse
60
- * @param {boolean} rejects.transferFulfils
61
- */
62
-
63
- beforeAll(async () => {
64
- logger = new Logger.Logger({ context: { app: 'outbound-model-unit-tests-cache' }, stringify: () => '' });
65
- transactionRequestResponse = JSON.parse(JSON.stringify(transactionRequestResponseTemplate));
66
- });
67
-
68
- beforeEach(async () => {
69
- config = JSON.parse(JSON.stringify(defaultConfig));
70
- MojaloopRequests.__postParticipants = jest.fn(() => Promise.resolve());
71
- MojaloopRequests.__getParties = jest.fn(() => Promise.resolve());
72
- MojaloopRequests.__postTransactionRequests = jest.fn(() => Promise.resolve());
73
-
74
- cache = new Cache({
75
- cacheUrl: 'redis://dummy:1234',
76
- logger,
77
- });
78
- await cache.connect();
79
- });
80
-
81
- afterEach(async () => {
82
- await cache.disconnect();
83
- });
84
-
85
- test('initializes to starting state', async () => {
86
- const model = new Model({
87
- cache,
88
- logger,
89
- ...config,
90
- });
91
-
92
- await model.initialize(JSON.parse(JSON.stringify(requestToPayRequest)));
93
- expect(StateMachine.__instance.state).toBe('start');
94
- });
95
-
96
-
97
- test('executes all two stages without halting when AUTO_ACCEPT_PARTY is true', async () => {
98
- config.autoAcceptParty = true;
99
-
100
- MojaloopRequests.__getParties = jest.fn(() => {
101
- emitPartyCacheMessage(cache, payeeParty);
102
- return Promise.resolve();
103
- });
104
-
105
- MojaloopRequests.__postTransactionRequests = jest.fn((postTransactionRequestsBody) => {
106
- // simulate a callback with the quote response
107
- emitTransactionRequestResponseCacheMessage(cache, postTransactionRequestsBody.transactionRequestId, transactionRequestResponse);
108
- return Promise.resolve();
109
- });
110
-
111
- const model = new Model({
112
- cache,
113
- logger,
114
- ...config,
115
- });
116
-
117
- await model.initialize(JSON.parse(JSON.stringify(requestToPayRequest)));
118
-
119
- expect(StateMachine.__instance.state).toBe('start');
120
-
121
- // start the model running
122
- const result = await model.run();
123
-
124
- expect(MojaloopRequests.__getParties).toHaveBeenCalledTimes(1);
125
- expect(MojaloopRequests.__postTransactionRequests).toHaveBeenCalledTimes(1);
126
-
127
- // check we stopped at payeeResolved state
128
- expect(result.currentState).toBe(SDKStateEnum.COMPLETED);
129
- expect(result.requestToPayState).toBe('RECEIVED');
130
- expect(StateMachine.__instance.state).toBe('succeeded');
131
- });
132
-
133
- test('resolves payee and halts when AUTO_ACCEPT_PARTY is false', async () => {
134
- config.autoAcceptParty = false;
135
-
136
- MojaloopRequests.__getParties = jest.fn(() => {
137
- emitPartyCacheMessage(cache, payeeParty);
138
- return Promise.resolve();
139
- });
140
-
141
- const model = new Model({
142
- cache,
143
- logger,
144
- ...config,
145
- });
146
-
147
- await model.initialize(JSON.parse(JSON.stringify(requestToPayRequest)));
148
-
149
- expect(StateMachine.__instance.state).toBe('start');
150
-
151
- // start the model running
152
- const resultPromise = model.run();
153
-
154
- // now we started the model running we simulate a callback with the resolved party
155
- emitPartyCacheMessage(cache, payeeParty);
156
-
157
- // wait for the model to reach a terminal state
158
- const result = await resultPromise;
159
-
160
- // check we stopped at payeeResolved state
161
- expect(result.currentState).toBe(SDKStateEnum.WAITING_FOR_PARTY_ACCEPTANCE);
162
- expect(StateMachine.__instance.state).toBe('payeeResolved');
163
- });
164
-
165
-
166
- });