@applicaster/zapp-react-native-ui-components 16.0.0-rc.104 → 16.0.0-rc.106

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.
@@ -10,6 +10,28 @@ jest.useFakeTimers({ legacyFakeTimers: true });
10
10
  // isConnected/isInternetReachable/details fields, so the mock has to mirror
11
11
  // that shape for online/offline to actually be distinguishable.
12
12
  let mockConnectionStatus = false;
13
+ let mockStillOfflineAfterResumeCount = 0;
14
+
15
+ const mockComponentsLogger = {
16
+ log: jest.fn(),
17
+ debug: jest.fn(),
18
+ info: jest.fn(),
19
+ warning: jest.fn(),
20
+ error: jest.fn(),
21
+ };
22
+
23
+ jest.mock("../../../Helpers/logger", () => {
24
+ const proxy = {
25
+ log: (event) => mockComponentsLogger.log(event),
26
+ debug: (event) => mockComponentsLogger.debug(event),
27
+ info: (event) => mockComponentsLogger.info(event),
28
+ warning: (event) => mockComponentsLogger.warning(event),
29
+ error: (event) => mockComponentsLogger.error(event),
30
+ addSubsystem: () => proxy,
31
+ };
32
+
33
+ return { componentsLogger: proxy };
34
+ });
13
35
 
14
36
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/connection", () => {
15
37
  return {
@@ -20,6 +42,7 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/connection", () => {
20
42
  details: {},
21
43
  isConnected: mockConnectionStatus,
22
44
  isInternetReachable: mockConnectionStatus,
45
+ stillOfflineAfterResumeCount: mockStillOfflineAfterResumeCount,
23
46
  })),
24
47
  };
25
48
  });
@@ -58,6 +81,7 @@ describe("OfflineHandler", () => {
58
81
 
59
82
  beforeEach(() => {
60
83
  mockConnectionStatus = false;
84
+ mockStillOfflineAfterResumeCount = 0;
61
85
  });
62
86
 
63
87
  it("renders its children without wrapping them in a notification view", () => {
@@ -131,4 +155,89 @@ describe("OfflineHandler", () => {
131
155
 
132
156
  unsubscribe();
133
157
  });
158
+
159
+ it("re-shows the offline toast when still offline after app resume", () => {
160
+ mockConnectionStatus = false;
161
+
162
+ const handleShowToast = jest.fn();
163
+ const unsubscribe = subscriberFor("showToast", handleShowToast);
164
+
165
+ const { rerender } = render(<OfflineHandler />);
166
+ handleShowToast.mockClear();
167
+
168
+ mockStillOfflineAfterResumeCount = 1;
169
+ rerender(<OfflineHandler />);
170
+
171
+ expect(handleShowToast).toHaveBeenCalledTimes(1);
172
+
173
+ expect(handleShowToast).toHaveBeenCalledWith(
174
+ expect.objectContaining({
175
+ id: "offline-status",
176
+ message: "No internet connection",
177
+ timeout: 5000,
178
+ }),
179
+ expect.any(Function)
180
+ );
181
+
182
+ // further renders with the same counter must not re-emit
183
+ rerender(<OfflineHandler />);
184
+ expect(handleShowToast).toHaveBeenCalledTimes(1);
185
+
186
+ unsubscribe();
187
+ });
188
+
189
+ it("does not re-show the offline toast for a counter bump while online", () => {
190
+ mockConnectionStatus = true;
191
+
192
+ const handleShowToast = jest.fn();
193
+ const unsubscribe = subscriberFor("showToast", handleShowToast);
194
+
195
+ const { rerender } = render(<OfflineHandler />);
196
+
197
+ mockStillOfflineAfterResumeCount = 1;
198
+ rerender(<OfflineHandler />);
199
+
200
+ expect(handleShowToast).not.toHaveBeenCalled();
201
+
202
+ unsubscribe();
203
+ });
204
+
205
+ it("does not emit on mount just because the counter is already > 0", () => {
206
+ mockConnectionStatus = true;
207
+ mockStillOfflineAfterResumeCount = 3;
208
+
209
+ const handleShowToast = jest.fn();
210
+ const unsubscribe = subscriberFor("showToast", handleShowToast);
211
+
212
+ render(<OfflineHandler />);
213
+
214
+ expect(handleShowToast).not.toHaveBeenCalled();
215
+
216
+ unsubscribe();
217
+ });
218
+
219
+ it("logs toast emissions at info level", () => {
220
+ mockConnectionStatus = false;
221
+ mockComponentsLogger.info.mockClear();
222
+ mockComponentsLogger.warning.mockClear();
223
+
224
+ const { rerender } = render(<OfflineHandler />);
225
+
226
+ mockConnectionStatus = true;
227
+ rerender(<OfflineHandler />);
228
+
229
+ expect(mockComponentsLogger.info).toHaveBeenCalledWith(
230
+ expect.objectContaining({
231
+ message: "OfflineHandler: device is offline, emit toast",
232
+ })
233
+ );
234
+
235
+ expect(mockComponentsLogger.info).toHaveBeenCalledWith(
236
+ expect.objectContaining({
237
+ message: "OfflineHandler: device is back online, emit toast",
238
+ })
239
+ );
240
+
241
+ expect(mockComponentsLogger.warning).not.toHaveBeenCalled();
242
+ });
134
243
  });
@@ -29,12 +29,22 @@ export const OfflineHandler = ({ children }: Props) => {
29
29
  const { online } = parseConnectionInfo(connectionInfo);
30
30
  const prevOnline = usePrevious(online);
31
31
 
32
+ const stillOfflineAfterResumeCount =
33
+ connectionInfo?.stillOfflineAfterResumeCount ?? 0;
34
+
35
+ const prevStillOfflineAfterResumeCount = usePrevious(
36
+ stillOfflineAfterResumeCount
37
+ );
38
+
32
39
  const emitShowToast = useSubscriberFor(SHOW_TOAST_EVENT);
33
40
 
34
41
  const { message, extraMessage, style } = useOfflineHandlerProps(online);
35
42
 
36
43
  const showOnlineToast = useCallback(() => {
37
- logger.log("Device is back online, emit toast");
44
+ logger.info({
45
+ message: "OfflineHandler: device is back online, emit toast",
46
+ data: { online, prevOnline },
47
+ });
38
48
 
39
49
  emitShowToast({
40
50
  id: OFFLINE_STATUS_TOAST_ID,
@@ -43,10 +53,13 @@ export const OfflineHandler = ({ children }: Props) => {
43
53
  style,
44
54
  timeout: timers.goingOnline,
45
55
  });
46
- }, [emitShowToast, message, extraMessage, style]);
56
+ }, [emitShowToast, message, extraMessage, style, online, prevOnline]);
47
57
 
48
58
  const showOfflineToast = useCallback(() => {
49
- logger.log("Device went offline, emit toast");
59
+ logger.info({
60
+ message: "OfflineHandler: device is offline, emit toast",
61
+ data: { online, prevOnline, stillOfflineAfterResumeCount },
62
+ });
50
63
 
51
64
  emitShowToast({
52
65
  id: OFFLINE_STATUS_TOAST_ID,
@@ -55,7 +68,15 @@ export const OfflineHandler = ({ children }: Props) => {
55
68
  style,
56
69
  timeout: timers.goingOffline,
57
70
  });
58
- }, [emitShowToast, message, extraMessage, style]);
71
+ }, [
72
+ emitShowToast,
73
+ message,
74
+ extraMessage,
75
+ style,
76
+ online,
77
+ prevOnline,
78
+ stillOfflineAfterResumeCount,
79
+ ]);
59
80
 
60
81
  useEffect(() => {
61
82
  // On mount there is no previous state yet: only surface the offline toast
@@ -79,5 +100,22 @@ export const OfflineHandler = ({ children }: Props) => {
79
100
  }
80
101
  }, [online, prevOnline, showOfflineToast, showOnlineToast]);
81
102
 
103
+ useEffect(() => {
104
+ // NetworkStatusProvider bumps this counter when the app resumed while offline
105
+ // and is still offline after the verification delay: remind the user.
106
+ if (
107
+ prevStillOfflineAfterResumeCount !== undefined &&
108
+ stillOfflineAfterResumeCount > prevStillOfflineAfterResumeCount &&
109
+ !online
110
+ ) {
111
+ showOfflineToast();
112
+ }
113
+ }, [
114
+ stillOfflineAfterResumeCount,
115
+ prevStillOfflineAfterResumeCount,
116
+ online,
117
+ showOfflineToast,
118
+ ]);
119
+
82
120
  return children;
83
121
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "16.0.0-rc.104",
3
+ "version": "16.0.0-rc.106",
4
4
  "description": "Applicaster Zapp React Native ui components for the Quick Brick App",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "16.0.0-rc.104",
32
- "@applicaster/zapp-react-native-bridge": "16.0.0-rc.104",
33
- "@applicaster/zapp-react-native-redux": "16.0.0-rc.104",
34
- "@applicaster/zapp-react-native-utils": "16.0.0-rc.104",
31
+ "@applicaster/applicaster-types": "16.0.0-rc.106",
32
+ "@applicaster/zapp-react-native-bridge": "16.0.0-rc.106",
33
+ "@applicaster/zapp-react-native-redux": "16.0.0-rc.106",
34
+ "@applicaster/zapp-react-native-utils": "16.0.0-rc.106",
35
35
  "fast-json-stable-stringify": "^2.1.0",
36
36
  "promise": "^8.3.0",
37
37
  "react-native-sortables": "1.7.1",