@applicaster/zapp-react-native-ui-components 13.0.0-alpha.5033140607 → 13.0.0-alpha.5255052345

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 (126) hide show
  1. package/Components/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
  2. package/Components/AudioPlayer/__tests__/__snapshots__/Runtime.test.js.snap +4 -4
  3. package/Components/AudioPlayer/__tests__/__snapshots__/artWork.test.js.snap +3 -3
  4. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +6 -6
  5. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +7 -7
  6. package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +3 -3
  7. package/Components/AudioPlayer/__tests__/__snapshots__/summary.test.js.snap +2 -2
  8. package/Components/AudioPlayer/__tests__/__snapshots__/title.test.js.snap +2 -2
  9. package/Components/BaseFocusable/index.ios.ts +1 -1
  10. package/Components/BaseFocusable/index.tsx +66 -29
  11. package/Components/Cell/Cell.tsx +14 -9
  12. package/Components/Cell/CellWithFocusable.ios.tsx +126 -0
  13. package/Components/Cell/CellWithFocusable.tsx +44 -60
  14. package/Components/Cell/TvOSCellComponent.tsx +3 -8
  15. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  16. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +20 -20
  17. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +5 -3
  18. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +5 -5
  19. package/Components/ComponentResolver/__tests__/componentResolver.test.js +11 -9
  20. package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
  21. package/Components/Focusable/Focusable.tsx +0 -54
  22. package/Components/Focusable/FocusableTvOS.tsx +1 -1
  23. package/Components/Focusable/Touchable.tsx +19 -20
  24. package/Components/FocusableList/index.tsx +0 -1
  25. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +76 -7
  26. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +53 -9
  27. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +1 -0
  28. package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
  29. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -3
  30. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +9 -9
  31. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  32. package/Components/Layout/TV/__tests__/index.test.tsx +7 -3
  33. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  34. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  35. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +6 -0
  36. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +12 -12
  37. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  38. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
  39. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  40. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  41. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  42. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
  43. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +7 -7
  44. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +34 -34
  45. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  46. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  47. package/Components/MasterCell/utils/index.ts +1 -1
  48. package/Components/ModalComponent/Header/index.tsx +3 -3
  49. package/Components/NativeFocusables/{index.js → index.ts} +4 -2
  50. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
  51. package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
  52. package/Components/PlayerContainer/PlayerContainer.tsx +5 -11
  53. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  54. package/Components/River/ComponentsMap/ComponentsMap.tsx +39 -65
  55. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  56. package/Components/River/RefreshControl.tsx +1 -1
  57. package/Components/River/RiverFooter.tsx +39 -9
  58. package/Components/River/RiverItem.tsx +37 -2
  59. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +114 -45
  60. package/Components/River/__tests__/__snapshots__/river.test.js.snap +12 -12
  61. package/Components/River/__tests__/componentsMap.test.js +64 -17
  62. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -1
  63. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +1 -1
  64. package/Components/Screen/__tests__/Screen.test.tsx +41 -27
  65. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -4
  66. package/Components/Screen/hooks.ts +56 -0
  67. package/Components/Screen/index.tsx +13 -39
  68. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +2 -2
  69. package/Components/ScreenResolver/__tests__/screenResolver.test.js +31 -27
  70. package/Components/Tabs/Tab.tsx +7 -6
  71. package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
  72. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
  73. package/Components/TextInputTv/index.tsx +4 -4
  74. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
  75. package/Components/Transitioner/AnimationManager.js +8 -8
  76. package/Components/Transitioner/Scene.tsx +52 -23
  77. package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
  78. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +62 -46
  79. package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
  80. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
  81. package/Components/Transitioner/index.js +8 -4
  82. package/Components/VideoLive/LiveImageManager.ts +27 -1
  83. package/Components/VideoLive/PlayerLiveImageComponent.tsx +29 -21
  84. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
  85. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +5 -10
  86. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +5 -1
  87. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +5 -1
  88. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +8 -7
  89. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +6 -13
  90. package/Components/VideoModal/ModalAnimation/index.ts +2 -1
  91. package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
  92. package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
  93. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  94. package/Components/VideoModal/PlayerWrapper.tsx +16 -35
  95. package/Components/VideoModal/VideoModal.tsx +14 -23
  96. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
  97. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
  98. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +4 -4
  99. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +66 -156
  100. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  101. package/Components/VideoModal/hooks/index.ts +7 -0
  102. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  103. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  104. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  105. package/Components/VideoModal/utils.ts +3 -5
  106. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +2 -2
  107. package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
  108. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +11 -11
  109. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +30 -30
  110. package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
  111. package/Contexts/ScreenContext/index.tsx +3 -2
  112. package/Decorators/Analytics/{index.js → index.tsx} +11 -11
  113. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +2 -2
  114. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
  115. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
  116. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
  117. package/Decorators/RiverFeedLoader/index.tsx +1 -1
  118. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
  119. package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
  120. package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
  121. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +5 -5
  122. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +16 -10
  123. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  124. package/Decorators/ZappPipesDataConnector/index.tsx +32 -2
  125. package/package.json +12 -6
  126. package/Decorators/RiverFeedLoader/utils.ts +0 -100
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  import { renderHook } from "@testing-library/react-hooks";
2
3
 
3
4
  import {
@@ -9,6 +10,51 @@ import {
9
10
  import * as redux from "react-redux";
10
11
  import * as layoutPresets from "@applicaster/zapp-react-native-redux/hooks/useLayoutPresets";
11
12
  import * as pipesFeeds from "@applicaster/zapp-react-native-redux/hooks/useZappPipesFeeds";
13
+ import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
14
+ import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
15
+
16
+ import { Provider } from "react-redux";
17
+ import configureStore from "redux-mock-store";
18
+
19
+ jest.mock(
20
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute",
21
+ () => ({
22
+ useRoute: jest.fn().mockReturnValue({
23
+ pathname: "/home",
24
+ }),
25
+ })
26
+ );
27
+
28
+ const homeStack = {
29
+ route: "/home",
30
+ state: {
31
+ screen: { id: "123" },
32
+ entry: { id: "abc" },
33
+ },
34
+ };
35
+
36
+ const mainStackNavigator = {
37
+ getStackForPathname: jest.fn().mockReturnValue(homeStack),
38
+ modalState: {
39
+ screen: {
40
+ id: "modal-1",
41
+ },
42
+ },
43
+ };
44
+
45
+ const store = configureStore()({});
46
+
47
+ const wrapper = ({ children }) => (
48
+ <Provider store={store}>
49
+ <NavigationContext.Provider
50
+ value={{ ...mainStackNavigator, currentRoute: homeStack.route }}
51
+ >
52
+ <PathnameContext.Provider value={homeStack.route}>
53
+ {children}
54
+ </PathnameContext.Provider>
55
+ </NavigationContext.Provider>
56
+ </Provider>
57
+ );
12
58
 
13
59
  describe("getTransformedPreset should return the passed components if smartComponents is empty", () => {
14
60
  describe("getTransformedPreset function", () => {
@@ -94,9 +140,13 @@ describe("getTransformedPreset should return the passed components if smartCompo
94
140
  },
95
141
  };
96
142
 
143
+ const mockUrlsMap = {
144
+ [mockSmartComp.id]: mockSmartComp.data.source,
145
+ };
146
+
97
147
  it("should return the component itself if its component_type is not SMART_COMPONENT_TYPE", () => {
98
148
  expect(
99
- enrichComponent(mockComp, 0, mockFeeds, mockLayoutPresets)
149
+ enrichComponent(mockComp, 0, mockFeeds, mockLayoutPresets, mockUrlsMap)
100
150
  ).toEqual([mockComp]);
101
151
  });
102
152
 
@@ -106,8 +156,18 @@ describe("getTransformedPreset should return the passed components if smartCompo
106
156
  data: { source: "missing_source" },
107
157
  };
108
158
 
159
+ const missing_source_urls_map = {
160
+ [missing_source_comp.id]: missing_source_comp.data.source,
161
+ };
162
+
109
163
  expect(
110
- enrichComponent(missing_source_comp, 0, mockFeeds, mockLayoutPresets)
164
+ enrichComponent(
165
+ missing_source_comp,
166
+ 0,
167
+ mockFeeds,
168
+ mockLayoutPresets,
169
+ missing_source_urls_map
170
+ )
111
171
  ).toEqual(null);
112
172
  });
113
173
 
@@ -116,7 +176,8 @@ describe("getTransformedPreset should return the passed components if smartCompo
116
176
  mockSmartComp,
117
177
  0,
118
178
  mockFeeds,
119
- mockLayoutPresets
179
+ mockLayoutPresets,
180
+ mockUrlsMap
120
181
  );
121
182
 
122
183
  expect(Array.isArray(result)).toBe(true);
@@ -262,7 +323,9 @@ describe("getTransformedPreset should return the passed components if smartCompo
262
323
 
263
324
  mockUseLayoutPresets.mockReturnValue({});
264
325
 
265
- const { result } = renderHook(() => useCurationAPI(mockComponents));
326
+ const { result } = renderHook(() => useCurationAPI(mockComponents), {
327
+ wrapper,
328
+ });
266
329
 
267
330
  // if there are no smart components, it should return the original array
268
331
  expect(result.current).toEqual(mockComponents);
@@ -313,7 +376,9 @@ describe("getTransformedPreset should return the passed components if smartCompo
313
376
 
314
377
  mockUseLayoutPresets.mockReturnValue(mockLayoutPresets);
315
378
 
316
- const { result } = renderHook(() => useCurationAPI(mockComponents));
379
+ const { result } = renderHook(() => useCurationAPI(mockComponents), {
380
+ wrapper,
381
+ });
317
382
 
318
383
  expect(result.current).toEqual(mockTransformedComponents);
319
384
  });
@@ -383,7 +448,9 @@ describe("getTransformedPreset should return the passed components if smartCompo
383
448
 
384
449
  mockUseLayoutPresets.mockReturnValue(mockLayoutPresets);
385
450
 
386
- const { result } = renderHook(() => useCurationAPI(mockComponents));
451
+ const { result } = renderHook(() => useCurationAPI(mockComponents), {
452
+ wrapper,
453
+ });
387
454
 
388
455
  expect(result.current).toEqual(mockTransformedComponents);
389
456
  });
@@ -434,7 +501,9 @@ describe("getTransformedPreset should return the passed components if smartCompo
434
501
  const mockUseLayoutPresets = jest.spyOn(layoutPresets, "useLayoutPresets");
435
502
  mockUseLayoutPresets.mockReturnValue(mockLayoutPresets);
436
503
 
437
- const { result } = renderHook(() => useCurationAPI(mockComponents));
504
+ const { result } = renderHook(() => useCurationAPI(mockComponents), {
505
+ wrapper,
506
+ });
438
507
 
439
508
  expect(result.current).toEqual(mockTransformedComponents);
440
509
  });
@@ -9,6 +9,18 @@ import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
9
9
  import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
10
10
  import { Categories } from "./logger";
11
11
  import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
12
+ import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useRoute";
13
+ import {
14
+ ZappPipesEntryContext,
15
+ ZappPipesScreenContext,
16
+ ZappPipesSearchContext,
17
+ } from "@applicaster/zapp-react-native-ui-components/Contexts";
18
+
19
+ import {
20
+ getInflatedDataSourceUrl,
21
+ getSearchContext,
22
+ } from "@applicaster/zapp-react-native-utils/reactHooks/feed/useInflatedUrl";
23
+
12
24
  import { produce } from "immer";
13
25
  // types reference
14
26
 
@@ -20,6 +32,7 @@ type LayoutPresets = PresetsMapping["presets_mappings"];
20
32
 
21
33
  const SMART_COMPONENT_TYPE = "quick-brick-smart-component";
22
34
  const SOURCE_PATH = ["data", "source"];
35
+ const MAPPING_PATH = ["data", "mapping"];
23
36
 
24
37
  const isSmartComponent = (component) =>
25
38
  component.component_type === SMART_COMPONENT_TYPE;
@@ -58,13 +71,14 @@ export const enrichComponent = (
58
71
  comp: ZappUIComponent,
59
72
  index: number,
60
73
  feeds: Feeds,
61
- layoutPresets: LayoutPresets
74
+ layoutPresets: LayoutPresets,
75
+ urlsMap: { [key: string]: string }
62
76
  ): ZappUIComponent[] | null => {
63
77
  if (!isSmartComponent(comp)) {
64
78
  return [comp];
65
79
  }
66
80
 
67
- const presets = prop<string[]>(path(SOURCE_PATH, comp), feeds);
81
+ const presets = prop<string[]>(urlsMap[comp.id], feeds);
68
82
 
69
83
  if (presets && presets.data && presets.data.entry) {
70
84
  return presets.data.entry
@@ -113,11 +127,35 @@ export const useCurationAPI = (
113
127
  [components]
114
128
  );
115
129
 
116
- const urls = useMemo<string[]>(
117
- () =>
118
- smartComponents?.map?.((component) => path(SOURCE_PATH, component)) ?? [],
119
- [smartComponents]
120
- );
130
+ const { pathname } = useRoute();
131
+ const [entryContext] = ZappPipesEntryContext.useZappPipesContext(pathname);
132
+ const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
133
+ const [screenContext] = ZappPipesScreenContext.useZappPipesContext();
134
+
135
+ const urlsMap = useMemo<{ [key: string]: string }>(() => {
136
+ const map = {};
137
+
138
+ smartComponents?.forEach?.((component) => {
139
+ const url = path(SOURCE_PATH, component);
140
+ const mapping = path(MAPPING_PATH, component);
141
+
142
+ map[component.id] = mapping
143
+ ? getInflatedDataSourceUrl({
144
+ source: url,
145
+ contexts: {
146
+ entry: entryContext,
147
+ screen: screenContext,
148
+ search: getSearchContext(searchContext, mapping),
149
+ },
150
+ mapping,
151
+ })
152
+ : url;
153
+ });
154
+
155
+ return map;
156
+ }, [smartComponents, entryContext, screenContext, searchContext]);
157
+
158
+ const urls = useMemo<string[]>(() => Object.values(urlsMap), [urlsMap]);
121
159
 
122
160
  useEffect(() => {
123
161
  urls.forEach((url, index) => {
@@ -138,11 +176,17 @@ export const useCurationAPI = (
138
176
  if (!components) return [];
139
177
 
140
178
  return components.reduce((acc, comp, index) => {
141
- const enrichedComp = enrichComponent(comp, index, feeds, layoutPresets);
179
+ const enrichedComp = enrichComponent(
180
+ comp,
181
+ index,
182
+ feeds,
183
+ layoutPresets,
184
+ urlsMap
185
+ );
142
186
 
143
187
  return enrichedComp ? [...acc, ...enrichedComp] : acc;
144
188
  }, [] as Array<ZappUIComponent>);
145
- }, [components, feeds, layoutPresets]);
189
+ }, [components, feeds, layoutPresets, urlsMap]);
146
190
 
147
191
  return getFinalComponents(
148
192
  enrichedComponents,
@@ -39,6 +39,7 @@ jest.mock(
39
39
  );
40
40
 
41
41
  jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
42
+ ...jest.requireActual<any>("@applicaster/zapp-react-native-utils/theme"),
42
43
  useTheme: () => ({}),
43
44
  }));
44
45
 
@@ -3,7 +3,7 @@
3
3
  exports[`LayoutContainer renders 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "flex": 1,
8
8
  "height": 1080,
9
9
  "width": 1920,
@@ -3,14 +3,14 @@
3
3
  exports[`NavBarContainer renders 1`] = `
4
4
  <View
5
5
  style={
6
- Array [
7
- Object {
6
+ [
7
+ {
8
8
  "position": "absolute",
9
9
  "top": 0,
10
10
  "width": 1920,
11
11
  "zIndex": 10,
12
12
  },
13
- Object {
13
+ {
14
14
  "maxHeight": 10,
15
15
  },
16
16
  ]
@@ -4,8 +4,8 @@ exports[`ScreenContainer renders 1`] = `
4
4
  <RNCSafeAreaProvider
5
5
  onInsetsChange={[Function]}
6
6
  style={
7
- Array [
8
- Object {
7
+ [
8
+ {
9
9
  "flex": 1,
10
10
  },
11
11
  undefined,
@@ -14,14 +14,14 @@ exports[`ScreenContainer renders 1`] = `
14
14
  >
15
15
  <View
16
16
  style={
17
- Array [
18
- Object {
17
+ [
18
+ {
19
19
  "position": "absolute",
20
20
  "top": 0,
21
21
  "width": 1920,
22
22
  "zIndex": 10,
23
23
  },
24
- Object {
24
+ {
25
25
  "maxHeight": 10,
26
26
  },
27
27
  ]
@@ -30,7 +30,7 @@ exports[`ScreenContainer renders 1`] = `
30
30
  >
31
31
  <View
32
32
  isVisible={true}
33
- menuPlugin={Object {}}
33
+ menuPlugin={{}}
34
34
  navigationProps={null}
35
35
  />
36
36
  </View>
@@ -38,13 +38,13 @@ exports[`ScreenContainer renders 1`] = `
38
38
  `;
39
39
 
40
40
  exports[`ScreenContainer sets margins provided by the theme 1`] = `
41
- Array [
42
- Object {
41
+ [
42
+ {
43
43
  "flex": 1,
44
44
  "height": "100%",
45
45
  "width": "100%",
46
46
  },
47
- Object {
47
+ {
48
48
  "backgroundColor": "transparent",
49
49
  "marginBottom": 10,
50
50
  "paddingBottom": 0,
@@ -8,7 +8,7 @@ exports[`Layout TV renders 1`] = `
8
8
  >
9
9
  <View
10
10
  Components={
11
- Object {
11
+ {
12
12
  "Background": [Function],
13
13
  "NavBar": [Function],
14
14
  }
@@ -8,9 +8,13 @@ import configureStore from "redux-mock-store";
8
8
 
9
9
  const withoutChildren = omit(["children"]);
10
10
 
11
- jest.mock("../../../Screen/TV/index.web", () => ({
12
- Screen: View,
13
- }));
11
+ jest.mock("../../../Screen/TV/index.web", () => {
12
+ const View = jest.requireActual("react-native").View;
13
+
14
+ return {
15
+ Screen: View,
16
+ };
17
+ });
14
18
 
15
19
  const Layout = require("../index.web").default;
16
20
 
@@ -0,0 +1,66 @@
1
+ import {
2
+ BorderContainerView,
3
+ getBorderPadding, // Export for testing (using a double underscore prefix is a common convention)
4
+ } from "../index";
5
+ import * as React from "react";
6
+ import { render } from "@testing-library/react-native";
7
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
8
+ import { View } from "react-native";
9
+
10
+ jest.mock("@applicaster/zapp-react-native-utils/numberUtils", () => ({
11
+ toNumberWithDefaultZero: jest.fn((value) => Number(value) || 0),
12
+ }));
13
+
14
+ describe("BorderContainerView", () => {
15
+ describe("getBorderPadding", () => {
16
+ it("returns 0 for inside", () => {
17
+ expect(getBorderPadding("inside", 10)).toBe(0);
18
+ });
19
+
20
+ it("returns borderWidth / 2 for center", () => {
21
+ expect(getBorderPadding("center", 10)).toBe(5);
22
+ });
23
+
24
+ it("returns borderWidth for outside", () => {
25
+ expect(getBorderPadding("outside", 10)).toBe(10);
26
+ });
27
+
28
+ it("returns borderWidth for invalid position", () => {
29
+ // @ts-ignore
30
+ expect(getBorderPadding("other_value", 10)).toBe(10);
31
+ });
32
+ });
33
+
34
+ it("Border component renders null if no borderPosition", () => {
35
+ const style = { borderWidth: 5, borderRadius: 10, borderColor: "red" };
36
+
37
+ const padding = {
38
+ paddingTop: 2,
39
+ paddingRight: 3,
40
+ paddingBottom: 4,
41
+ paddingLeft: 5,
42
+ };
43
+
44
+ const borderPosition = null;
45
+
46
+ const { queryByTestId } = render(
47
+ <BorderContainerView
48
+ style={style}
49
+ testID="border-container"
50
+ borderPosition={borderPosition}
51
+ borderPaddingTop={toNumberWithDefaultZero(padding.paddingTop)}
52
+ borderPaddingRight={toNumberWithDefaultZero(padding.paddingRight)}
53
+ borderPaddingBottom={toNumberWithDefaultZero(padding.paddingBottom)}
54
+ borderPaddingLeft={toNumberWithDefaultZero(padding.paddingLeft)}
55
+ >
56
+ <View testID="child" />
57
+ </BorderContainerView>
58
+ );
59
+
60
+ const children = queryByTestId("border-container").children;
61
+
62
+ expect(children[1].props.testID).toBe("child");
63
+
64
+ expect(children[0].children.length).toBe(0);
65
+ });
66
+ });
@@ -28,7 +28,10 @@ const styles = StyleSheet.create({
28
28
  },
29
29
  });
30
30
 
31
- const getBorderPadding = (borderPosition: BorderPosition, borderWidth) => {
31
+ export const getBorderPadding = (
32
+ borderPosition: BorderPosition,
33
+ borderWidth: number
34
+ ) => {
32
35
  switch (borderPosition) {
33
36
  case "inside":
34
37
  return 0;
@@ -43,6 +43,8 @@ export default function Image({
43
43
  // toFiniteNumberWithDefault(0, style.height)
44
44
  // );
45
45
 
46
+ // const index = R.pathOr(-1, ["item", "index"], otherProps);
47
+
46
48
  const source = useImageSourceWithDefault({
47
49
  uri,
48
50
  entry,
@@ -51,6 +53,10 @@ export default function Image({
51
53
  otherProps,
52
54
  });
53
55
 
56
+ // const source = {
57
+ // uri: `https://placehold.co/200x200/orange/white.png?text=${index}`,
58
+ // };
59
+
54
60
  const onError = React.useCallback(() => {
55
61
  appendFailedToLoadUri(uri);
56
62
  setShowDefault(true);
@@ -31,6 +31,12 @@ function Image({
31
31
 
32
32
  const source = useImageSource({ uri, entry, otherProps });
33
33
 
34
+ // const index = R.pathOr(-1, ["item", "index"], otherProps);
35
+
36
+ // const source = {
37
+ // uri: `https://placehold.co/200x200/orange/white.png?text=${index}`,
38
+ // };
39
+
34
40
  React.useEffect(() => {
35
41
  // reset error state on URI change as the error is referencing previous uri
36
42
  setErrorState(null);
@@ -38,22 +44,16 @@ function Image({
38
44
 
39
45
  const shouldRenderImg = source && !error;
40
46
 
41
- // Default placeholder image fallback is empty string because it won't rerender
42
- // in case of undefined or {uri: undefined} source
43
- // https://github.com/facebook/react-native/issues/9195
44
- const defaultPlaceHolderImage = React.useMemo(
45
- () => ({ uri: placeholderImage || "" }),
46
- [source, error]
47
- );
47
+ const _source = shouldRenderImg
48
+ ? withDimensions(source)
49
+ : { uri: placeholderImage };
48
50
 
49
51
  return (
50
- // @ts-ignore
51
52
  <MemoizedImage
52
53
  style={style as ImageStyle}
53
- onError={() => setErrorState(true)}
54
- source={
55
- shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
56
- }
54
+ onError={React.useCallback(() => setErrorState(true), [])}
55
+ // as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
56
+ source={_source?.uri ? _source : undefined}
57
57
  {...R.omit(["source"], otherProps)}
58
58
  />
59
59
  );
@@ -0,0 +1,93 @@
1
+ import { ImageBorderContainer } from "../index";
2
+ import { getImageContainerMarginStyles } from "@applicaster/zapp-react-native-utils/cellUtils";
3
+
4
+ const mockValue = (key) => {
5
+ const values = {
6
+ cell_padding_top: 1,
7
+ cell_padding_left: 2,
8
+ cell_padding_right: 3,
9
+ cell_padding_bottom: 4,
10
+ image_border_size: 5,
11
+ image_focused_border_color: "red",
12
+ image_selected_border_color: "blue",
13
+ image_focused_selected_border_color: "green",
14
+ image_border_color: "black",
15
+ image_corner_radius: 10,
16
+ image_border_position: "outside",
17
+ image_border_padding_top: 6,
18
+ image_border_padding_right: 7,
19
+ image_border_padding_bottom: 8,
20
+ image_border_padding_left: 9,
21
+ image_margin_top: 11,
22
+ image_margin_left: 12,
23
+ image_margin_right: 13,
24
+ image_margin_bottom: 14,
25
+ };
26
+
27
+ return values[key] || 0;
28
+ };
29
+
30
+ describe("ImageBorderContainer", () => {
31
+ it("calculates style properties correctly", () => {
32
+ const marginStyles = getImageContainerMarginStyles({ value: mockValue });
33
+
34
+ expect(marginStyles.marginTop).toBe(11);
35
+ expect(marginStyles.marginLeft).toBe(12);
36
+ expect(marginStyles.marginRight).toBe(13);
37
+ expect(marginStyles.marginBottom).toBe(14);
38
+
39
+ const props = {
40
+ value: mockValue,
41
+ state: "default",
42
+ imageStyles: {},
43
+ };
44
+
45
+ const result = ImageBorderContainer(props);
46
+
47
+ expect(result.style.marginTop).toBe(12); // 11 + 1
48
+ expect(result.style.marginLeft).toBe(14); // 12 + 2
49
+ expect(result.style.marginRight).toBe(16); // 13 + 3
50
+ expect(result.style.marginBottom).toBe(18); // 14 + 4
51
+ expect(result.style.borderWidth).toBe(5);
52
+ expect(result.style.borderColor).toBe("black");
53
+ expect(result.style.borderRadius).toBe(10);
54
+ expect(result.additionalProps.borderPosition).toBe("outside");
55
+ expect(result.additionalProps.borderPaddingTop).toBe(6);
56
+ expect(result.additionalProps.borderPaddingRight).toBe(7);
57
+ expect(result.additionalProps.borderPaddingBottom).toBe(8);
58
+ expect(result.additionalProps.borderPaddingLeft).toBe(9);
59
+ });
60
+
61
+ it("handles focused state correctly", () => {
62
+ const props = {
63
+ value: mockValue,
64
+ state: "focused",
65
+ imageStyles: {},
66
+ };
67
+
68
+ const result = ImageBorderContainer(props);
69
+ expect(result.style.borderColor).toBe("red");
70
+ });
71
+
72
+ it("handles selected state correctly", () => {
73
+ const props = {
74
+ value: mockValue,
75
+ state: "selected",
76
+ imageStyles: {},
77
+ };
78
+
79
+ const result = ImageBorderContainer(props);
80
+ expect(result.style.borderColor).toBe("blue");
81
+ });
82
+
83
+ it("handles focused and selected state correctly", () => {
84
+ const props = {
85
+ value: mockValue,
86
+ state: "focused_selected",
87
+ imageStyles: {},
88
+ };
89
+
90
+ const result = ImageBorderContainer(props);
91
+ expect(result.style.borderColor).toBe("green");
92
+ });
93
+ });
@@ -6,7 +6,7 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
6
6
  <View
7
7
  onLayout={[Function]}
8
8
  style={
9
- Object {
9
+ {
10
10
  "borderRadius": 10,
11
11
  "height": 100,
12
12
  "width": 100,
@@ -16,12 +16,12 @@ exports[`SecondaryImage - Image SecondaryImage should render if known dimensions
16
16
  <Image
17
17
  onAsyncRender={[Function]}
18
18
  source={
19
- Object {
19
+ {
20
20
  "uri": "",
21
21
  }
22
22
  }
23
23
  style={
24
- Object {
24
+ {
25
25
  "aspectRatio": 1,
26
26
  "borderRadius": 10,
27
27
  "height": 100,
@@ -17,7 +17,7 @@ const SECONDARY_IMAGE_PREFIX = "secondary_image";
17
17
 
18
18
  type ImageSizing = typeof IMAGE_SIZING_FIT | typeof IMAGE_SIZING_FILL;
19
19
 
20
- type ImagePosition = typeof IMAGE_POSITION[keyof typeof IMAGE_POSITION];
20
+ type ImagePosition = (typeof IMAGE_POSITION)[keyof typeof IMAGE_POSITION];
21
21
 
22
22
  export type DisplayMode =
23
23
  | typeof DISPLAY_MODE_FIXED
@@ -39,6 +39,6 @@ describe("image with no source", () => {
39
39
  );
40
40
 
41
41
  const testInstance = testRenderer.root;
42
- expect(testInstance.findByType(Image).props.source).toEqual({ uri: "" });
42
+ expect(testInstance.findByType(Image).props.source).toBeUndefined();
43
43
  });
44
44
  });
@@ -3,7 +3,7 @@
3
3
  exports[`CollapsibleTextContainer render container+children when label is presented 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "backgroundColor": "#000000",
8
8
  }
9
9
  }