@applicaster/quick-brick-core 15.0.0-rc.5 → 15.0.0-rc.50

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 (21) hide show
  1. package/App/ActionSetters/index.ts +5 -4
  2. package/App/ActionsProvider/ActionsProvider.tsx +6 -1
  3. package/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/__tests__/useOpenSchemeHandler.test.tsx +12 -27
  4. package/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/__tests__/useUrlSchemeHandler.test.tsx +196 -103
  5. package/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/useOpenSchemeHandler/index.ts +4 -7
  6. package/App/DeepLinking/URLSchemeHandler/SchemeHandlerHooks/useUrlSchemeHandler.ts +42 -30
  7. package/App/DeepLinking/URLSchemeHandler/URLSchemeHandler.tsx +4 -1
  8. package/App/DeepLinking/URLSchemeHandler/__tests__/URLSchemeHandler.test.tsx +20 -13
  9. package/App/DeepLinking/URLSchemeListener/index.tsx +3 -4
  10. package/App/ModalProvider/ModalBottomSheet/ModalBottomSheetFrame.tsx +6 -1
  11. package/App/NavigationProvider/Loader.tsx +3 -4
  12. package/App/NavigationProvider/NavigationProvider.tsx +21 -35
  13. package/App/NavigationProvider/ScreenHooks/usePluginScreenHooks.ts +2 -2
  14. package/App/NavigationProvider/__tests__/navigationProvider.test.tsx +141 -152
  15. package/App/NavigationProvider/navigator/selectors.ts +21 -5
  16. package/App/NetworkStatusProvider/NetworkStatusProvider.tsx +2 -2
  17. package/App/components/ZappAppWrapper.web.ts +2 -2
  18. package/App/remoteContextReloader/getRemoteContextData/getNativeRemoteContextData.ts +1 -1
  19. package/App/remoteContextReloader/helpers.ts +3 -3
  20. package/package.json +8 -8
  21. package/App/DeepLinking/URLSchemeHandler/__tests__/__snapshots__/URLSchemeHandler.test.tsx.snap +0 -24
@@ -21,7 +21,8 @@ const warnUndefinedContext = (context) =>
21
21
  });
22
22
 
23
23
  type Subscription = {
24
- [x: string]: () => any;
24
+ [x: string]: (() => any) | string;
25
+ pluginId?: string;
25
26
  };
26
27
 
27
28
  const getModuleContext = R.path(["module", "context"]);
@@ -29,7 +30,7 @@ const getModuleContext = R.path(["module", "context"]);
29
30
  const getContexts = R.compose(
30
31
  R.map((action) => {
31
32
  const item = getModuleContext(action);
32
- item["pluginId"] = action.name;
33
+ item.pluginId = action.name;
33
34
 
34
35
  return item;
35
36
  }),
@@ -46,10 +47,10 @@ const useSubscribeToActionProviders = () => {
46
47
  }, [actionContext]);
47
48
 
48
49
  const subscriptions = getContexts(actionContext.actions).map((context) => {
49
- const subscription = React.useContext<{}>(context);
50
+ const subscription = React.useContext<Subscription>(context);
50
51
 
51
52
  if (subscription) {
52
- subscription["pluginId"] = context.pluginId;
53
+ subscription.pluginId = context.pluginId;
53
54
 
54
55
  return subscription;
55
56
  } else {
@@ -90,8 +90,13 @@ export function ActionsProvider(props: Props) {
90
90
  []
91
91
  );
92
92
 
93
+ const contextValue = React.useMemo(
94
+ () => ({ actions: actionPlugins }),
95
+ [actionPlugins]
96
+ );
97
+
93
98
  return (
94
- <ActionsContext.Provider value={{ actions: actionPlugins }}>
99
+ <ActionsContext.Provider value={contextValue}>
95
100
  <Context>{children}</Context>
96
101
  </ActionsContext.Provider>
97
102
  );
@@ -1,14 +1,13 @@
1
1
  /* eslint-disable max-len */
2
- import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
3
2
  import * as feedLoader from "@applicaster/zapp-react-native-utils/reactHooks/feed/useFeedLoader";
4
3
  import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
5
4
  import { waitFor, cleanup, renderHook } from "@testing-library/react-native";
6
5
  import nock from "nock";
7
- import * as R from "ramda";
8
6
  import React from "react";
9
- import { Provider } from "react-redux";
10
- import configureStore from "redux-mock-store";
7
+ import { mergeDeepRight } from "ramda";
11
8
  import * as helpers from "../../../helpers";
9
+ import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
10
+
12
11
  import {
13
12
  noTargetScreenError,
14
13
  resolveError,
@@ -24,6 +23,7 @@ const rivers: Record<string, Partial<ZappRiver>> = {
24
23
  home: true,
25
24
  },
26
25
  B0987: {
26
+ type: "any",
27
27
  id: "B0987",
28
28
  },
29
29
  C5678: {
@@ -42,7 +42,7 @@ const contentTypes: ZappContentTypes = {
42
42
  const endpoint = "http://feed.com";
43
43
 
44
44
  const pipesEndpoints: ZappPipesEndpoints = {
45
- [`${endpoint}`]: {
45
+ [endpoint]: {
46
46
  context_keys: [],
47
47
  context_obj: [],
48
48
  },
@@ -55,7 +55,6 @@ const navigator = {
55
55
  goHome: jest.fn(),
56
56
  } as any;
57
57
 
58
- const mockStore = configureStore();
59
58
  jest.spyOn(useNavigationHooks, "useNavigation").mockReturnValue(navigator);
60
59
 
61
60
  const helperSpy = jest.spyOn(helpers, "handlePresentNavigation");
@@ -80,31 +79,17 @@ jest.mock("../../../logger", () => ({
80
79
  // to use import instead of require it's required to use jest.mock above
81
80
  const { useOpenSchemeHandler } = require("../useOpenSchemeHandler");
82
81
 
83
- const getWrapper = (storeProps = {}) => {
84
- const store = mockStore(
85
- R.mergeDeepRight(
86
- { rivers, contentTypes, pipesEndpoints, appData },
87
- storeProps
88
- )
89
- );
90
-
91
- appStore.set(store);
92
-
93
- const Wrapper = ({ children }: { children: React.ReactChild }) => (
94
- /* @ts-ignore */
95
- <Provider store={store}>{children}</Provider>
96
- );
97
-
98
- return Wrapper;
99
- };
100
-
101
- const testHook = async ({ url, query, storeProps = {}, tests }) => {
102
- const wrapper = getWrapper(storeProps);
82
+ const mockStoreObj = { rivers, contentTypes, pipesEndpoints, appData };
103
83
 
84
+ const testHook = async ({ url, query, storeProps = {}, tests }: any) => {
104
85
  const callback = jest.fn((fn) => fn(tests));
105
86
 
106
87
  renderHook(() => useOpenSchemeHandler({ url, query, onFinish: callback }), {
107
- wrapper,
88
+ wrapper: ({ children }) => (
89
+ <WrappedWithProviders store={mergeDeepRight(mockStoreObj, storeProps)}>
90
+ {children}
91
+ </WrappedWithProviders>
92
+ ),
108
93
  });
109
94
 
110
95
  await waitFor(() => expect(callback).toHaveBeenCalled());
@@ -6,6 +6,30 @@ import { Provider } from "react-redux";
6
6
  import configureStore from "redux-mock-store";
7
7
 
8
8
  import { log_warning } from "../../../logger";
9
+ import { handleActionSchemeUrl } from "../useUrlSchemeHandler";
10
+ import { appStore } from "../../../../../../zapp-react-native-redux/AppStore";
11
+
12
+ type UrlSchemeHandlerArgs = {
13
+ query: Record<string, unknown>;
14
+ url: string;
15
+ onFinish?: (callback: () => void) => void;
16
+ };
17
+
18
+ type PluginType = "general" | "player";
19
+
20
+ interface ZappPlugin {
21
+ urlScheme?: {
22
+ host: string;
23
+ handler: (args: UrlSchemeHandlerArgs) => void;
24
+ };
25
+ }
26
+
27
+ interface QuickBrickPlugin {
28
+ module: ZappPlugin;
29
+ name: string;
30
+ identifier: string;
31
+ type: PluginType;
32
+ }
9
33
 
10
34
  const mockStore = configureStore();
11
35
 
@@ -14,153 +38,222 @@ jest.mock("../../../logger", () => ({
14
38
  log_warning: jest.fn(),
15
39
  }));
16
40
 
17
- const lambdaPlugin = {
18
- module: jest.fn() as ZappPlugin,
41
+ const mockHandler = jest.fn(({ onFinish }) => {
42
+ onFinish?.(() => {});
43
+ });
44
+
45
+ const mockComplexHandler = jest.fn(({ onFinish }) => {
46
+ onFinish?.(() => {});
47
+ });
48
+
49
+ const lambdaPlugin: QuickBrickPlugin = {
50
+ module: {} as ZappPlugin,
19
51
  name: "Lambda plugin",
20
52
  identifier: "someplugin",
21
- type: "general" as PluginType,
53
+ type: "general",
22
54
  };
23
55
 
24
- const pluginWithHandler = {
56
+ const pluginWithHandler: QuickBrickPlugin = {
25
57
  name: "Plugin handling scheme",
26
58
  identifier: "plugin-with-handler",
27
- type: "general" as PluginType,
59
+ type: "general",
28
60
  module: {
29
61
  urlScheme: {
30
62
  host: "foo",
31
- handler: jest.fn(({ onFinish }) => {
32
- onFinish(() => {});
33
- }),
63
+ handler: mockHandler,
64
+ },
65
+ },
66
+ };
67
+
68
+ const pluginWithComplexHandler: QuickBrickPlugin = {
69
+ name: "Plugin with nested handler",
70
+ identifier: "plugin-with-nested-handler",
71
+ type: "general",
72
+ module: {
73
+ urlScheme: {
74
+ host: "complex",
75
+ handler: mockComplexHandler,
34
76
  },
35
- } as ZappPlugin,
77
+ },
36
78
  };
37
79
 
38
- const plugins: QuickBrickPlugin[] = [lambdaPlugin, pluginWithHandler];
80
+ const plugins = [lambdaPlugin, pluginWithHandler, pluginWithComplexHandler];
39
81
 
40
82
  const { useUrlSchemeHandler } = require("../useUrlSchemeHandler");
41
83
 
42
84
  describe("useUrlSchemeHandler", () => {
43
- // beforeEach(() => {
44
- // log_warning.mockClear();
45
- // });
85
+ const store = mockStore({ plugins });
46
86
 
47
- const store = mockStore({ test: "test", plugins });
87
+ appStore.set(store);
48
88
 
49
- const wrapper: React.FC<any> = ({ children }) => (
89
+ const wrapper: React.FC = ({ children }) => (
50
90
  <Provider store={store}>{children}</Provider>
51
91
  );
52
92
 
53
- it("calls correct urlScheme handler with query params", () => {
54
- const presentSpy = jest.fn();
55
- const onFinish = jest.fn();
56
- const url = "test://present?foo=bar";
93
+ beforeEach(() => {
94
+ jest.clearAllMocks();
57
95
 
58
- URLHandlersMap.schemeHandlerHooks.present = presentSpy;
59
-
60
- renderHook(
61
- () =>
62
- useUrlSchemeHandler({
63
- url,
64
- onFinish,
65
- }),
66
- { wrapper }
67
- );
68
-
69
- expect(presentSpy).toBeCalledWith({ query: { foo: "bar" }, url, onFinish });
96
+ Object.keys(URLHandlersMap.schemeHandlerHooks).forEach((key) => {
97
+ delete (URLHandlersMap.schemeHandlerHooks as any)[key];
98
+ });
70
99
  });
71
100
 
72
- it("not throws an error and calls onFinish if correct url scheme handler can not be found", () => {
73
- const url = "test://nonExistingHost?foo=bar";
74
-
75
- const onFinish = jest.fn((cb) => {
76
- cb();
101
+ describe("Basic URL scheme handling", () => {
102
+ it("handles query params correctly", () => {
103
+ const testHandler = jest.fn();
104
+ (URLHandlersMap.schemeHandlerHooks as any).test = testHandler;
105
+ const testUrl = "test://test?foo=bar";
106
+
107
+ renderHook(
108
+ () =>
109
+ useUrlSchemeHandler({
110
+ url: testUrl,
111
+ onFinish: jest.fn(),
112
+ }),
113
+ { wrapper }
114
+ );
115
+
116
+ expect(testHandler).toBeCalledWith({
117
+ query: { foo: "bar" },
118
+ url: testUrl,
119
+ onFinish: expect.any(Function),
120
+ });
77
121
  });
78
122
 
79
- renderHook(
80
- () =>
81
- useUrlSchemeHandler({
82
- url,
83
- onFinish,
84
- }),
85
- { wrapper }
86
- );
123
+ it("handles missing scheme handlers gracefully", () => {
124
+ const testUrl = "test://unknown?foo=bar";
125
+ const finishCallback = jest.fn();
87
126
 
88
- expect(onFinish).toBeCalled();
127
+ const onFinish = jest.fn((cb) => {
128
+ cb();
129
+ finishCallback();
130
+ });
89
131
 
90
- expect(log_warning).toHaveBeenCalledWith(
91
- `unable to resolve ${url}: Non of the installed plugins knows how to handle this urlScheme ${url}`
92
- );
93
- });
132
+ renderHook(
133
+ () =>
134
+ useUrlSchemeHandler({
135
+ url: testUrl,
136
+ onFinish,
137
+ }),
138
+ { wrapper }
139
+ );
94
140
 
95
- it("calls onFinish when the handler does", () => {
96
- const url = "test://present?foo=bar";
97
- const onFinish = jest.fn();
141
+ expect(finishCallback).toBeCalled();
98
142
 
99
- const presentSpy = jest.fn(() => {
100
- onFinish();
143
+ expect(log_warning).toBeCalledWith(expect.stringContaining(testUrl));
101
144
  });
102
-
103
- URLHandlersMap.schemeHandlerHooks.present = presentSpy;
104
-
105
- renderHook(
106
- () =>
107
- useUrlSchemeHandler({
108
- url,
109
- onFinish,
110
- }),
111
- { wrapper }
112
- );
113
-
114
- expect(onFinish).toBeCalled();
115
145
  });
116
146
 
117
- it("calls onFinish if handler returns an error", () => {
118
- const url = "test://present?foo=bar";
119
-
120
- const onFinish = jest.fn((cb) => {
121
- cb();
147
+ describe("Plugin-based scheme handling", () => {
148
+ it("resolves and calls plugin handlers", () => {
149
+ const testUrl = "test://foo?param=test";
150
+ const onFinish = jest.fn();
151
+
152
+ renderHook(
153
+ () =>
154
+ useUrlSchemeHandler({
155
+ url: testUrl,
156
+ onFinish,
157
+ }),
158
+ { wrapper }
159
+ );
160
+
161
+ expect(mockHandler).toBeCalledWith({
162
+ query: { param: "test" },
163
+ url: testUrl,
164
+ onFinish,
165
+ });
122
166
  });
123
167
 
124
- const presentSpy = jest.fn(() => {
125
- throw new Error("error");
168
+ it("handles complex plugin configurations", () => {
169
+ const testUrl = "test://complex?param=nested";
170
+ const onFinish = jest.fn();
171
+
172
+ renderHook(
173
+ () =>
174
+ useUrlSchemeHandler({
175
+ url: testUrl,
176
+ onFinish,
177
+ }),
178
+ { wrapper }
179
+ );
180
+
181
+ expect(mockComplexHandler).toBeCalledWith({
182
+ query: { param: "nested" },
183
+ url: testUrl,
184
+ onFinish,
185
+ });
126
186
  });
127
187
 
128
- URLHandlersMap.schemeHandlerHooks.present = presentSpy;
188
+ it("ignores plugins without urlScheme", () => {
189
+ const testUrl = "test://nonexistent?param=value";
190
+ const finishCallback = jest.fn();
191
+
192
+ const onFinish = jest.fn((cb) => {
193
+ cb();
194
+ finishCallback();
195
+ });
196
+
197
+ renderHook(
198
+ () =>
199
+ useUrlSchemeHandler({
200
+ url: testUrl,
201
+ onFinish,
202
+ }),
203
+ { wrapper }
204
+ );
205
+
206
+ expect(lambdaPlugin.module).not.toHaveProperty("urlScheme");
207
+ expect(finishCallback).toBeCalled();
208
+ });
209
+ });
129
210
 
130
- renderHook(
131
- () =>
132
- useUrlSchemeHandler({
133
- url,
134
- onFinish,
135
- }),
136
- { wrapper }
137
- );
211
+ describe("Action scheme handling", () => {
212
+ it("handles action schemes using plugins", () => {
213
+ const testUrl = "test://foo?action=test";
138
214
 
139
- expect(onFinish).toBeCalled();
215
+ handleActionSchemeUrl({
216
+ url: testUrl,
217
+ plugins,
218
+ } as any);
140
219
 
141
- expect(log_warning).toHaveBeenCalledWith(`unable to resolve ${url}: error`);
142
- });
220
+ expect(mockHandler).toBeCalledWith({
221
+ query: { action: "test" },
222
+ url: testUrl,
223
+ });
224
+ });
143
225
 
144
- it("finds the plugin for the host", () => {
145
- const url = "scheme://foo?whatever=bar";
226
+ it("throws for unknown action schemes", () => {
227
+ const testUrl = "test://unknown?action=test";
146
228
 
147
- const onFinish = jest.fn((cb) => {
148
- cb();
229
+ expect(() => {
230
+ handleActionSchemeUrl({
231
+ url: testUrl,
232
+ plugins,
233
+ } as any);
234
+ }).toThrow(/Non of the installed plugins/);
149
235
  });
150
236
 
151
- renderHook(
152
- () => {
153
- useUrlSchemeHandler({ url, onFinish });
154
- },
155
- { wrapper }
156
- );
157
-
158
- expect(pluginWithHandler.module.urlScheme.handler).toBeCalledWith({
159
- url,
160
- onFinish,
161
- query: { whatever: "bar" },
237
+ it("handles malformed URLs gracefully", () => {
238
+ const testUrl = "invalid-url";
239
+ const finishCallback = jest.fn();
240
+
241
+ const onFinish = jest.fn((cb) => {
242
+ cb();
243
+ finishCallback();
244
+ });
245
+
246
+ renderHook(
247
+ () =>
248
+ useUrlSchemeHandler({
249
+ url: testUrl,
250
+ onFinish,
251
+ }),
252
+ { wrapper }
253
+ );
254
+
255
+ expect(log_warning).toBeCalled();
256
+ expect(finishCallback).toBeCalled();
162
257
  });
163
-
164
- expect(onFinish).toBeCalled();
165
258
  });
166
259
  });
@@ -1,8 +1,4 @@
1
- import {
2
- useAppSelector,
3
- selectContentTypes,
4
- selectRivers,
5
- } from "@applicaster/zapp-react-native-redux";
1
+ import { useContentTypes } from "@applicaster/zapp-react-native-redux";
6
2
  import { ZappPipesEntryContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
7
3
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
8
4
  import { useEffect } from "react";
@@ -24,6 +20,7 @@ import {
24
20
  withInitialPlayerState,
25
21
  } from "./utils";
26
22
  import { log_warning } from "../../../logger";
23
+ import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks";
27
24
 
28
25
  async function handleQuery({
29
26
  query,
@@ -101,8 +98,8 @@ async function handleQuery({
101
98
  }
102
99
 
103
100
  export function useOpenSchemeHandler({ query, url, onFinish }) {
104
- const rivers = useAppSelector(selectRivers);
105
- const contentTypes = useAppSelector(selectContentTypes);
101
+ const rivers = useRivers();
102
+ const contentTypes = useContentTypes();
106
103
  const navigator = useNavigation();
107
104
  const homeId = getHomeScreenId(rivers);
108
105
  const homeRoute = `/river/${homeId}`;
@@ -1,55 +1,59 @@
1
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
1
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
3
- import * as R from "ramda";
2
+ import {
3
+ selectUrlSchemePlugins,
4
+ useAppSelector,
5
+ } from "@applicaster/zapp-react-native-redux";
4
6
 
5
7
  import { schemeHandlerHooks } from ".";
6
8
  import { parseUrl } from "../../helpers";
7
-
8
9
  import { log_warning } from "../../logger";
10
+ import { getPluginModuleUrlScheme } from "@applicaster/zapp-react-native-utils/pluginUtils";
9
11
 
10
12
  type useUrlSchemeHandlerArgs = {
11
13
  url: string;
12
14
  onFinish: (callback: (done: () => void) => void) => void;
13
15
  };
14
16
 
15
- function resolveSchemeHandler(host, plugins) {
17
+ function resolveSchemeHandler(
18
+ host: string,
19
+ eligiblePlugins: QuickBrickPlugin[]
20
+ ) {
21
+ // First check built-in scheme handlers
16
22
  if (schemeHandlerHooks?.[host]) return schemeHandlerHooks?.[host];
17
23
 
18
- const elligiblePlugins = R.filter(
19
- R.hasPath(["module", "urlScheme"]),
20
- plugins
21
- );
22
-
23
- if (elligiblePlugins?.length > 0) {
24
- const match = R.compose(
25
- R.prop("handler"),
26
- R.head,
27
- R.filter(R.propEq("host", host)),
28
- R.map(R.path(["module", "urlScheme"]))
29
- )(elligiblePlugins);
24
+ if (eligiblePlugins?.length > 0) {
25
+ // Find the first plugin with matching host
26
+ const matchingPlugin = eligiblePlugins.find(
27
+ (plugin) => getPluginModuleUrlScheme(plugin)?.host === host
28
+ );
30
29
 
31
- return match;
30
+ return getPluginModuleUrlScheme(matchingPlugin)?.handler || null;
32
31
  }
33
- }
34
32
 
35
- const skipSchemeHandle = ({ url }) => {
36
- throw new Error(
37
- `Non of the installed plugins knows how to handle this urlScheme ${url}`
38
- );
39
- };
33
+ return null;
34
+ }
40
35
 
41
36
  export function useUrlSchemeHandler({
42
37
  url,
43
38
  onFinish,
44
39
  }: useUrlSchemeHandlerArgs) {
45
40
  const { host, query } = parseUrl(url);
46
- const { plugins } = usePickFromState(["plugins"]);
41
+ const pluginsWithUrlScheme = useAppSelector(selectUrlSchemePlugins) || [];
47
42
 
48
- const useSchemeHandler =
49
- resolveSchemeHandler(host, plugins) || skipSchemeHandle;
43
+ const schemeHandler = resolveSchemeHandler(host, pluginsWithUrlScheme);
50
44
 
51
45
  try {
52
- useSchemeHandler({ query, url, onFinish });
46
+ if (schemeHandler) {
47
+ schemeHandler({ query, url, onFinish });
48
+ } else {
49
+ onFinish((done) => {
50
+ log_warning(
51
+ `unable to resolve ${url}: No handler found for scheme ${host}`
52
+ );
53
+
54
+ done?.();
55
+ });
56
+ }
53
57
  } catch (e) {
54
58
  onFinish((done) => {
55
59
  log_warning(`unable to resolve ${url}: ${e.message}`);
@@ -58,11 +62,19 @@ export function useUrlSchemeHandler({
58
62
  }
59
63
  }
60
64
 
61
- export function handleActionSchemeUrl({ url }) {
65
+ export function handleActionSchemeUrl({
66
+ url,
67
+ availablePlugins = appStore.get("plugins"),
68
+ }) {
62
69
  const { host, query } = parseUrl(url);
63
- const plugins = appStore.get("plugins");
64
70
 
65
- const actionScheme = resolveSchemeHandler(host, plugins) || skipSchemeHandle;
71
+ const actionScheme = resolveSchemeHandler(host, availablePlugins);
72
+
73
+ if (!actionScheme) {
74
+ throw new Error(
75
+ `Non of the installed plugins knows how to handle this urlScheme ${url}`
76
+ );
77
+ }
66
78
 
67
79
  actionScheme({ query, url });
68
80
  }
@@ -30,7 +30,10 @@ export function URLSchemeHandler({ url, onFinish }: Props) {
30
30
  useUrlSchemeHandler({ url, onFinish });
31
31
 
32
32
  return (
33
- <View style={[viewStyles.container, { width, height, backgroundColor }]}>
33
+ <View
34
+ testID="URLSchemeHandler"
35
+ style={[viewStyles.container, { width, height, backgroundColor }]}
36
+ >
34
37
  <Spinner size="large" />
35
38
  </View>
36
39
  );
@@ -1,5 +1,7 @@
1
1
  import React from "react";
2
- import { cleanup, render, waitFor } from "@testing-library/react-native";
2
+ import { StyleSheet } from "react-native";
3
+ import { cleanup } from "@testing-library/react-native";
4
+ import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
3
5
 
4
6
  const theme = {
5
7
  screen_margin_top: 0,
@@ -10,14 +12,6 @@ jest.mock(
10
12
  "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation"
11
13
  );
12
14
 
13
- jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
14
- useTheme: jest.fn(() => theme),
15
- }));
16
-
17
- jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
18
- usePickFromState: jest.fn(() => ({})),
19
- }));
20
-
21
15
  const { URLSchemeHandler } = require("../URLSchemeHandler");
22
16
  const schemeHooks = require("../SchemeHandlerHooks/useUrlSchemeHandler");
23
17
 
@@ -36,12 +30,25 @@ describe("URLSchemeHandler", () => {
36
30
 
37
31
  afterEach(cleanup);
38
32
 
39
- it("renders correctly and invokes the hook", async () => {
40
- const wrapper = await waitFor(() =>
41
- render(<URLSchemeHandler url={url} onFinish={onFinish} />)
33
+ it("renders correctly and invokes the hook", () => {
34
+ const wrapper = renderWithProviders(
35
+ <URLSchemeHandler url={url} onFinish={onFinish} />,
36
+ {},
37
+ theme
42
38
  );
43
39
 
44
- expect(wrapper.toJSON()).toMatchSnapshot();
40
+ expect(wrapper.getByTestId("URLSchemeHandler")).toBeTruthy();
41
+
42
+ expect(
43
+ StyleSheet.flatten(wrapper.getByTestId("URLSchemeHandler").props.style)
44
+ ).toMatchObject({
45
+ alignItems: "center",
46
+ backgroundColor: "white",
47
+ flex: 1,
48
+ height: 1334,
49
+ justifyContent: "center",
50
+ width: 750,
51
+ });
45
52
 
46
53
  expect(hookSpy).toHaveBeenCalledWith(
47
54
  expect.objectContaining({ url, onFinish })