@applicaster/zapp-react-native-ui-components 15.1.4 → 16.0.0-alpha.1042942411

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.
Files changed (202) hide show
  1. package/Components/BackgroundImage/index.ts +1 -8
  2. package/Components/BaseFocusable/index.ios.ts +12 -2
  3. package/Components/Cell/FocusableWrapper.tsx +3 -0
  4. package/Components/Cell/TvOSCellComponent.tsx +6 -3
  5. package/Components/CellRendererResolver/index.ts +1 -1
  6. package/Components/Focusable/Focusable.tsx +4 -2
  7. package/Components/Focusable/FocusableTvOS.tsx +18 -1
  8. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
  9. package/Components/FocusableGroup/FocusableTvOS.tsx +30 -1
  10. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +39 -0
  11. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
  12. package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
  13. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  14. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  15. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
  16. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  17. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
  18. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
  19. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
  20. package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
  21. package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
  22. package/Components/GeneralContentScreen/index.ts +2 -0
  23. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  24. package/Components/HandlePlayable/HandlePlayable.tsx +13 -8
  25. package/Components/Layout/TV/NavBarContainer.tsx +1 -10
  26. package/Components/Layout/TV/ScreenContainer.tsx +2 -6
  27. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
  28. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
  29. package/Components/Layout/TV/index.tsx +3 -4
  30. package/Components/Layout/TV/index.web.tsx +3 -4
  31. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  32. package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
  33. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +27 -48
  34. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
  35. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +213 -0
  36. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/selectors.test.ts +45 -0
  37. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/style.test.ts +49 -0
  38. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
  39. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
  40. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
  41. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
  42. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +198 -0
  43. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/selectors.ts +26 -0
  44. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/style.ts +29 -0
  45. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/types.ts +37 -0
  46. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +217 -46
  47. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +50 -119
  48. package/Components/MasterCell/DefaultComponents/Button.tsx +50 -58
  49. package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
  50. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.android.tv.tsx +58 -0
  51. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
  52. package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
  53. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
  54. package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
  55. package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/__snapshots__/index.test.tsx.snap +18 -0
  56. package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/index.test.tsx +90 -0
  57. package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +13 -14
  58. package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
  59. package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
  60. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
  61. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +8 -2
  62. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
  63. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
  64. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
  65. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
  66. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +1 -2
  67. package/Components/MasterCell/DefaultComponents/PressableView.tsx +54 -0
  68. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +46 -50
  69. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +47 -39
  70. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
  71. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +19 -6
  72. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +15 -0
  73. package/Components/MasterCell/DefaultComponents/Text/index.tsx +45 -15
  74. package/Components/MasterCell/DefaultComponents/UIKitAdapters/Badge.tsx +49 -0
  75. package/Components/MasterCell/DefaultComponents/__tests__/ActionButton.test.tsx +122 -0
  76. package/Components/MasterCell/DefaultComponents/__tests__/Button.test.tsx +186 -0
  77. package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
  78. package/Components/MasterCell/DefaultComponents/__tests__/DynamicBadge.test.tsx +156 -0
  79. package/Components/MasterCell/DefaultComponents/__tests__/__snapshots__/ActionButton.test.tsx.snap +60 -0
  80. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +196 -67
  81. package/Components/MasterCell/DefaultComponents/index.ts +13 -3
  82. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +189 -0
  83. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +33 -0
  84. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +33 -0
  85. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +159 -0
  86. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +18 -0
  87. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
  88. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +39 -0
  89. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +402 -0
  90. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +141 -0
  91. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +354 -0
  92. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
  93. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +129 -0
  94. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +123 -0
  95. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +238 -0
  96. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
  97. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
  98. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
  99. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
  100. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +89 -0
  101. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
  102. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +47 -48
  103. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
  104. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
  105. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +101 -144
  106. package/Components/MasterCell/MappingFunctions/index.js +3 -2
  107. package/Components/MasterCell/README.md +4 -0
  108. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
  109. package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
  110. package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
  111. package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
  112. package/Components/MasterCell/dataAdapter.ts +4 -1
  113. package/Components/MasterCell/elementMapper.tsx +54 -7
  114. package/Components/MasterCell/hooks/index.ts +2 -0
  115. package/Components/MasterCell/hooks/usePressedState.ts +4 -0
  116. package/Components/MasterCell/index.tsx +20 -4
  117. package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
  118. package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
  119. package/Components/MasterCell/utils/index.ts +82 -16
  120. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -69
  121. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +25 -47
  122. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +122 -39
  123. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
  124. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +257 -88
  125. package/Components/ModalComponent/AudioPlayer/Components/index.ts +6 -4
  126. package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
  127. package/Components/ModalComponent/BottomSheetModalContent.tsx +17 -10
  128. package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
  129. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
  130. package/Components/OfflineHandler/__tests__/index.test.tsx +101 -32
  131. package/Components/OfflineHandler/hooks.ts +123 -0
  132. package/Components/OfflineHandler/index.tsx +51 -73
  133. package/Components/OfflineHandler/utils/index.ts +1 -13
  134. package/Components/PlayerContainer/PlayerContainer.tsx +6 -5
  135. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +2 -4
  136. package/Components/PreloaderWrapper/index.tsx +1 -1
  137. package/Components/River/ComponentsMap/ComponentsMap.tsx +8 -21
  138. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  139. package/Components/River/RefreshControl.tsx +19 -105
  140. package/Components/River/River.tsx +9 -82
  141. package/Components/River/TV/River.tsx +31 -14
  142. package/Components/River/TV/index.tsx +8 -4
  143. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
  144. package/Components/River/TV/utils/index.ts +4 -0
  145. package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
  146. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +4 -0
  147. package/Components/River/__tests__/componentsMap.test.js +38 -0
  148. package/Components/River/hooks/__tests__/usePullToRefresh.test.ts +132 -0
  149. package/Components/River/hooks/index.ts +1 -0
  150. package/Components/River/hooks/usePullToRefresh.ts +51 -0
  151. package/Components/Screen/TV/index.web.tsx +4 -2
  152. package/Components/Screen/__tests__/Screen.test.tsx +65 -42
  153. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
  154. package/Components/Screen/hooks.ts +2 -3
  155. package/Components/Screen/index.tsx +2 -3
  156. package/Components/Screen/orientationHandler.ts +3 -3
  157. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
  158. package/Components/ScreenResolver/index.tsx +9 -5
  159. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
  160. package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
  161. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
  162. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +1 -1
  163. package/Components/Tabs/TabContent.tsx +7 -4
  164. package/Components/TopCutoffOverlay/__tests__/TopCutoffOverlay.test.tsx +201 -0
  165. package/Components/TopCutoffOverlay/hooks/__tests__/useMarginTop.test.ts +130 -0
  166. package/Components/TopCutoffOverlay/hooks/index.ts +1 -0
  167. package/Components/TopCutoffOverlay/hooks/useMarginTop.ts +59 -0
  168. package/Components/TopCutoffOverlay/index.tsx +55 -0
  169. package/Components/Transitioner/index.js +3 -3
  170. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
  171. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
  172. package/Components/VideoModal/utils.ts +12 -10
  173. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
  174. package/Components/Viewport/ViewportAware/index.tsx +16 -7
  175. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  176. package/Components/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
  177. package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
  178. package/Contexts/ScreenContext/index.tsx +25 -18
  179. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  180. package/Decorators/Analytics/index.tsx +6 -5
  181. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
  182. package/Decorators/ConfigurationWrapper/const.ts +1 -0
  183. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
  184. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  185. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  186. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  187. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
  188. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
  189. package/Helpers/DataSourceHelper/index.ts +19 -0
  190. package/package.json +5 -5
  191. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
  192. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
  193. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
  194. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
  195. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
  196. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -67
  197. package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
  198. package/Components/River/TV/withTVEventHandler.tsx +0 -36
  199. package/Helpers/DataSourceHelper/index.js +0 -19
  200. /package/Components/BackgroundImage/{BackgroundImage.tv.android.tsx → BackgroundImage.android.tv.tsx} +0 -0
  201. /package/Components/BackgroundImage/{BackgroundImage.tv.ios.tsx → BackgroundImage.ios.tv.tsx} +0 -0
  202. /package/Components/BackgroundImage/{BackgroundImage.tv.web.tsx → BackgroundImage.tsx} +0 -0
@@ -0,0 +1,186 @@
1
+ import React from "react";
2
+ import { TouchableOpacity } from "react-native";
3
+ import { render } from "@testing-library/react-native";
4
+
5
+ import { Button } from "../Button";
6
+ import { masterCellLogger } from "../../logger";
7
+
8
+ const mockUseActions = jest.fn();
9
+
10
+ const baseProps = {
11
+ item: { id: "entry-id" } as any,
12
+ action: { identifier: "bookmark", type: "plugin" },
13
+ asset: {
14
+ type: "Image" as const,
15
+ src: {
16
+ active: "active.png",
17
+ inactive: "inactive.png",
18
+ },
19
+ style: {
20
+ width: 24,
21
+ height: 24,
22
+ },
23
+ props: {
24
+ testID: "button-image",
25
+ },
26
+ },
27
+ style: {
28
+ width: 40,
29
+ height: 40,
30
+ },
31
+ testID: "button",
32
+ accessibilityLabel: "button-label",
33
+ };
34
+
35
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/actions", () => ({
36
+ useActions: (...args) => mockUseActions(...args),
37
+ }));
38
+
39
+ jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
40
+ useTheme: jest.fn(() => ({
41
+ use_downscaling_images: false,
42
+ })),
43
+ }));
44
+
45
+ jest.mock("../../logger", () => ({
46
+ masterCellLogger: {
47
+ warning: jest.fn(),
48
+ error: jest.fn(),
49
+ },
50
+ }));
51
+
52
+ describe("MasterCell Button", () => {
53
+ beforeEach(() => {
54
+ jest.clearAllMocks();
55
+ });
56
+
57
+ it("renders the UIKit button with the inactive asset when the item is not selected", () => {
58
+ mockUseActions.mockReturnValue({
59
+ state: [],
60
+ });
61
+
62
+ const wrapper = render(<Button {...baseProps} />);
63
+ const button = wrapper.getByTestId("button");
64
+ const image = wrapper.getByTestId("button-image");
65
+
66
+ expect(button.props).toMatchObject({
67
+ testID: "button",
68
+ accessibilityLabel: "button-label",
69
+ style: { width: 40, height: 40 },
70
+ });
71
+
72
+ expect(wrapper.UNSAFE_getByType(TouchableOpacity).props.id).toBe(
73
+ "entry-id"
74
+ );
75
+
76
+ expect(image.props.source).toEqual({ uri: "inactive.png" });
77
+
78
+ expect(image.props.style).toMatchObject({
79
+ width: 24,
80
+ height: 24,
81
+ });
82
+ });
83
+
84
+ it("renders the active asset when the legacy action context marks the item as selected", () => {
85
+ mockUseActions.mockReturnValue({
86
+ state: [],
87
+ masterCell: {
88
+ isSelected: jest.fn(() => true),
89
+ },
90
+ });
91
+
92
+ const wrapper = render(<Button {...baseProps} />);
93
+
94
+ expect(wrapper.getByTestId("button-image").props.source).toEqual({
95
+ uri: "active.png",
96
+ });
97
+ });
98
+
99
+ it("defaults ButtonAsset to the Image component when asset.type is missing", () => {
100
+ mockUseActions.mockReturnValue({
101
+ state: [],
102
+ });
103
+
104
+ const wrapper = render(
105
+ <Button
106
+ {...baseProps}
107
+ asset={{
108
+ ...baseProps.asset,
109
+ type: undefined as any,
110
+ }}
111
+ />
112
+ );
113
+
114
+ expect(wrapper.getByTestId("button-image").props.source).toEqual({
115
+ uri: "inactive.png",
116
+ });
117
+ });
118
+
119
+ it("forwards asset.props to the ButtonAsset component", () => {
120
+ mockUseActions.mockReturnValue({
121
+ state: [],
122
+ });
123
+
124
+ const wrapper = render(
125
+ <Button
126
+ {...baseProps}
127
+ asset={{
128
+ ...baseProps.asset,
129
+ props: {
130
+ testID: "button-image",
131
+ resizeMode: "contain",
132
+ nativeID: "button-asset",
133
+ },
134
+ }}
135
+ />
136
+ );
137
+
138
+ expect(wrapper.getByTestId("button-image").props).toMatchObject({
139
+ testID: "button-image",
140
+ resizeMode: "contain",
141
+ nativeID: "button-asset",
142
+ });
143
+ });
144
+
145
+ it("renders the ActionButton when the action context uses the new API", () => {
146
+ const addListener = jest.fn(() => jest.fn());
147
+
148
+ mockUseActions.mockReturnValue({
149
+ initialEntryState: jest.fn(() => ({
150
+ asset: "active.png",
151
+ })),
152
+ invokeAction: jest.fn(),
153
+ addListener,
154
+ isActionAvailable: jest.fn(() => true),
155
+ });
156
+
157
+ const wrapper = render(<Button {...baseProps} />);
158
+ const button = wrapper.getByTestId("button");
159
+ const image = wrapper.getByTestId("button-image");
160
+
161
+ expect(button.props.accessibilityLabel).toBe("button-label");
162
+ expect(image.props.source).toEqual({ uri: "inactive.png" });
163
+ expect(addListener).toHaveBeenCalledWith("entry-id", expect.any(Function));
164
+
165
+ expect(wrapper.UNSAFE_getByType(TouchableOpacity).props.id).toBe(
166
+ "action-button-entry-id"
167
+ );
168
+ });
169
+
170
+ it("returns null and logs a warning when the action plugin is missing", () => {
171
+ mockUseActions.mockReturnValue(undefined);
172
+
173
+ const wrapper = render(
174
+ <Button
175
+ {...baseProps}
176
+ action={{ identifier: "missing-plugin", type: "plugin" }}
177
+ />
178
+ );
179
+
180
+ expect(wrapper.toJSON()).toBeNull();
181
+
182
+ expect(masterCellLogger.warning).toHaveBeenCalledWith(
183
+ "You're missing an action plugin(missing-plugin) required by your button. \n Button can't be displayed"
184
+ );
185
+ });
186
+ });
@@ -0,0 +1,141 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react-native";
3
+
4
+ import { defaultComponents } from "../index";
5
+ import { elementMapper } from "../../elementMapper";
6
+
7
+ const WrapperProbe = jest.fn(({ children }) => <>{children}</>);
8
+ const LeafProbe = jest.fn(() => null);
9
+
10
+ const components = {
11
+ ...defaultComponents,
12
+ View: WrapperProbe,
13
+ Text: LeafProbe,
14
+ };
15
+
16
+ const entry = { id: "entry-1" };
17
+ const item = { id: "item-1" };
18
+
19
+ const renderNode = (node) =>
20
+ render(
21
+ <React.Fragment>{elementMapper(components)(node as never)}</React.Fragment>
22
+ );
23
+
24
+ describe("DataProvider", () => {
25
+ beforeEach(() => {
26
+ jest.clearAllMocks();
27
+ });
28
+
29
+ it("injects resolved runtime props under dataProviderProps into the direct child and its direct children only", () => {
30
+ renderNode({
31
+ type: "DataProvider",
32
+ props: { _dataKey: "entry", entry },
33
+ elements: [
34
+ {
35
+ type: "View",
36
+ props: {},
37
+ elements: [
38
+ {
39
+ type: "View",
40
+ props: {},
41
+ elements: [{ type: "Text", props: {} }],
42
+ },
43
+ ],
44
+ },
45
+ ],
46
+ });
47
+
48
+ expect(WrapperProbe).toHaveBeenNthCalledWith(
49
+ 1,
50
+ expect.objectContaining({
51
+ dataProviderProps: expect.objectContaining({ entry }),
52
+ }),
53
+ expect.anything()
54
+ );
55
+
56
+ expect(WrapperProbe).toHaveBeenNthCalledWith(
57
+ 2,
58
+ expect.objectContaining({
59
+ dataProviderProps: expect.objectContaining({ entry }),
60
+ }),
61
+ expect.anything()
62
+ );
63
+
64
+ expect(LeafProbe).toHaveBeenCalledWith(
65
+ expect.not.objectContaining({
66
+ dataProviderProps: expect.anything(),
67
+ }),
68
+ expect.anything()
69
+ );
70
+ });
71
+
72
+ it("derives the namespaced values from the resolved runtime props", () => {
73
+ renderNode({
74
+ type: "DataProvider",
75
+ props: { _dataKey: "item", item },
76
+ elements: [
77
+ {
78
+ type: "View",
79
+ props: {},
80
+ elements: [{ type: "View", props: {} }],
81
+ },
82
+ ],
83
+ });
84
+
85
+ expect(WrapperProbe).toHaveBeenNthCalledWith(
86
+ 1,
87
+ expect.objectContaining({
88
+ dataProviderProps: expect.objectContaining({ item }),
89
+ }),
90
+ expect.anything()
91
+ );
92
+
93
+ expect(WrapperProbe).toHaveBeenNthCalledWith(
94
+ 2,
95
+ expect.objectContaining({
96
+ dataProviderProps: expect.objectContaining({ item }),
97
+ }),
98
+ expect.anything()
99
+ );
100
+ });
101
+
102
+ it("does not overwrite explicit dataProviderProps on the direct child", () => {
103
+ const explicitEntry = { id: "explicit" };
104
+
105
+ renderNode({
106
+ type: "DataProvider",
107
+ props: { _dataKey: "entry", entry },
108
+ elements: [
109
+ {
110
+ type: "View",
111
+ props: {
112
+ dataProviderProps: {
113
+ entry: explicitEntry,
114
+ source: "child",
115
+ },
116
+ },
117
+ elements: [{ type: "View", props: {} }],
118
+ },
119
+ ],
120
+ });
121
+
122
+ expect(WrapperProbe).toHaveBeenNthCalledWith(
123
+ 1,
124
+ expect.objectContaining({
125
+ dataProviderProps: expect.objectContaining({
126
+ entry: explicitEntry,
127
+ source: "child",
128
+ }),
129
+ }),
130
+ expect.anything()
131
+ );
132
+
133
+ expect(WrapperProbe).toHaveBeenNthCalledWith(
134
+ 2,
135
+ expect.objectContaining({
136
+ dataProviderProps: expect.objectContaining({ entry }),
137
+ }),
138
+ expect.anything()
139
+ );
140
+ });
141
+ });
@@ -0,0 +1,156 @@
1
+ import React from "react";
2
+ import { StyleSheet } from "react-native";
3
+ import { act, render } from "@testing-library/react-native";
4
+ import { DynamicBadge } from "../DynamicBadge";
5
+
6
+ const mockAddListener = jest.fn();
7
+ const mockUsePlayer = jest.fn();
8
+
9
+ jest.mock(
10
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer",
11
+ () => ({
12
+ usePlayer: (...args) => mockUsePlayer(...args),
13
+ })
14
+ );
15
+
16
+ jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
17
+ useTheme: jest.fn(() => ({
18
+ use_downscaling_images: false,
19
+ })),
20
+ }));
21
+
22
+ describe("DynamicBadge", () => {
23
+ beforeEach(() => {
24
+ jest.clearAllMocks();
25
+ });
26
+
27
+ it("renders through UIKitBadge and maps layout props from style", () => {
28
+ mockUsePlayer.mockReturnValue(undefined);
29
+
30
+ const style = {
31
+ width: 32,
32
+ height: 16,
33
+ };
34
+
35
+ const { getByTestId, toJSON } = render(
36
+ <DynamicBadge
37
+ cellUUID="player-1"
38
+ uri="badge.png"
39
+ style={style}
40
+ resizeMode="cover"
41
+ testID="badge"
42
+ accessibilityLabel="Badge"
43
+ accessibilityHint="Hint"
44
+ />
45
+ );
46
+
47
+ const root = getByTestId("badge");
48
+ const flattenedRootStyle = StyleSheet.flatten(root.props.style);
49
+ const tree = toJSON() as any;
50
+
51
+ expect(flattenedRootStyle).toEqual(
52
+ expect.objectContaining({
53
+ width: 32,
54
+ height: 16,
55
+ })
56
+ );
57
+
58
+ expect(root.props.accessibilityLabel).toBe("Badge");
59
+ expect(root.props.accessibilityHint).toBe("Hint");
60
+
61
+ expect(tree.props.resizeMode).toBe("cover");
62
+ expect(tree.props.source).toEqual({ uri: "badge.png" });
63
+
64
+ expect(StyleSheet.flatten(tree.props.style)).toEqual({
65
+ width: 32,
66
+ height: 16,
67
+ });
68
+ });
69
+
70
+ it("renders through UIKitBadge and maps layout props including positioning and margins", () => {
71
+ mockUsePlayer.mockReturnValue(undefined);
72
+
73
+ const style = {
74
+ width: 32,
75
+ height: 16,
76
+ position: "absolute" as const,
77
+ bottom: 0,
78
+ left: 0,
79
+ marginTop: 1,
80
+ marginRight: 2,
81
+ marginBottom: 3,
82
+ marginLeft: 4,
83
+ backgroundColor: "transparent",
84
+ };
85
+
86
+ const { getByTestId, toJSON } = render(
87
+ <DynamicBadge
88
+ cellUUID="player-1"
89
+ uri="badge.png"
90
+ style={style}
91
+ resizeMode="cover"
92
+ testID="badge"
93
+ accessibilityLabel="Badge"
94
+ accessibilityHint="Hint"
95
+ />
96
+ );
97
+
98
+ const root = getByTestId("badge");
99
+ const flattenedRootStyle = StyleSheet.flatten(root.props.style);
100
+ const tree = toJSON() as any;
101
+
102
+ expect(flattenedRootStyle).toEqual({
103
+ width: 32,
104
+ height: 16,
105
+ position: "absolute",
106
+ bottom: 0,
107
+ left: 0,
108
+ marginTop: 1,
109
+ marginRight: 2,
110
+ marginBottom: 3,
111
+ marginLeft: 4,
112
+ backgroundColor: "transparent",
113
+ });
114
+
115
+ expect(root.props.accessibilityLabel).toBe("Badge");
116
+ expect(root.props.accessibilityHint).toBe("Hint");
117
+
118
+ expect(tree.props.resizeMode).toBe("cover");
119
+ expect(tree.props.source).toEqual({ uri: "badge.png" });
120
+ });
121
+
122
+ it("hides the badge while the player is loading and shows it again after close", () => {
123
+ let listeners;
124
+
125
+ mockAddListener.mockImplementation(({ listener }) => {
126
+ listeners = listener;
127
+
128
+ return jest.fn();
129
+ });
130
+
131
+ mockUsePlayer.mockReturnValue({ addListener: mockAddListener });
132
+
133
+ const { queryByTestId } = render(
134
+ <DynamicBadge
135
+ cellUUID="player-1"
136
+ uri="badge.png"
137
+ style={{ width: 32, height: 16, bottom: 0, left: 0 }}
138
+ testID="badge"
139
+ />
140
+ );
141
+
142
+ expect(queryByTestId("badge")).not.toBeNull();
143
+
144
+ act(() => {
145
+ listeners.onLoad();
146
+ });
147
+
148
+ expect(queryByTestId("badge")).toBeNull();
149
+
150
+ act(() => {
151
+ listeners.onPlayerClose();
152
+ });
153
+
154
+ expect(queryByTestId("badge")).not.toBeNull();
155
+ });
156
+ });
@@ -0,0 +1,60 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`MasterCell ActionButton matches the rendered "action-button" snapshot 1`] = `
4
+ <View
5
+ accessibilityLabel="action-button-label"
6
+ accessibilityState={
7
+ {
8
+ "busy": undefined,
9
+ "checked": undefined,
10
+ "disabled": undefined,
11
+ "expanded": undefined,
12
+ "selected": undefined,
13
+ }
14
+ }
15
+ accessibilityValue={
16
+ {
17
+ "max": undefined,
18
+ "min": undefined,
19
+ "now": undefined,
20
+ "text": undefined,
21
+ }
22
+ }
23
+ accessible={true}
24
+ collapsable={false}
25
+ focusable={true}
26
+ nativeID="action-button-entry-id"
27
+ onClick={[Function]}
28
+ onResponderGrant={[Function]}
29
+ onResponderMove={[Function]}
30
+ onResponderRelease={[Function]}
31
+ onResponderTerminate={[Function]}
32
+ onResponderTerminationRequest={[Function]}
33
+ onStartShouldSetResponder={[Function]}
34
+ style={
35
+ {
36
+ "height": 32,
37
+ "opacity": 1,
38
+ "width": 32,
39
+ }
40
+ }
41
+ testID="action-button"
42
+ >
43
+ <Image
44
+ fadeDuration={0}
45
+ onError={[Function]}
46
+ source={
47
+ {
48
+ "uri": "inactive.png",
49
+ }
50
+ }
51
+ style={
52
+ {
53
+ "height": 32,
54
+ "width": 32,
55
+ }
56
+ }
57
+ testID="action-button-image"
58
+ />
59
+ </View>
60
+ `;