cozy-harvest-lib 7.2.4 → 7.3.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.
- package/CHANGELOG.md +16 -0
- package/dist/helpers/konnectors.js +2 -1
- package/dist/locales/en.json +4 -0
- package/dist/locales/fr.json +4 -0
- package/dist/services/budget-insight.js +99 -10
- package/dist/services/budget-insight.spec.js +317 -102
- package/package.json +18 -18
- package/src/helpers/konnectors.js +4 -1
- package/src/locales/en.json +4 -0
- package/src/locales/fr.json +4 -0
- package/src/services/budget-insight.js +62 -3
- package/src/services/budget-insight.spec.js +122 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [7.3.0](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@7.2.4...cozy-harvest-lib@7.3.0) (2022-02-18)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **deps:** pin dependencies ([e53d065](https://github.com/cozy/cozy-libs/commit/e53d065090224ea340b2c25c3afd14f223f4d119))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* Do not allow multiple accounts with same BI connection ID ([55b5f23](https://github.com/cozy/cozy-libs/commit/55b5f23f0adbc308c3b70fa287c3938ee1b0a4cc))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [7.2.4](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@7.2.3...cozy-harvest-lib@7.2.4) (2022-02-15)
|
|
7
23
|
|
|
8
24
|
|
|
@@ -36,7 +36,8 @@ var TERMS_VERSION_MISMATCH = 'TERMS_VERSION_MISMATCH';
|
|
|
36
36
|
var UNKNOWN_ERROR = 'UNKNOWN_ERROR';
|
|
37
37
|
var USER_ACTION_NEEDED = 'USER_ACTION_NEEDED';
|
|
38
38
|
var VENDOR_DOWN = 'VENDOR_DOWN';
|
|
39
|
-
var
|
|
39
|
+
var ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED = 'ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED';
|
|
40
|
+
var KNOWN_ERRORS = [CHALLENGE_ASKED, DISK_QUOTA_EXCEEDED, LOGIN_FAILED, MAINTENANCE, NOT_EXISTING_DIRECTORY, TERMS_VERSION_MISMATCH, USER_ACTION_NEEDED, VENDOR_DOWN, ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED];
|
|
40
41
|
var USER_ERRORS = [CHALLENGE_ASKED, DISK_QUOTA_EXCEEDED, LOGIN_FAILED, NOT_EXISTING_DIRECTORY, USER_ACTION_NEEDED];
|
|
41
42
|
var sanitizeAccountIdentifierRx = /\//g;
|
|
42
43
|
/**
|
package/dist/locales/en.json
CHANGED
|
@@ -204,6 +204,10 @@
|
|
|
204
204
|
"VENDOR_DOWN.LINXO_DOWN": {
|
|
205
205
|
"title": "Unavailable service",
|
|
206
206
|
"description": "It seems that we are experiencing overload with our bank konnectors at the moment. Please rerun the connector later."
|
|
207
|
+
},
|
|
208
|
+
"ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED": {
|
|
209
|
+
"title": "This account already exists",
|
|
210
|
+
"description": "You already have configured an account with these identifiers."
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
},
|
package/dist/locales/fr.json
CHANGED
|
@@ -204,6 +204,10 @@
|
|
|
204
204
|
"VENDOR_DOWN.LINXO_DOWN": {
|
|
205
205
|
"title": "Service non disponible",
|
|
206
206
|
"description": "Il semble que le service [%{name}](%{link}) ne nous ait pas répondu dans les temps. Vous pouvez tenter de le relancer manuellement maintenant ou ultérieurement."
|
|
207
|
+
},
|
|
208
|
+
"ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED": {
|
|
209
|
+
"title": "Ce compte est déjà configuré",
|
|
210
|
+
"description": "Vous avez déjà configuré un compte avec ces identifiants."
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
1
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
3
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
4
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
@@ -23,7 +24,9 @@ import get from 'lodash/get';
|
|
|
23
24
|
import omit from 'lodash/omit';
|
|
24
25
|
import clone from 'lodash/clone';
|
|
25
26
|
import set from 'lodash/set';
|
|
27
|
+
import keyBy from 'lodash/keyBy';
|
|
26
28
|
import defaults from 'lodash/defaults';
|
|
29
|
+
import { Q } from 'cozy-client';
|
|
27
30
|
import { waitForRealtimeEvent } from './jobUtils';
|
|
28
31
|
import { getBIConnection, createBIConnection, updateBIConnection, getBIUserConfig, updateBIUserConfig, setBIConnectionSyncStatus } from './bi-http';
|
|
29
32
|
import assert from '../assert';
|
|
@@ -51,7 +54,8 @@ var getBIIdFromContract = function getBIIdFromContract(bankAccount) {
|
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
var extraBIErrorMap = {
|
|
54
|
-
config: 'LOGIN_FAILED'
|
|
57
|
+
config: 'LOGIN_FAILED',
|
|
58
|
+
ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED: 'ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED'
|
|
55
59
|
};
|
|
56
60
|
/**
|
|
57
61
|
* Converts and chains error
|
|
@@ -144,7 +148,7 @@ export var getBIConfig = function getBIConfig(flow) {
|
|
|
144
148
|
|
|
145
149
|
export var createOrUpdateBIConnection = /*#__PURE__*/function () {
|
|
146
150
|
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_ref3) {
|
|
147
|
-
var account, client, konnector, flow, connId, biConfig, tempToken, config, credentials, credsToSend, biConnection, connection;
|
|
151
|
+
var account, client, konnector, flow, connId, biConfig, tempToken, config, credentials, credsToSend, biConnection, isUpdate, connection, sameAccount, err;
|
|
148
152
|
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
149
153
|
while (1) {
|
|
150
154
|
switch (_context2.prev = _context2.next) {
|
|
@@ -212,25 +216,52 @@ export var createOrUpdateBIConnection = /*#__PURE__*/function () {
|
|
|
212
216
|
|
|
213
217
|
case 31:
|
|
214
218
|
logger.info('Creating or updating connection...');
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
isUpdate = Boolean(connId);
|
|
220
|
+
_context2.next = 35;
|
|
221
|
+
return isUpdate ? updateBIConnection(config, connId, credsToSend, tempToken) : createBIConnection(config, credsToSend, tempToken);
|
|
217
222
|
|
|
218
|
-
case
|
|
223
|
+
case 35:
|
|
219
224
|
connection = _context2.sent;
|
|
225
|
+
|
|
226
|
+
if (isUpdate) {
|
|
227
|
+
_context2.next = 44;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
_context2.next = 39;
|
|
232
|
+
return findAccountWithBiConnection({
|
|
233
|
+
client: client,
|
|
234
|
+
konnector: konnector,
|
|
235
|
+
connectionId: connection.id
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
case 39:
|
|
239
|
+
sameAccount = _context2.sent;
|
|
240
|
+
|
|
241
|
+
if (!sameAccount) {
|
|
242
|
+
_context2.next = 44;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
err = new KonnectorJobError('ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED');
|
|
247
|
+
err.accountId = sameAccount._id;
|
|
248
|
+
throw err;
|
|
249
|
+
|
|
250
|
+
case 44:
|
|
220
251
|
logger.info("Created or updated connection ".concat(connection.id));
|
|
221
252
|
return _context2.abrupt("return", connection);
|
|
222
253
|
|
|
223
|
-
case
|
|
224
|
-
_context2.prev =
|
|
254
|
+
case 48:
|
|
255
|
+
_context2.prev = 48;
|
|
225
256
|
_context2.t1 = _context2["catch"](15);
|
|
226
257
|
return _context2.abrupt("return", convertBIErrortoKonnectorJobError(_context2.t1));
|
|
227
258
|
|
|
228
|
-
case
|
|
259
|
+
case 51:
|
|
229
260
|
case "end":
|
|
230
261
|
return _context2.stop();
|
|
231
262
|
}
|
|
232
263
|
}
|
|
233
|
-
}, _callee2, null, [[15,
|
|
264
|
+
}, _callee2, null, [[15, 48], [17, 27]]);
|
|
234
265
|
}));
|
|
235
266
|
|
|
236
267
|
return function createOrUpdateBIConnection(_x2) {
|
|
@@ -761,7 +792,64 @@ export var fetchExtraOAuthUrlParams = /*#__PURE__*/function () {
|
|
|
761
792
|
var shouldResumeConnection = function shouldResumeConnection(error) {
|
|
762
793
|
return error === DECOUPLED_ERROR || error === ADDITIONAL_INFORMATION_NEEDED_ERROR;
|
|
763
794
|
};
|
|
795
|
+
/**
|
|
796
|
+
* Tries to find an existing account, associated to an existing trigger
|
|
797
|
+
* with the given bi connection id
|
|
798
|
+
*
|
|
799
|
+
* @param {CozyClient} options.client - Cozy client
|
|
800
|
+
* @param {Object} options.konnector - Konnector manifest
|
|
801
|
+
* @param {Integer} options.connectionId - BI connection id
|
|
802
|
+
* @return {Account|null} An account with a trigger with the same identifier if any
|
|
803
|
+
*/
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
export var findAccountWithBiConnection = /*#__PURE__*/function () {
|
|
807
|
+
var _ref22 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11(_ref21) {
|
|
808
|
+
var client, konnector, connectionId, _yield$Promise$all, _yield$Promise$all2, accountsResult, triggersResult, accountsIndex, trigger;
|
|
809
|
+
|
|
810
|
+
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
|
|
811
|
+
while (1) {
|
|
812
|
+
switch (_context11.prev = _context11.next) {
|
|
813
|
+
case 0:
|
|
814
|
+
client = _ref21.client, konnector = _ref21.konnector, connectionId = _ref21.connectionId;
|
|
815
|
+
_context11.next = 3;
|
|
816
|
+
return Promise.all([client.query(Q('io.cozy.accounts').where({
|
|
817
|
+
data: {
|
|
818
|
+
auth: {
|
|
819
|
+
bi: {
|
|
820
|
+
connId: connectionId
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}).indexFields(['data.auth.bi.connId'])), client.query(Q('io.cozy.triggers').where({
|
|
825
|
+
message: {
|
|
826
|
+
konnector: konnector.slug
|
|
827
|
+
}
|
|
828
|
+
}).indexFields(['message.konnector']))]);
|
|
829
|
+
|
|
830
|
+
case 3:
|
|
831
|
+
_yield$Promise$all = _context11.sent;
|
|
832
|
+
_yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
|
|
833
|
+
accountsResult = _yield$Promise$all2[0];
|
|
834
|
+
triggersResult = _yield$Promise$all2[1];
|
|
835
|
+
accountsIndex = keyBy(accountsResult.data, '_id');
|
|
836
|
+
trigger = triggersResult.data.find(function (t) {
|
|
837
|
+
return accountsIndex[get(t, 'message.account')];
|
|
838
|
+
});
|
|
839
|
+
return _context11.abrupt("return", trigger ? accountsIndex[trigger.message.account] : null);
|
|
764
840
|
|
|
841
|
+
case 10:
|
|
842
|
+
case "end":
|
|
843
|
+
return _context11.stop();
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}, _callee11);
|
|
847
|
+
}));
|
|
848
|
+
|
|
849
|
+
return function findAccountWithBiConnection(_x12) {
|
|
850
|
+
return _ref22.apply(this, arguments);
|
|
851
|
+
};
|
|
852
|
+
}();
|
|
765
853
|
export var konnectorPolicy = {
|
|
766
854
|
name: 'budget-insight',
|
|
767
855
|
match: isBudgetInsightConnector,
|
|
@@ -772,5 +860,6 @@ export var konnectorPolicy = {
|
|
|
772
860
|
fetchExtraOAuthUrlParams: fetchExtraOAuthUrlParams,
|
|
773
861
|
getAdditionalInformationNeeded: getAdditionalInformationNeeded,
|
|
774
862
|
handleOAuthAccount: handleOAuthAccount,
|
|
775
|
-
setSync: setSync
|
|
863
|
+
setSync: setSync,
|
|
864
|
+
findAccountWithBiConnection: findAccountWithBiConnection
|
|
776
865
|
};
|
|
@@ -449,6 +449,22 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
449
449
|
}
|
|
450
450
|
}, _callee10);
|
|
451
451
|
})));
|
|
452
|
+
jest.spyOn(client, 'query').mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
|
|
453
|
+
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
|
|
454
|
+
while (1) {
|
|
455
|
+
switch (_context11.prev = _context11.next) {
|
|
456
|
+
case 0:
|
|
457
|
+
return _context11.abrupt("return", {
|
|
458
|
+
data: []
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
case 1:
|
|
462
|
+
case "end":
|
|
463
|
+
return _context11.stop();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}, _callee11);
|
|
467
|
+
})));
|
|
452
468
|
createBIConnection.mockReset().mockResolvedValue({
|
|
453
469
|
id: 'created-bi-connection-id-789'
|
|
454
470
|
});
|
|
@@ -461,15 +477,15 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
461
477
|
};
|
|
462
478
|
};
|
|
463
479
|
|
|
464
|
-
it('should accept a connector without parameter and find bank id in the account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
480
|
+
it('should accept a connector without parameter and find bank id in the account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12() {
|
|
465
481
|
var _setup7, client, flow, connection;
|
|
466
482
|
|
|
467
|
-
return _regeneratorRuntime.wrap(function
|
|
483
|
+
return _regeneratorRuntime.wrap(function _callee12$(_context12) {
|
|
468
484
|
while (1) {
|
|
469
|
-
switch (
|
|
485
|
+
switch (_context12.prev = _context12.next) {
|
|
470
486
|
case 0:
|
|
471
487
|
_setup7 = setup(), client = _setup7.client, flow = _setup7.flow;
|
|
472
|
-
|
|
488
|
+
_context12.next = 3;
|
|
473
489
|
return createOrUpdateBIConnection({
|
|
474
490
|
client: client,
|
|
475
491
|
account: account,
|
|
@@ -478,7 +494,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
478
494
|
});
|
|
479
495
|
|
|
480
496
|
case 3:
|
|
481
|
-
connection =
|
|
497
|
+
connection = _context12.sent;
|
|
482
498
|
expect(waitForRealtimeEvent).toHaveBeenCalledWith(client, {
|
|
483
499
|
_id: 'job-id-1337'
|
|
484
500
|
}, 'result', 60000);
|
|
@@ -494,20 +510,20 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
494
510
|
|
|
495
511
|
case 8:
|
|
496
512
|
case "end":
|
|
497
|
-
return
|
|
513
|
+
return _context12.stop();
|
|
498
514
|
}
|
|
499
515
|
}
|
|
500
|
-
},
|
|
516
|
+
}, _callee12);
|
|
501
517
|
})));
|
|
502
|
-
it('should create a BI connection if no connection id in account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
518
|
+
it('should create a BI connection if no connection id in account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee13() {
|
|
503
519
|
var _setup8, client, flow, connection;
|
|
504
520
|
|
|
505
|
-
return _regeneratorRuntime.wrap(function
|
|
521
|
+
return _regeneratorRuntime.wrap(function _callee13$(_context13) {
|
|
506
522
|
while (1) {
|
|
507
|
-
switch (
|
|
523
|
+
switch (_context13.prev = _context13.next) {
|
|
508
524
|
case 0:
|
|
509
525
|
_setup8 = setup(), client = _setup8.client, flow = _setup8.flow;
|
|
510
|
-
|
|
526
|
+
_context13.next = 3;
|
|
511
527
|
return createOrUpdateBIConnection({
|
|
512
528
|
client: client,
|
|
513
529
|
account: account,
|
|
@@ -516,7 +532,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
516
532
|
});
|
|
517
533
|
|
|
518
534
|
case 3:
|
|
519
|
-
connection =
|
|
535
|
+
connection = _context13.sent;
|
|
520
536
|
expect(waitForRealtimeEvent).toHaveBeenCalledWith(client, {
|
|
521
537
|
_id: 'job-id-1337'
|
|
522
538
|
}, 'result', 60000);
|
|
@@ -532,17 +548,17 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
532
548
|
|
|
533
549
|
case 8:
|
|
534
550
|
case "end":
|
|
535
|
-
return
|
|
551
|
+
return _context13.stop();
|
|
536
552
|
}
|
|
537
553
|
}
|
|
538
|
-
},
|
|
554
|
+
}, _callee13);
|
|
539
555
|
})));
|
|
540
|
-
it('should update the BI connection if connection id in account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
556
|
+
it('should update the BI connection if connection id in account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
|
|
541
557
|
var _setup9, client, flow, connection;
|
|
542
558
|
|
|
543
|
-
return _regeneratorRuntime.wrap(function
|
|
559
|
+
return _regeneratorRuntime.wrap(function _callee14$(_context14) {
|
|
544
560
|
while (1) {
|
|
545
|
-
switch (
|
|
561
|
+
switch (_context14.prev = _context14.next) {
|
|
546
562
|
case 0:
|
|
547
563
|
_setup9 = setup(), client = _setup9.client, flow = _setup9.flow;
|
|
548
564
|
getBIConnection.mockReset().mockResolvedValue({
|
|
@@ -551,7 +567,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
551
567
|
updateBIConnection.mockReset().mockResolvedValue({
|
|
552
568
|
id: 'updated-bi-connection-id-789'
|
|
553
569
|
});
|
|
554
|
-
|
|
570
|
+
_context14.next = 5;
|
|
555
571
|
return createOrUpdateBIConnection({
|
|
556
572
|
client: client,
|
|
557
573
|
flow: flow,
|
|
@@ -568,7 +584,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
568
584
|
});
|
|
569
585
|
|
|
570
586
|
case 5:
|
|
571
|
-
connection =
|
|
587
|
+
connection = _context14.sent;
|
|
572
588
|
expect(waitForRealtimeEvent).toHaveBeenCalledWith(client, {
|
|
573
589
|
_id: 'job-id-1337'
|
|
574
590
|
}, 'result', 60000);
|
|
@@ -590,21 +606,21 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
590
606
|
|
|
591
607
|
case 11:
|
|
592
608
|
case "end":
|
|
593
|
-
return
|
|
609
|
+
return _context14.stop();
|
|
594
610
|
}
|
|
595
611
|
}
|
|
596
|
-
},
|
|
612
|
+
}, _callee14);
|
|
597
613
|
})));
|
|
598
|
-
it('should create the BI connection if connection id in the account does not exist', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
614
|
+
it('should create the BI connection if connection id in the account does not exist', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee15() {
|
|
599
615
|
var _setup10, client, flow, connection;
|
|
600
616
|
|
|
601
|
-
return _regeneratorRuntime.wrap(function
|
|
617
|
+
return _regeneratorRuntime.wrap(function _callee15$(_context15) {
|
|
602
618
|
while (1) {
|
|
603
|
-
switch (
|
|
619
|
+
switch (_context15.prev = _context15.next) {
|
|
604
620
|
case 0:
|
|
605
621
|
_setup10 = setup(), client = _setup10.client, flow = _setup10.flow;
|
|
606
622
|
getBIConnection.mockRejectedValueOnce();
|
|
607
|
-
|
|
623
|
+
_context15.next = 4;
|
|
608
624
|
return createOrUpdateBIConnection({
|
|
609
625
|
client: client,
|
|
610
626
|
flow: flow,
|
|
@@ -621,7 +637,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
621
637
|
});
|
|
622
638
|
|
|
623
639
|
case 4:
|
|
624
|
-
connection =
|
|
640
|
+
connection = _context15.sent;
|
|
625
641
|
expect(waitForRealtimeEvent).toHaveBeenCalledWith(client, {
|
|
626
642
|
_id: 'job-id-1337'
|
|
627
643
|
}, 'result', 60000);
|
|
@@ -643,24 +659,24 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
643
659
|
|
|
644
660
|
case 10:
|
|
645
661
|
case "end":
|
|
646
|
-
return
|
|
662
|
+
return _context15.stop();
|
|
647
663
|
}
|
|
648
664
|
}
|
|
649
|
-
},
|
|
665
|
+
}, _callee15);
|
|
650
666
|
})));
|
|
651
|
-
it('should convert wrongpass correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
667
|
+
it('should convert wrongpass correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee16() {
|
|
652
668
|
var _setup11, client, flow, err;
|
|
653
669
|
|
|
654
|
-
return _regeneratorRuntime.wrap(function
|
|
670
|
+
return _regeneratorRuntime.wrap(function _callee16$(_context16) {
|
|
655
671
|
while (1) {
|
|
656
|
-
switch (
|
|
672
|
+
switch (_context16.prev = _context16.next) {
|
|
657
673
|
case 0:
|
|
658
674
|
_setup11 = setup(), client = _setup11.client, flow = _setup11.flow;
|
|
659
675
|
err = new Error();
|
|
660
676
|
err.code = 'wrongpass';
|
|
661
677
|
getBIConnection.mockReset().mockResolvedValueOnce({});
|
|
662
678
|
updateBIConnection.mockReset().mockRejectedValue(err);
|
|
663
|
-
|
|
679
|
+
_context16.next = 7;
|
|
664
680
|
return expect(createOrUpdateBIConnection({
|
|
665
681
|
client: client,
|
|
666
682
|
flow: flow,
|
|
@@ -678,24 +694,24 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
678
694
|
|
|
679
695
|
case 7:
|
|
680
696
|
case "end":
|
|
681
|
-
return
|
|
697
|
+
return _context16.stop();
|
|
682
698
|
}
|
|
683
699
|
}
|
|
684
|
-
},
|
|
700
|
+
}, _callee16);
|
|
685
701
|
})));
|
|
686
|
-
it('should convert config correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
702
|
+
it('should convert config correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee17() {
|
|
687
703
|
var _setup12, client, flow, err;
|
|
688
704
|
|
|
689
|
-
return _regeneratorRuntime.wrap(function
|
|
705
|
+
return _regeneratorRuntime.wrap(function _callee17$(_context17) {
|
|
690
706
|
while (1) {
|
|
691
|
-
switch (
|
|
707
|
+
switch (_context17.prev = _context17.next) {
|
|
692
708
|
case 0:
|
|
693
709
|
_setup12 = setup(), client = _setup12.client, flow = _setup12.flow;
|
|
694
710
|
err = new Error();
|
|
695
711
|
err.code = 'config';
|
|
696
712
|
getBIConnection.mockReset().mockResolvedValueOnce({});
|
|
697
713
|
updateBIConnection.mockReset().mockRejectedValue(err);
|
|
698
|
-
|
|
714
|
+
_context17.next = 7;
|
|
699
715
|
return expect(createOrUpdateBIConnection({
|
|
700
716
|
client: client,
|
|
701
717
|
flow: flow,
|
|
@@ -713,24 +729,24 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
713
729
|
|
|
714
730
|
case 7:
|
|
715
731
|
case "end":
|
|
716
|
-
return
|
|
732
|
+
return _context17.stop();
|
|
717
733
|
}
|
|
718
734
|
}
|
|
719
|
-
},
|
|
735
|
+
}, _callee17);
|
|
720
736
|
})));
|
|
721
|
-
it('should convert SCARequired correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
737
|
+
it('should convert SCARequired correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee18() {
|
|
722
738
|
var _setup13, client, flow, err;
|
|
723
739
|
|
|
724
|
-
return _regeneratorRuntime.wrap(function
|
|
740
|
+
return _regeneratorRuntime.wrap(function _callee18$(_context18) {
|
|
725
741
|
while (1) {
|
|
726
|
-
switch (
|
|
742
|
+
switch (_context18.prev = _context18.next) {
|
|
727
743
|
case 0:
|
|
728
744
|
_setup13 = setup(), client = _setup13.client, flow = _setup13.flow;
|
|
729
745
|
err = new Error();
|
|
730
746
|
err.code = 'SCARequired';
|
|
731
747
|
getBIConnection.mockReset().mockResolvedValueOnce({});
|
|
732
748
|
updateBIConnection.mockReset().mockRejectedValue(err);
|
|
733
|
-
|
|
749
|
+
_context18.next = 7;
|
|
734
750
|
return expect(createOrUpdateBIConnection({
|
|
735
751
|
client: client,
|
|
736
752
|
flow: flow,
|
|
@@ -748,17 +764,17 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
748
764
|
|
|
749
765
|
case 7:
|
|
750
766
|
case "end":
|
|
751
|
-
return
|
|
767
|
+
return _context18.stop();
|
|
752
768
|
}
|
|
753
769
|
}
|
|
754
|
-
},
|
|
770
|
+
}, _callee18);
|
|
755
771
|
})));
|
|
756
|
-
it('should remove sensible data from account and create bi connection', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
772
|
+
it('should remove sensible data from account and create bi connection', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee19() {
|
|
757
773
|
var _setup14, client, flow, account, konnector, createOrUpdateBIConnection, accountToSave;
|
|
758
774
|
|
|
759
|
-
return _regeneratorRuntime.wrap(function
|
|
775
|
+
return _regeneratorRuntime.wrap(function _callee19$(_context19) {
|
|
760
776
|
while (1) {
|
|
761
|
-
switch (
|
|
777
|
+
switch (_context19.prev = _context19.next) {
|
|
762
778
|
case 0:
|
|
763
779
|
_setup14 = setup(), client = _setup14.client, flow = _setup14.flow;
|
|
764
780
|
account = {
|
|
@@ -780,7 +796,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
780
796
|
createOrUpdateBIConnection = jest.fn().mockResolvedValue({
|
|
781
797
|
id: 'created-bi-connection-id'
|
|
782
798
|
});
|
|
783
|
-
|
|
799
|
+
_context19.next = 7;
|
|
784
800
|
return onBIAccountCreation({
|
|
785
801
|
client: client,
|
|
786
802
|
flow: flow,
|
|
@@ -790,7 +806,7 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
790
806
|
});
|
|
791
807
|
|
|
792
808
|
case 7:
|
|
793
|
-
accountToSave =
|
|
809
|
+
accountToSave = _context19.sent;
|
|
794
810
|
expect(createOrUpdateBIConnection).toHaveBeenCalledWith(expect.objectContaining({
|
|
795
811
|
account: {
|
|
796
812
|
_id: 'created-account-id',
|
|
@@ -825,10 +841,209 @@ describe('createOrUpdateBIConnection', function () {
|
|
|
825
841
|
|
|
826
842
|
case 11:
|
|
827
843
|
case "end":
|
|
828
|
-
return
|
|
844
|
+
return _context19.stop();
|
|
829
845
|
}
|
|
830
846
|
}
|
|
831
|
-
},
|
|
847
|
+
}, _callee19);
|
|
848
|
+
})));
|
|
849
|
+
it('should refuse to create an account with a bi connection id which already exists', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
|
|
850
|
+
var _setup15, client, flow, account, konnector;
|
|
851
|
+
|
|
852
|
+
return _regeneratorRuntime.wrap(function _callee21$(_context21) {
|
|
853
|
+
while (1) {
|
|
854
|
+
switch (_context21.prev = _context21.next) {
|
|
855
|
+
case 0:
|
|
856
|
+
_setup15 = setup(), client = _setup15.client, flow = _setup15.flow;
|
|
857
|
+
account = {
|
|
858
|
+
auth: {
|
|
859
|
+
login: '1234',
|
|
860
|
+
password: '4567',
|
|
861
|
+
dob: '20/12/1890',
|
|
862
|
+
bankId: '100000'
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
konnector = {
|
|
866
|
+
slug: 'bankingconnectortest'
|
|
867
|
+
};
|
|
868
|
+
jest.spyOn(flow, 'saveAccount').mockImplementation(function (account) {
|
|
869
|
+
return _objectSpread({
|
|
870
|
+
_id: 'created-account-id'
|
|
871
|
+
}, account);
|
|
872
|
+
});
|
|
873
|
+
jest.spyOn(client, 'query').mockImplementation( /*#__PURE__*/function () {
|
|
874
|
+
var _ref22 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee20(_ref21) {
|
|
875
|
+
var doctype;
|
|
876
|
+
return _regeneratorRuntime.wrap(function _callee20$(_context20) {
|
|
877
|
+
while (1) {
|
|
878
|
+
switch (_context20.prev = _context20.next) {
|
|
879
|
+
case 0:
|
|
880
|
+
doctype = _ref21.doctype;
|
|
881
|
+
|
|
882
|
+
if (!(doctype === 'io.cozy.accounts')) {
|
|
883
|
+
_context20.next = 5;
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
return _context20.abrupt("return", {
|
|
888
|
+
data: [{
|
|
889
|
+
_id: 'account_id',
|
|
890
|
+
auth: {
|
|
891
|
+
bi: {
|
|
892
|
+
connId: 12
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}]
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
case 5:
|
|
899
|
+
if (!(doctype === 'io.cozy.triggers')) {
|
|
900
|
+
_context20.next = 9;
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
return _context20.abrupt("return", {
|
|
905
|
+
data: [{
|
|
906
|
+
message: {
|
|
907
|
+
account: 'account_id'
|
|
908
|
+
}
|
|
909
|
+
}]
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
case 9:
|
|
913
|
+
throw new Error('unexpected doctype ' + doctype);
|
|
914
|
+
|
|
915
|
+
case 10:
|
|
916
|
+
case "end":
|
|
917
|
+
return _context20.stop();
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}, _callee20);
|
|
921
|
+
}));
|
|
922
|
+
|
|
923
|
+
return function (_x2) {
|
|
924
|
+
return _ref22.apply(this, arguments);
|
|
925
|
+
};
|
|
926
|
+
}());
|
|
927
|
+
_context21.next = 7;
|
|
928
|
+
return expect(onBIAccountCreation({
|
|
929
|
+
client: client,
|
|
930
|
+
flow: flow,
|
|
931
|
+
account: account,
|
|
932
|
+
konnector: konnector
|
|
933
|
+
})).rejects.toEqual(new Error('ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED'));
|
|
934
|
+
|
|
935
|
+
case 7:
|
|
936
|
+
case "end":
|
|
937
|
+
return _context21.stop();
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}, _callee21);
|
|
941
|
+
})));
|
|
942
|
+
it('should create an account if bi connection is not already used', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee23() {
|
|
943
|
+
var _setup16, client, flow, account, konnector;
|
|
944
|
+
|
|
945
|
+
return _regeneratorRuntime.wrap(function _callee23$(_context23) {
|
|
946
|
+
while (1) {
|
|
947
|
+
switch (_context23.prev = _context23.next) {
|
|
948
|
+
case 0:
|
|
949
|
+
_setup16 = setup(), client = _setup16.client, flow = _setup16.flow;
|
|
950
|
+
account = {
|
|
951
|
+
auth: {
|
|
952
|
+
login: '1234',
|
|
953
|
+
password: '4567',
|
|
954
|
+
dob: '20/12/1890',
|
|
955
|
+
bankId: '100000'
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
konnector = {
|
|
959
|
+
slug: 'bankingconnectortest'
|
|
960
|
+
};
|
|
961
|
+
jest.spyOn(flow, 'saveAccount').mockImplementation(function (account) {
|
|
962
|
+
return _objectSpread({
|
|
963
|
+
_id: 'created-account-id'
|
|
964
|
+
}, account);
|
|
965
|
+
});
|
|
966
|
+
jest.spyOn(client, 'query').mockImplementation( /*#__PURE__*/function () {
|
|
967
|
+
var _ref25 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee22(_ref24) {
|
|
968
|
+
var doctype;
|
|
969
|
+
return _regeneratorRuntime.wrap(function _callee22$(_context22) {
|
|
970
|
+
while (1) {
|
|
971
|
+
switch (_context22.prev = _context22.next) {
|
|
972
|
+
case 0:
|
|
973
|
+
doctype = _ref24.doctype;
|
|
974
|
+
|
|
975
|
+
if (!(doctype === 'io.cozy.accounts')) {
|
|
976
|
+
_context22.next = 5;
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
return _context22.abrupt("return", {
|
|
981
|
+
data: [{
|
|
982
|
+
_id: 'account_id',
|
|
983
|
+
auth: {
|
|
984
|
+
bi: {
|
|
985
|
+
connId: 12
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}]
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
case 5:
|
|
992
|
+
if (!(doctype === 'io.cozy.triggers')) {
|
|
993
|
+
_context22.next = 9;
|
|
994
|
+
break;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
return _context22.abrupt("return", {
|
|
998
|
+
data: [{
|
|
999
|
+
message: {
|
|
1000
|
+
account: 'other_account_id'
|
|
1001
|
+
}
|
|
1002
|
+
}]
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
case 9:
|
|
1006
|
+
throw new Error('unexpected doctype ' + doctype);
|
|
1007
|
+
|
|
1008
|
+
case 10:
|
|
1009
|
+
case "end":
|
|
1010
|
+
return _context22.stop();
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}, _callee22);
|
|
1014
|
+
}));
|
|
1015
|
+
|
|
1016
|
+
return function (_x3) {
|
|
1017
|
+
return _ref25.apply(this, arguments);
|
|
1018
|
+
};
|
|
1019
|
+
}());
|
|
1020
|
+
_context23.next = 7;
|
|
1021
|
+
return expect(onBIAccountCreation({
|
|
1022
|
+
client: client,
|
|
1023
|
+
flow: flow,
|
|
1024
|
+
account: account,
|
|
1025
|
+
konnector: konnector
|
|
1026
|
+
})).resolves.toEqual({
|
|
1027
|
+
_id: 'created-account-id',
|
|
1028
|
+
auth: {
|
|
1029
|
+
bankId: '100000',
|
|
1030
|
+
login: '1234'
|
|
1031
|
+
},
|
|
1032
|
+
data: {
|
|
1033
|
+
auth: {
|
|
1034
|
+
bi: {
|
|
1035
|
+
connId: 'created-bi-connection-id-789'
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
case 7:
|
|
1042
|
+
case "end":
|
|
1043
|
+
return _context23.stop();
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}, _callee23);
|
|
832
1047
|
})));
|
|
833
1048
|
});
|
|
834
1049
|
describe('fetchExtraOAuthUrlParams', function () {
|
|
@@ -843,13 +1058,13 @@ describe('fetchExtraOAuthUrlParams', function () {
|
|
|
843
1058
|
}
|
|
844
1059
|
}
|
|
845
1060
|
});
|
|
846
|
-
waitForRealtimeEvent.mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
847
|
-
return _regeneratorRuntime.wrap(function
|
|
1061
|
+
waitForRealtimeEvent.mockImplementation( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee24() {
|
|
1062
|
+
return _regeneratorRuntime.wrap(function _callee24$(_context24) {
|
|
848
1063
|
while (1) {
|
|
849
|
-
switch (
|
|
1064
|
+
switch (_context24.prev = _context24.next) {
|
|
850
1065
|
case 0:
|
|
851
1066
|
sleep(2);
|
|
852
|
-
return
|
|
1067
|
+
return _context24.abrupt("return", {
|
|
853
1068
|
data: {
|
|
854
1069
|
result: {
|
|
855
1070
|
code: 'bi-temporary-access-token-121212',
|
|
@@ -862,24 +1077,24 @@ describe('fetchExtraOAuthUrlParams', function () {
|
|
|
862
1077
|
|
|
863
1078
|
case 2:
|
|
864
1079
|
case "end":
|
|
865
|
-
return
|
|
1080
|
+
return _context24.stop();
|
|
866
1081
|
}
|
|
867
1082
|
}
|
|
868
|
-
},
|
|
1083
|
+
}, _callee24);
|
|
869
1084
|
})));
|
|
870
1085
|
return {
|
|
871
1086
|
client: client
|
|
872
1087
|
};
|
|
873
1088
|
};
|
|
874
1089
|
|
|
875
|
-
it('should create a temporary token', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
876
|
-
var
|
|
1090
|
+
it('should create a temporary token', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee25() {
|
|
1091
|
+
var _setup17, client, konnector, account, _yield$fetchExtraOAut, id_connector, token;
|
|
877
1092
|
|
|
878
|
-
return _regeneratorRuntime.wrap(function
|
|
1093
|
+
return _regeneratorRuntime.wrap(function _callee25$(_context25) {
|
|
879
1094
|
while (1) {
|
|
880
|
-
switch (
|
|
1095
|
+
switch (_context25.prev = _context25.next) {
|
|
881
1096
|
case 0:
|
|
882
|
-
|
|
1097
|
+
_setup17 = setup(), client = _setup17.client;
|
|
883
1098
|
konnector = {
|
|
884
1099
|
slug: 'revolut',
|
|
885
1100
|
parameters: {
|
|
@@ -887,7 +1102,7 @@ describe('fetchExtraOAuthUrlParams', function () {
|
|
|
887
1102
|
}
|
|
888
1103
|
};
|
|
889
1104
|
account = {};
|
|
890
|
-
|
|
1105
|
+
_context25.next = 5;
|
|
891
1106
|
return fetchExtraOAuthUrlParams({
|
|
892
1107
|
client: client,
|
|
893
1108
|
konnector: konnector,
|
|
@@ -895,7 +1110,7 @@ describe('fetchExtraOAuthUrlParams', function () {
|
|
|
895
1110
|
});
|
|
896
1111
|
|
|
897
1112
|
case 5:
|
|
898
|
-
_yield$fetchExtraOAut =
|
|
1113
|
+
_yield$fetchExtraOAut = _context25.sent;
|
|
899
1114
|
id_connector = _yield$fetchExtraOAut.id_connector;
|
|
900
1115
|
token = _yield$fetchExtraOAut.token;
|
|
901
1116
|
expect(token).toEqual('bi-temporary-access-token-121212');
|
|
@@ -903,18 +1118,18 @@ describe('fetchExtraOAuthUrlParams', function () {
|
|
|
903
1118
|
|
|
904
1119
|
case 10:
|
|
905
1120
|
case "end":
|
|
906
|
-
return
|
|
1121
|
+
return _context25.stop();
|
|
907
1122
|
}
|
|
908
1123
|
}
|
|
909
|
-
},
|
|
1124
|
+
}, _callee25);
|
|
910
1125
|
})));
|
|
911
1126
|
});
|
|
912
1127
|
describe('handleOAuthAccount', function () {
|
|
913
|
-
it('should handle webauth if any connection is found in the account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
1128
|
+
it('should handle webauth if any connection is found in the account', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee27() {
|
|
914
1129
|
var client, flow, account, t;
|
|
915
|
-
return _regeneratorRuntime.wrap(function
|
|
1130
|
+
return _regeneratorRuntime.wrap(function _callee27$(_context27) {
|
|
916
1131
|
while (1) {
|
|
917
|
-
switch (
|
|
1132
|
+
switch (_context27.prev = _context27.next) {
|
|
918
1133
|
case 0:
|
|
919
1134
|
client = new CozyClient({
|
|
920
1135
|
uri: 'http://testcozy.mycozy.cloud'
|
|
@@ -924,23 +1139,23 @@ describe('handleOAuthAccount', function () {
|
|
|
924
1139
|
flow.handleFormSubmit = jest.fn();
|
|
925
1140
|
|
|
926
1141
|
flow.saveAccount = /*#__PURE__*/function () {
|
|
927
|
-
var
|
|
928
|
-
return _regeneratorRuntime.wrap(function
|
|
1142
|
+
var _ref29 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee26(account) {
|
|
1143
|
+
return _regeneratorRuntime.wrap(function _callee26$(_context26) {
|
|
929
1144
|
while (1) {
|
|
930
|
-
switch (
|
|
1145
|
+
switch (_context26.prev = _context26.next) {
|
|
931
1146
|
case 0:
|
|
932
|
-
return
|
|
1147
|
+
return _context26.abrupt("return", account);
|
|
933
1148
|
|
|
934
1149
|
case 1:
|
|
935
1150
|
case "end":
|
|
936
|
-
return
|
|
1151
|
+
return _context26.stop();
|
|
937
1152
|
}
|
|
938
1153
|
}
|
|
939
|
-
},
|
|
1154
|
+
}, _callee26);
|
|
940
1155
|
}));
|
|
941
1156
|
|
|
942
|
-
return function (
|
|
943
|
-
return
|
|
1157
|
+
return function (_x4) {
|
|
1158
|
+
return _ref29.apply(this, arguments);
|
|
944
1159
|
};
|
|
945
1160
|
}();
|
|
946
1161
|
|
|
@@ -952,7 +1167,7 @@ describe('handleOAuthAccount', function () {
|
|
|
952
1167
|
}
|
|
953
1168
|
};
|
|
954
1169
|
t = jest.fn();
|
|
955
|
-
|
|
1170
|
+
_context27.next = 9;
|
|
956
1171
|
return handleOAuthAccount({
|
|
957
1172
|
account: account,
|
|
958
1173
|
flow: flow,
|
|
@@ -983,18 +1198,18 @@ describe('handleOAuthAccount', function () {
|
|
|
983
1198
|
|
|
984
1199
|
case 10:
|
|
985
1200
|
case "end":
|
|
986
|
-
return
|
|
1201
|
+
return _context27.stop();
|
|
987
1202
|
}
|
|
988
1203
|
}
|
|
989
|
-
},
|
|
1204
|
+
}, _callee27);
|
|
990
1205
|
})));
|
|
991
1206
|
});
|
|
992
1207
|
describe('setSync', function () {
|
|
993
|
-
it('should set synchronization status for a contract', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
1208
|
+
it('should set synchronization status for a contract', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee29() {
|
|
994
1209
|
var client, flow, biConnId, tempToken, biContractId, account, contract, createTemporaryToken, setBIConnectionSyncStatus;
|
|
995
|
-
return _regeneratorRuntime.wrap(function
|
|
1210
|
+
return _regeneratorRuntime.wrap(function _callee29$(_context29) {
|
|
996
1211
|
while (1) {
|
|
997
|
-
switch (
|
|
1212
|
+
switch (_context29.prev = _context29.next) {
|
|
998
1213
|
case 0:
|
|
999
1214
|
client = new CozyClient({
|
|
1000
1215
|
uri: 'http://testcozy.mycozy.cloud'
|
|
@@ -1004,23 +1219,23 @@ describe('setSync', function () {
|
|
|
1004
1219
|
flow.handleFormSubmit = jest.fn();
|
|
1005
1220
|
|
|
1006
1221
|
flow.saveAccount = /*#__PURE__*/function () {
|
|
1007
|
-
var
|
|
1008
|
-
return _regeneratorRuntime.wrap(function
|
|
1222
|
+
var _ref31 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee28(account) {
|
|
1223
|
+
return _regeneratorRuntime.wrap(function _callee28$(_context28) {
|
|
1009
1224
|
while (1) {
|
|
1010
|
-
switch (
|
|
1225
|
+
switch (_context28.prev = _context28.next) {
|
|
1011
1226
|
case 0:
|
|
1012
|
-
return
|
|
1227
|
+
return _context28.abrupt("return", account);
|
|
1013
1228
|
|
|
1014
1229
|
case 1:
|
|
1015
1230
|
case "end":
|
|
1016
|
-
return
|
|
1231
|
+
return _context28.stop();
|
|
1017
1232
|
}
|
|
1018
1233
|
}
|
|
1019
|
-
},
|
|
1234
|
+
}, _callee28);
|
|
1020
1235
|
}));
|
|
1021
1236
|
|
|
1022
|
-
return function (
|
|
1023
|
-
return
|
|
1237
|
+
return function (_x5) {
|
|
1238
|
+
return _ref31.apply(this, arguments);
|
|
1024
1239
|
};
|
|
1025
1240
|
}();
|
|
1026
1241
|
|
|
@@ -1043,7 +1258,7 @@ describe('setSync', function () {
|
|
|
1043
1258
|
code: tempToken
|
|
1044
1259
|
});
|
|
1045
1260
|
setBIConnectionSyncStatus = jest.fn();
|
|
1046
|
-
|
|
1261
|
+
_context29.next = 14;
|
|
1047
1262
|
return setSync({
|
|
1048
1263
|
client: client,
|
|
1049
1264
|
account: account,
|
|
@@ -1060,18 +1275,18 @@ describe('setSync', function () {
|
|
|
1060
1275
|
|
|
1061
1276
|
case 15:
|
|
1062
1277
|
case "end":
|
|
1063
|
-
return
|
|
1278
|
+
return _context29.stop();
|
|
1064
1279
|
}
|
|
1065
1280
|
}
|
|
1066
|
-
},
|
|
1281
|
+
}, _callee29);
|
|
1067
1282
|
})));
|
|
1068
1283
|
});
|
|
1069
1284
|
describe('updateBIConnectionFromFlow', function () {
|
|
1070
|
-
it('should update a connection with given fields', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
1285
|
+
it('should update a connection with given fields', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee30() {
|
|
1071
1286
|
var client, biConnId, account, flow, connectionData;
|
|
1072
|
-
return _regeneratorRuntime.wrap(function
|
|
1287
|
+
return _regeneratorRuntime.wrap(function _callee30$(_context30) {
|
|
1073
1288
|
while (1) {
|
|
1074
|
-
switch (
|
|
1289
|
+
switch (_context30.prev = _context30.next) {
|
|
1075
1290
|
case 0:
|
|
1076
1291
|
client = new CozyClient({
|
|
1077
1292
|
uri: 'http://testcozy.mycozy.cloud'
|
|
@@ -1098,7 +1313,7 @@ describe('updateBIConnectionFromFlow', function () {
|
|
|
1098
1313
|
connectionData = {
|
|
1099
1314
|
login: '1234'
|
|
1100
1315
|
};
|
|
1101
|
-
|
|
1316
|
+
_context30.next = 10;
|
|
1102
1317
|
return updateBIConnectionFromFlow(flow, connectionData);
|
|
1103
1318
|
|
|
1104
1319
|
case 10:
|
|
@@ -1110,10 +1325,10 @@ describe('updateBIConnectionFromFlow', function () {
|
|
|
1110
1325
|
|
|
1111
1326
|
case 11:
|
|
1112
1327
|
case "end":
|
|
1113
|
-
return
|
|
1328
|
+
return _context30.stop();
|
|
1114
1329
|
}
|
|
1115
1330
|
}
|
|
1116
|
-
},
|
|
1331
|
+
}, _callee30);
|
|
1117
1332
|
})));
|
|
1118
1333
|
});
|
|
1119
1334
|
describe('sendTwoFACode', function () {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-harvest-lib",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0",
|
|
4
4
|
"description": "Provides logic, modules and components for Cozy's harvest applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"@cozy/minilog": "^1.0.0",
|
|
30
30
|
"@sentry/browser": "^6.0.1",
|
|
31
31
|
"cozy-bi-auth": "0.0.24",
|
|
32
|
-
"cozy-doctypes": "^1.83.
|
|
33
|
-
"cozy-logger": "^1.8.
|
|
32
|
+
"cozy-doctypes": "^1.83.6",
|
|
33
|
+
"cozy-logger": "^1.8.1",
|
|
34
34
|
"date-fns": "^1.30.1",
|
|
35
35
|
"final-form": "^4.18.5",
|
|
36
36
|
"lodash": "^4.17.19",
|
|
@@ -45,37 +45,37 @@
|
|
|
45
45
|
"@babel/core": "7.16.12",
|
|
46
46
|
"@babel/register": "7.16.9",
|
|
47
47
|
"@cozy/cli-tree": "^0.5.0",
|
|
48
|
-
"@material-ui/core": "4",
|
|
49
|
-
"@material-ui/lab": "
|
|
50
|
-
"@testing-library/jest-dom": "
|
|
48
|
+
"@material-ui/core": "4.11.3",
|
|
49
|
+
"@material-ui/lab": "4.0.0-alpha.57",
|
|
50
|
+
"@testing-library/jest-dom": "4.2.4",
|
|
51
51
|
"@testing-library/react": "10.4.9",
|
|
52
52
|
"babel-jest": "26.6.3",
|
|
53
53
|
"babel-plugin-inline-react-svg": "1.1.2",
|
|
54
54
|
"babel-preset-cozy-app": "^2.0.2",
|
|
55
|
-
"cozy-client": "
|
|
55
|
+
"cozy-client": "27.14.3",
|
|
56
56
|
"cozy-device-helper": "^1.17.0",
|
|
57
|
-
"cozy-flags": "^2.8.
|
|
57
|
+
"cozy-flags": "^2.8.5",
|
|
58
58
|
"cozy-keys-lib": "3.8.0",
|
|
59
59
|
"cozy-realtime": "^4.0.5",
|
|
60
|
-
"cozy-ui": "
|
|
60
|
+
"cozy-ui": "57.6.0",
|
|
61
61
|
"enzyme": "3.11.0",
|
|
62
62
|
"enzyme-adapter-react-16": "1.15.6",
|
|
63
63
|
"form-data": "3.0.0",
|
|
64
64
|
"identity-obj-proxy": "3.0.0",
|
|
65
65
|
"jest": "26.6.3",
|
|
66
|
-
"jest-environment-jsdom-sixteen": "
|
|
67
|
-
"jest-resolve-cached": "
|
|
68
|
-
"jsdom": "
|
|
69
|
-
"leaflet": "
|
|
66
|
+
"jest-environment-jsdom-sixteen": "1.0.3",
|
|
67
|
+
"jest-resolve-cached": "1.0.0",
|
|
68
|
+
"jsdom": "16.4.0",
|
|
69
|
+
"leaflet": "1.7.1",
|
|
70
70
|
"prop-types": "15.7.2",
|
|
71
|
-
"react": "
|
|
72
|
-
"react-dom": "
|
|
73
|
-
"react-swipeable-views": "
|
|
71
|
+
"react": "16.12.0",
|
|
72
|
+
"react-dom": "16.12.0",
|
|
73
|
+
"react-swipeable-views": "0.13.9"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@babel/runtime": ">=7.12.5",
|
|
77
77
|
"@material-ui/core": ">=4",
|
|
78
|
-
"cozy-client": ">=
|
|
78
|
+
"cozy-client": ">=27.14.3",
|
|
79
79
|
"cozy-device-helper": ">=1.10.2",
|
|
80
80
|
"cozy-flags": ">=2.3.5",
|
|
81
81
|
"cozy-keys-lib": ">=3.7.0",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"react-router-dom": "^5.0.1"
|
|
86
86
|
},
|
|
87
87
|
"sideEffects": false,
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "3bfcea11a7a0d354b5feabc3d4a2655345eee2ee"
|
|
89
89
|
}
|
|
@@ -22,6 +22,8 @@ const TERMS_VERSION_MISMATCH = 'TERMS_VERSION_MISMATCH'
|
|
|
22
22
|
const UNKNOWN_ERROR = 'UNKNOWN_ERROR'
|
|
23
23
|
const USER_ACTION_NEEDED = 'USER_ACTION_NEEDED'
|
|
24
24
|
const VENDOR_DOWN = 'VENDOR_DOWN'
|
|
25
|
+
const ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED =
|
|
26
|
+
'ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED'
|
|
25
27
|
|
|
26
28
|
const KNOWN_ERRORS = [
|
|
27
29
|
CHALLENGE_ASKED,
|
|
@@ -31,7 +33,8 @@ const KNOWN_ERRORS = [
|
|
|
31
33
|
NOT_EXISTING_DIRECTORY,
|
|
32
34
|
TERMS_VERSION_MISMATCH,
|
|
33
35
|
USER_ACTION_NEEDED,
|
|
34
|
-
VENDOR_DOWN
|
|
36
|
+
VENDOR_DOWN,
|
|
37
|
+
ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED
|
|
35
38
|
]
|
|
36
39
|
|
|
37
40
|
const USER_ERRORS = [
|
package/src/locales/en.json
CHANGED
|
@@ -204,6 +204,10 @@
|
|
|
204
204
|
"VENDOR_DOWN.LINXO_DOWN": {
|
|
205
205
|
"title": "Unavailable service",
|
|
206
206
|
"description": "It seems that we are experiencing overload with our bank konnectors at the moment. Please rerun the connector later."
|
|
207
|
+
},
|
|
208
|
+
"ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED": {
|
|
209
|
+
"title": "This account already exists",
|
|
210
|
+
"description": "You already have configured an account with these identifiers."
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
},
|
package/src/locales/fr.json
CHANGED
|
@@ -204,6 +204,10 @@
|
|
|
204
204
|
"VENDOR_DOWN.LINXO_DOWN": {
|
|
205
205
|
"title": "Service non disponible",
|
|
206
206
|
"description": "Il semble que le service [%{name}](%{link}) ne nous ait pas répondu dans les temps. Vous pouvez tenter de le relancer manuellement maintenant ou ultérieurement."
|
|
207
|
+
},
|
|
208
|
+
"ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED": {
|
|
209
|
+
"title": "Ce compte est déjà configuré",
|
|
210
|
+
"description": "Vous avez déjà configuré un compte avec ces identifiants."
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
},
|
|
@@ -9,7 +9,9 @@ import get from 'lodash/get'
|
|
|
9
9
|
import omit from 'lodash/omit'
|
|
10
10
|
import clone from 'lodash/clone'
|
|
11
11
|
import set from 'lodash/set'
|
|
12
|
+
import keyBy from 'lodash/keyBy'
|
|
12
13
|
import defaults from 'lodash/defaults'
|
|
14
|
+
import { Q } from 'cozy-client'
|
|
13
15
|
|
|
14
16
|
import { waitForRealtimeEvent } from './jobUtils'
|
|
15
17
|
import {
|
|
@@ -42,7 +44,9 @@ const getBIIdFromContract = bankAccount => bankAccount.vendorId
|
|
|
42
44
|
* front-end.
|
|
43
45
|
*/
|
|
44
46
|
const extraBIErrorMap = {
|
|
45
|
-
config: 'LOGIN_FAILED'
|
|
47
|
+
config: 'LOGIN_FAILED',
|
|
48
|
+
ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED:
|
|
49
|
+
'ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED'
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
/**
|
|
@@ -166,10 +170,26 @@ export const createOrUpdateBIConnection = async ({
|
|
|
166
170
|
}
|
|
167
171
|
}
|
|
168
172
|
logger.info('Creating or updating connection...')
|
|
169
|
-
const
|
|
173
|
+
const isUpdate = Boolean(connId)
|
|
174
|
+
const connection = await (isUpdate
|
|
170
175
|
? updateBIConnection(config, connId, credsToSend, tempToken)
|
|
171
176
|
: createBIConnection(config, credsToSend, tempToken))
|
|
172
177
|
|
|
178
|
+
if (!isUpdate) {
|
|
179
|
+
const sameAccount = await findAccountWithBiConnection({
|
|
180
|
+
client,
|
|
181
|
+
konnector,
|
|
182
|
+
connectionId: connection.id
|
|
183
|
+
})
|
|
184
|
+
if (sameAccount) {
|
|
185
|
+
const err = new KonnectorJobError(
|
|
186
|
+
'ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED'
|
|
187
|
+
)
|
|
188
|
+
err.accountId = sameAccount._id
|
|
189
|
+
throw err
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
173
193
|
logger.info(`Created or updated connection ${connection.id}`)
|
|
174
194
|
return connection
|
|
175
195
|
} catch (e) {
|
|
@@ -505,6 +525,44 @@ const shouldResumeConnection = error => {
|
|
|
505
525
|
)
|
|
506
526
|
}
|
|
507
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Tries to find an existing account, associated to an existing trigger
|
|
530
|
+
* with the given bi connection id
|
|
531
|
+
*
|
|
532
|
+
* @param {CozyClient} options.client - Cozy client
|
|
533
|
+
* @param {Object} options.konnector - Konnector manifest
|
|
534
|
+
* @param {Integer} options.connectionId - BI connection id
|
|
535
|
+
* @return {Account|null} An account with a trigger with the same identifier if any
|
|
536
|
+
*/
|
|
537
|
+
export const findAccountWithBiConnection = async ({
|
|
538
|
+
client,
|
|
539
|
+
konnector,
|
|
540
|
+
connectionId
|
|
541
|
+
}) => {
|
|
542
|
+
const [accountsResult, triggersResult] = await Promise.all([
|
|
543
|
+
client.query(
|
|
544
|
+
Q('io.cozy.accounts')
|
|
545
|
+
.where({ data: { auth: { bi: { connId: connectionId } } } })
|
|
546
|
+
.indexFields(['data.auth.bi.connId'])
|
|
547
|
+
),
|
|
548
|
+
client.query(
|
|
549
|
+
Q('io.cozy.triggers')
|
|
550
|
+
.where({
|
|
551
|
+
message: {
|
|
552
|
+
konnector: konnector.slug
|
|
553
|
+
}
|
|
554
|
+
})
|
|
555
|
+
.indexFields(['message.konnector'])
|
|
556
|
+
)
|
|
557
|
+
])
|
|
558
|
+
|
|
559
|
+
const accountsIndex = keyBy(accountsResult.data, '_id')
|
|
560
|
+
const trigger = triggersResult.data.find(
|
|
561
|
+
t => accountsIndex[get(t, 'message.account')]
|
|
562
|
+
)
|
|
563
|
+
return trigger ? accountsIndex[trigger.message.account] : null
|
|
564
|
+
}
|
|
565
|
+
|
|
508
566
|
export const konnectorPolicy = {
|
|
509
567
|
name: 'budget-insight',
|
|
510
568
|
match: isBudgetInsightConnector,
|
|
@@ -515,5 +573,6 @@ export const konnectorPolicy = {
|
|
|
515
573
|
fetchExtraOAuthUrlParams: fetchExtraOAuthUrlParams,
|
|
516
574
|
getAdditionalInformationNeeded,
|
|
517
575
|
handleOAuthAccount,
|
|
518
|
-
setSync
|
|
576
|
+
setSync,
|
|
577
|
+
findAccountWithBiConnection
|
|
519
578
|
}
|
|
@@ -297,6 +297,7 @@ describe('createOrUpdateBIConnection', () => {
|
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
})
|
|
300
|
+
jest.spyOn(client, 'query').mockImplementation(async () => ({ data: [] }))
|
|
300
301
|
|
|
301
302
|
createBIConnection
|
|
302
303
|
.mockReset()
|
|
@@ -604,6 +605,127 @@ describe('createOrUpdateBIConnection', () => {
|
|
|
604
605
|
}
|
|
605
606
|
})
|
|
606
607
|
})
|
|
608
|
+
|
|
609
|
+
it('should refuse to create an account with a bi connection id which already exists', async () => {
|
|
610
|
+
const { client, flow } = setup()
|
|
611
|
+
|
|
612
|
+
const account = {
|
|
613
|
+
auth: {
|
|
614
|
+
login: '1234',
|
|
615
|
+
password: '4567',
|
|
616
|
+
dob: '20/12/1890',
|
|
617
|
+
bankId: '100000'
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
const konnector = {
|
|
622
|
+
slug: 'bankingconnectortest'
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
jest.spyOn(flow, 'saveAccount').mockImplementation(account => ({
|
|
626
|
+
_id: 'created-account-id',
|
|
627
|
+
...account
|
|
628
|
+
}))
|
|
629
|
+
|
|
630
|
+
jest.spyOn(client, 'query').mockImplementation(async ({ doctype }) => {
|
|
631
|
+
if (doctype === 'io.cozy.accounts') {
|
|
632
|
+
return {
|
|
633
|
+
data: [
|
|
634
|
+
{
|
|
635
|
+
_id: 'account_id',
|
|
636
|
+
auth: { bi: { connId: 12 } }
|
|
637
|
+
}
|
|
638
|
+
]
|
|
639
|
+
}
|
|
640
|
+
} else if (doctype === 'io.cozy.triggers') {
|
|
641
|
+
return {
|
|
642
|
+
data: [
|
|
643
|
+
{
|
|
644
|
+
message: { account: 'account_id' }
|
|
645
|
+
}
|
|
646
|
+
]
|
|
647
|
+
}
|
|
648
|
+
} else {
|
|
649
|
+
throw new Error('unexpected doctype ' + doctype)
|
|
650
|
+
}
|
|
651
|
+
})
|
|
652
|
+
|
|
653
|
+
await expect(
|
|
654
|
+
onBIAccountCreation({
|
|
655
|
+
client,
|
|
656
|
+
flow,
|
|
657
|
+
account,
|
|
658
|
+
konnector
|
|
659
|
+
})
|
|
660
|
+
).rejects.toEqual(new Error('ACCOUNT_WITH_SAME_IDENTIFIER_ALREADY_DEFINED'))
|
|
661
|
+
})
|
|
662
|
+
|
|
663
|
+
it('should create an account if bi connection is not already used', async () => {
|
|
664
|
+
const { client, flow } = setup()
|
|
665
|
+
|
|
666
|
+
const account = {
|
|
667
|
+
auth: {
|
|
668
|
+
login: '1234',
|
|
669
|
+
password: '4567',
|
|
670
|
+
dob: '20/12/1890',
|
|
671
|
+
bankId: '100000'
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
const konnector = {
|
|
676
|
+
slug: 'bankingconnectortest'
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
jest.spyOn(flow, 'saveAccount').mockImplementation(account => ({
|
|
680
|
+
_id: 'created-account-id',
|
|
681
|
+
...account
|
|
682
|
+
}))
|
|
683
|
+
|
|
684
|
+
jest.spyOn(client, 'query').mockImplementation(async ({ doctype }) => {
|
|
685
|
+
if (doctype === 'io.cozy.accounts') {
|
|
686
|
+
return {
|
|
687
|
+
data: [
|
|
688
|
+
{
|
|
689
|
+
_id: 'account_id',
|
|
690
|
+
auth: { bi: { connId: 12 } }
|
|
691
|
+
}
|
|
692
|
+
]
|
|
693
|
+
}
|
|
694
|
+
} else if (doctype === 'io.cozy.triggers') {
|
|
695
|
+
return {
|
|
696
|
+
data: [
|
|
697
|
+
{
|
|
698
|
+
message: { account: 'other_account_id' }
|
|
699
|
+
}
|
|
700
|
+
]
|
|
701
|
+
}
|
|
702
|
+
} else {
|
|
703
|
+
throw new Error('unexpected doctype ' + doctype)
|
|
704
|
+
}
|
|
705
|
+
})
|
|
706
|
+
|
|
707
|
+
await expect(
|
|
708
|
+
onBIAccountCreation({
|
|
709
|
+
client,
|
|
710
|
+
flow,
|
|
711
|
+
account,
|
|
712
|
+
konnector
|
|
713
|
+
})
|
|
714
|
+
).resolves.toEqual({
|
|
715
|
+
_id: 'created-account-id',
|
|
716
|
+
auth: {
|
|
717
|
+
bankId: '100000',
|
|
718
|
+
login: '1234'
|
|
719
|
+
},
|
|
720
|
+
data: {
|
|
721
|
+
auth: {
|
|
722
|
+
bi: {
|
|
723
|
+
connId: 'created-bi-connection-id-789'
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
})
|
|
728
|
+
})
|
|
607
729
|
})
|
|
608
730
|
|
|
609
731
|
describe('fetchExtraOAuthUrlParams', () => {
|