@applicaster/zapp-react-dom-app 12.0.0-alpha.4400210593 → 12.0.0-alpha.4510795609
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/App/InteractionManager/index.tsx +117 -16
- package/App/Loader/appLoader.js +2 -6
- package/App/Loader/setUpRTL.js +3 -3
- package/App/Loader/utils/const.js +3 -0
- package/App/Loader/utils/index.js +3 -4
- package/App/Loader/utils/platform.js +48 -0
- package/Polyfills/AnalyticsBridge/index.ts +5 -1
- package/Polyfills/AppLoaderBridge/utils/enums.ts +1 -0
- package/package.json +6 -6
- package/App/Loader/utils/__tests__/getAvailableAppLanguages.test.js +0 -22
|
@@ -31,14 +31,23 @@ import {
|
|
|
31
31
|
import { PlayerContentContext } from "@applicaster/zapp-react-dom-ui-components/Contexts";
|
|
32
32
|
|
|
33
33
|
import { withNavigator } from "@applicaster/zapp-react-native-ui-components/Decorators/Navigator";
|
|
34
|
-
import { Platform } from "react-native";
|
|
35
34
|
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
36
35
|
import { getXray } from "@applicaster/zapp-react-native-utils/logger";
|
|
37
36
|
import { confirmationDialogStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
|
|
37
|
+
import {
|
|
38
|
+
isVizioPlatform,
|
|
39
|
+
isSamsungPlatform,
|
|
40
|
+
isLgPlatform,
|
|
41
|
+
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
42
|
+
|
|
43
|
+
import { OnScreenKeyboard } from "@applicaster/zapp-react-dom-ui-components/Components/OnScreenKeyboard";
|
|
38
44
|
|
|
39
45
|
const { withXray } = getXray();
|
|
40
46
|
const globalAny: any = global;
|
|
41
47
|
|
|
48
|
+
const shouldUseOnScreenKeyboard = () =>
|
|
49
|
+
isVizioPlatform() || window.applicaster.useOnScreenKeyboard;
|
|
50
|
+
|
|
42
51
|
type Props = {
|
|
43
52
|
displayState: string;
|
|
44
53
|
setDisplayState: (state: string) => void;
|
|
@@ -56,7 +65,7 @@ type Props = {
|
|
|
56
65
|
};
|
|
57
66
|
};
|
|
58
67
|
|
|
59
|
-
type State = { isKeyboardVisible: boolean };
|
|
68
|
+
type State = { isKeyboardVisible: boolean; keyboardInput: string };
|
|
60
69
|
|
|
61
70
|
type KeyCode = { code: string; keyCode: number | string };
|
|
62
71
|
|
|
@@ -76,6 +85,7 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
76
85
|
sequenceTimeout: NodeJS.Timeout | null; // timeoutID
|
|
77
86
|
userSequence: number[] = [];
|
|
78
87
|
confirmDialog: any;
|
|
88
|
+
isDismissing = false;
|
|
79
89
|
|
|
80
90
|
constructor(props) {
|
|
81
91
|
super(props);
|
|
@@ -84,6 +94,7 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
84
94
|
|
|
85
95
|
this.state = {
|
|
86
96
|
isKeyboardVisible: false,
|
|
97
|
+
keyboardInput: "",
|
|
87
98
|
};
|
|
88
99
|
|
|
89
100
|
this.onMouseMoveListener = debounce({
|
|
@@ -116,6 +127,10 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
116
127
|
this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
|
|
117
128
|
this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
|
|
118
129
|
this.performExit = this.performExit.bind(this);
|
|
130
|
+
this.handleInputFocus = this.handleInputFocus.bind(this);
|
|
131
|
+
this.handleInputBlur = this.handleInputBlur.bind(this);
|
|
132
|
+
this.handleKeyboardInput = this.handleKeyboardInput.bind(this);
|
|
133
|
+
this.handleKeyboardDismiss = this.handleKeyboardDismiss.bind(this);
|
|
119
134
|
|
|
120
135
|
this.confirmDialog.setConfirmAction(this.performExit);
|
|
121
136
|
this.confirmDialog.setCancelAction(this.onConfirmDialogClose);
|
|
@@ -138,6 +153,8 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
138
153
|
false
|
|
139
154
|
);
|
|
140
155
|
|
|
156
|
+
document.addEventListener("focusin", this.handleInputFocus);
|
|
157
|
+
|
|
141
158
|
document.addEventListener(
|
|
142
159
|
"cursorStateChange",
|
|
143
160
|
this.cursorVisibilityChange,
|
|
@@ -155,28 +172,31 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
155
172
|
this.cursorVisibilityChange
|
|
156
173
|
);
|
|
157
174
|
|
|
158
|
-
document.removeEventListener(
|
|
159
|
-
"keyboardStateChange",
|
|
160
|
-
this.onKeyboardStateChange
|
|
161
|
-
);
|
|
175
|
+
document.removeEventListener("focusin", this.handleInputFocus);
|
|
162
176
|
|
|
163
177
|
document.removeEventListener("mousedown", this.onMouseDownListener);
|
|
164
178
|
|
|
165
179
|
if (this.timeout) {
|
|
166
180
|
this.clearTimeout();
|
|
167
181
|
}
|
|
182
|
+
|
|
183
|
+
this.isDismissing = false;
|
|
168
184
|
}
|
|
169
185
|
|
|
170
186
|
performExit() {
|
|
171
|
-
if (
|
|
187
|
+
if (isSamsungPlatform()) {
|
|
172
188
|
this.onConfirmDialogClose();
|
|
173
189
|
sendQuickBrickEvent(QUICK_BRICK_EVENTS.MOVE_APP_TO_BACKGROUND);
|
|
174
190
|
}
|
|
175
191
|
|
|
176
|
-
if (
|
|
192
|
+
if (isLgPlatform()) {
|
|
177
193
|
// webOS recommend to use this method when implemention a custom exit
|
|
178
194
|
globalAny.close();
|
|
179
195
|
}
|
|
196
|
+
|
|
197
|
+
if (isVizioPlatform()) {
|
|
198
|
+
window?.VIZIO?.exitApplication();
|
|
199
|
+
}
|
|
180
200
|
}
|
|
181
201
|
|
|
182
202
|
handleWebOsBack() {
|
|
@@ -205,7 +225,7 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
205
225
|
platformBack() {
|
|
206
226
|
try {
|
|
207
227
|
// TODO: temporary hack until this code is refactored
|
|
208
|
-
if (
|
|
228
|
+
if (isSamsungPlatform() || isVizioPlatform()) {
|
|
209
229
|
const { isDialogVisible } = confirmationDialogStore.getState();
|
|
210
230
|
|
|
211
231
|
if (isDialogVisible) {
|
|
@@ -218,7 +238,7 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
218
238
|
cancelCompletion: this.onConfirmDialogClose,
|
|
219
239
|
});
|
|
220
240
|
}
|
|
221
|
-
} else if (
|
|
241
|
+
} else if (isLgPlatform()) {
|
|
222
242
|
this.handleWebOsBack();
|
|
223
243
|
}
|
|
224
244
|
} catch (e) {
|
|
@@ -441,6 +461,7 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
441
461
|
|
|
442
462
|
onKeyDown(event) {
|
|
443
463
|
const { displayState, setDisplayState, navigator } = this.props;
|
|
464
|
+
const { isKeyboardVisible } = this.state;
|
|
444
465
|
|
|
445
466
|
const { isDialogVisible } = confirmationDialogStore.getState();
|
|
446
467
|
|
|
@@ -451,6 +472,16 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
451
472
|
}, LONG_KEY_PRESS_TIMEOUT);
|
|
452
473
|
}
|
|
453
474
|
|
|
475
|
+
if (isKeyboardVisible && shouldUseOnScreenKeyboard()) {
|
|
476
|
+
if (keyCode(event).matchesAny("Escape", "Back")) {
|
|
477
|
+
event.preventDefault();
|
|
478
|
+
event.stopPropagation();
|
|
479
|
+
this.handleKeyboardDismiss();
|
|
480
|
+
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
454
485
|
/**
|
|
455
486
|
When the player is displayed, we listen to Native Play / Pause / Stop
|
|
456
487
|
buttons. Any other key press will display the transport controls
|
|
@@ -567,7 +598,7 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
567
598
|
}
|
|
568
599
|
|
|
569
600
|
if (keyCode(event).matches(KEYS.Exit)) {
|
|
570
|
-
if (
|
|
601
|
+
if (isSamsungPlatform() || shouldUseOnScreenKeyboard()) {
|
|
571
602
|
this.performExit();
|
|
572
603
|
|
|
573
604
|
return;
|
|
@@ -592,6 +623,12 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
592
623
|
focusManager.moveFocus(direction);
|
|
593
624
|
}
|
|
594
625
|
|
|
626
|
+
if (!isDialogVisible) {
|
|
627
|
+
// run focus recovery on user interaction attempt
|
|
628
|
+
// probably we failed to set initial focus for some reason
|
|
629
|
+
focusManager.recoverFocus();
|
|
630
|
+
}
|
|
631
|
+
|
|
595
632
|
if (
|
|
596
633
|
displayState === DISPLAY_STATES.PLAYER ||
|
|
597
634
|
displayState === DISPLAY_STATES.HUD
|
|
@@ -616,11 +653,9 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
616
653
|
};
|
|
617
654
|
|
|
618
655
|
if (deltaY > 0) {
|
|
619
|
-
DIRECTION.value =
|
|
620
|
-
Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "down" : "up";
|
|
656
|
+
DIRECTION.value = isLgPlatform() ? "down" : "up";
|
|
621
657
|
} else if (deltaY < 0) {
|
|
622
|
-
DIRECTION.value =
|
|
623
|
-
Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "up" : "down";
|
|
658
|
+
DIRECTION.value = isLgPlatform() ? "up" : "down";
|
|
624
659
|
}
|
|
625
660
|
|
|
626
661
|
if (
|
|
@@ -656,10 +691,76 @@ export function withInteractionManager(Component: React.FC) {
|
|
|
656
691
|
|
|
657
692
|
onConfirmDialogClose() {
|
|
658
693
|
this.confirmDialog.hideDialog();
|
|
694
|
+
|
|
695
|
+
// restore initial focus after closing dialog
|
|
696
|
+
focusManager.setInitialFocus();
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
handleInputFocus = (event: FocusEvent) => {
|
|
700
|
+
if (!shouldUseOnScreenKeyboard()) return;
|
|
701
|
+
const target = event.target as HTMLElement;
|
|
702
|
+
|
|
703
|
+
if (this.isDismissing) {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
|
|
708
|
+
this.setState({
|
|
709
|
+
isKeyboardVisible: true,
|
|
710
|
+
keyboardInput: (target as HTMLInputElement).value || "",
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
handleInputBlur(event: FocusEvent) {
|
|
716
|
+
if (!shouldUseOnScreenKeyboard()) return;
|
|
717
|
+
|
|
718
|
+
const target = event.target as HTMLElement;
|
|
719
|
+
|
|
720
|
+
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
|
|
721
|
+
const relatedTarget = event.relatedTarget as HTMLElement;
|
|
722
|
+
|
|
723
|
+
if (
|
|
724
|
+
!relatedTarget ||
|
|
725
|
+
(relatedTarget.tagName !== "INPUT" &&
|
|
726
|
+
relatedTarget.tagName !== "TEXTAREA")
|
|
727
|
+
) {
|
|
728
|
+
this.setState({ isKeyboardVisible: false });
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
handleKeyboardDismiss = () => {
|
|
734
|
+
this.isDismissing = true;
|
|
735
|
+
|
|
736
|
+
this.setState(
|
|
737
|
+
{
|
|
738
|
+
isKeyboardVisible: false,
|
|
739
|
+
keyboardInput: "",
|
|
740
|
+
},
|
|
741
|
+
() => {
|
|
742
|
+
this.isDismissing = false;
|
|
743
|
+
}
|
|
744
|
+
);
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
handleKeyboardInput(value: string) {
|
|
748
|
+
this.setState({ keyboardInput: value });
|
|
659
749
|
}
|
|
660
750
|
|
|
661
751
|
render() {
|
|
662
|
-
return
|
|
752
|
+
return (
|
|
753
|
+
<>
|
|
754
|
+
<Component {...this.props} />
|
|
755
|
+
{shouldUseOnScreenKeyboard() && this.state.isKeyboardVisible && (
|
|
756
|
+
<OnScreenKeyboard
|
|
757
|
+
initialValue={this.state.keyboardInput}
|
|
758
|
+
onInput={this.handleKeyboardInput}
|
|
759
|
+
onDismiss={this.handleKeyboardDismiss}
|
|
760
|
+
/>
|
|
761
|
+
)}
|
|
762
|
+
</>
|
|
763
|
+
);
|
|
663
764
|
}
|
|
664
765
|
}
|
|
665
766
|
|
package/App/Loader/appLoader.js
CHANGED
|
@@ -8,11 +8,7 @@ export const appLoaderImpl =
|
|
|
8
8
|
) =>
|
|
9
9
|
async (dispatch, getState) => {
|
|
10
10
|
try {
|
|
11
|
-
const {
|
|
12
|
-
plugins,
|
|
13
|
-
pluginConfigurations,
|
|
14
|
-
remoteConfigurations: { localizations },
|
|
15
|
-
} = getState();
|
|
11
|
+
const { plugins, pluginConfigurations } = getState();
|
|
16
12
|
|
|
17
13
|
// Await crucial tasks
|
|
18
14
|
await loadLocale();
|
|
@@ -20,7 +16,7 @@ export const appLoaderImpl =
|
|
|
20
16
|
await loadAnalyticsPlugins(plugins, pluginConfigurations);
|
|
21
17
|
|
|
22
18
|
// Remaining loaders
|
|
23
|
-
const loaders = [loadDomPlugins(plugins), setUpRTL(
|
|
19
|
+
const loaders = [loadDomPlugins(plugins), setUpRTL()];
|
|
24
20
|
|
|
25
21
|
// Await for the remaining tasks and return when they are all complete
|
|
26
22
|
await Promise.all(loaders);
|
package/App/Loader/setUpRTL.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
2
2
|
import { I18nManager } from "react-native";
|
|
3
3
|
|
|
4
|
-
export async function setUpRTL(
|
|
5
|
-
const isRTL =
|
|
4
|
+
export async function setUpRTL() {
|
|
5
|
+
const isRTL = getIsRTL();
|
|
6
6
|
I18nManager.forceRTL(isRTL);
|
|
7
7
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
import { appStore as AppStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
3
3
|
import { NativeModules } from "react-native";
|
|
4
|
-
import { getAppData } from "../../../Polyfills/AppData";
|
|
5
4
|
|
|
6
5
|
export const UI_LANGUAGE = "uiLanguage";
|
|
7
6
|
|
|
@@ -15,11 +14,11 @@ export const persistLanguageSelection = async (languageCode) => {
|
|
|
15
14
|
return NativeModules.LocalStorage.setItem(UI_LANGUAGE, languageCode);
|
|
16
15
|
};
|
|
17
16
|
|
|
18
|
-
export const getAvailableAppLanguagesImpl = () => {
|
|
17
|
+
export const getAvailableAppLanguagesImpl = (appStore) => {
|
|
19
18
|
try {
|
|
20
|
-
const
|
|
19
|
+
const remoteConfigurations = appStore.get("remoteConfigurations");
|
|
21
20
|
|
|
22
|
-
return
|
|
21
|
+
return R.keys(remoteConfigurations.localizations);
|
|
23
22
|
} catch (e) {
|
|
24
23
|
return [];
|
|
25
24
|
}
|
|
@@ -42,6 +42,36 @@ export const isSamsungPlatform = () => {
|
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Checks if we are on the Vizio platform by using the userAgent string
|
|
47
|
+
*
|
|
48
|
+
* Use this method when you need to identify the platform on runtime
|
|
49
|
+
* before the VIZIO Companion Library has loaded
|
|
50
|
+
*/
|
|
51
|
+
export const isVizioPlatform = () => {
|
|
52
|
+
const userAgent = getUserAgent();
|
|
53
|
+
|
|
54
|
+
const isVizioAgent =
|
|
55
|
+
userAgent.includes(PLATFORMS.vizio) ||
|
|
56
|
+
userAgent.includes(PLATFORMS.smartcast) ||
|
|
57
|
+
userAgent.includes(PLATFORMS.conjure);
|
|
58
|
+
|
|
59
|
+
return isVizioAgent;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Checks if we are on the Vizio platform by checking for the global VIZIO object
|
|
64
|
+
* and the VIZIO Companion Library. This method does not use the userAgent string,
|
|
65
|
+
* because it mainly checks whether we have access to apis, which may not be available yet
|
|
66
|
+
*/
|
|
67
|
+
export const hasVizioAPIs = () => {
|
|
68
|
+
const hasAPIs =
|
|
69
|
+
typeof window.VIZIO !== "undefined" &&
|
|
70
|
+
window?.applicaster?.vizioLibraryDidLoad;
|
|
71
|
+
|
|
72
|
+
return hasAPIs;
|
|
73
|
+
};
|
|
74
|
+
|
|
45
75
|
/**
|
|
46
76
|
* platformSelect can't be used, because Platform.OS is overriden
|
|
47
77
|
* by overloadReactNativePlatform and don't support 'web' value
|
|
@@ -253,6 +283,24 @@ export const getDeviceData = async () => {
|
|
|
253
283
|
...tizenConnectionInfo,
|
|
254
284
|
device_type: getDeviceType(),
|
|
255
285
|
};
|
|
286
|
+
} else if (isVizioPlatform()) {
|
|
287
|
+
deviceData = {
|
|
288
|
+
...deviceData,
|
|
289
|
+
platform: "vizio",
|
|
290
|
+
deviceMake: "Vizio",
|
|
291
|
+
deviceType: "tv",
|
|
292
|
+
userAgent: getUserAgent(),
|
|
293
|
+
deviceWidth: window.innerWidth,
|
|
294
|
+
deviceHeight: window.innerHeight,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
if (hasVizioAPIs()) {
|
|
298
|
+
window.VIZIO.getFirmwareVersion(function (firmwareVersion) {
|
|
299
|
+
deviceData.osVersion = firmwareVersion;
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
deviceData.deviceModel = window.VIZIO.deviceModel;
|
|
303
|
+
}
|
|
256
304
|
}
|
|
257
305
|
|
|
258
306
|
return deviceData;
|
|
@@ -105,7 +105,11 @@ function isInvalidAnalyticsData(eventName, payload = null) {
|
|
|
105
105
|
|
|
106
106
|
export const AnalyticsBridge = (function () {
|
|
107
107
|
let registeredAnalyticPlugins: {
|
|
108
|
-
module: {
|
|
108
|
+
module: {
|
|
109
|
+
sendEvent: Function;
|
|
110
|
+
initialize?: Function;
|
|
111
|
+
getPlayerConfiguration?: Function;
|
|
112
|
+
};
|
|
109
113
|
configuration?: any;
|
|
110
114
|
}[] = [];
|
|
111
115
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-dom-app",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.4510795609",
|
|
4
4
|
"description": "Zapp App Component for Applicaster's Quick Brick React Native App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/applicaster/zapp-react-dom-app#readme",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@applicaster/zapp-react-dom-ui-components": "12.0.0-alpha.
|
|
26
|
-
"@applicaster/zapp-react-native-bridge": "12.0.0-alpha.
|
|
27
|
-
"@applicaster/zapp-react-native-redux": "12.0.0-alpha.
|
|
28
|
-
"@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.
|
|
29
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.
|
|
25
|
+
"@applicaster/zapp-react-dom-ui-components": "12.0.0-alpha.4510795609",
|
|
26
|
+
"@applicaster/zapp-react-native-bridge": "12.0.0-alpha.4510795609",
|
|
27
|
+
"@applicaster/zapp-react-native-redux": "12.0.0-alpha.4510795609",
|
|
28
|
+
"@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.4510795609",
|
|
29
|
+
"@applicaster/zapp-react-native-utils": "12.0.0-alpha.4510795609",
|
|
30
30
|
"abortcontroller-polyfill": "^1.7.5",
|
|
31
31
|
"history": "^4.7.2",
|
|
32
32
|
"react-router-dom": "^5.1.2",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
jest.mock("../../../../Polyfills/AppData", () => ({
|
|
2
|
-
getAppData: jest.fn(),
|
|
3
|
-
}));
|
|
4
|
-
|
|
5
|
-
describe("getAvailableAppLanguages", () => {
|
|
6
|
-
const { getAppData } = require("../../../../Polyfills/AppData");
|
|
7
|
-
const { getAvailableAppLanguagesImpl } = require("..");
|
|
8
|
-
|
|
9
|
-
it("return list of languages", () => {
|
|
10
|
-
const languages = ["en", "de", "fr", "en-UK", "en-GB"];
|
|
11
|
-
|
|
12
|
-
getAppData.mockReturnValue({ languages });
|
|
13
|
-
|
|
14
|
-
expect(getAvailableAppLanguagesImpl()).toEqual(languages);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("return list of languages", () => {
|
|
18
|
-
getAppData.mockReturnValue(undefined);
|
|
19
|
-
|
|
20
|
-
expect(getAvailableAppLanguagesImpl()).toEqual([]);
|
|
21
|
-
});
|
|
22
|
-
});
|