cozy-ui 116.0.0 → 117.1.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 +21 -0
- package/package.json +1 -1
- package/react/ActionsMenu/Actions/addToFavorites.js +66 -0
- package/react/ActionsMenu/Actions/download.js +42 -0
- package/react/ActionsMenu/Actions/index.js +3 -0
- package/react/ActionsMenu/Actions/locales/en.json +12 -0
- package/react/ActionsMenu/Actions/locales/fr.json +12 -0
- package/react/ActionsMenu/Actions/removeFromFavorites.js +66 -0
- package/react/AppLinker/Readme.md +3 -31
- package/react/AppLinker/__snapshots__/index.spec.jsx.snap +0 -12
- package/react/AppLinker/index.jsx +8 -144
- package/react/AppLinker/index.spec.jsx +1 -94
- package/react/AppLinker/native.config.js +0 -14
- package/transpiled/react/ActionsMenu/Actions/addToFavorites.js +144 -0
- package/transpiled/react/ActionsMenu/Actions/download.js +49 -0
- package/transpiled/react/ActionsMenu/Actions/index.js +3 -0
- package/transpiled/react/ActionsMenu/Actions/locales/withActionsLocales.js +24 -0
- package/transpiled/react/ActionsMenu/Actions/removeFromFavorites.js +144 -0
- package/transpiled/react/AppLinker/index.js +10 -179
- package/transpiled/react/AppLinker/native.config.js +0 -13
- package/react/AppLinker/__snapshots__/index.deprecated.spec.jsx.snap +0 -25
- package/react/AppLinker/expiringMemoize.js +0 -13
- package/react/AppLinker/index.deprecated.spec.jsx +0 -162
- package/transpiled/react/AppLinker/expiringMemoize.js +0 -17
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
3
|
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
|
|
@@ -11,8 +10,6 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
11
10
|
|
|
12
11
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
13
12
|
|
|
14
|
-
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
15
|
-
|
|
16
13
|
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
17
14
|
|
|
18
15
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
@@ -20,20 +17,10 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
|
|
|
20
17
|
import PropTypes from 'prop-types';
|
|
21
18
|
import React from 'react';
|
|
22
19
|
import { withClient } from 'cozy-client';
|
|
23
|
-
import {
|
|
20
|
+
import { isFlagshipApp } from 'cozy-device-helper';
|
|
24
21
|
import { WebviewContext } from 'cozy-intent';
|
|
25
22
|
import logger from 'cozy-logger';
|
|
26
|
-
import expiringMemoize from "cozy-ui/transpiled/react/AppLinker/expiringMemoize";
|
|
27
23
|
import { generateUniversalLink, generateWebLink, getUniversalLinkDomain } from "cozy-ui/transpiled/react/AppLinker/native";
|
|
28
|
-
import { NATIVE_APP_INFOS } from "cozy-ui/transpiled/react/AppLinker/native.config";
|
|
29
|
-
var expirationDelay = 10 * 1000;
|
|
30
|
-
var memoizedCheckApp = expiringMemoize(function (appInfo) {
|
|
31
|
-
return checkApp(appInfo).catch(function () {
|
|
32
|
-
return false;
|
|
33
|
-
});
|
|
34
|
-
}, expirationDelay, function (appInfo) {
|
|
35
|
-
return appInfo.appId;
|
|
36
|
-
});
|
|
37
24
|
export var AppLinker = /*#__PURE__*/function (_React$Component) {
|
|
38
25
|
_inherits(AppLinker, _React$Component);
|
|
39
26
|
|
|
@@ -47,8 +34,7 @@ export var AppLinker = /*#__PURE__*/function (_React$Component) {
|
|
|
47
34
|
_this = _super.call(this, props);
|
|
48
35
|
|
|
49
36
|
_defineProperty(_assertThisInitialized(_this), "state", {
|
|
50
|
-
|
|
51
|
-
isFetchingAppInfo: false
|
|
37
|
+
imgRef: null
|
|
52
38
|
});
|
|
53
39
|
|
|
54
40
|
_defineProperty(_assertThisInitialized(_this), "setImgRef", function (img) {
|
|
@@ -59,105 +45,36 @@ export var AppLinker = /*#__PURE__*/function (_React$Component) {
|
|
|
59
45
|
});
|
|
60
46
|
});
|
|
61
47
|
|
|
62
|
-
_this.imgRef = null;
|
|
63
48
|
return _this;
|
|
64
49
|
}
|
|
65
50
|
|
|
66
51
|
_createClass(AppLinker, [{
|
|
67
|
-
key: "componentDidMount",
|
|
68
|
-
value: function componentDidMount() {
|
|
69
|
-
if (isMobileApp()) {
|
|
70
|
-
this.checkAppAvailability();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}, {
|
|
74
|
-
key: "checkAppAvailability",
|
|
75
|
-
value: function () {
|
|
76
|
-
var _checkAppAvailability = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
77
|
-
var slug, appInfo, nativeAppIsAvailable;
|
|
78
|
-
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
79
|
-
while (1) {
|
|
80
|
-
switch (_context.prev = _context.next) {
|
|
81
|
-
case 0:
|
|
82
|
-
slug = AppLinker.getSlug(this.props);
|
|
83
|
-
appInfo = NATIVE_APP_INFOS[slug];
|
|
84
|
-
|
|
85
|
-
if (!appInfo) {
|
|
86
|
-
_context.next = 9;
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
_context.t0 = Boolean;
|
|
91
|
-
_context.next = 6;
|
|
92
|
-
return memoizedCheckApp(appInfo);
|
|
93
|
-
|
|
94
|
-
case 6:
|
|
95
|
-
_context.t1 = _context.sent;
|
|
96
|
-
nativeAppIsAvailable = (0, _context.t0)(_context.t1);
|
|
97
|
-
this.setState({
|
|
98
|
-
nativeAppIsAvailable: nativeAppIsAvailable
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
case 9:
|
|
102
|
-
case "end":
|
|
103
|
-
return _context.stop();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}, _callee, this);
|
|
107
|
-
}));
|
|
108
|
-
|
|
109
|
-
function checkAppAvailability() {
|
|
110
|
-
return _checkAppAvailability.apply(this, arguments);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return checkAppAvailability;
|
|
114
|
-
}()
|
|
115
|
-
}, {
|
|
116
52
|
key: "render",
|
|
117
53
|
value: function render() {
|
|
118
54
|
var children = this.props.children;
|
|
119
|
-
AppLinker.deprecateSlug(this.props);
|
|
120
|
-
var slug = AppLinker.getSlug(this.props);
|
|
121
|
-
var nativeAppIsAvailable = this.state.nativeAppIsAvailable;
|
|
122
|
-
var appInfo = NATIVE_APP_INFOS[slug];
|
|
123
55
|
|
|
124
|
-
var _AppLinker$getOnClick = AppLinker.getOnClickHref(this.props,
|
|
56
|
+
var _AppLinker$getOnClick = AppLinker.getOnClickHref(this.props, this.context, this.state.imgRef),
|
|
125
57
|
href = _AppLinker$getOnClick.href,
|
|
126
58
|
onClick = _AppLinker$getOnClick.onClick;
|
|
127
59
|
|
|
128
|
-
return children(
|
|
60
|
+
return children({
|
|
129
61
|
iconRef: this.setImgRef,
|
|
130
62
|
onClick: onClick,
|
|
131
63
|
href: href
|
|
132
|
-
})
|
|
64
|
+
});
|
|
133
65
|
}
|
|
134
66
|
}], [{
|
|
135
67
|
key: "getSlug",
|
|
136
68
|
value: function getSlug(props) {
|
|
137
|
-
|
|
138
|
-
return props.app.slug;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return props.slug;
|
|
142
|
-
}
|
|
143
|
-
}, {
|
|
144
|
-
key: "deprecateSlug",
|
|
145
|
-
value: function deprecateSlug(props) {
|
|
146
|
-
if (props.slug) {
|
|
147
|
-
console.warn("AppLinker's 'slug' prop is deprecated, please use 'app.slug' instead");
|
|
148
|
-
}
|
|
69
|
+
return props.app.slug;
|
|
149
70
|
}
|
|
150
71
|
}, {
|
|
151
72
|
key: "getOnClickHref",
|
|
152
|
-
value: function getOnClickHref(props,
|
|
73
|
+
value: function getOnClickHref(props, context, imgRef) {
|
|
153
74
|
var app = props.app,
|
|
154
|
-
client = props.client
|
|
155
|
-
nativePath = props.nativePath;
|
|
156
|
-
var slug = AppLinker.getSlug(props);
|
|
75
|
+
client = props.client;
|
|
157
76
|
var href = props.href;
|
|
158
77
|
var onClick = null;
|
|
159
|
-
var usingNativeApp = isMobileApp();
|
|
160
|
-
var appInfo = NATIVE_APP_INFOS[slug];
|
|
161
78
|
|
|
162
79
|
if (isFlagshipApp()) {
|
|
163
80
|
var _ref = client ? client.getInstanceOptions() : undefined,
|
|
@@ -175,64 +92,11 @@ export var AppLinker = /*#__PURE__*/function (_React$Component) {
|
|
|
175
92
|
}
|
|
176
93
|
}
|
|
177
94
|
|
|
178
|
-
if (usingNativeApp) {
|
|
179
|
-
if (nativeAppIsAvailable) {
|
|
180
|
-
// If we are on the native app and the other native app is available,
|
|
181
|
-
// we open the native app
|
|
182
|
-
onClick = AppLinker.openNativeFromNative.bind(this, props);
|
|
183
|
-
href = '#';
|
|
184
|
-
} else {
|
|
185
|
-
// If we are on a native app, but the other native app is not available
|
|
186
|
-
// we open the web link, this is done by the href prop. We still
|
|
187
|
-
// have to call the prop callback
|
|
188
|
-
onClick = AppLinker.openWeb.bind(this, props);
|
|
189
|
-
}
|
|
190
|
-
} else if (isMobile() && appInfo) {
|
|
191
|
-
// If we are on the "mobile web version", we try to open the native app
|
|
192
|
-
// if it exists with an universal links. If it fails, we redirect to the web
|
|
193
|
-
// version of the requested app
|
|
194
|
-
// Only on iOS ATM
|
|
195
|
-
if (isAndroid()) {
|
|
196
|
-
onClick = AppLinker.openNativeFromWeb.bind(this, props);
|
|
197
|
-
} else {
|
|
198
|
-
// Since generateUniversalLink can rise an error, let's catch it to not crash
|
|
199
|
-
// all the page.
|
|
200
|
-
try {
|
|
201
|
-
href = generateUniversalLink({
|
|
202
|
-
slug: slug,
|
|
203
|
-
nativePath: nativePath,
|
|
204
|
-
fallbackUrl: href
|
|
205
|
-
});
|
|
206
|
-
} catch (err) {
|
|
207
|
-
console.error(err);
|
|
208
|
-
href = '#';
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
95
|
return {
|
|
214
96
|
href: href,
|
|
215
97
|
onClick: onClick
|
|
216
98
|
};
|
|
217
99
|
}
|
|
218
|
-
}, {
|
|
219
|
-
key: "openNativeFromWeb",
|
|
220
|
-
value: function openNativeFromWeb(props, ev) {
|
|
221
|
-
var href = props.href,
|
|
222
|
-
nativePath = props.nativePath,
|
|
223
|
-
onAppSwitch = props.onAppSwitch;
|
|
224
|
-
var slug = AppLinker.getSlug(props);
|
|
225
|
-
var appInfo = NATIVE_APP_INFOS[slug];
|
|
226
|
-
|
|
227
|
-
if (ev) {
|
|
228
|
-
ev.preventDefault();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
AppLinker.onAppSwitch(onAppSwitch);
|
|
232
|
-
openDeeplinkOrRedirect(appInfo.uri + (nativePath === '/' ? '' : nativePath), function () {
|
|
233
|
-
window.location.href = href;
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
100
|
}, {
|
|
237
101
|
key: "onAppSwitch",
|
|
238
102
|
value: function onAppSwitch(onAppSwitchFn) {
|
|
@@ -240,22 +104,6 @@ export var AppLinker = /*#__PURE__*/function (_React$Component) {
|
|
|
240
104
|
onAppSwitchFn();
|
|
241
105
|
}
|
|
242
106
|
}
|
|
243
|
-
}, {
|
|
244
|
-
key: "openNativeFromNative",
|
|
245
|
-
value: function openNativeFromNative(props, ev) {
|
|
246
|
-
var onAppSwitch = props.onAppSwitch;
|
|
247
|
-
var slug = AppLinker.getSlug(props);
|
|
248
|
-
|
|
249
|
-
if (ev) {
|
|
250
|
-
ev.preventDefault();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
var appInfo = NATIVE_APP_INFOS[slug];
|
|
254
|
-
AppLinker.onAppSwitch(onAppSwitch);
|
|
255
|
-
startApp(appInfo).catch(function (err) {
|
|
256
|
-
console.error('AppLinker: Could not open native app', err);
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
107
|
}, {
|
|
260
108
|
key: "openWeb",
|
|
261
109
|
value: function openWeb(props) {
|
|
@@ -268,34 +116,17 @@ export var AppLinker = /*#__PURE__*/function (_React$Component) {
|
|
|
268
116
|
|
|
269
117
|
_defineProperty(AppLinker, "contextType", WebviewContext);
|
|
270
118
|
|
|
271
|
-
AppLinker.defaultProps = {
|
|
272
|
-
nativePath: '/'
|
|
273
|
-
};
|
|
274
119
|
AppLinker.propTypes = {
|
|
275
|
-
/** DEPRECATED: please use app.slug prop */
|
|
276
|
-
slug: PropTypes.string,
|
|
277
|
-
|
|
278
120
|
/*
|
|
279
121
|
Full web url : Used by default on desktop browser
|
|
280
122
|
Used as a fallback_uri on mobile web
|
|
281
123
|
*/
|
|
282
124
|
href: PropTypes.string,
|
|
283
|
-
|
|
284
|
-
/*
|
|
285
|
-
Path used for "native link"
|
|
286
|
-
*/
|
|
287
|
-
nativePath: PropTypes.string,
|
|
288
125
|
onAppSwitch: PropTypes.func,
|
|
289
126
|
app: PropTypes.shape({
|
|
290
127
|
// Slug of the app : drive / banks ...
|
|
291
|
-
slug: PropTypes.string.isRequired
|
|
292
|
-
// Information about mobile native app
|
|
293
|
-
mobile: PropTypes.shape({
|
|
294
|
-
schema: PropTypes.string,
|
|
295
|
-
id_playstore: PropTypes.string,
|
|
296
|
-
id_appstore: PropTypes.string
|
|
297
|
-
})
|
|
128
|
+
slug: PropTypes.string.isRequired
|
|
298
129
|
}).isRequired
|
|
299
130
|
};
|
|
300
131
|
export default withClient(AppLinker);
|
|
301
|
-
export {
|
|
132
|
+
export { getUniversalLinkDomain, generateWebLink, generateUniversalLink };
|
|
@@ -1,14 +1 @@
|
|
|
1
|
-
import { isAndroidApp } from 'cozy-device-helper';
|
|
2
|
-
export var NATIVE_APP_INFOS = {
|
|
3
|
-
drive: {
|
|
4
|
-
appId: 'io.cozy.drive.mobile',
|
|
5
|
-
uri: 'cozydrive://',
|
|
6
|
-
name: 'Cozy Drive'
|
|
7
|
-
},
|
|
8
|
-
banks: {
|
|
9
|
-
appId: isAndroidApp() ? 'io.cozy.banks.mobile' : 'io.cozy.banks',
|
|
10
|
-
uri: 'cozybanks://',
|
|
11
|
-
name: 'Cozy Banks'
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
1
|
export var UNIVERSAL_LINK_URL = 'https://links.mycozy.cloud';
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`app icon should not crash if no href 1`] = `
|
|
4
|
-
<div>
|
|
5
|
-
<div>
|
|
6
|
-
<a>
|
|
7
|
-
Open
|
|
8
|
-
Cozy Drive
|
|
9
|
-
</a>
|
|
10
|
-
</div>
|
|
11
|
-
</div>
|
|
12
|
-
`;
|
|
13
|
-
|
|
14
|
-
exports[`app icon should render correctly 1`] = `
|
|
15
|
-
<div>
|
|
16
|
-
<div>
|
|
17
|
-
<a
|
|
18
|
-
href="https://fake.link"
|
|
19
|
-
>
|
|
20
|
-
Open
|
|
21
|
-
Cozy Drive
|
|
22
|
-
</a>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
`;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export default function (fn, duration, keyFn) {
|
|
2
|
-
const memo = {}
|
|
3
|
-
return arg => {
|
|
4
|
-
const key = keyFn(arg)
|
|
5
|
-
const memoInfo = memo[key]
|
|
6
|
-
const uptodate =
|
|
7
|
-
memoInfo && memoInfo.result && memoInfo.date - Date.now() < duration
|
|
8
|
-
if (!uptodate) {
|
|
9
|
-
memo[key] = { result: fn(arg), date: Date.now() }
|
|
10
|
-
}
|
|
11
|
-
return memo[key].result
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Those tests are here to test previous AppLinker implementation base on
|
|
3
|
-
* `slug` prop.
|
|
4
|
-
* Now that AppLinkers implements `app` prop and uses `app.slug`, the old
|
|
5
|
-
* `slug` prop is deprecated
|
|
6
|
-
* Those tests should be kept until `slug` prop is completely removed
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { render } from '@testing-library/react'
|
|
10
|
-
import userEvent from '@testing-library/user-event'
|
|
11
|
-
import React from 'react'
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
isMobileApp,
|
|
15
|
-
isMobile,
|
|
16
|
-
openDeeplinkOrRedirect,
|
|
17
|
-
startApp,
|
|
18
|
-
isAndroid,
|
|
19
|
-
checkApp
|
|
20
|
-
} from 'cozy-device-helper'
|
|
21
|
-
|
|
22
|
-
import AppLinker from '.'
|
|
23
|
-
import { generateUniversalLink } from './native'
|
|
24
|
-
jest.useFakeTimers()
|
|
25
|
-
|
|
26
|
-
const setup = ({ app, onAppSwitch }) => {
|
|
27
|
-
return {
|
|
28
|
-
user: userEvent.setup({ delay: null }),
|
|
29
|
-
...render(
|
|
30
|
-
<AppLinker
|
|
31
|
-
onAppSwitch={onAppSwitch}
|
|
32
|
-
slug={app.slug}
|
|
33
|
-
href="https://fake.link"
|
|
34
|
-
>
|
|
35
|
-
{({ onClick, href, name }) => (
|
|
36
|
-
<div>
|
|
37
|
-
<a href={href} onClick={onClick}>
|
|
38
|
-
Open {name}
|
|
39
|
-
</a>
|
|
40
|
-
</div>
|
|
41
|
-
)}
|
|
42
|
-
</AppLinker>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
jest.mock('./native', () => ({
|
|
48
|
-
...jest.requireActual('./native'),
|
|
49
|
-
generateUniversalLink: jest.fn()
|
|
50
|
-
}))
|
|
51
|
-
|
|
52
|
-
jest.mock('cozy-device-helper', () => ({
|
|
53
|
-
...jest.requireActual('cozy-device-helper'),
|
|
54
|
-
isMobileApp: jest.fn(),
|
|
55
|
-
isMobile: jest.fn(),
|
|
56
|
-
openDeeplinkOrRedirect: jest.fn(),
|
|
57
|
-
startApp: jest.fn().mockResolvedValue(),
|
|
58
|
-
isAndroid: jest.fn(),
|
|
59
|
-
checkApp: jest.fn()
|
|
60
|
-
}))
|
|
61
|
-
|
|
62
|
-
const app = {
|
|
63
|
-
slug: 'drive',
|
|
64
|
-
name: 'Drive'
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
describe('app icon', () => {
|
|
68
|
-
let spyConsoleError, spyConsoleWarn, appSwitchMock
|
|
69
|
-
|
|
70
|
-
beforeEach(() => {
|
|
71
|
-
isMobileApp.mockReturnValue(false)
|
|
72
|
-
spyConsoleError = jest.spyOn(console, 'error')
|
|
73
|
-
spyConsoleError.mockImplementation(() => {})
|
|
74
|
-
spyConsoleWarn = jest.spyOn(console, 'warn')
|
|
75
|
-
spyConsoleWarn.mockImplementation(() => {})
|
|
76
|
-
isMobileApp.mockReturnValue(false)
|
|
77
|
-
isMobile.mockReturnValue(false)
|
|
78
|
-
isAndroid.mockReturnValue(false)
|
|
79
|
-
appSwitchMock = jest.fn()
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
afterEach(() => {
|
|
83
|
-
spyConsoleError.mockRestore()
|
|
84
|
-
spyConsoleWarn.mockRestore()
|
|
85
|
-
jest.restoreAllMocks()
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('should render correctly', () => {
|
|
89
|
-
const { container } = setup({ app })
|
|
90
|
-
expect(container).toMatchSnapshot()
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('should work for web -> web', async () => {
|
|
94
|
-
isMobileApp.mockReturnValue(false)
|
|
95
|
-
const { container, user } = setup({ app, onAppSwitch: appSwitchMock })
|
|
96
|
-
const link = container.querySelector('a')
|
|
97
|
-
await user.click(link)
|
|
98
|
-
expect(appSwitchMock).not.toHaveBeenCalled()
|
|
99
|
-
expect(startApp).not.toHaveBeenCalled()
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('should work for native -> native', async () => {
|
|
103
|
-
isMobileApp.mockReturnValue(true)
|
|
104
|
-
checkApp.mockResolvedValue(true)
|
|
105
|
-
const { container, user } = setup({ app, onAppSwitch: appSwitchMock })
|
|
106
|
-
const link = container.querySelector('a')
|
|
107
|
-
await user.click(link)
|
|
108
|
-
|
|
109
|
-
expect(startApp).toHaveBeenCalledWith({
|
|
110
|
-
appId: 'io.cozy.drive.mobile',
|
|
111
|
-
name: 'Cozy Drive',
|
|
112
|
-
uri: 'cozydrive://'
|
|
113
|
-
})
|
|
114
|
-
expect(appSwitchMock).toHaveBeenCalled()
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('should work for web -> native for Android (custom schema)', async () => {
|
|
118
|
-
isMobile.mockReturnValue(true)
|
|
119
|
-
isAndroid.mockResolvedValue(true)
|
|
120
|
-
const { container, user } = setup({ app, onAppSwitch: appSwitchMock })
|
|
121
|
-
const link = container.querySelector('a')
|
|
122
|
-
await user.click(link)
|
|
123
|
-
expect(openDeeplinkOrRedirect).toHaveBeenCalledWith(
|
|
124
|
-
'cozydrive://',
|
|
125
|
-
expect.any(Function)
|
|
126
|
-
)
|
|
127
|
-
expect(appSwitchMock).toHaveBeenCalled()
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('should work for web -> native for iOS (universal link)', async () => {
|
|
131
|
-
isMobile.mockReturnValue(true)
|
|
132
|
-
const { container, user } = setup({ app, onAppSwitch: appSwitchMock })
|
|
133
|
-
const link = container.querySelector('a')
|
|
134
|
-
await user.click(link)
|
|
135
|
-
|
|
136
|
-
expect(generateUniversalLink).toHaveBeenCalled()
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('should work for native -> web', async () => {
|
|
140
|
-
isMobileApp.mockReturnValue(true)
|
|
141
|
-
const { container, user } = setup({ app, onAppSwitch: appSwitchMock })
|
|
142
|
-
const link = container.querySelector('a')
|
|
143
|
-
await user.click(link)
|
|
144
|
-
expect(appSwitchMock).toHaveBeenCalled()
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('should not crash if no href', () => {
|
|
148
|
-
isMobileApp.mockReturnValue(true)
|
|
149
|
-
const { container } = render(
|
|
150
|
-
<AppLinker onAppSwitch={appSwitchMock} slug={app.slug}>
|
|
151
|
-
{({ onClick, href, name }) => (
|
|
152
|
-
<div>
|
|
153
|
-
<a href={href} onClick={onClick}>
|
|
154
|
-
Open {name}
|
|
155
|
-
</a>
|
|
156
|
-
</div>
|
|
157
|
-
)}
|
|
158
|
-
</AppLinker>
|
|
159
|
-
)
|
|
160
|
-
expect(container).toMatchSnapshot()
|
|
161
|
-
})
|
|
162
|
-
})
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export default function (fn, duration, keyFn) {
|
|
2
|
-
var memo = {};
|
|
3
|
-
return function (arg) {
|
|
4
|
-
var key = keyFn(arg);
|
|
5
|
-
var memoInfo = memo[key];
|
|
6
|
-
var uptodate = memoInfo && memoInfo.result && memoInfo.date - Date.now() < duration;
|
|
7
|
-
|
|
8
|
-
if (!uptodate) {
|
|
9
|
-
memo[key] = {
|
|
10
|
-
result: fn(arg),
|
|
11
|
-
date: Date.now()
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return memo[key].result;
|
|
16
|
-
};
|
|
17
|
-
}
|