@applicaster/zapp-react-native-ui-components 15.0.0-alpha.5170277721 → 15.0.0-alpha.5197372201
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/Components/BaseFocusable/index.ios.ts +12 -2
- package/Components/Cell/Cell.tsx +14 -3
- package/Components/Cell/CellWithFocusable.tsx +9 -0
- package/Components/Cell/FocusableWrapper.tsx +3 -0
- package/Components/Cell/TvOSCellComponent.tsx +26 -5
- package/Components/Focusable/Focusable.tsx +4 -2
- package/Components/Focusable/FocusableTvOS.tsx +18 -1
- package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
- package/Components/FocusableGroup/FocusableTvOS.tsx +32 -1
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -8
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -6
- package/Components/HandlePlayable/HandlePlayable.tsx +26 -36
- package/Components/HandlePlayable/utils.ts +31 -0
- package/Components/Layout/TV/LayoutBackground.tsx +5 -2
- package/Components/Layout/TV/ScreenContainer.tsx +2 -6
- package/Components/Layout/TV/index.tsx +3 -4
- package/Components/Layout/TV/index.web.tsx +3 -4
- package/Components/LinkHandler/LinkHandler.tsx +2 -2
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +30 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
- package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +10 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +40 -39
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +95 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +86 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/index.test.ts +141 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
- package/Components/MasterCell/DefaultComponents/SecondaryImage/index.ts +1 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +8 -8
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -2
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +233 -11
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +19 -15
- package/Components/MasterCell/hoc/__tests__/withAsyncRender.test.tsx +219 -0
- package/Components/MasterCell/hoc/withAsyncRender.tsx +9 -7
- package/Components/MasterCell/index.tsx +2 -0
- package/Components/MasterCell/utils/__tests__/resolveColor.test.js +82 -3
- package/Components/MasterCell/utils/index.ts +61 -31
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +102 -87
- package/Components/MeasurmentsPortal/__tests__/MeasurementsPortal.test.tsx +355 -0
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +17 -9
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +16 -8
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
- package/Components/OfflineHandler/NotificationView/utils.ts +34 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
- package/Components/PlayerContainer/PlayerContainer.tsx +43 -55
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/River/ComponentsMap/ComponentsMap.tsx +16 -0
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
- package/Components/River/RefreshControl.tsx +9 -3
- package/Components/River/TV/River.tsx +31 -14
- package/Components/River/TV/index.tsx +8 -4
- package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
- package/Components/River/TV/utils/index.ts +4 -0
- package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/River/__tests__/componentsMap.test.js +38 -0
- package/Components/Screen/TV/index.web.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +66 -42
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
- package/Components/Screen/hooks.ts +75 -6
- package/Components/Screen/index.tsx +9 -4
- package/Components/Screen/navigationHandler.ts +49 -24
- package/Components/Screen/orientationHandler.ts +10 -13
- package/Components/ScreenResolver/index.tsx +26 -16
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
- package/Components/Tabs/TV/Tabs.tsx +20 -3
- package/Components/Tabs/TabContent.tsx +7 -4
- package/Components/Transitioner/Scene.tsx +10 -3
- package/Components/Transitioner/index.js +3 -3
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +118 -171
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerWrapper.tsx +14 -52
- package/Components/VideoModal/VideoModal.tsx +1 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
- package/Components/VideoModal/hooks/useModalSize.ts +5 -1
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +16 -12
- package/Components/VideoModal/utils.ts +19 -9
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
- package/Components/Viewport/ViewportAware/index.tsx +16 -7
- package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
- package/Contexts/ScreenContext/index.tsx +54 -19
- package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
- package/Contexts/ZappHookModalContext/index.tsx +37 -61
- package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
- package/Contexts/index.ts +0 -2
- package/Decorators/Analytics/index.tsx +6 -5
- package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
- package/Decorators/ConfigurationWrapper/const.ts +1 -0
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
- package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
- package/Helpers/DataSourceHelper/index.ts +19 -0
- package/events/index.ts +3 -0
- package/events/scrollEndReached.ts +15 -0
- package/index.d.ts +7 -0
- package/package.json +6 -5
- package/Components/River/TV/withTVEventHandler.tsx +0 -27
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
- package/Helpers/DataSourceHelper/index.js +0 -19
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
+
exports[`SecondaryImage - Image SecondaryImage fixed mode should not use async render props 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
style={
|
|
6
|
+
{
|
|
7
|
+
"borderRadius": 10,
|
|
8
|
+
"height": 100,
|
|
9
|
+
"width": 100,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
>
|
|
13
|
+
<Image
|
|
14
|
+
displayMode="fixed"
|
|
15
|
+
fitPosition="center"
|
|
16
|
+
fixedHeight={100}
|
|
17
|
+
fixedWidth={100}
|
|
18
|
+
imageSizing="fill"
|
|
19
|
+
source={
|
|
20
|
+
{
|
|
21
|
+
"uri": "someUrl",
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
style={
|
|
25
|
+
{
|
|
26
|
+
"aspectRatio": 1,
|
|
27
|
+
"borderRadius": 10,
|
|
28
|
+
"height": 100,
|
|
29
|
+
"width": 100,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
uri="someUrl"
|
|
33
|
+
/>
|
|
34
|
+
</View>
|
|
35
|
+
`;
|
|
36
|
+
|
|
3
37
|
exports[`SecondaryImage - Image SecondaryImage should not render if no aspect ratio (dynamic) 1`] = `null`;
|
|
4
38
|
|
|
5
39
|
exports[`SecondaryImage - Image SecondaryImage should not render if no uri 1`] = `null`;
|
|
6
40
|
|
|
41
|
+
exports[`SecondaryImage - Image SecondaryImage should not render in dynamic mode without image 1`] = `null`;
|
|
42
|
+
|
|
7
43
|
exports[`SecondaryImage - Image SecondaryImage should render if known dimensions 1`] = `
|
|
8
44
|
<View
|
|
9
45
|
onLayout={[Function]}
|
|
@@ -17,6 +53,10 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
|
|
|
17
53
|
>
|
|
18
54
|
<Image
|
|
19
55
|
displayMode="dynamic"
|
|
56
|
+
fitPosition="center"
|
|
57
|
+
fixedHeight={0}
|
|
58
|
+
fixedWidth={0}
|
|
59
|
+
imageSizing="fill"
|
|
20
60
|
onAsyncRender={[Function]}
|
|
21
61
|
source={
|
|
22
62
|
{
|
|
@@ -35,3 +75,49 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
|
|
|
35
75
|
/>
|
|
36
76
|
</View>
|
|
37
77
|
`;
|
|
78
|
+
|
|
79
|
+
exports[`SecondaryImage - Image SecondaryImage should render in fixed mode with known dimensions 1`] = `
|
|
80
|
+
<View
|
|
81
|
+
style={
|
|
82
|
+
{
|
|
83
|
+
"borderRadius": 10,
|
|
84
|
+
"height": 100,
|
|
85
|
+
"width": 100,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
>
|
|
89
|
+
<Image
|
|
90
|
+
displayMode="fixed"
|
|
91
|
+
fitPosition="center"
|
|
92
|
+
fixedHeight={100}
|
|
93
|
+
fixedWidth={100}
|
|
94
|
+
imageSizing="fill"
|
|
95
|
+
source={
|
|
96
|
+
{
|
|
97
|
+
"uri": "someUrl",
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
style={
|
|
101
|
+
{
|
|
102
|
+
"aspectRatio": 1,
|
|
103
|
+
"borderRadius": 10,
|
|
104
|
+
"height": 100,
|
|
105
|
+
"width": 100,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
uri="someUrl"
|
|
109
|
+
/>
|
|
110
|
+
</View>
|
|
111
|
+
`;
|
|
112
|
+
|
|
113
|
+
exports[`SecondaryImage - Image SecondaryImage should render in fixed mode without image until loaded 1`] = `
|
|
114
|
+
<View
|
|
115
|
+
style={
|
|
116
|
+
{
|
|
117
|
+
"borderRadius": 5,
|
|
118
|
+
"height": 100,
|
|
119
|
+
"width": 100,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/>
|
|
123
|
+
`;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { SecondaryImage } from "../index";
|
|
2
|
+
|
|
3
|
+
describe("SecondaryImage - Configuration Builder", () => {
|
|
4
|
+
const mockValue = (config: any) => (key: string, transformer?: Function) => {
|
|
5
|
+
const value = config[key];
|
|
6
|
+
|
|
7
|
+
return transformer ? transformer(value) : value;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
it("should pass false as second argument to image_src_from_media_item", () => {
|
|
11
|
+
const config = {
|
|
12
|
+
secondary_image_switch: true,
|
|
13
|
+
secondary_image_position: "over_image",
|
|
14
|
+
secondary_image_visibility: "always",
|
|
15
|
+
secondary_image_image_key: "custom_image",
|
|
16
|
+
secondary_image_display_mode: "dynamic",
|
|
17
|
+
secondary_image_dynamic_width: 100,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const result = SecondaryImage({
|
|
21
|
+
value: mockValue(config),
|
|
22
|
+
currentPosition: "over_image",
|
|
23
|
+
state: "default",
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
expect(result).not.toBeNull();
|
|
27
|
+
expect(result?.elements).toBeDefined();
|
|
28
|
+
expect(result?.elements[0].data).toBeDefined();
|
|
29
|
+
|
|
30
|
+
const imageData = result?.elements[0].data[0];
|
|
31
|
+
expect(imageData.func).toBe("image_src_from_media_item");
|
|
32
|
+
expect(imageData.args).toEqual(["custom_image", false]);
|
|
33
|
+
expect(imageData.propName).toBe("uri");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should return null when secondary image is disabled", () => {
|
|
37
|
+
const config = {
|
|
38
|
+
secondary_image_switch: false,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const result = SecondaryImage({
|
|
42
|
+
value: mockValue(config),
|
|
43
|
+
currentPosition: "over_image",
|
|
44
|
+
state: "default",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(result).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should return null when position does not match currentPosition", () => {
|
|
51
|
+
const config = {
|
|
52
|
+
secondary_image_switch: true,
|
|
53
|
+
secondary_image_position: "above_text_label_1",
|
|
54
|
+
secondary_image_visibility: "always",
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const result = SecondaryImage({
|
|
58
|
+
value: mockValue(config),
|
|
59
|
+
currentPosition: "over_image",
|
|
60
|
+
state: "default",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(result).toBeNull();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should return null when visibility does not match state", () => {
|
|
67
|
+
const config = {
|
|
68
|
+
secondary_image_switch: true,
|
|
69
|
+
secondary_image_position: "over_image",
|
|
70
|
+
secondary_image_visibility: "focused",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const result = SecondaryImage({
|
|
74
|
+
value: mockValue(config),
|
|
75
|
+
currentPosition: "over_image",
|
|
76
|
+
state: "default",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(result).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should include display mode and image sizing in additionalProps", () => {
|
|
83
|
+
const config = {
|
|
84
|
+
secondary_image_switch: true,
|
|
85
|
+
secondary_image_position: "over_image",
|
|
86
|
+
secondary_image_visibility: "always",
|
|
87
|
+
secondary_image_image_key: "logo",
|
|
88
|
+
secondary_image_display_mode: "fixed",
|
|
89
|
+
secondary_image_image_sizing: "fill",
|
|
90
|
+
secondary_image_fit_position: "center",
|
|
91
|
+
secondary_image_fixed_width: 200,
|
|
92
|
+
secondary_image_fixed_height: 150,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const result = SecondaryImage({
|
|
96
|
+
value: mockValue(config),
|
|
97
|
+
currentPosition: "over_image",
|
|
98
|
+
state: "default",
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
expect(result?.elements[0].additionalProps).toMatchObject({
|
|
102
|
+
displayMode: "fixed",
|
|
103
|
+
imageSizing: "fill",
|
|
104
|
+
fitPosition: "center",
|
|
105
|
+
fixedWidth: 200,
|
|
106
|
+
fixedHeight: 150,
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should apply correct styles including margins and border radius", () => {
|
|
111
|
+
const config = {
|
|
112
|
+
secondary_image_switch: true,
|
|
113
|
+
secondary_image_position: "over_image",
|
|
114
|
+
secondary_image_visibility: "always",
|
|
115
|
+
secondary_image_display_mode: "fixed",
|
|
116
|
+
secondary_image_fixed_width: 100,
|
|
117
|
+
secondary_image_fixed_height: 100,
|
|
118
|
+
secondary_image_corner_radius: 12,
|
|
119
|
+
secondary_image_margin_top: 10,
|
|
120
|
+
secondary_image_margin_left: 5,
|
|
121
|
+
secondary_image_margin_right: 5,
|
|
122
|
+
secondary_image_margin_bottom: 10,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const result = SecondaryImage({
|
|
126
|
+
value: mockValue(config),
|
|
127
|
+
currentPosition: "over_image",
|
|
128
|
+
state: "default",
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(result?.elements[0].style).toMatchObject({
|
|
132
|
+
width: 100,
|
|
133
|
+
height: 100,
|
|
134
|
+
borderRadius: 12,
|
|
135
|
+
marginTop: 10,
|
|
136
|
+
marginLeft: 5,
|
|
137
|
+
marginRight: 5,
|
|
138
|
+
marginBottom: 10,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react-
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react-native";
|
|
2
2
|
import { Image } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { useGetImageDimensions } from "../useGetImageDimensions";
|
|
@@ -13,15 +13,16 @@ jest.spyOn(Image, "getSize").mockImplementation((_uri, success) => {
|
|
|
13
13
|
|
|
14
14
|
describe("useGetImageDimensions", () => {
|
|
15
15
|
it("should return aspect ration initially when known dimensions", async () => {
|
|
16
|
-
const { result
|
|
16
|
+
const { result } = renderHook(() =>
|
|
17
17
|
useGetImageDimensions("https://some_url.com", WIDTH, undefined)
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
expect(result.current).toBeUndefined();
|
|
21
|
-
await waitForNextUpdate();
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
await waitFor(() => {
|
|
23
|
+
expect(result.current).toEqual(
|
|
24
|
+
getDimension({ width: WIDTH, height: HEIGTH })
|
|
25
|
+
);
|
|
26
|
+
});
|
|
26
27
|
});
|
|
27
28
|
});
|
|
@@ -52,14 +52,14 @@ const _Text = ({
|
|
|
52
52
|
: textTransform(transformText, _label);
|
|
53
53
|
|
|
54
54
|
React.useLayoutEffect(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
if (cellFocused) {
|
|
56
|
+
switch (otherProps.state) {
|
|
57
|
+
case "focused":
|
|
58
|
+
accessibilityManager.addHeading(textLabel);
|
|
59
|
+
break;
|
|
60
|
+
case "focused_selected":
|
|
61
|
+
accessibilityManager.addHeading(`${textLabel}, Selected`);
|
|
62
|
+
break;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}, [cellFocused, otherProps.state, textLabel]);
|
|
@@ -4,7 +4,7 @@ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/nu
|
|
|
4
4
|
import { Button } from "./Button";
|
|
5
5
|
import {
|
|
6
6
|
getButtonsCount,
|
|
7
|
-
|
|
7
|
+
memoizedGetPluginIdentifier,
|
|
8
8
|
mapSelfAlignment,
|
|
9
9
|
} from "./utils";
|
|
10
10
|
|
|
@@ -80,7 +80,11 @@ export const TvActionButtons = ({
|
|
|
80
80
|
prefix: independentStyles ? prefixSpecificButton : buttonId(1),
|
|
81
81
|
value,
|
|
82
82
|
platformValue,
|
|
83
|
-
pluginIdentifier:
|
|
83
|
+
pluginIdentifier: memoizedGetPluginIdentifier(
|
|
84
|
+
configuration,
|
|
85
|
+
PREFIX,
|
|
86
|
+
index
|
|
87
|
+
),
|
|
84
88
|
suffixId: prefixSpecificButton,
|
|
85
89
|
preferredFocus: index === 0,
|
|
86
90
|
});
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { getPluginIdentifier } from "..";
|
|
1
|
+
import { getPluginIdentifier, memoizedGetPluginIdentifier } from "..";
|
|
2
2
|
|
|
3
3
|
describe("getPluginIdentifier", () => {
|
|
4
4
|
const prefix = "tv_buttons";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
beforeAll(() => {
|
|
7
|
+
memoizedGetPluginIdentifier.clear();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("returns the first valid plugin identifier", () => {
|
|
11
|
+
expect.assertions(2);
|
|
12
|
+
|
|
7
13
|
const configuration = {
|
|
8
14
|
tv_buttons_button_1_other: "value",
|
|
9
15
|
tv_buttons_button_1_assign_action:
|
|
@@ -13,13 +19,21 @@ describe("getPluginIdentifier", () => {
|
|
|
13
19
|
};
|
|
14
20
|
|
|
15
21
|
const index = 0;
|
|
16
|
-
|
|
17
22
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
18
23
|
|
|
24
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
25
|
+
configuration,
|
|
26
|
+
prefix,
|
|
27
|
+
index
|
|
28
|
+
);
|
|
29
|
+
|
|
19
30
|
expect(result).toEqual(configuration.tv_buttons_button_1_assign_action);
|
|
31
|
+
expect(memoizedResult).toEqual(result);
|
|
20
32
|
});
|
|
21
33
|
|
|
22
|
-
it("
|
|
34
|
+
it("returns the second valid plugin identifier", () => {
|
|
35
|
+
expect.assertions(2);
|
|
36
|
+
|
|
23
37
|
const configuration = {
|
|
24
38
|
tv_buttons_button_1_other: "value_1",
|
|
25
39
|
tv_buttons_button_1_assign_action:
|
|
@@ -30,24 +44,216 @@ describe("getPluginIdentifier", () => {
|
|
|
30
44
|
};
|
|
31
45
|
|
|
32
46
|
const index = 1;
|
|
33
|
-
|
|
34
47
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
35
48
|
|
|
49
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
50
|
+
configuration,
|
|
51
|
+
prefix,
|
|
52
|
+
index
|
|
53
|
+
);
|
|
54
|
+
|
|
36
55
|
expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
|
|
56
|
+
expect(memoizedResult).toEqual(result);
|
|
37
57
|
});
|
|
38
58
|
|
|
39
|
-
it("
|
|
59
|
+
it("returns undefined when there are no assign_action keys", () => {
|
|
60
|
+
expect.assertions(2);
|
|
61
|
+
|
|
40
62
|
const configuration = {};
|
|
63
|
+
const index = 0;
|
|
64
|
+
|
|
65
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
66
|
+
|
|
67
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
68
|
+
configuration,
|
|
69
|
+
prefix,
|
|
70
|
+
index
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(result).toBeUndefined();
|
|
74
|
+
expect(memoizedResult).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("skips undefined values and returns the correct plugin identifier", () => {
|
|
78
|
+
expect.assertions(2);
|
|
79
|
+
|
|
80
|
+
const configuration = {
|
|
81
|
+
tv_buttons_button_1_assign_action: "tv_buttons_button_1_assign_action",
|
|
82
|
+
tv_buttons_button_2_assign_action: undefined,
|
|
83
|
+
tv_buttons_button_3_assign_action: "tv_buttons_button_3_assign_action",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const index = 1;
|
|
87
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
88
|
+
|
|
89
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
90
|
+
configuration,
|
|
91
|
+
prefix,
|
|
92
|
+
index
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
expect(result).toEqual(configuration.tv_buttons_button_3_assign_action);
|
|
96
|
+
expect(memoizedResult).toEqual(result);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("handles missing intermediate keys and returns the correct plugin identifier", () => {
|
|
100
|
+
expect.assertions(2);
|
|
101
|
+
|
|
102
|
+
const configuration = {
|
|
103
|
+
tv_buttons_button_1_assign_action: "tv_buttons_button_1_assign_action",
|
|
104
|
+
tv_buttons_button_3_assign_action: "tv_buttons_button_3_assign_action",
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const index = 1;
|
|
108
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
109
|
+
|
|
110
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
111
|
+
configuration,
|
|
112
|
+
prefix,
|
|
113
|
+
index
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect(result).toEqual(configuration.tv_buttons_button_3_assign_action);
|
|
117
|
+
expect(memoizedResult).toEqual(result);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("skips empty string values and returns the first non-empty assign_action", () => {
|
|
121
|
+
expect.assertions(2);
|
|
122
|
+
|
|
123
|
+
const configuration = {
|
|
124
|
+
tv_buttons_button_1_assign_action: "",
|
|
125
|
+
tv_buttons_button_2_assign_action: "tv_buttons_button_2_assign_action",
|
|
126
|
+
};
|
|
41
127
|
|
|
42
128
|
const index = 0;
|
|
129
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
130
|
+
|
|
131
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
132
|
+
configuration,
|
|
133
|
+
prefix,
|
|
134
|
+
index
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
|
|
138
|
+
expect(memoizedResult).toEqual(result);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("returns undefined for negative index", () => {
|
|
142
|
+
expect.assertions(2);
|
|
143
|
+
|
|
144
|
+
const configuration = {
|
|
145
|
+
tv_buttons_button_1_assign_action: "a",
|
|
146
|
+
tv_buttons_button_2_assign_action: "b",
|
|
147
|
+
};
|
|
43
148
|
|
|
149
|
+
const index = -1;
|
|
44
150
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
45
151
|
|
|
152
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
153
|
+
configuration,
|
|
154
|
+
prefix,
|
|
155
|
+
index
|
|
156
|
+
);
|
|
157
|
+
|
|
46
158
|
expect(result).toBeUndefined();
|
|
159
|
+
expect(memoizedResult).toBeUndefined();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("returns undefined for out-of-bounds index", () => {
|
|
163
|
+
expect.assertions(2);
|
|
164
|
+
|
|
165
|
+
const configuration = {
|
|
166
|
+
tv_buttons_button_1_assign_action: "a",
|
|
167
|
+
tv_buttons_button_2_assign_action: "b",
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const index = 5;
|
|
171
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
172
|
+
|
|
173
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
174
|
+
configuration,
|
|
175
|
+
prefix,
|
|
176
|
+
index
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(result).toBeUndefined();
|
|
180
|
+
expect(memoizedResult).toBeUndefined();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("ignores keys with wrong prefix or format", () => {
|
|
184
|
+
expect.assertions(2);
|
|
185
|
+
|
|
186
|
+
const configuration = {
|
|
187
|
+
tv_buttons_button_1_assign_action: "a",
|
|
188
|
+
tv_buttons_wrongprefix_2_assign_action: "b",
|
|
189
|
+
tv_buttons_button_x_assign_action: "c",
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const index = 1;
|
|
193
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
194
|
+
|
|
195
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
196
|
+
configuration,
|
|
197
|
+
prefix,
|
|
198
|
+
index
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
expect(result).toBeUndefined();
|
|
202
|
+
expect(memoizedResult).toBeUndefined();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("returns undefined if all assign_actions are null or empty", () => {
|
|
206
|
+
expect.assertions(2);
|
|
207
|
+
|
|
208
|
+
const configuration = {
|
|
209
|
+
tv_buttons_button_1_assign_action: null,
|
|
210
|
+
tv_buttons_button_2_assign_action: undefined,
|
|
211
|
+
tv_buttons_button_3_assign_action: "",
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const index = 0;
|
|
215
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
216
|
+
|
|
217
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
218
|
+
configuration,
|
|
219
|
+
prefix,
|
|
220
|
+
index
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
expect(result).toBeUndefined();
|
|
224
|
+
expect(memoizedResult).toBeUndefined();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("handles non-string values correctly", () => {
|
|
228
|
+
expect.assertions(6);
|
|
229
|
+
|
|
230
|
+
const configuration = {
|
|
231
|
+
tv_buttons_button_1_assign_action: 123,
|
|
232
|
+
tv_buttons_button_2_assign_action: true,
|
|
233
|
+
tv_buttons_button_3_assign_action: { nested: "value" },
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
expect(getPluginIdentifier(configuration, prefix, 0)).toEqual(123);
|
|
237
|
+
expect(getPluginIdentifier(configuration, prefix, 1)).toEqual(true);
|
|
238
|
+
|
|
239
|
+
expect(getPluginIdentifier(configuration, prefix, 2)).toEqual({
|
|
240
|
+
nested: "value",
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
expect(memoizedGetPluginIdentifier(configuration, prefix, 0)).toEqual(123);
|
|
244
|
+
expect(memoizedGetPluginIdentifier(configuration, prefix, 1)).toEqual(true);
|
|
245
|
+
|
|
246
|
+
expect(memoizedGetPluginIdentifier(configuration, prefix, 2)).toEqual({
|
|
247
|
+
nested: "value",
|
|
248
|
+
});
|
|
47
249
|
});
|
|
48
250
|
});
|
|
49
251
|
|
|
50
|
-
describe("getPluginIdentifier - when configuration has
|
|
252
|
+
describe("getPluginIdentifier - when configuration has duplicate values", () => {
|
|
253
|
+
beforeAll(() => {
|
|
254
|
+
memoizedGetPluginIdentifier.clear();
|
|
255
|
+
});
|
|
256
|
+
|
|
51
257
|
const prefix = "tv_buttons";
|
|
52
258
|
|
|
53
259
|
const configuration = {
|
|
@@ -55,19 +261,35 @@ describe("getPluginIdentifier - when configuration has same values for different
|
|
|
55
261
|
tv_buttons_button_2_assign_action: "navigation_action",
|
|
56
262
|
};
|
|
57
263
|
|
|
58
|
-
it("
|
|
59
|
-
|
|
264
|
+
it("returns the first plugin identifier when values are identical", () => {
|
|
265
|
+
expect.assertions(2);
|
|
60
266
|
|
|
267
|
+
const index = 0;
|
|
61
268
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
62
269
|
|
|
270
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
271
|
+
configuration,
|
|
272
|
+
prefix,
|
|
273
|
+
index
|
|
274
|
+
);
|
|
275
|
+
|
|
63
276
|
expect(result).toEqual(configuration.tv_buttons_button_1_assign_action);
|
|
277
|
+
expect(memoizedResult).toEqual(result);
|
|
64
278
|
});
|
|
65
279
|
|
|
66
|
-
it("
|
|
67
|
-
|
|
280
|
+
it("returns the second plugin identifier when values are identical", () => {
|
|
281
|
+
expect.assertions(2);
|
|
68
282
|
|
|
283
|
+
const index = 1;
|
|
69
284
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
70
285
|
|
|
286
|
+
const memoizedResult = memoizedGetPluginIdentifier(
|
|
287
|
+
configuration,
|
|
288
|
+
prefix,
|
|
289
|
+
index
|
|
290
|
+
);
|
|
291
|
+
|
|
71
292
|
expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
|
|
293
|
+
expect(memoizedResult).toEqual(result);
|
|
72
294
|
});
|
|
73
295
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
|
+
import memoizee from "memoizee";
|
|
2
3
|
|
|
3
4
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
-
import { isNotNil } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
5
5
|
|
|
6
6
|
export const getButtonsCount = (
|
|
7
7
|
configuration: Record<string, unknown>,
|
|
@@ -21,23 +21,27 @@ export const getPluginIdentifier = (
|
|
|
21
21
|
configuration: Record<string, unknown>,
|
|
22
22
|
prefix: string,
|
|
23
23
|
index: number
|
|
24
|
-
): string => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
): string | undefined => {
|
|
25
|
+
const re = new RegExp(`${prefix}_button_\\d_assign_action`);
|
|
26
|
+
let count = 0;
|
|
27
|
+
|
|
28
|
+
for (const [key, value] of Object.entries(configuration)) {
|
|
29
|
+
if (
|
|
30
|
+
key.startsWith(`${prefix}_button`) &&
|
|
31
|
+
re.test(key) &&
|
|
32
|
+
value != null &&
|
|
33
|
+
value !== ""
|
|
34
|
+
) {
|
|
35
|
+
if (count === index) return value as string;
|
|
36
|
+
count++;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
})
|
|
38
|
-
);
|
|
40
|
+
return undefined;
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
export const memoizedGetPluginIdentifier = memoizee(getPluginIdentifier);
|
|
44
|
+
|
|
41
45
|
type Label = {
|
|
42
46
|
name: string;
|
|
43
47
|
};
|