cozy-harvest-lib 9.24.3 → 9.26.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 CHANGED
@@ -3,6 +3,47 @@
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
+ # [9.26.0](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@9.25.0...cozy-harvest-lib@9.26.0) (2022-08-22)
7
+
8
+
9
+ ### Features
10
+
11
+ * Detect reconnect explicitely ([b092392](https://github.com/cozy/cozy-libs/commit/b0923923727bdb08123bd78073a0dda238361f02))
12
+ * Handle cas with multiple bank ids ([9729626](https://github.com/cozy/cozy-libs/commit/97296267e941265a08ad052f1e5a62c3830566f2))
13
+ * Use BI account creation webview to handle accounts synchonization ([1b5e5ff](https://github.com/cozy/cozy-libs/commit/1b5e5ff06b6c98b14d0d8c388d31970ae36bfac0))
14
+
15
+
16
+
17
+
18
+
19
+ # [9.25.0](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@9.24.4...cozy-harvest-lib@9.25.0) (2022-08-05)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * Let OAuthForm component decide when to remove the OAuth window ([59a132f](https://github.com/cozy/cozy-libs/commit/59a132f71d528cb311d436041951aaae811aed6e))
25
+
26
+
27
+ ### Features
28
+
29
+ * Close OAuthWindow only on login success ([a8cf6a3](https://github.com/cozy/cozy-libs/commit/a8cf6a37a9c76bf2702c1d73d292a4d337f7dc5a))
30
+
31
+
32
+
33
+
34
+
35
+ ## [9.24.4](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@9.24.3...cozy-harvest-lib@9.24.4) (2022-08-05)
36
+
37
+
38
+ ### Bug Fixes
39
+
40
+ * Remove a reconnection step ([05d2cb6](https://github.com/cozy/cozy-libs/commit/05d2cb674d9ce69164cf0a099059520cbf4f1722))
41
+ * Remove unused request to BI connection ([be09798](https://github.com/cozy/cozy-libs/commit/be09798e3c551fd9628d15e6f79b9de77b3d1aa5))
42
+
43
+
44
+
45
+
46
+
6
47
  ## [9.24.3](https://github.com/cozy/cozy-libs/compare/cozy-harvest-lib@9.24.2...cozy-harvest-lib@9.24.3) (2022-08-01)
7
48
 
8
49
 
@@ -4,15 +4,14 @@ import React from 'react';
4
4
  import CozyClient from 'cozy-client';
5
5
  import { render, fireEvent, act, waitFor } from '@testing-library/react';
6
6
  import AppLike from '../../../../test/AppLike';
7
- import BIContractActivationWindow from './BiContractActivationWindow';
8
- var fetchContractSynchronizationUrl = jest.fn();
7
+ var fetchExtraOAuthUrlParams = jest.fn();
9
8
  var refreshContracts = jest.fn();
10
9
  jest.mock('../../../konnector-policies', function () {
11
10
  return {
12
11
  findKonnectorPolicy: jest.fn()
13
12
  };
14
13
  });
15
- jest.mock('cozy-ui/transpiled/react/Popup', function () {
14
+ jest.mock('../../Popup', function () {
16
15
  return jest.fn().mockImplementation(function (_ref) {
17
16
  var onClose = _ref.onClose;
18
17
  setTimeout(onClose, 1);
@@ -26,14 +25,18 @@ jest.mock('../../InAppBrowser', function () {
26
25
  return null;
27
26
  });
28
27
  });
28
+ jest.mock('../../../helpers/oauth');
29
+ jest.mock('cozy-realtime');
29
30
  jest.mock('cozy-device-helper');
31
+ import BIContractActivationWindow from './BiContractActivationWindow';
30
32
  import { findKonnectorPolicy } from '../../../konnector-policies';
31
- import Popup from 'cozy-ui/transpiled/react/Popup';
33
+ import Popup from '../../Popup';
32
34
  import InAppBrowser from '../../InAppBrowser';
33
35
  import { isFlagshipApp } from 'cozy-device-helper';
36
+ import { prepareOAuth } from '../../../helpers/oauth';
34
37
  findKonnectorPolicy.mockImplementation(function () {
35
38
  return {
36
- fetchContractSynchronizationUrl: fetchContractSynchronizationUrl,
39
+ fetchExtraOAuthUrlParams: fetchExtraOAuthUrlParams,
37
40
  refreshContracts: refreshContracts
38
41
  };
39
42
  });
@@ -66,12 +69,17 @@ describe('BIContractActivationWindow', function () {
66
69
  while (1) {
67
70
  switch (_context3.prev = _context3.next) {
68
71
  case 0:
72
+ prepareOAuth.mockImplementation(function () {
73
+ return {
74
+ oAuthUrl: 'https://test.url'
75
+ };
76
+ });
69
77
  isFlagshipApp.mockImplementation(function () {
70
78
  return false;
71
79
  });
72
- fetchContractSynchronizationUrl.mockResolvedValue('bi url');
80
+ fetchExtraOAuthUrlParams.mockResolvedValue({});
73
81
  _setup = setup(), getByRole = _setup.getByRole;
74
- _context3.next = 5;
82
+ _context3.next = 6;
75
83
  return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
76
84
  return _regeneratorRuntime.wrap(function _callee$(_context) {
77
85
  while (1) {
@@ -90,8 +98,8 @@ describe('BIContractActivationWindow', function () {
90
98
  }, _callee);
91
99
  })));
92
100
 
93
- case 5:
94
- _context3.next = 7;
101
+ case 6:
102
+ _context3.next = 8;
95
103
  return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
96
104
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
97
105
  while (1) {
@@ -111,14 +119,14 @@ describe('BIContractActivationWindow', function () {
111
119
  }, _callee2);
112
120
  })));
113
121
 
114
- case 7:
115
- expect(fetchContractSynchronizationUrl).toHaveBeenCalled();
122
+ case 8:
123
+ expect(fetchExtraOAuthUrlParams).toHaveBeenCalled();
116
124
  expect(refreshContracts).toHaveBeenCalledTimes(1);
117
125
  expect(Popup).toHaveBeenCalledWith(expect.objectContaining({
118
- initialUrl: 'bi url'
119
- }), expect.anything());
126
+ url: 'https://test.url'
127
+ }), {});
120
128
 
121
- case 10:
129
+ case 11:
122
130
  case "end":
123
131
  return _context3.stop();
124
132
  }
@@ -135,9 +143,14 @@ describe('BIContractActivationWindow', function () {
135
143
  isFlagshipApp.mockImplementation(function () {
136
144
  return true;
137
145
  });
138
- fetchContractSynchronizationUrl.mockResolvedValue('bi url');
146
+ prepareOAuth.mockImplementation(function () {
147
+ return {
148
+ oAuthUrl: 'https://testiab.url'
149
+ };
150
+ });
151
+ fetchExtraOAuthUrlParams.mockResolvedValue({});
139
152
  _setup2 = setup(), getByRole = _setup2.getByRole;
140
- _context6.next = 5;
153
+ _context6.next = 6;
141
154
  return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
142
155
  return _regeneratorRuntime.wrap(function _callee4$(_context4) {
143
156
  while (1) {
@@ -156,8 +169,8 @@ describe('BIContractActivationWindow', function () {
156
169
  }, _callee4);
157
170
  })));
158
171
 
159
- case 5:
160
- _context6.next = 7;
172
+ case 6:
173
+ _context6.next = 8;
161
174
  return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
162
175
  return _regeneratorRuntime.wrap(function _callee5$(_context5) {
163
176
  while (1) {
@@ -177,14 +190,14 @@ describe('BIContractActivationWindow', function () {
177
190
  }, _callee5);
178
191
  })));
179
192
 
180
- case 7:
181
- expect(fetchContractSynchronizationUrl).toHaveBeenCalled();
193
+ case 8:
194
+ expect(fetchExtraOAuthUrlParams).toHaveBeenCalled();
182
195
  expect(refreshContracts).toHaveBeenCalledTimes(1);
183
196
  expect(InAppBrowser).toHaveBeenCalledWith(expect.objectContaining({
184
- url: 'bi url'
197
+ url: 'https://testiab.url'
185
198
  }), expect.anything());
186
199
 
187
- case 10:
200
+ case 11:
188
201
  case "end":
189
202
  return _context6.stop();
190
203
  }
@@ -5,11 +5,9 @@ import React, { useState, useEffect } from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { useClient } from 'cozy-client';
7
7
  import Button from 'cozy-ui/transpiled/react/MuiCozyTheme/Buttons';
8
- import Popup from 'cozy-ui/transpiled/react/Popup';
9
8
  import ListItem from 'cozy-ui/transpiled/react/MuiCozyTheme/ListItem';
10
9
  import { findKonnectorPolicy } from '../../../konnector-policies';
11
- import { isFlagshipApp } from 'cozy-device-helper';
12
- import InAppBrowser from '../../InAppBrowser';
10
+ import OAuthWindow from '../../OAuthWindow';
13
11
  import withLocales from '../../hoc/withLocales';
14
12
  import { intentsApiProptype, innerAccountModalOverridesProptype } from '../../../helpers/proptypes';
15
13
 
@@ -22,8 +20,8 @@ var BIContractActivationWindow = function BIContractActivationWindow(_ref) {
22
20
 
23
21
  var _useState = useState(null),
24
22
  _useState2 = _slicedToArray(_useState, 2),
25
- initialUrl = _useState2[0],
26
- setInitialUrl = _useState2[1];
23
+ extraParams = _useState2[0],
24
+ setExtraParams = _useState2[1];
27
25
 
28
26
  var _useState3 = useState(false),
29
27
  _useState4 = _slicedToArray(_useState3, 2),
@@ -91,7 +89,7 @@ var BIContractActivationWindow = function BIContractActivationWindow(_ref) {
91
89
  switch (_context2.prev = _context2.next) {
92
90
  case 0:
93
91
  _context2.next = 2;
94
- return konnectorPolicy.fetchContractSynchronizationUrl({
92
+ return konnectorPolicy.fetchExtraOAuthUrlParams({
95
93
  client: client,
96
94
  account: account,
97
95
  konnector: konnector
@@ -99,7 +97,7 @@ var BIContractActivationWindow = function BIContractActivationWindow(_ref) {
99
97
 
100
98
  case 2:
101
99
  result = _context2.sent;
102
- setInitialUrl(result);
100
+ setExtraParams(result);
103
101
 
104
102
  case 4:
105
103
  case "end":
@@ -111,29 +109,27 @@ var BIContractActivationWindow = function BIContractActivationWindow(_ref) {
111
109
  return _handleLinkFetch.apply(this, arguments);
112
110
  }
113
111
 
114
- if (konnectorPolicy.fetchContractSynchronizationUrl) {
112
+ if (konnectorPolicy.fetchExtraOAuthUrlParams) {
115
113
  handleLinkFetch();
116
114
  }
117
115
  }, [konnector.slug, account, client, konnectorPolicy]);
118
- if (!konnectorPolicy.fetchContractSynchronizationUrl) return null;
116
+ if (!konnectorPolicy.fetchExtraOAuthUrlParams) return null;
119
117
  var ButtonWrapper = innerAccountModalOverrides !== null && innerAccountModalOverrides !== void 0 && innerAccountModalOverrides.SyncButtonWrapperComp ? innerAccountModalOverrides.SyncButtonWrapperComp : React.Fragment;
120
118
  return /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(ButtonWrapper, null, /*#__PURE__*/React.createElement(Button, {
121
119
  variant: "text",
122
120
  color: "primary",
123
- disabled: !initialUrl,
121
+ disabled: !extraParams,
124
122
  onClick: function onClick() {
125
123
  return setWindowVisible(true);
126
124
  }
127
- }, t('contracts.handle-synchronization'))), isWindowVisible && (isFlagshipApp() || intentsApi ? /*#__PURE__*/React.createElement(InAppBrowser, {
128
- url: initialUrl,
129
- onClose: onPopupClosed,
130
- intentsApi: intentsApi
131
- }) : /*#__PURE__*/React.createElement(Popup, {
132
- initialUrl: initialUrl,
133
- width: "800",
134
- height: "800",
135
- onClose: onPopupClosed
136
- })));
125
+ }, t('contracts.handle-synchronization'))), isWindowVisible && /*#__PURE__*/React.createElement(OAuthWindow, {
126
+ extraParams: extraParams,
127
+ konnector: konnector,
128
+ account: account,
129
+ intentsApi: intentsApi,
130
+ onSuccess: onPopupClosed,
131
+ onCancel: onPopupClosed
132
+ }));
137
133
  };
138
134
 
139
135
  BIContractActivationWindow.propTypes = {
@@ -19,7 +19,7 @@ import withLocales from './hoc/withLocales';
19
19
  import { findKonnectorPolicy } from '../konnector-policies';
20
20
  import { intentsApiProptype } from '../helpers/proptypes';
21
21
  import TriggerErrorInfo from './infos/TriggerErrorInfo';
22
- import { ERROR_EVENT } from '../models/flowEvents';
22
+ import { ERROR_EVENT, LOGIN_SUCCESS_EVENT } from '../models/flowEvents';
23
23
  import { KonnectorJobError } from '../helpers/konnectors';
24
24
  /**
25
25
  * The OAuth Form is responsible for displaying a form for OAuth konnectors. It
@@ -41,9 +41,8 @@ export var OAuthForm = /*#__PURE__*/function (_PureComponent) {
41
41
  _this.handleConnect = _this.handleConnect.bind(_assertThisInitialized(_this));
42
42
  _this.handleOAuthCancel = _this.handleOAuthCancel.bind(_assertThisInitialized(_this));
43
43
  _this.handleExtraParams = _this.handleExtraParams.bind(_assertThisInitialized(_this));
44
- _this.state = {
45
- showingOAuthModal: false
46
- };
44
+ _this.handleLoginSuccess = _this.handleLoginSuccess.bind(_assertThisInitialized(_this));
45
+ _this.state = {};
47
46
  return _this;
48
47
  }
49
48
 
@@ -54,21 +53,34 @@ export var OAuthForm = /*#__PURE__*/function (_PureComponent) {
54
53
  account = _this$props.account,
55
54
  konnector = _this$props.konnector,
56
55
  flow = _this$props.flow,
57
- client = _this$props.client;
56
+ client = _this$props.client,
57
+ reconnect = _this$props.reconnect;
58
58
  var konnectorPolicy = findKonnectorPolicy(konnector);
59
59
 
60
60
  if (konnectorPolicy.fetchExtraOAuthUrlParams) {
61
61
  this.setState({
62
62
  needExtraParams: true
63
- }); // eslint-disable-next-line promise/catch-or-return
63
+ });
64
+
65
+ if (reconnect) {
66
+ this.showOAuthWindow();
67
+ } // eslint-disable-next-line promise/catch-or-return
68
+
64
69
 
65
70
  konnectorPolicy.fetchExtraOAuthUrlParams({
66
- flow: flow,
67
71
  account: account,
68
72
  konnector: konnector,
69
- client: client
73
+ client: client,
74
+ reconnect: reconnect
70
75
  }).then(this.handleExtraParams);
71
76
  }
77
+
78
+ flow.on(LOGIN_SUCCESS_EVENT, this.handleLoginSuccess);
79
+ }
80
+ }, {
81
+ key: "handleLoginSuccess",
82
+ value: function handleLoginSuccess() {
83
+ this.hideOAuthWindow();
72
84
  }
73
85
  }, {
74
86
  key: "handleExtraParams",
@@ -81,7 +93,6 @@ export var OAuthForm = /*#__PURE__*/function (_PureComponent) {
81
93
  key: "handleAccountId",
82
94
  value: function handleAccountId(accountId) {
83
95
  var onSuccess = this.props.onSuccess;
84
- this.hideOAuthWindow();
85
96
  if (typeof onSuccess === 'function') onSuccess(accountId);
86
97
  }
87
98
  }, {
@@ -89,6 +100,12 @@ export var OAuthForm = /*#__PURE__*/function (_PureComponent) {
89
100
  value: function handleConnect() {
90
101
  this.showOAuthWindow();
91
102
  }
103
+ }, {
104
+ key: "componentWillUnmount",
105
+ value: function componentWillUnmount() {
106
+ var flow = this.props.flow;
107
+ flow.removeListener(LOGIN_SUCCESS_EVENT, this.handleLoginSuccess);
108
+ }
92
109
  /**
93
110
  * Translates errors from oauth redirection url to harvest know error messages
94
111
  *
@@ -149,14 +166,14 @@ export var OAuthForm = /*#__PURE__*/function (_PureComponent) {
149
166
  className: "u-mb-1",
150
167
  error: error,
151
168
  konnector: konnector
152
- }), /*#__PURE__*/React.createElement(Button, {
169
+ }), !reconnect && /*#__PURE__*/React.createElement(Button, {
153
170
  className: "u-mt-1",
154
171
  busy: isBusy,
155
172
  disabled: isBusy,
156
173
  extension: "full",
157
174
  label: t(buttonLabel),
158
175
  onClick: this.handleConnect
159
- }), showOAuthWindow && /*#__PURE__*/React.createElement(OAuthWindow, {
176
+ }), showOAuthWindow && extraParams && /*#__PURE__*/React.createElement(OAuthWindow, {
160
177
  extraParams: extraParams,
161
178
  konnector: konnector,
162
179
  reconnect: reconnect,
@@ -4,11 +4,13 @@ import { shallow } from 'enzyme';
4
4
  import { OAuthForm } from 'components/OAuthForm';
5
5
  import { findKonnectorPolicy } from '../konnector-policies';
6
6
  import { KonnectorJobError } from '../helpers/konnectors';
7
+ import ConnectionFlow from '../models/ConnectionFlow';
7
8
  jest.mock('../konnector-policies', function () {
8
9
  return {
9
10
  findKonnectorPolicy: jest.fn()
10
11
  };
11
12
  });
13
+ jest.mock('../models/ConnectionFlow');
12
14
  var fetchExtraOAuthUrlParams = jest.fn();
13
15
  fetchExtraOAuthUrlParams.mockResolvedValue({});
14
16
  findKonnectorPolicy.mockReturnValue({
@@ -22,17 +24,20 @@ var fixtures = {
22
24
  slug: 'test-konnector'
23
25
  }
24
26
  };
27
+ var flow = new ConnectionFlow();
25
28
  describe('OAuthForm', function () {
26
29
  it('should render', function () {
27
30
  var component = shallow( /*#__PURE__*/React.createElement(OAuthForm, {
31
+ flow: flow,
28
32
  flowState: {},
29
33
  konnector: fixtures.konnector,
30
34
  t: t
31
35
  })).getElement();
32
36
  expect(component).toMatchSnapshot();
33
37
  });
34
- it('should render reconnect button when updating an account', function () {
38
+ it('should bypass reconnect button when updating an account', function () {
35
39
  var component = shallow( /*#__PURE__*/React.createElement(OAuthForm, {
40
+ flow: flow,
36
41
  flowState: {},
37
42
  account: {
38
43
  oauth: {
@@ -47,6 +52,7 @@ describe('OAuthForm', function () {
47
52
  });
48
53
  it('should call policy fetchExtraOAuthUrlParams with proper params', function () {
49
54
  shallow( /*#__PURE__*/React.createElement(OAuthForm, {
55
+ flow: flow,
50
56
  flowState: {},
51
57
  account: {
52
58
  oauth: {
@@ -63,7 +69,6 @@ describe('OAuthForm', function () {
63
69
  }
64
70
  },
65
71
  client: undefined,
66
- flow: undefined,
67
72
  konnector: {
68
73
  slug: 'test-konnector'
69
74
  }
@@ -71,6 +76,7 @@ describe('OAuthForm', function () {
71
76
  });
72
77
  it('should handle oauth cancelation', function () {
73
78
  var component = shallow( /*#__PURE__*/React.createElement(OAuthForm, {
79
+ flow: flow,
74
80
  flowState: {
75
81
  error: new KonnectorJobError('OAUTH_CANCELED')
76
82
  },
@@ -133,9 +133,6 @@ export var OAuthWindow = /*#__PURE__*/function (_PureComponent) {
133
133
  succeed: true
134
134
  });
135
135
  if (typeof onSuccess !== 'function') return;
136
- this.setState({
137
- succeed: true
138
- });
139
136
  onSuccess(data.key);
140
137
  }
141
138
  /**
@@ -200,10 +197,8 @@ export var OAuthWindow = /*#__PURE__*/function (_PureComponent) {
200
197
  var _this$props3 = this.props,
201
198
  t = _this$props3.t,
202
199
  intentsApi = _this$props3.intentsApi;
203
- var _this$state = this.state,
204
- oAuthUrl = _this$state.oAuthUrl,
205
- succeed = _this$state.succeed;
206
- return oAuthUrl && !succeed && (!isFlagshipApp() && !intentsApi ? /*#__PURE__*/React.createElement(Popup, {
200
+ var oAuthUrl = this.state.oAuthUrl;
201
+ return oAuthUrl && (!isFlagshipApp() && !intentsApi ? /*#__PURE__*/React.createElement(Popup, {
207
202
  url: oAuthUrl,
208
203
  height: OAUTH_POPUP_HEIGHT,
209
204
  width: OAUTH_POPUP_WIDTH,
@@ -1,5 +1,7 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`OAuthForm should bypass reconnect button when updating an account 1`] = `<React.Fragment />`;
4
+
3
5
  exports[`OAuthForm should handle oauth cancelation 1`] = `
4
6
  <React.Fragment>
5
7
  <withI18n(withClient(withKonnectorLocales(TriggerErrorInfo))
@@ -34,16 +36,3 @@ exports[`OAuthForm should render 1`] = `
34
36
  />
35
37
  </React.Fragment>
36
38
  `;
37
-
38
- exports[`OAuthForm should render reconnect button when updating an account 1`] = `
39
- <React.Fragment>
40
- <DefaultButton
41
- busy={true}
42
- className="u-mt-1"
43
- disabled={true}
44
- extension="full"
45
- label="oauth.reconnect.label"
46
- onClick={[Function]}
47
- />
48
- </React.Fragment>
49
- `;