account-lookup-service 17.7.0 → 17.8.0-snapshot.6
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.
- package/package.json +9 -6
- package/src/constants.js +34 -2
- package/src/domain/parties/deps.js +4 -3
- package/src/domain/parties/getPartiesByTypeAndID.js +9 -13
- package/src/domain/parties/partiesUtils.js +4 -34
- package/src/domain/parties/putParties.js +26 -71
- package/src/domain/parties/services/BasePartiesService.js +143 -15
- package/src/domain/parties/services/GetPartiesService.js +189 -164
- package/src/domain/parties/services/PutPartiesErrorService.js +50 -27
- package/src/domain/parties/services/PutPartiesService.js +51 -33
- package/src/domain/parties/services/TimeoutPartiesService.js +84 -0
- package/src/domain/parties/services/index.js +3 -1
- package/src/domain/timeout/createSpan.js +55 -0
- package/src/domain/timeout/index.js +27 -36
- package/src/handlers/TimeoutHandler.js +2 -2
- package/src/lib/util.js +11 -3
- package/test/fixtures/index.js +46 -0
- package/test/integration/domain/timeout/index.test.js +83 -28
- package/test/unit/domain/parties/parties.test.js +26 -18
- package/test/unit/domain/parties/partiesUtils.test.js +51 -0
- package/test/unit/domain/parties/services/BasePartiesService.test.js +71 -0
- package/test/unit/domain/parties/services/GetPartiesService.test.js +224 -0
- package/test/unit/domain/parties/services/PutPartiesErrorService.test.js +50 -0
- package/test/unit/domain/parties/services/TimeoutPartiesService.test.js +72 -0
- package/test/unit/domain/parties/services/deps.js +49 -0
- package/test/unit/domain/timeout/index.test.js +17 -12
- package/test/util/apiClients/BasicApiClient.js +33 -6
- package/test/util/apiClients/ProxyApiClient.js +46 -1
- package/test/util/index.js +5 -6
- package/test/util/mockDeps.js +61 -0
- package/src/domain/timeout/dto.js +0 -54
- package/test/unit/domain/parties/utils.test.js +0 -60
- package/test/unit/domain/timeout/dto.test.js +0 -24
@@ -56,7 +56,7 @@ const fixtures = require('../../../fixtures')
|
|
56
56
|
const { type: proxyCacheType, proxyConfig: proxyCacheConfig } = Config.PROXY_CACHE_CONFIG
|
57
57
|
|
58
58
|
const { encodePayload } = Util.StreamingProtocol
|
59
|
-
const { RestMethods } = Enum.Http
|
59
|
+
const { RestMethods, Headers } = Enum.Http
|
60
60
|
|
61
61
|
Logger.isDebugEnabled = jest.fn(() => true)
|
62
62
|
Logger.isErrorEnabled = jest.fn(() => true)
|
@@ -192,24 +192,26 @@ describe('Parties Tests', () => {
|
|
192
192
|
expect(cached).toBe(proxy)
|
193
193
|
})
|
194
194
|
|
195
|
-
it('should
|
195
|
+
it('should cleanup oracle and trigger discovery flow, if destination is not in scheme and no dfsp-to-proxy mapping', async () => {
|
196
|
+
Config.PROXY_CACHE_CONFIG.enabled = true
|
196
197
|
participant.validateParticipant = sandbox.stub()
|
197
198
|
.onFirstCall().resolves({}) // source
|
198
199
|
.onSecondCall().resolves(null) // destination
|
199
200
|
participant.sendRequest = sandbox.stub().resolves()
|
200
201
|
participant.sendErrorToParticipant = sandbox.stub().resolves()
|
201
202
|
sandbox.stub(oracle, 'oracleRequest')
|
203
|
+
const proxy = 'some-proxy'
|
204
|
+
Util.proxies.getAllProxiesNames = sandbox.stub().resolves([proxy])
|
202
205
|
const headers = fixtures.partiesCallHeadersDto()
|
203
206
|
|
204
207
|
await partiesDomain.getPartiesByTypeAndID(headers, Helper.getByTypeIdRequest.params, Helper.getByTypeIdRequest.method, Helper.getByTypeIdRequest.query, Helper.mockSpan(), null, proxyCache)
|
205
208
|
|
206
|
-
expect(
|
207
|
-
expect(
|
208
|
-
expect(participant.
|
209
|
-
|
210
|
-
const
|
211
|
-
expect(
|
212
|
-
expect(errorInformation.errorDescription).toContain(ERROR_MESSAGES.partyDestinationFspNotFound)
|
209
|
+
expect(oracle.oracleRequest.lastCall.args[1]).toBe(RestMethods.DELETE)
|
210
|
+
expect(participant.sendErrorToParticipant.callCount).toBe(0)
|
211
|
+
expect(participant.sendRequest.callCount).toBe(1)
|
212
|
+
// eslint-disable-next-line no-unused-vars
|
213
|
+
const [_, sendTo] = participant.sendRequest.lastCall.args
|
214
|
+
expect(sendTo).toBe(proxy)
|
213
215
|
})
|
214
216
|
|
215
217
|
it('should send request to proxy, if destination is not in the scheme, but has proxyMapping', async () => {
|
@@ -470,7 +472,7 @@ describe('Parties Tests', () => {
|
|
470
472
|
expect(firstCallArgs[2]).toBe(expectedCallbackEnpointType)
|
471
473
|
})
|
472
474
|
|
473
|
-
it('should send
|
475
|
+
it('should send errorCallback if oracle returns external dfsp, and source is external', async () => {
|
474
476
|
Config.PROXY_CACHE_CONFIG.enabled = true
|
475
477
|
const proxyName = `proxy-${Date.now()}`
|
476
478
|
const fspId = `dfspNotFromScheme-${Date.now()}`
|
@@ -479,7 +481,7 @@ describe('Parties Tests', () => {
|
|
479
481
|
})
|
480
482
|
sandbox.stub(oracle, 'oracleRequest').resolves(oracleResponse)
|
481
483
|
participant.validateParticipant = sandbox.stub()
|
482
|
-
.onFirstCall().resolves(
|
484
|
+
.onFirstCall().resolves(null) // source
|
483
485
|
.onSecondCall().resolves(null) // oracle dfsp
|
484
486
|
participant.sendRequest = sandbox.stub().resolves()
|
485
487
|
participant.sendErrorToParticipant = sandbox.stub().resolves()
|
@@ -487,15 +489,20 @@ describe('Parties Tests', () => {
|
|
487
489
|
const isAdded = await proxyCache.addDfspIdToProxyMapping(fspId, proxyName)
|
488
490
|
expect(isAdded).toBe(true)
|
489
491
|
|
490
|
-
const
|
492
|
+
const source = `fromDfsp-${Date.now()}`
|
493
|
+
const headers = fixtures.partiesCallHeadersDto({ destination: '', source, proxy: 'proxy' })
|
491
494
|
const { params, method, query } = Helper.getByTypeIdRequest
|
492
495
|
|
493
496
|
await partiesDomain.getPartiesByTypeAndID(headers, params, method, query, null, null, proxyCache)
|
494
497
|
|
495
|
-
expect(participant.
|
496
|
-
expect(participant.
|
497
|
-
|
498
|
-
|
498
|
+
expect(participant.sendRequest.callCount).toBe(0)
|
499
|
+
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
500
|
+
// eslint-disable-next-line no-unused-vars
|
501
|
+
const [sentTo, _, payload, sentHeaders] = participant.sendErrorToParticipant.lastCall.args
|
502
|
+
expect(sentTo).toBe(source)
|
503
|
+
expect(payload.errorInformation.errorCode).toBe('3200')
|
504
|
+
expect(sentHeaders[Headers.FSPIOP.SOURCE]).toBe(Config.HUB_NAME)
|
505
|
+
expect(sentHeaders[Headers.FSPIOP.DESTINATION]).toBe(headers[Headers.FSPIOP.SOURCE])
|
499
506
|
})
|
500
507
|
|
501
508
|
it('handles error when `oracleRequest` returns no result', async () => {
|
@@ -554,13 +561,14 @@ describe('Parties Tests', () => {
|
|
554
561
|
participant.sendRequest = sandbox.stub().rejects(new Error('Some network issue'))
|
555
562
|
participant.sendErrorToParticipant = sandbox.stub().resolves()
|
556
563
|
const headers = fixtures.partiesCallHeadersDto({ destination: '' })
|
564
|
+
const params = fixtures.partiesParamsDto()
|
557
565
|
|
558
|
-
await partiesDomain.getPartiesByTypeAndID(headers,
|
566
|
+
await partiesDomain.getPartiesByTypeAndID(headers, params, Helper.getByTypeIdRequest.method, Helper.getByTypeIdRequest.query, Helper.mockSpan(), null, proxyCache)
|
559
567
|
|
560
568
|
expect(participant.sendRequest.callCount).toBe(proxyNames.length)
|
561
569
|
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
562
570
|
|
563
|
-
const { errorInformation } = participant.sendErrorToParticipant.
|
571
|
+
const { errorInformation } = participant.sendErrorToParticipant.lastCall.args[2]
|
564
572
|
expect(errorInformation.errorCode).toBe('3200')
|
565
573
|
expect(errorInformation.errorDescription).toContain(ERROR_MESSAGES.proxyConnectionError)
|
566
574
|
})
|
@@ -0,0 +1,51 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
8
|
+
|
9
|
+
Contributors
|
10
|
+
--------------
|
11
|
+
This is the official list of the Mojaloop project contributors for this file.
|
12
|
+
Names of the original copyright holders (individuals or organizations)
|
13
|
+
should be listed with a '*' in the first column. People who have
|
14
|
+
contributed from an organization can be listed under the organization
|
15
|
+
that actually holds the copyright for their contributions (see the
|
16
|
+
Mojaloop Foundation organization for an example). Those individuals should have
|
17
|
+
their names indented and be marked with a '-'. Email address can be added
|
18
|
+
optionally within square brackets <email>.
|
19
|
+
* Mojaloop Foundation
|
20
|
+
- Name Surname <name.surname@mojaloop.io>
|
21
|
+
|
22
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
23
|
+
--------------
|
24
|
+
**********/
|
25
|
+
|
26
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
27
|
+
const partiesUtils = require('#src/domain/parties/partiesUtils')
|
28
|
+
const config = require('#src/lib/config')
|
29
|
+
const { API_TYPES } = require('#src/constants')
|
30
|
+
const fixtures = require('#test/fixtures/index')
|
31
|
+
|
32
|
+
describe('partiesUtils Tests -->', () => {
|
33
|
+
describe('makePutPartiesErrorPayload Tests', () => {
|
34
|
+
const error = ErrorHandler.Factory.reformatFSPIOPError(new Error('Test Error'))
|
35
|
+
const ERR_CODE = '2001'
|
36
|
+
const headers = fixtures.partiesCallHeadersDto()
|
37
|
+
const params = fixtures.partiesParamsDto()
|
38
|
+
|
39
|
+
test('should make putParties error payload in FSPIOP format', async () => {
|
40
|
+
const fspiopConfig = { ...config, API_TYPE: API_TYPES.fspiop }
|
41
|
+
const payload = await partiesUtils.makePutPartiesErrorPayload(fspiopConfig, error, headers, params)
|
42
|
+
expect(payload.errorInformation.errorCode).toBe(ERR_CODE)
|
43
|
+
})
|
44
|
+
|
45
|
+
test('should make putParties error payload in ISO20022 format', async () => {
|
46
|
+
const fspiopConfig = { ...config, API_TYPE: API_TYPES.iso20022 }
|
47
|
+
const payload = await partiesUtils.makePutPartiesErrorPayload(fspiopConfig, error, headers, params)
|
48
|
+
expect(payload.Rpt.Rsn.Cd).toBe(ERR_CODE)
|
49
|
+
})
|
50
|
+
})
|
51
|
+
})
|
@@ -0,0 +1,71 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
+
|
11
|
+
Contributors
|
12
|
+
--------------
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
15
|
+
should be listed with a '*' in the first column. People who have
|
16
|
+
contributed from an organization can be listed under the organization
|
17
|
+
that actually holds the copyright for their contributions (see the
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
20
|
+
optionally within square brackets <email>.
|
21
|
+
|
22
|
+
* Mojaloop Foundation
|
23
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
+
|
25
|
+
--------------
|
26
|
+
******/
|
27
|
+
|
28
|
+
const { createMockDeps, participantMock } = require('./deps')
|
29
|
+
// ↑ should be first require to mock external deps ↑
|
30
|
+
const BasePartiesService = require('#src/domain/parties/services/BasePartiesService')
|
31
|
+
const config = require('#src/lib/config')
|
32
|
+
const { API_TYPES } = require('#src/constants')
|
33
|
+
const fixtures = require('#test/fixtures/index')
|
34
|
+
|
35
|
+
describe('BasePartiesService Tests -->', () => {
|
36
|
+
beforeEach(() => {
|
37
|
+
jest.clearAllMocks()
|
38
|
+
})
|
39
|
+
|
40
|
+
test('should send error party callback in ISO20022 format', async () => {
|
41
|
+
const deps = {
|
42
|
+
...createMockDeps(),
|
43
|
+
config: { ...config, API_TYPE: API_TYPES.iso20022 }
|
44
|
+
}
|
45
|
+
const source = 'sourceFsp'
|
46
|
+
const headers = fixtures.partiesCallHeadersDto({ source })
|
47
|
+
const params = fixtures.partiesParamsDto()
|
48
|
+
const service = new BasePartiesService(deps, { headers, params })
|
49
|
+
|
50
|
+
await service.handleError(new Error('test error'))
|
51
|
+
expect(participantMock.sendErrorToParticipant.mock.calls.length).toBe(1)
|
52
|
+
// eslint-disable-next-line no-unused-vars
|
53
|
+
const [sentTo, _, payload] = participantMock.sendErrorToParticipant.mock.lastCall
|
54
|
+
expect(sentTo).toBe(source)
|
55
|
+
expect(payload.Rpt.Rsn.Cd).toBe('2001')
|
56
|
+
expect(payload.Rpt.OrgnlId).toBe(`${params.Type}/${params.ID}`)
|
57
|
+
expect(payload.Assgnmt.Assgnr.Agt.FinInstnId.Othr.Id).toBe(source)
|
58
|
+
})
|
59
|
+
|
60
|
+
test('should remove proxy getParties timeout cache key', async () => {
|
61
|
+
const deps = createMockDeps()
|
62
|
+
const proxy = 'proxyAB'
|
63
|
+
const headers = fixtures.partiesCallHeadersDto({ proxy })
|
64
|
+
const params = fixtures.partiesParamsDto()
|
65
|
+
const alsReq = {}
|
66
|
+
const service = new BasePartiesService(deps, { headers, params })
|
67
|
+
|
68
|
+
await service.removeProxyGetPartiesTimeoutCache(alsReq)
|
69
|
+
expect(deps.proxyCache.removeProxyGetPartiesTimeout).toHaveBeenCalledWith(alsReq, proxy)
|
70
|
+
})
|
71
|
+
})
|
@@ -0,0 +1,224 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
+
|
11
|
+
Contributors
|
12
|
+
--------------
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
15
|
+
should be listed with a '*' in the first column. People who have
|
16
|
+
contributed from an organization can be listed under the organization
|
17
|
+
that actually holds the copyright for their contributions (see the
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
20
|
+
optionally within square brackets <email>.
|
21
|
+
|
22
|
+
* Mojaloop Foundation
|
23
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
+
|
25
|
+
--------------
|
26
|
+
******/
|
27
|
+
|
28
|
+
const { createMockDeps, createProxyCacheMock, oracleMock, participantMock } = require('./deps')
|
29
|
+
// ↑ should be first require to mock external deps ↑
|
30
|
+
const { GetPartiesService } = require('#src/domain/parties/services/index')
|
31
|
+
const fixtures = require('#test/fixtures/index')
|
32
|
+
|
33
|
+
const { RestMethods, Headers } = GetPartiesService.enums()
|
34
|
+
|
35
|
+
describe('GetPartiesService Tests -->', () => {
|
36
|
+
beforeEach(() => {
|
37
|
+
jest.clearAllMocks()
|
38
|
+
})
|
39
|
+
|
40
|
+
describe('forwardRequestToDestination method', () => {
|
41
|
+
test('should delete party info from oracle, if no destination DFSP in proxy mapping', async () => {
|
42
|
+
participantMock.validateParticipant = jest.fn().mockResolvedValueOnce(null)
|
43
|
+
const proxyCache = createProxyCacheMock({
|
44
|
+
lookupProxyByDfspId: jest.fn().mockResolvedValueOnce(null)
|
45
|
+
})
|
46
|
+
const deps = createMockDeps({ proxyCache })
|
47
|
+
|
48
|
+
const destination = 'dfsp'
|
49
|
+
const headers = fixtures.partiesCallHeadersDto({ destination, proxy: 'proxy' })
|
50
|
+
const params = fixtures.partiesParamsDto()
|
51
|
+
const service = new GetPartiesService(deps, { headers, params })
|
52
|
+
service.triggerInterSchemeDiscoveryFlow = jest.fn()
|
53
|
+
|
54
|
+
await service.forwardRequestToDestination()
|
55
|
+
|
56
|
+
expect(oracleMock.oracleRequest.mock.calls.length).toBe(1)
|
57
|
+
const [sentHeaders, method, sentParams] = oracleMock.oracleRequest.mock.lastCall
|
58
|
+
expect(method).toBe(RestMethods.DELETE)
|
59
|
+
expect(sentHeaders).toEqual(headers)
|
60
|
+
expect(sentParams).toEqual(params)
|
61
|
+
|
62
|
+
expect(service.triggerInterSchemeDiscoveryFlow.mock.calls.length).toBe(1)
|
63
|
+
expect(service.triggerInterSchemeDiscoveryFlow.mock.lastCall[0]).toEqual({
|
64
|
+
...headers,
|
65
|
+
[Headers.FSPIOP.DESTINATION]: undefined
|
66
|
+
})
|
67
|
+
})
|
68
|
+
})
|
69
|
+
|
70
|
+
describe('processOraclePartyList for external participants', () => {
|
71
|
+
const EXTERNAL_DFSP_ID = 'externalFsp'
|
72
|
+
const PROXY_ID = 'externalProxy'
|
73
|
+
let deps
|
74
|
+
let proxyCache
|
75
|
+
|
76
|
+
beforeEach(async () => {
|
77
|
+
oracleMock.oracleRequest = jest.fn().mockResolvedValueOnce(
|
78
|
+
fixtures.oracleRequestResponseDto({ partyList: [{ fspId: EXTERNAL_DFSP_ID }] })
|
79
|
+
)
|
80
|
+
participantMock.validateParticipant = jest.fn()
|
81
|
+
.mockResolvedValueOnce(null) // source
|
82
|
+
.mockResolvedValueOnce({}) // proxy
|
83
|
+
|
84
|
+
proxyCache = createProxyCacheMock({
|
85
|
+
addDfspIdToProxyMapping: jest.fn().mockResolvedValueOnce(true),
|
86
|
+
lookupProxyByDfspId: jest.fn().mockResolvedValueOnce(PROXY_ID)
|
87
|
+
})
|
88
|
+
deps = createMockDeps({ proxyCache })
|
89
|
+
})
|
90
|
+
|
91
|
+
test('should cleanup oracle and trigger interScheme discovery, if no proxyMapping for external dfsp', async () => {
|
92
|
+
proxyCache.lookupProxyByDfspId = jest.fn().mockResolvedValueOnce(null)
|
93
|
+
const headers = fixtures.partiesCallHeadersDto({
|
94
|
+
destination: '', proxy: 'proxyA'
|
95
|
+
})
|
96
|
+
const params = fixtures.partiesParamsDto()
|
97
|
+
const service = new GetPartiesService(deps, { headers, params })
|
98
|
+
service.triggerInterSchemeDiscoveryFlow = jest.fn()
|
99
|
+
|
100
|
+
await service.handleRequest()
|
101
|
+
expect(oracleMock.oracleRequest).toHaveBeenCalledTimes(2) // GET + DELETE
|
102
|
+
expect(oracleMock.oracleRequest.mock.lastCall[1]).toBe(RestMethods.DELETE)
|
103
|
+
expect(service.triggerInterSchemeDiscoveryFlow).toHaveBeenCalledWith(headers)
|
104
|
+
})
|
105
|
+
|
106
|
+
test('should trigger interScheme discovery flow, if source is external', async () => {
|
107
|
+
const headers = fixtures.partiesCallHeadersDto({
|
108
|
+
destination: '', proxy: 'proxyA'
|
109
|
+
})
|
110
|
+
const params = fixtures.partiesParamsDto()
|
111
|
+
const service = new GetPartiesService(deps, { headers, params })
|
112
|
+
service.triggerInterSchemeDiscoveryFlow = jest.fn()
|
113
|
+
|
114
|
+
await service.handleRequest()
|
115
|
+
expect(service.triggerInterSchemeDiscoveryFlow).toHaveBeenCalledWith(headers)
|
116
|
+
})
|
117
|
+
|
118
|
+
test('should forward request, if source is in scheme (no proxy header)', async () => {
|
119
|
+
participantMock.validateParticipant = jest.fn(async (fsp) => (fsp === EXTERNAL_DFSP_ID ? null : {}))
|
120
|
+
const headers = fixtures.partiesCallHeadersDto({
|
121
|
+
destination: '', proxy: ''
|
122
|
+
})
|
123
|
+
const params = fixtures.partiesParamsDto()
|
124
|
+
const service = new GetPartiesService(deps, { headers, params })
|
125
|
+
|
126
|
+
await service.handleRequest()
|
127
|
+
expect(participantMock.sendRequest.mock.calls.length).toBe(1)
|
128
|
+
const [sentHeaders, sendTo] = participantMock.sendRequest.mock.lastCall
|
129
|
+
expect(sendTo).toEqual(PROXY_ID)
|
130
|
+
expect(sentHeaders[Headers.FSPIOP.DESTINATION]).toBe(EXTERNAL_DFSP_ID)
|
131
|
+
})
|
132
|
+
|
133
|
+
test('should trigger inter-scheme discovery flow, if source is NOT in scheme', async () => {
|
134
|
+
const source = 'test-zm-dfsp'
|
135
|
+
const proxyZm = 'proxy-zm'
|
136
|
+
participantMock.validateParticipant = jest.fn(
|
137
|
+
async (fsp) => ([EXTERNAL_DFSP_ID, source].includes(fsp) ? null : {})
|
138
|
+
)
|
139
|
+
deps.proxies.getAllProxiesNames = jest.fn().mockResolvedValueOnce([PROXY_ID, proxyZm])
|
140
|
+
const headers = fixtures.partiesCallHeadersDto({
|
141
|
+
source, destination: '', proxy: proxyZm
|
142
|
+
})
|
143
|
+
const params = fixtures.partiesParamsDto()
|
144
|
+
const service = new GetPartiesService(deps, { headers, params })
|
145
|
+
|
146
|
+
await service.handleRequest()
|
147
|
+
expect(participantMock.sendRequest).toHaveBeenCalledTimes(1)
|
148
|
+
const [sentHeaders, sendTo] = participantMock.sendRequest.mock.lastCall
|
149
|
+
expect(sendTo).toEqual(PROXY_ID)
|
150
|
+
expect(sentHeaders[Headers.FSPIOP.DESTINATION]).toBeUndefined()
|
151
|
+
})
|
152
|
+
})
|
153
|
+
|
154
|
+
describe('setProxyGetPartiesTimeout Tests', () => {
|
155
|
+
test('should set getParties timeout for local source and external destination', async () => {
|
156
|
+
participantMock.validateParticipant = jest.fn()
|
157
|
+
.mockResolvedValueOnce({}) // source
|
158
|
+
.mockResolvedValueOnce(null) // destination
|
159
|
+
const proxyId = 'proxy-destination'
|
160
|
+
const proxyCache = createProxyCacheMock({
|
161
|
+
lookupProxyByDfspId: jest.fn().mockResolvedValueOnce(proxyId)
|
162
|
+
})
|
163
|
+
const deps = createMockDeps({ proxyCache })
|
164
|
+
const headers = fixtures.partiesCallHeadersDto()
|
165
|
+
const params = fixtures.partiesParamsDto()
|
166
|
+
const service = new GetPartiesService(deps, { headers, params })
|
167
|
+
|
168
|
+
await service.handleRequest()
|
169
|
+
expect(proxyCache.setProxyGetPartiesTimeout).toHaveBeenCalledTimes(1)
|
170
|
+
expect(proxyCache.setProxyGetPartiesTimeout.mock.lastCall[1]).toBe(proxyId)
|
171
|
+
expect(participantMock.sendRequest).toHaveBeenCalledTimes(1)
|
172
|
+
})
|
173
|
+
|
174
|
+
test('should NOT set getParties timeout if source is external', async () => {
|
175
|
+
participantMock.validateParticipant = jest.fn()
|
176
|
+
.mockResolvedValueOnce(null) // source
|
177
|
+
.mockResolvedValueOnce({}) // proxy-src
|
178
|
+
const proxyCache = createProxyCacheMock({
|
179
|
+
lookupProxyByDfspId: jest.fn().mockResolvedValue('proxy-desc')
|
180
|
+
})
|
181
|
+
const deps = createMockDeps({ proxyCache })
|
182
|
+
const headers = fixtures.partiesCallHeadersDto({ proxy: 'proxy-src' })
|
183
|
+
const params = fixtures.partiesParamsDto()
|
184
|
+
const service = new GetPartiesService(deps, { headers, params })
|
185
|
+
|
186
|
+
await service.handleRequest()
|
187
|
+
expect(proxyCache.setProxyGetPartiesTimeout).not.toHaveBeenCalled()
|
188
|
+
expect(participantMock.sendRequest).toHaveBeenCalledTimes(1)
|
189
|
+
})
|
190
|
+
|
191
|
+
test('should NOT set getParties timeout if destination is local', async () => {
|
192
|
+
participantMock.validateParticipant = jest.fn().mockResolvedValue({})
|
193
|
+
const proxyCache = createProxyCacheMock()
|
194
|
+
const deps = createMockDeps({ proxyCache })
|
195
|
+
const headers = fixtures.partiesCallHeadersDto()
|
196
|
+
const params = fixtures.partiesParamsDto()
|
197
|
+
const service = new GetPartiesService(deps, { headers, params })
|
198
|
+
|
199
|
+
await service.handleRequest()
|
200
|
+
expect(proxyCache.setProxyGetPartiesTimeout).not.toHaveBeenCalled()
|
201
|
+
expect(participantMock.sendRequest).toHaveBeenCalledTimes(1)
|
202
|
+
})
|
203
|
+
|
204
|
+
test('should set getParties timeout if oracle returns external participant', async () => {
|
205
|
+
participantMock.validateParticipant = jest.fn()
|
206
|
+
.mockResolvedValueOnce({}) // source
|
207
|
+
.mockResolvedValueOnce(null) // externalDfsp
|
208
|
+
oracleMock.oracleRequest = jest.fn(async () => fixtures.oracleRequestResponseDto({
|
209
|
+
partyList: [{ fspId: 'externalDfsp' }]
|
210
|
+
}))
|
211
|
+
const proxyCache = createProxyCacheMock({
|
212
|
+
lookupProxyByDfspId: jest.fn().mockResolvedValue('proxyExternal')
|
213
|
+
})
|
214
|
+
const deps = createMockDeps({ proxyCache })
|
215
|
+
const headers = fixtures.partiesCallHeadersDto({ destination: '' })
|
216
|
+
const params = fixtures.partiesParamsDto()
|
217
|
+
const service = new GetPartiesService(deps, { headers, params })
|
218
|
+
|
219
|
+
await service.handleRequest()
|
220
|
+
expect(proxyCache.setProxyGetPartiesTimeout).toHaveBeenCalledTimes(1)
|
221
|
+
expect(participantMock.sendRequest).toHaveBeenCalledTimes(1)
|
222
|
+
})
|
223
|
+
})
|
224
|
+
})
|
@@ -0,0 +1,50 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
+
|
11
|
+
Contributors
|
12
|
+
--------------
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
15
|
+
should be listed with a '*' in the first column. People who have
|
16
|
+
contributed from an organization can be listed under the organization
|
17
|
+
that actually holds the copyright for their contributions (see the
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
20
|
+
optionally within square brackets <email>.
|
21
|
+
|
22
|
+
* Mojaloop Foundation
|
23
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
+
|
25
|
+
--------------
|
26
|
+
******/
|
27
|
+
|
28
|
+
const { createMockDeps, oracleMock } = require('./deps')
|
29
|
+
// ↑ should be first require to mock external deps ↑
|
30
|
+
const { PutPartiesErrorService } = require('#src/domain/parties/services/index')
|
31
|
+
const fixtures = require('#test/fixtures/index')
|
32
|
+
|
33
|
+
const { RestMethods } = PutPartiesErrorService.enums()
|
34
|
+
|
35
|
+
describe('PutPartiesErrorService Tests -->', () => {
|
36
|
+
beforeEach(() => {
|
37
|
+
jest.clearAllMocks()
|
38
|
+
})
|
39
|
+
|
40
|
+
test('should cleanup oracle and trigger discovery flow for party from external dfsp', async () => {
|
41
|
+
const headers = fixtures.partiesCallHeadersDto({ proxy: 'proxyA' })
|
42
|
+
const params = fixtures.partiesParamsDto()
|
43
|
+
const service = new PutPartiesErrorService(createMockDeps(), { headers, params })
|
44
|
+
|
45
|
+
const needDiscovery = await service.handleRequest()
|
46
|
+
expect(needDiscovery).toBe(true)
|
47
|
+
expect(oracleMock.oracleRequest.mock.calls.length).toBe(1)
|
48
|
+
expect(oracleMock.oracleRequest.mock.lastCall[1]).toBe(RestMethods.DELETE)
|
49
|
+
})
|
50
|
+
})
|
@@ -0,0 +1,72 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
+
|
11
|
+
Contributors
|
12
|
+
--------------
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
15
|
+
should be listed with a '*' in the first column. People who have
|
16
|
+
contributed from an organization can be listed under the organization
|
17
|
+
that actually holds the copyright for their contributions (see the
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
20
|
+
optionally within square brackets <email>.
|
21
|
+
|
22
|
+
* Mojaloop Foundation
|
23
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
+
|
25
|
+
--------------
|
26
|
+
******/
|
27
|
+
|
28
|
+
const { createMockDeps, createProxyCacheMock, participantMock } = require('./deps')
|
29
|
+
// ↑ should be first require to mock external deps ↑
|
30
|
+
const { TimeoutPartiesService } = require('#src/domain/parties/services/index')
|
31
|
+
const { API_TYPES } = require('#src/constants')
|
32
|
+
const fixtures = require('#test/fixtures/index')
|
33
|
+
|
34
|
+
describe('TimeoutPartiesService Tests -->', () => {
|
35
|
+
const { config } = createMockDeps()
|
36
|
+
|
37
|
+
beforeEach(() => {
|
38
|
+
jest.clearAllMocks()
|
39
|
+
})
|
40
|
+
|
41
|
+
test('should send error callback to external participant through proxy', async () => {
|
42
|
+
participantMock.validateParticipant = jest.fn().mockResolvedValue(null)
|
43
|
+
const proxy = 'proxyAB'
|
44
|
+
const proxyCache = createProxyCacheMock({
|
45
|
+
lookupProxyByDfspId: jest.fn().mockResolvedValue(proxy)
|
46
|
+
})
|
47
|
+
const deps = createMockDeps({ proxyCache })
|
48
|
+
const cacheKey = fixtures.expiredCacheKeyDto()
|
49
|
+
const service = TimeoutPartiesService.createInstance(deps, cacheKey, 'test')
|
50
|
+
|
51
|
+
await service.handleExpiredKey()
|
52
|
+
expect(participantMock.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
53
|
+
expect(participantMock.sendErrorToParticipant.mock.lastCall[0]).toBe(proxy)
|
54
|
+
})
|
55
|
+
|
56
|
+
test('should send error callback in ISO20022 format', async () => {
|
57
|
+
participantMock.validateParticipant = jest.fn().mockResolvedValue({})
|
58
|
+
const deps = {
|
59
|
+
...createMockDeps(),
|
60
|
+
config: { ...config, API_TYPE: API_TYPES.iso20022 }
|
61
|
+
}
|
62
|
+
const sourceId = 'sourceFsp'
|
63
|
+
const cacheKey = fixtures.expiredCacheKeyDto({ sourceId })
|
64
|
+
const service = TimeoutPartiesService.createInstance(deps, cacheKey, 'test')
|
65
|
+
|
66
|
+
await service.handleExpiredKey()
|
67
|
+
expect(participantMock.sendErrorToParticipant).toHaveBeenCalledTimes(1)
|
68
|
+
const { Assgnr, Assgne } = participantMock.sendErrorToParticipant.mock.lastCall[2].Assgnmt
|
69
|
+
expect(Assgnr.Agt.FinInstnId.Othr.Id).toBe(config.HUB_NAME)
|
70
|
+
expect(Assgne.Agt.FinInstnId.Othr.Id).toBe(sourceId)
|
71
|
+
})
|
72
|
+
})
|
@@ -0,0 +1,49 @@
|
|
1
|
+
/*****
|
2
|
+
License
|
3
|
+
--------------
|
4
|
+
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
+
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
+
|
11
|
+
Contributors
|
12
|
+
--------------
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
15
|
+
should be listed with a '*' in the first column. People who have
|
16
|
+
contributed from an organization can be listed under the organization
|
17
|
+
that actually holds the copyright for their contributions (see the
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
20
|
+
optionally within square brackets <email>.
|
21
|
+
|
22
|
+
* Mojaloop Foundation
|
23
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
+
|
25
|
+
--------------
|
26
|
+
******/
|
27
|
+
|
28
|
+
jest.mock('#src/models/oracle/facade')
|
29
|
+
jest.mock('#src/models/participantEndpoint/facade')
|
30
|
+
|
31
|
+
const oracleMock = require('#src/models/oracle/facade')
|
32
|
+
const participantMock = require('#src/models/participantEndpoint/facade')
|
33
|
+
const { createDeps } = require('#src/domain/parties/deps')
|
34
|
+
const { logger } = require('#src/lib/index')
|
35
|
+
const { createProxyCacheMock } = require('#test/util/mockDeps')
|
36
|
+
|
37
|
+
/** @returns {PartiesDeps} */
|
38
|
+
const createMockDeps = ({
|
39
|
+
proxyCache = createProxyCacheMock(),
|
40
|
+
log = logger.child({ test: true }),
|
41
|
+
cache
|
42
|
+
} = {}) => createDeps({ cache, proxyCache, log })
|
43
|
+
|
44
|
+
module.exports = {
|
45
|
+
createMockDeps,
|
46
|
+
createProxyCacheMock,
|
47
|
+
oracleMock,
|
48
|
+
participantMock
|
49
|
+
}
|