@mojaloop/sdk-scheme-adapter 14.0.0 → 16.0.0

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 (44) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/audit-resolve.json +59 -473
  3. package/docs/dfspInboundApi.yaml +11 -0
  4. package/package.json +27 -25
  5. package/src/ControlAgent/index.js +8 -11
  6. package/src/ControlServer/index.js +13 -13
  7. package/src/InboundServer/index.js +12 -61
  8. package/src/OAuthTestServer/index.js +0 -13
  9. package/src/OutboundServer/api.yaml +370 -44
  10. package/src/OutboundServer/index.js +11 -54
  11. package/src/TestServer/index.js +6 -33
  12. package/src/config.js +1 -4
  13. package/src/index.js +163 -146
  14. package/src/lib/cache.js +93 -186
  15. package/src/lib/metrics.js +1 -1
  16. package/src/lib/model/InboundTransfersModel.js +10 -6
  17. package/src/lib/model/OutboundTransfersModel.js +1 -1
  18. package/test/__mocks__/redis.js +51 -26
  19. package/test/config/integration.env +1 -2
  20. package/test/integration/lib/cache.test.js +1 -2
  21. package/test/integration/testEnv.js +1 -4
  22. package/test/unit/ControlClient.test.js +1 -45
  23. package/test/unit/ControlServer/index.js +18 -22
  24. package/test/unit/ControlServer.test.js +0 -60
  25. package/test/unit/InboundServer.test.js +8 -8
  26. package/test/unit/TestServer.test.js +1 -1
  27. package/test/unit/api/accounts/accounts.test.js +2 -2
  28. package/test/unit/api/transfers/transfers.test.js +1 -1
  29. package/test/unit/api/utils.js +12 -4
  30. package/test/unit/config.test.js +1 -2
  31. package/test/unit/data/defaultConfig.json +1 -5
  32. package/test/unit/index.test.js +5 -64
  33. package/test/unit/lib/cache.test.js +5 -6
  34. package/test/unit/lib/model/AccountsModel.test.js +3 -4
  35. package/test/unit/lib/model/InboundTransfersModel.test.js +55 -16
  36. package/test/unit/lib/model/OutboundBulkQuotesModel.test.js +3 -4
  37. package/test/unit/lib/model/OutboundBulkTransfersModel.test.js +1 -2
  38. package/test/unit/lib/model/OutboundRequestToPayModel.test.js +3 -4
  39. package/test/unit/lib/model/OutboundRequestToPayTransferModel.test.js +3 -4
  40. package/test/unit/lib/model/OutboundTransfersModel.test.js +2 -3
  41. package/test/unit/lib/model/common/PersistentStateMachine.test.js +3 -4
  42. package/test/unit/lib/model/data/defaultConfig.json +1 -4
  43. package/test/unit/lib/model/data/notificationAbortedToPayee.json +10 -0
  44. package/test/unit/lib/model/data/notificationReservedToPayee.json +10 -0
@@ -139,7 +139,11 @@ class Server extends ws.Server {
139
139
 
140
140
  // Close the server then wait for all the client sockets to close
141
141
  async stop() {
142
- await new Promise(this.close.bind(this));
142
+ const closing = new Promise(resolve => this.close(resolve));
143
+ for (const client of this.clients) {
144
+ client.terminate();
145
+ }
146
+ await closing;
143
147
  this._logger.log('Control server shutdown complete');
144
148
  }
145
149
 
@@ -186,9 +190,7 @@ class Server extends ws.Server {
186
190
  * from other modules.
187
191
  */
188
192
  registerInternalEvents() {
189
- ControlServerEventEmitter.on(INTERNAL_EVENTS.SERVER.BROADCAST_CONFIG_CHANGE, (params) => {
190
- this.broadcastConfigChange(params);
191
- });
193
+ ControlServerEventEmitter.on(INTERNAL_EVENTS.SERVER.BROADCAST_CONFIG_CHANGE, (params) => this.broadcastConfigChange(params));
192
194
  }
193
195
 
194
196
  /**
@@ -196,28 +198,22 @@ class Server extends ws.Server {
196
198
  *
197
199
  * @param {object} params Updated configuration
198
200
  */
199
- async broadcastConfigChange(updatedConfig) {
201
+ broadcastConfigChange(updatedConfig) {
200
202
  const updateConfMsg = build.CONFIGURATION.PATCH({}, updatedConfig, generateSlug(4));
201
- const errorLogger = (socket, message) => (err) =>
202
- this._logger
203
- .push({ message, ip: this._clientData.get(socket).ip, err })
204
- .log('Error sending JWS keys notification to client');
205
- return await this.broadcast(updateConfMsg, errorLogger);
203
+ this.broadcast(updateConfMsg);
206
204
  }
207
205
 
208
206
  /**
209
- * Broadcasts a protocol message to all connected clients.
210
- *
211
- * @param {string} msg
212
- * @param {object} errorLogger
213
- */
214
- async broadcast(msg, errorLogger) {
215
- const sendToAllClients = (msg, errorLogger) => Promise.all(
216
- [...this.clients.values()].map((socket) =>
217
- (new Promise((resolve) => socket.send(msg, resolve))).catch(errorLogger(socket, msg))
218
- )
219
- );
220
- return await sendToAllClients(msg, errorLogger);
207
+ * Broadcasts a protocol message to all connected clients.
208
+ *
209
+ * @param {string} msg
210
+ */
211
+ broadcast(msg) {
212
+ this.clients.forEach((client) => {
213
+ if (client.readyState === ws.WebSocket.OPEN) {
214
+ client.send(msg);
215
+ }
216
+ });
221
217
  }
222
218
  }
223
219
 
@@ -1,13 +1,8 @@
1
1
 
2
2
  const ControlServer = require('~/ControlServer');
3
- const InboundServer = require('~/InboundServer');
4
- const OutboundServer = require('~/OutboundServer');
5
- const TestServer = require('~/TestServer');
6
- const defaultConfig = require('./data/defaultConfig.json');
7
3
  const { Logger } = require('@mojaloop/sdk-standard-components');
8
4
 
9
5
  jest.mock('~/lib/cache');
10
- const Cache = require('~/lib/cache');
11
6
 
12
7
  // TODO:
13
8
  // - diff against master to determine what else needs testing
@@ -67,60 +62,5 @@ describe('ControlServer', () => {
67
62
  const newConfEventData = await newConfigEvent;
68
63
  expect(newConfEventData).toEqual(changedConfig);
69
64
  });
70
-
71
- it('sends new config to clients when instructed', async () => {
72
- const client2 = await ControlServer.Client.Create({
73
- address: 'localhost',
74
- port: server.address().port,
75
- logger
76
- });
77
- const changedConfig = { ...appConfig, some: 'thing' };
78
- await client.send(ControlServer.build.CONFIGURATION.PATCH(appConfig, changedConfig));
79
- const restart = server.reconfigure({ appConfig: changedConfig });
80
- restart();
81
- await server.notifyClientsOfCurrentConfig();
82
- const [notification, notification2] =
83
- await Promise.all([client.receive(), client2.receive()]);
84
- const expected = ControlServer.build.CONFIGURATION.NOTIFY(changedConfig, notification.id);
85
- expect(JSON.stringify(notification)).toEqual(expected);
86
- expect(JSON.stringify(notification2)).toEqual(expected);
87
- });
88
- });
89
- });
90
-
91
- describe('Server reconfigure methods', () => {
92
- let conf, logger, cache;
93
-
94
- const isPromise = (o) => Promise.resolve(o) === o;
95
-
96
- beforeEach(() => {
97
- conf = JSON.parse(JSON.stringify(defaultConfig));
98
- logger = new Logger.Logger({ stringify: () => '' });
99
- cache = new Cache({ ...conf.cacheConfig, logger: logger.push({ component: 'cache' }) });
100
- });
101
-
102
- test('InboundServer reconfigure method returns sync function', async () => {
103
- const server = new InboundServer(conf, logger, cache);
104
- const res = await server.reconfigure(conf, logger, cache);
105
- expect(isPromise(res)).toEqual(false);
106
- });
107
-
108
- test('OutboundServer reconfigure method returns sync function', async () => {
109
- const server = new OutboundServer(conf, logger, cache);
110
- const res = await server.reconfigure(conf, logger, cache);
111
- expect(isPromise(res)).toEqual(false);
112
- });
113
-
114
- test('TestServer reconfigure method returns sync function', async () => {
115
- const server = new TestServer({ logger, cache });
116
- const res = await server.reconfigure({ logger, cache });
117
- expect(isPromise(res)).toEqual(false);
118
- });
119
-
120
- test('ControlServer reconfigure method returns sync function', async () => {
121
- const server = new ControlServer.Server({ logger, appConfig: {} });
122
- const res = await server.reconfigure({ logger, appConfig: {} });
123
- expect(isPromise(res)).toEqual(false);
124
- await server.close();
125
65
  });
126
66
  });
@@ -45,7 +45,7 @@ describe('Inbound Server', () => {
45
45
  serverConfig.validateInboundJws = validateInboundJws;
46
46
  serverConfig.validateInboundPutPartiesJws = validateInboundPutPartiesJws;
47
47
  const logger = new Logger.Logger({ stringify: () => '' });
48
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
48
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
49
49
  const svr = new InboundServer(serverConfig, logger, cache);
50
50
  await svr.start();
51
51
  await supertest(svr._server)
@@ -61,7 +61,7 @@ describe('Inbound Server', () => {
61
61
 
62
62
  async function testPartiesHeaderValidation(contentType, expectedStatusCode, expectedBody = null) {
63
63
  const logger = new Logger.Logger({ stringify: () => '' });
64
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
64
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
65
65
  const svr = new InboundServer(serverConfig, logger, cache);
66
66
  await svr.start();
67
67
  const result = await supertest(svr._server)
@@ -141,7 +141,7 @@ describe('Inbound Server', () => {
141
141
  serverConfig.validateInboundJws = validateInboundJws;
142
142
  serverConfig.validateInboundPutPartiesJws = validateInboundPutPartiesJws;
143
143
  const logger = new Logger.Logger({ stringify: () => '' });
144
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
144
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
145
145
  const svr = new InboundServer(serverConfig, logger, cache);
146
146
  await svr.start();
147
147
  await supertest(svr._server)
@@ -158,7 +158,7 @@ describe('Inbound Server', () => {
158
158
 
159
159
  async function testQuotesHeaderValidation(contentType, expectedStatusCode, expectedBody = null) {
160
160
  const logger = new Logger.Logger({ stringify: () => '' });
161
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
161
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
162
162
  const svr = new InboundServer(serverConfig, logger, cache);
163
163
  await svr.start();
164
164
  const result = await supertest(svr._server)
@@ -232,7 +232,7 @@ describe('Inbound Server', () => {
232
232
  serverConfig.validateInboundJws = validateInboundJws;
233
233
  serverConfig.validateInboundPutPartiesJws = validateInboundPutPartiesJws;
234
234
  const logger = new Logger.Logger({ stringify: () => '' });
235
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
235
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
236
236
  const svr = new InboundServer(serverConfig, logger, cache);
237
237
  await svr.start();
238
238
  await supertest(svr._server)
@@ -249,7 +249,7 @@ describe('Inbound Server', () => {
249
249
 
250
250
  async function testParticipantsHeaderValidation(contentType, expectedStatusCode, expectedBody = null) {
251
251
  const logger = new Logger.Logger({ stringify: () => '' });
252
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
252
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
253
253
  const svr = new InboundServer(serverConfig, logger, cache);
254
254
  await svr.start();
255
255
  const result = await supertest(svr._server)
@@ -336,7 +336,7 @@ describe('Inbound Server', () => {
336
336
  async function testTlsServer(enableTls) {
337
337
  defConfig.inbound.tls.mutualTLS.enabled = enableTls;
338
338
  const logger = new Logger.Logger({ stringify: () => '' });
339
- const cache = new Cache({ ...defConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
339
+ const cache = new Cache({ cacheUrl: defConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
340
340
  const server = new InboundServer(defConfig, logger, cache);
341
341
  await server.start();
342
342
  if (enableTls) {
@@ -369,7 +369,7 @@ describe('Inbound Server', () => {
369
369
  fs.writeFileSync(mockFilePath, 'foo-key');
370
370
  serverConfig.jwsVerificationKeysDirectory = keysDir;
371
371
  const logger = new Logger.Logger({ stringify: () => '' });
372
- const cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }) });
372
+ const cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }) });
373
373
  svr = new InboundServer(serverConfig, logger, cache);
374
374
  await svr.start();
375
375
  });
@@ -50,7 +50,7 @@ describe('Test Server', () => {
50
50
  ...JSON.parse(JSON.stringify(defaultConfig)),
51
51
  enableTestFeatures: true,
52
52
  };
53
- cache = new Cache({ ...serverConfig.cacheConfig, logger: logger.push({ component: 'cache' }), enableTestFeatures: true });
53
+ cache = new Cache({ cacheUrl: serverConfig.cacheUrl, logger: logger.push({ component: 'cache' }), enableTestFeatures: true });
54
54
 
55
55
  testServer = new TestServer({ logger, cache });
56
56
  await testServer.start();
@@ -35,7 +35,7 @@ describe('Outbound Accounts API', () => {
35
35
 
36
36
  beforeAll(async () => {
37
37
  validatorsInfo = await createValidators();
38
- redisClient = redis.createClient();
38
+ redisClient = redis.createClient(defaultConfig);
39
39
  });
40
40
 
41
41
  beforeEach(async () => {
@@ -52,7 +52,7 @@ describe('Outbound Accounts API', () => {
52
52
  });
53
53
 
54
54
  afterAll(async () => {
55
- redisClient.end();
55
+ // redisClient.end();
56
56
  });
57
57
 
58
58
  describe('POST /accounts', () => {
@@ -42,7 +42,7 @@ describe('Outbound Transfers API', () => {
42
42
 
43
43
  beforeAll(async () => {
44
44
  validatorsInfo = await createValidators();
45
- redisClient = redis.createClient();
45
+ redisClient = redis.createClient({ cacheUrl: 'redis://dummy:1234' });
46
46
  });
47
47
 
48
48
  beforeEach(async () => {
@@ -7,7 +7,7 @@ const Validate = require('~/lib/validate');
7
7
  const InboundServer = require('~/InboundServer');
8
8
  const OutboundServer = require('~/OutboundServer');
9
9
  const { MetricsClient } = require('~/lib/metrics');
10
- const { Logger } = require('@mojaloop/sdk-standard-components');
10
+ const { Logger, WSO2Auth } = require('@mojaloop/sdk-standard-components');
11
11
  const Cache = require('~/lib/cache');
12
12
 
13
13
  /**
@@ -43,18 +43,26 @@ const createTestServers = async (config) => {
43
43
  const logger = new Logger.Logger({ stringify: () => '' });
44
44
  const defConfig = JSON.parse(JSON.stringify(config));
45
45
  const cache = new Cache({
46
- ...defConfig.cacheConfig,
46
+ cacheUrl: defConfig.cacheUrl,
47
47
  logger: logger.push({ component: 'cache' })
48
48
  });
49
49
  await cache.connect();
50
50
  defConfig.requestProcessingTimeoutSeconds = 2;
51
51
  const metricsClient = new MetricsClient();
52
52
  metricsClient._prometheusRegister.clear();
53
- const serverOutbound = new OutboundServer(defConfig, logger, cache, metricsClient);
53
+ const wso2 = {
54
+ auth: new WSO2Auth({
55
+ ...defConfig.wso2.auth,
56
+ logger,
57
+ tlsCreds: defConfig.outbound.tls.mutualTLS.enabled && defConfig.outbound.tls.creds,
58
+ }),
59
+ retryWso2AuthFailureTimes: defConfig.wso2.requestAuthFailureRetryTimes,
60
+ };
61
+ const serverOutbound = new OutboundServer(defConfig, logger, cache, metricsClient, wso2);
54
62
  await serverOutbound.start();
55
63
  const reqOutbound = supertest(serverOutbound._server);
56
64
 
57
- const serverInbound = new InboundServer(defConfig, logger, cache);
65
+ const serverInbound = new InboundServer(defConfig, logger, cache, wso2);
58
66
  await serverInbound.start();
59
67
  const reqInbound = supertest(serverInbound._server);
60
68
 
@@ -26,8 +26,7 @@ describe('config', () => {
26
26
  env = { ...process.env };
27
27
  process.env.PEER_ENDPOINT = '172.17.0.3:4000';
28
28
  process.env.BACKEND_ENDPOINT = '172.17.0.5:4000';
29
- process.env.CACHE_HOST = '172.17.0.2';
30
- process.env.CACHE_PORT = '6379';
29
+ process.env.CACHE_URL = 'redis://172.17.0.2:6379';
31
30
  process.env.MGMT_API_WS_URL = '0.0.0.0';
32
31
  certDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jest-'));
33
32
  });
@@ -49,12 +49,8 @@
49
49
  "jwsSignPutParties": false,
50
50
  "jwsSigningKey": "/jwsSigningKey.key",
51
51
  "jwsVerificationKeysDirectory": null,
52
- "cacheConfig": {
53
- "host": "localhost",
54
- "port": 6379
55
- },
52
+ "cacheUrl": "redis://localhost:6379",
56
53
  "enableTestFeatures": false,
57
- "testingDisableWSO2AuthStart": true,
58
54
  "oauthTestServer": {
59
55
  "enabled": false,
60
56
  "listenPort": 6000
@@ -17,15 +17,13 @@ jest.mock('dotenv', () => ({
17
17
  const promClient = require('prom-client');
18
18
  const defaultConfig = require('./data/defaultConfig.json');
19
19
  const { Logger } = require('@mojaloop/sdk-standard-components');
20
- const { MetricsClient } = require('~/lib/metrics');
21
20
 
22
21
  const TestControlServer = require('./ControlServer');
23
22
 
24
23
 
25
24
  process.env.PEER_ENDPOINT = '172.17.0.3:4000';
26
25
  process.env.BACKEND_ENDPOINT = '172.17.0.5:4000';
27
- process.env.CACHE_HOST = '172.17.0.2';
28
- process.env.CACHE_PORT = '6379';
26
+ process.env.CACHE_URL = 'redis://172.17.0.2:6379';
29
27
  process.env.MGMT_API_WS_URL = '0.0.0.0';
30
28
 
31
29
  const index = require('~/index.js');
@@ -35,24 +33,6 @@ describe('index.js', () => {
35
33
  promClient.register.clear();
36
34
  });
37
35
 
38
- test('WSO2 error events in OutboundServer propagate to top-level server', () => {
39
- const logger = new Logger.Logger({ stringify: () => '' });
40
- const svr = new index.Server(defaultConfig, logger);
41
- const cb = jest.fn();
42
- svr.on('error', cb);
43
- svr.outboundServer._api._wso2.auth.emit('error', 'msg');
44
- expect(cb).toHaveBeenCalledTimes(1);
45
- });
46
-
47
- test('WSO2 error events in InboundServer propagate to top-level server', () => {
48
- const logger = new Logger.Logger({ stringify: () => '' });
49
- const svr = new index.Server(defaultConfig, logger);
50
- const cb = jest.fn();
51
- svr.on('error', cb);
52
- svr.inboundServer._api._wso2.auth.emit('error', 'msg');
53
- expect(cb).toHaveBeenCalledTimes(1);
54
- });
55
-
56
36
  test('Exports expected modules', () => {
57
37
  expect(typeof(index.Server)).toBe('function');
58
38
  expect(typeof(index.InboundServerMiddleware)).toBe('object');
@@ -77,6 +57,7 @@ describe('Server', () => {
77
57
  conf.control.port = conf.control.mgmtAPIWsPort;
78
58
  controlServer = new TestControlServer.Server({ logger, appConfig: conf });
79
59
  server = new index.Server(conf, logger);
60
+ server.restart = jest.fn();
80
61
  await server.start();
81
62
  });
82
63
 
@@ -95,53 +76,13 @@ describe('Server', () => {
95
76
  });
96
77
 
97
78
  it('reconfigures and restarts constituent servers when triggered by control client', async () => {
98
- const [restartInbound, restartOutbound, restartControl, restartOAuthTest, restartTest] =
99
- Array.from({ length: 5 }).map(() => jest.fn());
100
- server.inboundServer.reconfigure = jest.fn(() => restartInbound);
101
- server.outboundServer.reconfigure = jest.fn(() => restartOutbound);
102
- server.testServer.reconfigure = jest.fn(() => restartTest);
103
- server.oauthTestServer.reconfigure = jest.fn(() => restartOAuthTest);
104
- server.controlClient.reconfigure = jest.fn(() => restartControl);
105
-
106
- await controlServer.broadcastConfigChange(newConf);
79
+ controlServer.broadcastConfigChange(newConf);
107
80
 
108
81
  // We wait for the servers to get restarted
109
82
  await new Promise((wait) => setTimeout(wait, 1000));
110
83
 
111
- expect(server.inboundServer.reconfigure).toHaveBeenCalledTimes(1);
112
- expect(server.inboundServer.reconfigure).toHaveBeenCalledWith(
113
- newConf, expect.any(Logger.Logger), expect.any(index.Cache)
114
- );
115
- expect(server.outboundServer.reconfigure).toHaveBeenCalledTimes(1);
116
- const metricsClient = new MetricsClient();
117
- expect(server.outboundServer.reconfigure).toHaveBeenCalledWith(
118
- newConf, expect.any(Logger.Logger), expect.any(index.Cache), metricsClient
119
- );
120
- expect(server.controlClient.reconfigure).toHaveBeenCalledTimes(1);
121
- expect(server.controlClient.reconfigure).toHaveBeenCalledWith({
122
- logger: expect.any(Logger.Logger),
123
- port: newConf.control.port,
124
- appConfig: newConf
125
- });
126
- expect(server.testServer.reconfigure).toHaveBeenCalledTimes(1);
127
- expect(server.testServer.reconfigure).toHaveBeenCalledWith({
128
- logger: expect.any(Logger.Logger),
129
- cache: expect.any(index.Cache),
130
- port: newConf.test.port
131
- });
132
- expect(server.oauthTestServer.reconfigure).toHaveBeenCalledTimes(1);
133
- expect(server.oauthTestServer.reconfigure).toHaveBeenCalledWith({
134
- logger: expect.any(Logger.Logger),
135
- clientKey: newConf.oauthTestServer.clientKey,
136
- clientSecret: newConf.oauthTestServer.clientSecret,
137
- port: newConf.oauthTestServer.listenPort,
138
- });
139
-
140
- expect(restartInbound).toHaveBeenCalledTimes(1);
141
- expect(restartOutbound).toHaveBeenCalledTimes(1);
142
- expect(restartTest).toHaveBeenCalledTimes(1);
143
- expect(restartOAuthTest).toHaveBeenCalledTimes(1);
144
- expect(restartControl).toHaveBeenCalledTimes(1);
84
+ expect(server.restart).toHaveBeenCalledTimes(1);
85
+ expect(server.restart).toHaveBeenCalledWith(newConf);
145
86
  });
146
87
  });
147
88
  });
@@ -18,9 +18,8 @@ const { Logger } = require('@mojaloop/sdk-standard-components');
18
18
  const createCache = async() => {
19
19
  const logger = new Logger.Logger({ context: { app: 'model-unit-tests-cache' }, stringify: () => '' });
20
20
  const cache = new Cache({
21
- host: 'dummyhost',
22
- port: 1234,
23
- logger,
21
+ cacheUrl: 'redis://dummy:1234',
22
+ logger,
24
23
  });
25
24
  await cache.connect();
26
25
  return cache;
@@ -75,11 +74,11 @@ describe('Cache', () => {
75
74
  expect(cbId1).toBe(0);
76
75
 
77
76
  // now we have subscribed, inject a message.
78
- cache.publish(chan1, msg1);
77
+ return cache.publish(chan1, msg1);
79
78
  });
80
79
  });
81
80
 
82
- // create a second promise that only gets resoled if the second subscription gets the
81
+ // create a second promise that only gets resolved if the second subscription gets the
83
82
  // correct message
84
83
  const cb2Promise = new Promise((resolve) => {
85
84
  const mockCb2 = jest.fn((cn, msg) => {
@@ -99,7 +98,7 @@ describe('Cache', () => {
99
98
  expect(cbId2).toBe(1);
100
99
 
101
100
  // now we have subscribed, inject a message.
102
- cache.publish(chan2, msg2);
101
+ return cache.publish(chan2, msg2);
103
102
  });
104
103
  });
105
104
 
@@ -93,10 +93,9 @@ describe('AccountsModel', () => {
93
93
 
94
94
  beforeEach(async () => {
95
95
  cache = new Cache({
96
- host: 'dummycachehost',
97
- port: 1234,
98
- logger,
99
- });
96
+ cacheUrl: 'redis://dummy:1234',
97
+ logger,
98
+ });
100
99
  await cache.connect();
101
100
  });
102
101
 
@@ -28,6 +28,8 @@ const getTransfersMojaloopResponse = require('./data/getTransfersMojaloopRespons
28
28
  const getBulkTransfersBackendResponse = require('./data/getBulkTransfersBackendResponse');
29
29
  const getBulkTransfersMojaloopResponse = require('./data/getBulkTransfersMojaloopResponse');
30
30
  const notificationToPayee = require('./data/notificationToPayee');
31
+ const notificationAbortedToPayee = require('./data/notificationAbortedToPayee');
32
+ const notificationReservedToPayee = require('./data/notificationReservedToPayee');
31
33
 
32
34
  describe('inboundModel', () => {
33
35
  let config;
@@ -63,8 +65,7 @@ describe('inboundModel', () => {
63
65
  }));
64
66
 
65
67
  cache = new Cache({
66
- host: 'dummycachehost',
67
- port: 1234,
68
+ cacheUrl: 'redis://dummy:1234',
68
69
  logger,
69
70
  });
70
71
  await cache.connect();
@@ -132,8 +133,7 @@ describe('inboundModel', () => {
132
133
  BackendRequests.__postBulkQuotes = jest.fn().mockReturnValue(Promise.resolve(mockArgs.internalBulkQuoteResponse));
133
134
 
134
135
  cache = new Cache({
135
- host: 'dummycachehost',
136
- port: 1234,
136
+ cacheUrl: 'redis://dummy:1234',
137
137
  logger,
138
138
  });
139
139
  await cache.connect();
@@ -189,8 +189,7 @@ describe('inboundModel', () => {
189
189
  BackendRequests.__postTransactionRequests = jest.fn().mockReturnValue(Promise.resolve(mockTxnReqArgs.internalTransactionRequestResponse));
190
190
 
191
191
  cache = new Cache({
192
- host: 'dummycachehost',
193
- port: 1234,
192
+ cacheUrl: 'redis://dummy:1234',
194
193
  logger,
195
194
  });
196
195
  await cache.connect();
@@ -226,8 +225,7 @@ describe('inboundModel', () => {
226
225
  BackendRequests.__getOTP = jest.fn().mockReturnValue(Promise.resolve(mockArgs.internalGetOTPResponse));
227
226
 
228
227
  cache = new Cache({
229
- host: 'dummycachehost',
230
- port: 1234,
228
+ cacheUrl: 'redis://dummy:1234',
231
229
  logger,
232
230
  });
233
231
  await cache.connect();
@@ -268,8 +266,7 @@ describe('inboundModel', () => {
268
266
  }));
269
267
 
270
268
  cache = new Cache({
271
- host: 'dummycachehost',
272
- port: 1234,
269
+ cacheUrl: 'redis://dummy:1234',
273
270
  logger,
274
271
  });
275
272
  await cache.connect();
@@ -547,8 +544,7 @@ describe('inboundModel', () => {
547
544
  BackendRequests.__postBulkTransfers = jest.fn().mockReturnValue(Promise.resolve({}));
548
545
 
549
546
  cache = new Cache({
550
- host: 'dummycachehost',
551
- port: 1234,
547
+ cacheUrl: 'redis://dummy:1234',
552
548
  logger,
553
549
  });
554
550
  await cache.connect();
@@ -727,8 +723,7 @@ describe('inboundModel', () => {
727
723
 
728
724
  beforeEach(async () => {
729
725
  cache = new Cache({
730
- host: 'dummycachehost',
731
- port: 1234,
726
+ cacheUrl: 'redis://dummy:1234',
732
727
  logger,
733
728
  });
734
729
  await cache.connect();
@@ -759,14 +754,58 @@ describe('inboundModel', () => {
759
754
  expect(call[0]).toEqual(expectedRequest);
760
755
  expect(call[1]).toEqual(transferId);
761
756
  });
757
+
758
+ test('sends ABORTED notification to fsp backend', async () => {
759
+ BackendRequests.__putTransfersNotification = jest.fn().mockReturnValue(Promise.resolve({}));
760
+ const notif = JSON.parse(JSON.stringify(notificationAbortedToPayee));
761
+
762
+ const expectedRequest = {
763
+ currentState: 'ABORTED',
764
+ finalNotification: notif.data,
765
+ };
766
+
767
+ const model = new Model({
768
+ ...config,
769
+ cache,
770
+ logger,
771
+ });
772
+
773
+ await model.sendNotificationToPayee(notif.data, transferId);
774
+ expect(BackendRequests.__putTransfersNotification).toHaveBeenCalledTimes(1);
775
+ const call = BackendRequests.__putTransfersNotification.mock.calls[0];
776
+ expect(call[0]).toEqual(expectedRequest);
777
+ expect(call[1]).toEqual(transferId);
778
+ });
779
+
780
+ test('sends RESERVED notification to fsp backend', async () => {
781
+ BackendRequests.__putTransfersNotification = jest.fn().mockReturnValue(Promise.resolve({}));
782
+ const notif = JSON.parse(JSON.stringify(notificationReservedToPayee));
783
+
784
+ const expectedRequest = {
785
+ finalNotification: notif.data,
786
+ lastError: 'Final notification state not COMMITTED',
787
+ };
788
+
789
+ const model = new Model({
790
+ ...config,
791
+ cache,
792
+ logger,
793
+ });
794
+
795
+ await model.sendNotificationToPayee(notif.data, transferId);
796
+ expect(BackendRequests.__putTransfersNotification).toHaveBeenCalledTimes(1);
797
+ const call = BackendRequests.__putTransfersNotification.mock.calls[0];
798
+ expect(call[0]).toEqual(expectedRequest);
799
+ expect(call[1]).toEqual(transferId);
800
+ });
801
+
762
802
  });
763
803
 
764
804
  describe('error handling:', () => {
765
805
  let cache;
766
806
  beforeEach(async () => {
767
807
  cache = new Cache({
768
- host: 'dummycachehost',
769
- port: 1234,
808
+ cacheUrl: 'redis://dummy:1234',
770
809
  logger,
771
810
  });
772
811
  await cache.connect();
@@ -91,10 +91,9 @@ describe('OutboundBulkQuotesModel', () => {
91
91
  MojaloopRequests.__putBulkQuotesError = jest.fn(() => Promise.resolve());
92
92
 
93
93
  cache = new Cache({
94
- host: 'dummycachehost',
95
- port: 1234,
96
- logger,
97
- });
94
+ cacheUrl: 'redis://dummy:1234',
95
+ logger,
96
+ });
98
97
  await cache.connect();
99
98
  });
100
99
 
@@ -83,8 +83,7 @@ describe('outboundBulkTransferModel', () => {
83
83
  MojaloopRequests.__postBulkTransfers = jest.fn(() => Promise.resolve());
84
84
 
85
85
  cache = new Cache({
86
- host: 'dummycachehost',
87
- port: 1234,
86
+ cacheUrl: 'redis://dummy:1234',
88
87
  logger,
89
88
  });
90
89
  await cache.connect();
@@ -71,10 +71,9 @@ describe('outboundModel', () => {
71
71
  MojaloopRequests.__postTransactionRequests = jest.fn(() => Promise.resolve());
72
72
 
73
73
  cache = new Cache({
74
- host: 'dummycachehost',
75
- port: 1234,
76
- logger,
77
- });
74
+ cacheUrl: 'redis://dummy:1234',
75
+ logger,
76
+ });
78
77
  await cache.connect();
79
78
  });
80
79