@applicaster/zapp-react-native-utils 15.0.0-rc.9 → 15.0.0-rc.90
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/actionsExecutor/ActionExecutorContext.tsx +3 -6
- package/actionsExecutor/feedDecorator.ts +6 -6
- package/adsUtils/index.ts +2 -2
- package/analyticsUtils/README.md +1 -1
- package/analyticsUtils/analyticsMapper.ts +10 -2
- package/appUtils/HooksManager/index.ts +10 -10
- package/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
- package/appUtils/accessibilityManager/__tests__/utils.test.ts +360 -0
- package/appUtils/accessibilityManager/const.ts +4 -0
- package/appUtils/accessibilityManager/hooks.ts +20 -13
- package/appUtils/accessibilityManager/index.ts +28 -1
- package/appUtils/accessibilityManager/utils.ts +59 -8
- package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
- package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
- package/appUtils/contextKeysManager/contextResolver.ts +51 -22
- package/appUtils/contextKeysManager/index.ts +65 -10
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +4 -0
- package/appUtils/focusManager/index.ios.ts +59 -3
- package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
- package/appUtils/focusManagerAux/utils/index.ts +19 -1
- package/appUtils/focusManagerAux/utils/utils.ios.ts +231 -0
- package/appUtils/keyCodes/keys/keys.web.ts +1 -4
- package/appUtils/orientationHelper.ts +2 -4
- package/appUtils/platform/platformUtils.ts +117 -18
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
- package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
- package/appUtils/playerManager/player.ts +4 -0
- package/appUtils/playerManager/playerNative.ts +29 -16
- package/appUtils/playerManager/usePlayerState.tsx +14 -2
- package/arrayUtils/__tests__/allTruthy.test.ts +24 -0
- package/arrayUtils/__tests__/anyThruthy.test.ts +24 -0
- package/arrayUtils/index.ts +5 -0
- package/cellUtils/index.ts +32 -0
- package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +38 -0
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
- package/configurationUtils/index.ts +17 -11
- package/focusManager/aux/index.ts +1 -1
- package/manifestUtils/defaultManifestConfigurations/player.js +96 -11
- package/manifestUtils/keys.js +21 -0
- package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
- package/manifestUtils/tvAction/container/index.js +1 -1
- package/navigationUtils/index.ts +15 -5
- package/package.json +4 -4
- package/playerUtils/usePlayerTTS.ts +8 -3
- package/pluginUtils/index.ts +4 -0
- package/reactHooks/advertising/index.ts +2 -2
- package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
- package/reactHooks/cell-click/__tests__/index.test.js +1 -3
- package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
- package/reactHooks/connection/__tests__/index.test.js +1 -1
- package/reactHooks/debugging/__tests__/index.test.js +4 -4
- package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
- package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +4 -1
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
- package/reactHooks/feed/__tests__/{useInflatedUrl.test.ts → useInflatedUrl.test.tsx} +62 -7
- package/reactHooks/feed/useBatchLoading.ts +7 -1
- package/reactHooks/feed/useEntryScreenId.ts +2 -2
- package/reactHooks/feed/useInflatedUrl.ts +43 -17
- package/reactHooks/feed/usePipesCacheReset.ts +3 -1
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
- package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +12 -8
- package/reactHooks/layout/__tests__/index.test.tsx +1 -1
- package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
- package/reactHooks/layout/index.ts +1 -1
- package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
- package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
- package/reactHooks/navigation/__tests__/index.test.tsx +40 -9
- package/reactHooks/navigation/index.ts +27 -11
- package/reactHooks/navigation/useRoute.ts +11 -7
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
- package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
- package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
- package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
- package/reactHooks/resolvers/useCellResolver.ts +6 -2
- package/reactHooks/resolvers/useComponentResolver.ts +8 -2
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
- package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +12 -4
- package/reactHooks/screen/useTargetScreenData.ts +4 -2
- package/reactHooks/state/useRefWithInitialValue.ts +10 -0
- package/reactHooks/state/useRivers.ts +1 -1
- package/reactHooks/usePluginConfiguration.ts +2 -2
- package/reactHooks/utils/__tests__/index.test.js +1 -1
- package/screenState/__tests__/index.test.ts +1 -1
- package/searchUtils/const.ts +7 -0
- package/searchUtils/index.ts +3 -0
- package/services/storageServiceSync.web.ts +1 -1
- package/stringUtils/index.ts +1 -1
- package/testUtils/index.tsx +30 -21
- package/utils/__tests__/mapAccum.test.ts +73 -0
- package/utils/__tests__/mergeRight.test.ts +48 -0
- package/utils/__tests__/selectors.test.ts +124 -0
- package/utils/index.ts +20 -0
- package/utils/mapAccum.ts +23 -0
- package/utils/mergeRight.ts +5 -0
- package/utils/path.ts +6 -3
- package/utils/pathOr.ts +5 -1
- package/utils/selectors.ts +46 -0
- package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +49 -12
- package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import { renderHook } from "@testing-library/react-
|
|
4
|
-
import { act, waitFor } from "@testing-library/react-native";
|
|
3
|
+
import { renderHook, act, waitFor } from "@testing-library/react-native";
|
|
5
4
|
import { Provider } from "react-redux";
|
|
6
5
|
import configureStore from "redux-mock-store";
|
|
7
6
|
import { useTrackedView } from "../useTrackedView";
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { cleanup, renderHook } from "@testing-library/react-
|
|
2
|
+
import { cleanup, renderHook, waitFor } from "@testing-library/react-native";
|
|
3
3
|
import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
|
|
4
4
|
import { ActionExecutorContext } from "@applicaster/zapp-react-native-utils/actionsExecutor/ActionExecutorContext";
|
|
5
5
|
|
|
6
|
-
import { waitFor } from "@testing-library/react-native";
|
|
7
|
-
|
|
8
6
|
const mockNavigator = {
|
|
9
7
|
getPathname: () => "pathnameMock",
|
|
10
8
|
push: jest.fn(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable react/prop-types */
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { renderHook, cleanup } from "@testing-library/react-
|
|
3
|
+
import { renderHook, cleanup } from "@testing-library/react-native";
|
|
4
4
|
import { ConfigurationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ConfigutaionContext";
|
|
5
5
|
import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { renderHook, cleanup } from "@testing-library/react-
|
|
2
|
+
import { renderHook, cleanup } from "@testing-library/react-native";
|
|
3
3
|
import { NetworkStatusContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NetworkStatusContext";
|
|
4
4
|
|
|
5
5
|
const MockNetInfo = {
|
|
@@ -27,20 +27,20 @@ describe("Debug utils", () => {
|
|
|
27
27
|
it("should create new timer if timer with a label does not exist", () => {
|
|
28
28
|
performanceNowMock.mockReturnValue(1000);
|
|
29
29
|
time("timer1");
|
|
30
|
-
expect(timers
|
|
31
|
-
expect(timers
|
|
30
|
+
expect(timers.timer1).toBeDefined();
|
|
31
|
+
expect(timers.timer1.startTime).toBe(1000);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
it("should update start time of timer if timer with a label exists", () => {
|
|
35
35
|
// First call to time()
|
|
36
36
|
performanceNowMock.mockReturnValue(1000);
|
|
37
37
|
time("timer1");
|
|
38
|
-
const previousStartTime = timers
|
|
38
|
+
const previousStartTime = timers.timer1.startTime;
|
|
39
39
|
|
|
40
40
|
// Second call to time()
|
|
41
41
|
performanceNowMock.mockReturnValue(2000);
|
|
42
42
|
time("timer1");
|
|
43
|
-
const currentStartTime = timers
|
|
43
|
+
const currentStartTime = timers.timer1.startTime;
|
|
44
44
|
|
|
45
45
|
expect(previousStartTime).toBe(1000);
|
|
46
46
|
expect(currentStartTime).toBe(2000);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
3
2
|
import { useIsTablet } from "./useIsTablet";
|
|
3
|
+
import { useAppData } from "@applicaster/zapp-react-native-redux";
|
|
4
4
|
|
|
5
5
|
export const useMemoizedIsTablet = () => {
|
|
6
6
|
const isTablet = useIsTablet();
|
|
@@ -14,9 +14,9 @@ export const useMemoizedIsTablet = () => {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export const useIsTabletLandscape = (): boolean => {
|
|
17
|
-
const {
|
|
17
|
+
const { isTabletPortrait } = useAppData();
|
|
18
18
|
|
|
19
19
|
const isTablet = useIsTablet();
|
|
20
20
|
|
|
21
|
-
return isTablet && !
|
|
21
|
+
return isTablet && !isTabletPortrait;
|
|
22
22
|
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react-
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react-native";
|
|
2
2
|
import { allFeedsIsReady, useBatchLoading } from "../useBatchLoading";
|
|
3
3
|
import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
4
4
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
5
|
-
import { waitFor } from "@testing-library/react-native";
|
|
6
5
|
|
|
7
6
|
jest.mock("../../navigation");
|
|
8
7
|
|
|
@@ -16,7 +15,11 @@ jest.mock(
|
|
|
16
15
|
})
|
|
17
16
|
);
|
|
18
17
|
|
|
19
|
-
const
|
|
18
|
+
const getWrapper =
|
|
19
|
+
(store) =>
|
|
20
|
+
({ children }) => (
|
|
21
|
+
<WrappedWithProviders store={store}>{children}</WrappedWithProviders>
|
|
22
|
+
);
|
|
20
23
|
|
|
21
24
|
describe("useBatchLoading", () => {
|
|
22
25
|
const data = [
|
|
@@ -63,8 +66,7 @@ describe("useBatchLoading", () => {
|
|
|
63
66
|
const riverId = "123";
|
|
64
67
|
|
|
65
68
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
66
|
-
wrapper,
|
|
67
|
-
initialProps: { store },
|
|
69
|
+
wrapper: getWrapper(store),
|
|
68
70
|
});
|
|
69
71
|
|
|
70
72
|
const actions = (appStore.getStore() as any).getActions();
|
|
@@ -84,7 +86,7 @@ describe("useBatchLoading", () => {
|
|
|
84
86
|
});
|
|
85
87
|
});
|
|
86
88
|
|
|
87
|
-
it("loadPipesData start loading new feed when 1 feed is done loading and 1 is in loading state", () => {
|
|
89
|
+
it("loadPipesData start loading new feed when 1 feed is done loading and 1 is in loading state", async () => {
|
|
88
90
|
const store = {
|
|
89
91
|
zappPipes: {
|
|
90
92
|
url1: {
|
|
@@ -110,13 +112,14 @@ describe("useBatchLoading", () => {
|
|
|
110
112
|
const riverId = "123";
|
|
111
113
|
|
|
112
114
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
113
|
-
wrapper,
|
|
114
|
-
initialProps: { store },
|
|
115
|
+
wrapper: getWrapper(store),
|
|
115
116
|
});
|
|
116
117
|
|
|
117
118
|
const actions = (appStore.getStore() as any).getActions();
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
await waitFor(() => {
|
|
121
|
+
expect(actions).toHaveLength(1);
|
|
122
|
+
});
|
|
120
123
|
|
|
121
124
|
expect(actions[0]).toMatchObject({
|
|
122
125
|
type: "ZAPP_PIPES_REQUEST_START",
|
|
@@ -124,7 +127,7 @@ describe("useBatchLoading", () => {
|
|
|
124
127
|
});
|
|
125
128
|
});
|
|
126
129
|
|
|
127
|
-
it("loadPipesData has been called when no data cached", () => {
|
|
130
|
+
it("loadPipesData has been called when no data cached", async () => {
|
|
128
131
|
const store = {
|
|
129
132
|
zappPipes: {},
|
|
130
133
|
test: "true",
|
|
@@ -134,16 +137,17 @@ describe("useBatchLoading", () => {
|
|
|
134
137
|
const riverId = "123";
|
|
135
138
|
|
|
136
139
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
137
|
-
wrapper,
|
|
138
|
-
initialProps: { store },
|
|
140
|
+
wrapper: getWrapper(store),
|
|
139
141
|
});
|
|
140
142
|
|
|
141
143
|
const actions = (appStore.getStore() as any).getActions();
|
|
142
144
|
|
|
143
|
-
|
|
145
|
+
await waitFor(() => {
|
|
146
|
+
expect(actions).toHaveLength(3);
|
|
147
|
+
});
|
|
144
148
|
});
|
|
145
149
|
|
|
146
|
-
it("initial batch ready when all initial items loaded", () => {
|
|
150
|
+
it("initial batch ready when all initial items loaded", async () => {
|
|
147
151
|
const store = {
|
|
148
152
|
zappPipes: {
|
|
149
153
|
url1: {
|
|
@@ -169,13 +173,15 @@ describe("useBatchLoading", () => {
|
|
|
169
173
|
|
|
170
174
|
const { result } = renderHook(
|
|
171
175
|
() => useBatchLoading(data, { initialBatchSize, riverId }),
|
|
172
|
-
{ wrapper
|
|
176
|
+
{ wrapper: getWrapper(store) }
|
|
173
177
|
);
|
|
174
178
|
|
|
175
|
-
|
|
179
|
+
await waitFor(() => {
|
|
180
|
+
expect(result.current).toBe(true);
|
|
181
|
+
});
|
|
176
182
|
});
|
|
177
183
|
|
|
178
|
-
it("gallery-qb: loadPipesData should be called only once for first component in the gallery", () => {
|
|
184
|
+
it("gallery-qb: loadPipesData should be called only once for first component in the gallery", async () => {
|
|
179
185
|
const store = {
|
|
180
186
|
zappPipes: {},
|
|
181
187
|
test: "true",
|
|
@@ -198,16 +204,17 @@ describe("useBatchLoading", () => {
|
|
|
198
204
|
];
|
|
199
205
|
|
|
200
206
|
renderHook(() => useBatchLoading(data, { initialBatchSize, riverId }), {
|
|
201
|
-
wrapper,
|
|
202
|
-
initialProps: { store },
|
|
207
|
+
wrapper: getWrapper(store),
|
|
203
208
|
});
|
|
204
209
|
|
|
205
210
|
const actions = (appStore.getStore() as any).getActions();
|
|
206
211
|
|
|
207
|
-
|
|
212
|
+
await waitFor(() => {
|
|
213
|
+
expect(actions).toHaveLength(1);
|
|
214
|
+
});
|
|
208
215
|
});
|
|
209
216
|
|
|
210
|
-
it("gallery-qb: initial batch ready when all initial items loaded", () => {
|
|
217
|
+
it("gallery-qb: initial batch ready when all initial items loaded", async () => {
|
|
211
218
|
const store = {
|
|
212
219
|
zappPipes: {
|
|
213
220
|
url1: {
|
|
@@ -233,10 +240,12 @@ describe("useBatchLoading", () => {
|
|
|
233
240
|
|
|
234
241
|
const { result } = renderHook(
|
|
235
242
|
() => useBatchLoading(data, { initialBatchSize, riverId }),
|
|
236
|
-
{ wrapper
|
|
243
|
+
{ wrapper: getWrapper(store) }
|
|
237
244
|
);
|
|
238
245
|
|
|
239
|
-
|
|
246
|
+
await waitFor(() => {
|
|
247
|
+
expect(result.current).toBe(true);
|
|
248
|
+
});
|
|
240
249
|
});
|
|
241
250
|
});
|
|
242
251
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react-
|
|
1
|
+
import { renderHook, waitFor } from "@testing-library/react-native";
|
|
2
2
|
import { encodeParams } from "@applicaster/zapp-pipes-v2-client/src/utils";
|
|
3
3
|
|
|
4
4
|
const appData = {
|
|
@@ -42,26 +42,26 @@ describe("useBuildPipesUrl", () => {
|
|
|
42
42
|
build: jest.fn(() => Promise.resolve(buildResult)),
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const { result
|
|
45
|
+
const { result } = renderHook(() =>
|
|
46
46
|
useBuildPipesUrl({ url, mapping, requestBuilder: mockedRequestBuilder })
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
expect(result.current.url).toBe("http://foo.com/show/show-1");
|
|
50
50
|
expect(result.current.requestParams).toBeNull();
|
|
51
51
|
|
|
52
|
-
await
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
);
|
|
52
|
+
await waitFor(() => {
|
|
53
|
+
expect(result.current.requestParams).toEqual(
|
|
54
|
+
expect.objectContaining({
|
|
55
|
+
params: {
|
|
56
|
+
version: appData.version_name,
|
|
57
|
+
ctx: encodeParams({ platform: appData.platform }),
|
|
58
|
+
},
|
|
59
|
+
headers: {
|
|
60
|
+
SDK: appData.sdk_version,
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
it("returns empty object if url is not in endpoints", async () => {
|
|
@@ -81,15 +81,15 @@ describe("useBuildPipesUrl", () => {
|
|
|
81
81
|
build: jest.fn(() => Promise.resolve(buildResult)),
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
const { result
|
|
84
|
+
const { result } = renderHook(() =>
|
|
85
85
|
useBuildPipesUrl({ url, mapping, requestBuilder: mockedRequestBuilder })
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
expect(result.current.url).toBe("http://foobar.com/show-1");
|
|
89
89
|
expect(result.current.requestParams).toBeNull();
|
|
90
90
|
|
|
91
|
-
await
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
await waitFor(() => {
|
|
92
|
+
expect(result.current.requestParams).toEqual({});
|
|
93
|
+
});
|
|
94
94
|
});
|
|
95
95
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { renderHook } from "@testing-library/react-
|
|
3
|
+
import { renderHook } from "@testing-library/react-native";
|
|
4
4
|
import { Provider } from "react-redux";
|
|
5
5
|
import { createStore } from "redux";
|
|
6
6
|
|
|
@@ -10,6 +10,9 @@ describe("useEntryScreenId", () => {
|
|
|
10
10
|
const mappedScreenId = "mapped-id";
|
|
11
11
|
|
|
12
12
|
const initialState = {
|
|
13
|
+
rivers: {
|
|
14
|
+
[mappedScreenId]: { id: mappedScreenId, type: "any" },
|
|
15
|
+
},
|
|
13
16
|
contentTypes: { mappedEntry: { screen_id: mappedScreenId } },
|
|
14
17
|
};
|
|
15
18
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react-
|
|
1
|
+
import { renderHook } from "@testing-library/react-native";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import * as zappPipesModule from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
4
4
|
import * as reactReduxModules from "react-redux";
|
|
@@ -50,6 +50,16 @@ const mockZappPipesData = {
|
|
|
50
50
|
url: "test://testfakeurl",
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
const createWrapper = (
|
|
54
|
+
getStore: () => any
|
|
55
|
+
): React.FC<{ children: React.ReactNode }> => {
|
|
56
|
+
const Wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
|
57
|
+
<WrappedWithProviders store={getStore()}>{children}</WrappedWithProviders>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return Wrapper;
|
|
61
|
+
};
|
|
62
|
+
|
|
53
63
|
describe("useFeedLoader", () => {
|
|
54
64
|
describe("with cached feed url", () => {
|
|
55
65
|
const store = {
|
|
@@ -57,11 +67,7 @@ describe("useFeedLoader", () => {
|
|
|
57
67
|
zappPipes: { "test://testfakeurl": mockZappPipesData },
|
|
58
68
|
};
|
|
59
69
|
|
|
60
|
-
const wrapper
|
|
61
|
-
<WrappedWithProviders store={props.store || store}>
|
|
62
|
-
{children}
|
|
63
|
-
</WrappedWithProviders>
|
|
64
|
-
);
|
|
70
|
+
const wrapper = createWrapper(() => store);
|
|
65
71
|
|
|
66
72
|
it("returns cached feed", () => {
|
|
67
73
|
const { result } = renderHook(
|
|
@@ -109,12 +115,6 @@ describe("useFeedLoader", () => {
|
|
|
109
115
|
describe("without cached feeds", () => {
|
|
110
116
|
const feedUrl = "test://testfakeurl2";
|
|
111
117
|
|
|
112
|
-
const wrapper: React.FC<any> = ({ children, ...props }) => (
|
|
113
|
-
<WrappedWithProviders store={props.store}>
|
|
114
|
-
{children}
|
|
115
|
-
</WrappedWithProviders>
|
|
116
|
-
);
|
|
117
|
-
|
|
118
118
|
it("It loads data for new url and returns it", () => {
|
|
119
119
|
const useDispatchSpy = jest
|
|
120
120
|
.spyOn(reactReduxModules, "useDispatch")
|
|
@@ -129,9 +129,12 @@ describe("useFeedLoader", () => {
|
|
|
129
129
|
zappPipes: { "test://testfakeurl": "foobar" },
|
|
130
130
|
};
|
|
131
131
|
|
|
132
|
+
let store = initialStore;
|
|
133
|
+
const wrapper = createWrapper(() => store);
|
|
134
|
+
|
|
132
135
|
const { result, rerender } = renderHook(
|
|
133
|
-
() => useFeedLoader({ feedUrl:
|
|
134
|
-
{ wrapper, initialProps: {
|
|
136
|
+
({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
|
|
137
|
+
{ wrapper, initialProps: { feedUrl } }
|
|
135
138
|
);
|
|
136
139
|
|
|
137
140
|
expect(result.current.data).toBeNull();
|
|
@@ -150,7 +153,8 @@ describe("useFeedLoader", () => {
|
|
|
150
153
|
zappPipes: { "test://testfakeurl2": mockZappPipesData },
|
|
151
154
|
};
|
|
152
155
|
|
|
153
|
-
|
|
156
|
+
store = store2;
|
|
157
|
+
rerender({ feedUrl });
|
|
154
158
|
|
|
155
159
|
expect(R.omit(["reloadData", "loadNext"], result.current)).toEqual(
|
|
156
160
|
mockZappPipesData
|
|
@@ -174,9 +178,12 @@ describe("useFeedLoader", () => {
|
|
|
174
178
|
zappPipes: { "test://testfakeurl": "foobar" },
|
|
175
179
|
};
|
|
176
180
|
|
|
181
|
+
let store = initialStore;
|
|
182
|
+
const wrapper = createWrapper(() => store);
|
|
183
|
+
|
|
177
184
|
const { result, rerender } = renderHook(
|
|
178
|
-
() => useFeedLoader({ feedUrl:
|
|
179
|
-
{ wrapper, initialProps: {
|
|
185
|
+
({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
|
|
186
|
+
{ wrapper, initialProps: { feedUrl } }
|
|
180
187
|
);
|
|
181
188
|
|
|
182
189
|
expect(result.current.data).toBeNull();
|
|
@@ -198,7 +205,8 @@ describe("useFeedLoader", () => {
|
|
|
198
205
|
zappPipes: { "test://testfakeurl2": mockZappPipesData },
|
|
199
206
|
};
|
|
200
207
|
|
|
201
|
-
|
|
208
|
+
store = store2;
|
|
209
|
+
rerender({ feedUrl });
|
|
202
210
|
|
|
203
211
|
loadPipesDataSpy.mockRestore();
|
|
204
212
|
useDispatchSpy.mockRestore();
|
|
@@ -209,12 +217,6 @@ describe("useFeedLoader", () => {
|
|
|
209
217
|
const feedUrl = "test://testfakeurl";
|
|
210
218
|
const feedUrlWithNext = "test://withnexttestfakeurl";
|
|
211
219
|
|
|
212
|
-
const wrapper: React.FC<any> = ({ children, ...props }) => (
|
|
213
|
-
<WrappedWithProviders store={props.store || {}}>
|
|
214
|
-
{children}
|
|
215
|
-
</WrappedWithProviders>
|
|
216
|
-
);
|
|
217
|
-
|
|
218
220
|
describe("reloadData", () => {
|
|
219
221
|
it("Tries to reload data in the redux store", () => {
|
|
220
222
|
const loadPipesDataSpy = jest
|
|
@@ -230,10 +232,17 @@ describe("useFeedLoader", () => {
|
|
|
230
232
|
zappPipes: { [feedUrl]: "foobar" },
|
|
231
233
|
};
|
|
232
234
|
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
const store = initialStore;
|
|
236
|
+
|
|
237
|
+
const wrapper = createWrapper(() => store);
|
|
238
|
+
|
|
239
|
+
const { result } = renderHook(
|
|
240
|
+
({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
|
|
241
|
+
{
|
|
242
|
+
wrapper,
|
|
243
|
+
initialProps: { feedUrl },
|
|
244
|
+
}
|
|
245
|
+
);
|
|
237
246
|
|
|
238
247
|
const { reloadData } = result.current;
|
|
239
248
|
|
|
@@ -279,11 +288,14 @@ describe("useFeedLoader", () => {
|
|
|
279
288
|
zappPipes: { [feedUrlWithNext]: { data: { next: nextUrl } } },
|
|
280
289
|
};
|
|
281
290
|
|
|
291
|
+
const store = initialStore;
|
|
292
|
+
const wrapper = createWrapper(() => store);
|
|
293
|
+
|
|
282
294
|
const { result } = renderHook(
|
|
283
|
-
() => useFeedLoader({ feedUrl:
|
|
295
|
+
({ feedUrl: url }) => useFeedLoader({ feedUrl: url }),
|
|
284
296
|
{
|
|
285
297
|
wrapper,
|
|
286
|
-
initialProps: {
|
|
298
|
+
initialProps: { feedUrl: feedUrlWithNext },
|
|
287
299
|
}
|
|
288
300
|
);
|
|
289
301
|
|
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
getInflatedDataSourceUrl,
|
|
7
|
+
getSearchContext,
|
|
8
|
+
useGetUrlInflater,
|
|
9
|
+
} from "../useInflatedUrl";
|
|
10
|
+
|
|
11
|
+
import { reactHooksLogger } from "../../logger";
|
|
12
|
+
|
|
13
|
+
jest.mock("../../navigation", () => ({
|
|
14
|
+
useRoute: () => ({ pathname: "/mock/path" }),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
// mock contexts hooks
|
|
18
|
+
jest.mock("@applicaster/zapp-react-native-ui-components/Contexts", () => ({
|
|
19
|
+
ZappPipesEntryContext: {
|
|
20
|
+
useZappPipesContext: () => [
|
|
21
|
+
{ id: "entry-1", extensions: { showId: "A123" } },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
ZappPipesSearchContext: {
|
|
25
|
+
useZappPipesContext: () => ["user%20query"],
|
|
26
|
+
},
|
|
27
|
+
ZappPipesScreenContext: {
|
|
28
|
+
useZappPipesContext: () => [{ id: "screen-1" }],
|
|
29
|
+
},
|
|
30
|
+
}));
|
|
31
|
+
|
|
1
32
|
jest.mock("../../logger", () => ({
|
|
2
33
|
reactHooksLogger: {
|
|
3
34
|
warning: jest.fn(),
|
|
@@ -5,13 +36,6 @@ jest.mock("../../logger", () => ({
|
|
|
5
36
|
},
|
|
6
37
|
}));
|
|
7
38
|
|
|
8
|
-
const {
|
|
9
|
-
getInflatedDataSourceUrl,
|
|
10
|
-
getSearchContext,
|
|
11
|
-
} = require("../useInflatedUrl");
|
|
12
|
-
|
|
13
|
-
const { reactHooksLogger } = require("../../logger");
|
|
14
|
-
|
|
15
39
|
let mockStore;
|
|
16
40
|
|
|
17
41
|
describe("getInflatedDataSourceUrl", () => {
|
|
@@ -188,3 +212,34 @@ describe("getSearchContext", () => {
|
|
|
188
212
|
expect(result).toHaveProperty(mapping.queryParam.property, searchContext);
|
|
189
213
|
});
|
|
190
214
|
});
|
|
215
|
+
|
|
216
|
+
describe("useGetUrlInflater", () => {
|
|
217
|
+
const { renderHook } = require("@testing-library/react-native");
|
|
218
|
+
|
|
219
|
+
it("returns original url when mapping is not provided", () => {
|
|
220
|
+
const { result } = renderHook(() => useGetUrlInflater(), {
|
|
221
|
+
wrapper: WrappedWithProviders,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const src = "https://foo.com/feed";
|
|
225
|
+
expect(result.current(src)).toBe(src);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("inflates url using entry/search/screen contexts when mapping provided", () => {
|
|
229
|
+
const { result } = renderHook(() => useGetUrlInflater(), {
|
|
230
|
+
wrapper: ({ children }) => (
|
|
231
|
+
<WrappedWithProviders>{children}</WrappedWithProviders>
|
|
232
|
+
),
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const source = "https://foo.com/shows/{{showId}}?q={{q}}";
|
|
236
|
+
|
|
237
|
+
const mapping = {
|
|
238
|
+
showId: { source: "entry", property: "extensions.showId" },
|
|
239
|
+
q: { source: "search", property: "q" },
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const url = result.current(source, mapping);
|
|
243
|
+
expect(url).toBe("https://foo.com/shows/A123?q=user%20query");
|
|
244
|
+
});
|
|
245
|
+
});
|
|
@@ -151,7 +151,13 @@ export const useBatchLoading = (
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
});
|
|
154
|
-
}, [
|
|
154
|
+
}, [
|
|
155
|
+
batchComponents,
|
|
156
|
+
feeds,
|
|
157
|
+
getUrl,
|
|
158
|
+
loadPipesDataDispatcher,
|
|
159
|
+
options.riverId,
|
|
160
|
+
]);
|
|
155
161
|
|
|
156
162
|
React.useEffect(() => {
|
|
157
163
|
runBatchLoading();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useContentTypes } from "@applicaster/zapp-react-native-redux";
|
|
2
2
|
|
|
3
3
|
export const useEntryScreenId = (entry?: ZappEntry): string | undefined => {
|
|
4
|
-
const
|
|
4
|
+
const contentTypes = useContentTypes();
|
|
5
5
|
|
|
6
6
|
if (!entry) {
|
|
7
7
|
return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
1
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -169,7 +169,7 @@ const encodeIfNeeded: (string) => string = R.tryCatch(
|
|
|
169
169
|
|
|
170
170
|
export function getSearchContext(
|
|
171
171
|
searchContext: string,
|
|
172
|
-
mapping: ZappTypeMapping
|
|
172
|
+
mapping: Nullable<ZappTypeMapping>
|
|
173
173
|
) {
|
|
174
174
|
if (!mapping) {
|
|
175
175
|
return {};
|
|
@@ -183,31 +183,57 @@ export function getSearchContext(
|
|
|
183
183
|
return { [property]: encodeIfNeeded(searchContext) };
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
mapping?: ZappTypeMapping;
|
|
192
|
-
}) {
|
|
186
|
+
/**
|
|
187
|
+
* Hook returns a function that replace placeholders with context values
|
|
188
|
+
* @returns function that inflates urls based on contexts
|
|
189
|
+
*/
|
|
190
|
+
export const useGetUrlInflater = () => {
|
|
193
191
|
const { pathname } = useRoute();
|
|
194
192
|
|
|
195
193
|
const [entryContext] = ZappPipesEntryContext.useZappPipesContext(pathname);
|
|
196
194
|
const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
|
|
197
195
|
const [screenContext] = ZappPipesScreenContext.useZappPipesContext();
|
|
198
196
|
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
const entryContextRef = useRef(entryContext);
|
|
198
|
+
entryContextRef.current = entryContext;
|
|
199
|
+
|
|
200
|
+
const screenContextRef = useRef(screenContext);
|
|
201
|
+
screenContextRef.current = screenContext;
|
|
202
|
+
|
|
203
|
+
const searchContextRef = useRef(searchContext);
|
|
204
|
+
searchContextRef.current = searchContext;
|
|
205
|
+
|
|
206
|
+
return useCallback(
|
|
207
|
+
(
|
|
208
|
+
feedUrl: Nullable<string>,
|
|
209
|
+
mapping?: Nullable<ZappTypeMapping>
|
|
210
|
+
): Nullable<string> => {
|
|
211
|
+
return getInflatedDataSourceUrl({
|
|
202
212
|
source: feedUrl,
|
|
203
213
|
contexts: {
|
|
204
|
-
entry:
|
|
205
|
-
screen:
|
|
206
|
-
search: getSearchContext(
|
|
214
|
+
entry: entryContextRef.current,
|
|
215
|
+
screen: screenContextRef.current,
|
|
216
|
+
search: getSearchContext(searchContextRef.current, mapping),
|
|
207
217
|
},
|
|
208
218
|
mapping,
|
|
209
|
-
})
|
|
210
|
-
|
|
219
|
+
});
|
|
220
|
+
},
|
|
221
|
+
[]
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export function useInflatedUrl({
|
|
226
|
+
feedUrl,
|
|
227
|
+
mapping,
|
|
228
|
+
}: {
|
|
229
|
+
feedUrl?: string;
|
|
230
|
+
mapping?: ZappTypeMapping;
|
|
231
|
+
}) {
|
|
232
|
+
const urlInflater = useGetUrlInflater();
|
|
233
|
+
|
|
234
|
+
const url = useMemo(
|
|
235
|
+
() => urlInflater(feedUrl, mapping),
|
|
236
|
+
[urlInflater, feedUrl, mapping]
|
|
211
237
|
);
|
|
212
238
|
|
|
213
239
|
return url;
|