@applicaster/zapp-react-native-ui-components 16.0.0-rc.104 → 16.0.0-rc.105
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.
|
|
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.
|
|
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
|
-
}, [
|
|
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.
|
|
3
|
+
"version": "16.0.0-rc.105",
|
|
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.
|
|
32
|
-
"@applicaster/zapp-react-native-bridge": "16.0.0-rc.
|
|
33
|
-
"@applicaster/zapp-react-native-redux": "16.0.0-rc.
|
|
34
|
-
"@applicaster/zapp-react-native-utils": "16.0.0-rc.
|
|
31
|
+
"@applicaster/applicaster-types": "16.0.0-rc.105",
|
|
32
|
+
"@applicaster/zapp-react-native-bridge": "16.0.0-rc.105",
|
|
33
|
+
"@applicaster/zapp-react-native-redux": "16.0.0-rc.105",
|
|
34
|
+
"@applicaster/zapp-react-native-utils": "16.0.0-rc.105",
|
|
35
35
|
"fast-json-stable-stringify": "^2.1.0",
|
|
36
36
|
"promise": "^8.3.0",
|
|
37
37
|
"react-native-sortables": "1.7.1",
|