@dhis2/app-service-offline 3.11.3 → 3.12.0-alpha.1
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/build/cjs/__tests__/integration.test.js +51 -82
- package/build/cjs/index.js +0 -7
- package/build/cjs/lib/__tests__/cacheable-section-state.test.js +7 -14
- package/build/cjs/lib/__tests__/clear-sensitive-caches.test.js +17 -20
- package/build/cjs/lib/__tests__/network-status.test.js +135 -148
- package/build/cjs/lib/__tests__/offline-provider.test.js +12 -22
- package/build/cjs/lib/__tests__/use-cacheable-section.test.js +87 -98
- package/build/cjs/lib/__tests__/use-online-status-message.test.js +7 -14
- package/build/cjs/lib/cacheable-section-state.js +27 -38
- package/build/cjs/lib/cacheable-section.js +26 -27
- package/build/cjs/lib/clear-sensitive-caches.js +14 -24
- package/build/cjs/lib/dhis2-connection-status/dev-debug-log.js +1 -3
- package/build/cjs/lib/dhis2-connection-status/dhis2-connection-status.js +27 -58
- package/build/cjs/lib/dhis2-connection-status/dhis2-connection-status.test.js +287 -230
- package/build/cjs/lib/dhis2-connection-status/index.js +0 -1
- package/build/cjs/lib/dhis2-connection-status/is-ping-available.js +0 -6
- package/build/cjs/lib/dhis2-connection-status/is-ping-available.test.js +0 -1
- package/build/cjs/lib/dhis2-connection-status/smart-interval.js +35 -49
- package/build/cjs/lib/dhis2-connection-status/use-ping-query.js +4 -5
- package/build/cjs/lib/global-state-service.js +9 -27
- package/build/cjs/lib/network-status.js +10 -13
- package/build/cjs/lib/offline-interface.js +3 -14
- package/build/cjs/lib/offline-provider.js +1 -12
- package/build/cjs/lib/online-status-message.js +5 -17
- package/build/cjs/setupRTL.js +1 -1
- package/build/cjs/utils/__tests__/render-counter.test.js +3 -12
- package/build/cjs/utils/render-counter.js +2 -10
- package/build/cjs/utils/test-mocks.js +13 -18
- package/build/es/__tests__/integration.test.js +51 -74
- package/build/es/index.js +2 -2
- package/build/es/lib/__tests__/cacheable-section-state.test.js +2 -4
- package/build/es/lib/__tests__/clear-sensitive-caches.test.js +19 -16
- package/build/es/lib/__tests__/network-status.test.js +105 -114
- package/build/es/lib/__tests__/offline-provider.test.js +13 -15
- package/build/es/lib/__tests__/use-cacheable-section.test.js +69 -73
- package/build/es/lib/__tests__/use-online-status-message.test.js +2 -3
- package/build/es/lib/cacheable-section-state.js +25 -26
- package/build/es/lib/cacheable-section.js +23 -15
- package/build/es/lib/clear-sensitive-caches.js +13 -21
- package/build/es/lib/dhis2-connection-status/dev-debug-log.js +1 -3
- package/build/es/lib/dhis2-connection-status/dhis2-connection-status.js +26 -37
- package/build/es/lib/dhis2-connection-status/dhis2-connection-status.test.js +223 -159
- package/build/es/lib/dhis2-connection-status/is-ping-available.js +0 -5
- package/build/es/lib/dhis2-connection-status/smart-interval.js +34 -42
- package/build/es/lib/dhis2-connection-status/use-ping-query.js +6 -3
- package/build/es/lib/global-state-service.js +6 -12
- package/build/es/lib/network-status.js +10 -9
- package/build/es/lib/offline-interface.js +0 -3
- package/build/es/lib/offline-provider.js +0 -3
- package/build/es/lib/online-status-message.js +3 -2
- package/build/es/setupRTL.js +1 -1
- package/build/es/utils/__tests__/render-counter.test.js +2 -4
- package/build/es/utils/render-counter.js +1 -3
- package/build/es/utils/test-mocks.js +8 -9
- package/build/types/lib/cacheable-section.d.ts +1 -1
- package/build/types/lib/dhis2-connection-status/dhis2-connection-status.d.ts +1 -1
- package/build/types/lib/network-status.d.ts +1 -1
- package/build/types/lib/online-status-message.d.ts +1 -1
- package/build/types/types.d.ts +1 -1
- package/package.json +4 -4
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { render, screen, waitFor } from '@testing-library/react';
|
|
2
|
-
import { act, renderHook } from '@testing-library/react-hooks';
|
|
1
|
+
import { render, screen, waitFor, act, renderHook } from '@testing-library/react';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import { useNetworkStatus as useOnlineStatus } from '../network-status';
|
|
5
|
-
|
|
6
4
|
function wait(ms) {
|
|
7
5
|
return new Promise(resolve => {
|
|
8
6
|
setTimeout(() => resolve(), ms);
|
|
9
7
|
});
|
|
10
8
|
}
|
|
11
|
-
|
|
12
9
|
beforeEach(() => {
|
|
13
10
|
jest.restoreAllMocks();
|
|
14
11
|
});
|
|
@@ -35,13 +32,12 @@ describe('initalizes to navigator.onLine value', () => {
|
|
|
35
32
|
});
|
|
36
33
|
describe('state changes in response to browser "online" and "offline" events', () => {
|
|
37
34
|
it('switches from online to offline when the "offline" event triggers', async () => {
|
|
38
|
-
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
39
|
-
|
|
35
|
+
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
36
|
+
// Capture callback to trigger later using addEventListener mock
|
|
40
37
|
const events = {};
|
|
41
38
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
42
39
|
const {
|
|
43
|
-
result
|
|
44
|
-
waitForNextUpdate
|
|
40
|
+
result
|
|
45
41
|
} = renderHook(function () {
|
|
46
42
|
return useOnlineStatus(...arguments);
|
|
47
43
|
}, {
|
|
@@ -52,21 +48,20 @@ describe('state changes in response to browser "online" and "offline" events', (
|
|
|
52
48
|
act(() => {
|
|
53
49
|
// Trigger callback captured by addEventListener mock
|
|
54
50
|
events.offline(new Event('offline'));
|
|
55
|
-
});
|
|
51
|
+
});
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
// Wait for debounce
|
|
54
|
+
await waitFor(() => {
|
|
55
|
+
expect(result.current.online).toBe(false);
|
|
56
|
+
expect(result.current.offline).toBe(true);
|
|
59
57
|
});
|
|
60
|
-
expect(result.current.online).toBe(false);
|
|
61
|
-
expect(result.current.offline).toBe(true);
|
|
62
58
|
});
|
|
63
59
|
it('switches from offline to online when the "online" event triggers', async () => {
|
|
64
60
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(false);
|
|
65
61
|
const events = {};
|
|
66
62
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
67
63
|
const {
|
|
68
|
-
result
|
|
69
|
-
waitForNextUpdate
|
|
64
|
+
result
|
|
70
65
|
} = renderHook(function () {
|
|
71
66
|
return useOnlineStatus(...arguments);
|
|
72
67
|
}, {
|
|
@@ -76,13 +71,13 @@ describe('state changes in response to browser "online" and "offline" events', (
|
|
|
76
71
|
});
|
|
77
72
|
act(() => {
|
|
78
73
|
events.online(new Event('online'));
|
|
79
|
-
});
|
|
74
|
+
});
|
|
80
75
|
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
// Wait for debounce
|
|
77
|
+
await waitFor(() => {
|
|
78
|
+
expect(result.current.online).toBe(true);
|
|
79
|
+
expect(result.current.offline).toBe(false);
|
|
83
80
|
});
|
|
84
|
-
expect(result.current.online).toBe(true);
|
|
85
|
-
expect(result.current.offline).toBe(false);
|
|
86
81
|
});
|
|
87
82
|
});
|
|
88
83
|
describe('debouncing state changes', () => {
|
|
@@ -92,22 +87,22 @@ describe('debouncing state changes', () => {
|
|
|
92
87
|
const events = {};
|
|
93
88
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
94
89
|
const {
|
|
95
|
-
result
|
|
96
|
-
waitForNextUpdate
|
|
90
|
+
result
|
|
97
91
|
} = renderHook(() => useOnlineStatus());
|
|
98
92
|
await act(async () => {
|
|
99
93
|
// Multiple events in succession
|
|
100
94
|
events.offline(new Event('offline'));
|
|
101
95
|
events.online(new Event('online'));
|
|
102
96
|
events.offline(new Event('offline'));
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
expect(result.current.online).toBe(true); // 1s later, final 'offline' event should resolve
|
|
97
|
+
});
|
|
106
98
|
|
|
107
|
-
|
|
108
|
-
|
|
99
|
+
// Immediately, nothing should happen
|
|
100
|
+
expect(result.current.online).toBe(true);
|
|
101
|
+
await wait(1000);
|
|
102
|
+
// 1s later, final 'offline' event should resolve
|
|
103
|
+
await waitFor(() => {
|
|
104
|
+
expect(result.current.online).toBe(false);
|
|
109
105
|
});
|
|
110
|
-
expect(result.current.online).toBe(false);
|
|
111
106
|
});
|
|
112
107
|
it('can have debounce delay set to another number', async () => {
|
|
113
108
|
// Start online
|
|
@@ -115,8 +110,7 @@ describe('debouncing state changes', () => {
|
|
|
115
110
|
const events = {};
|
|
116
111
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
117
112
|
const {
|
|
118
|
-
result
|
|
119
|
-
waitForNextUpdate
|
|
113
|
+
result
|
|
120
114
|
} = renderHook(function () {
|
|
121
115
|
return useOnlineStatus(...arguments);
|
|
122
116
|
}, {
|
|
@@ -129,22 +123,22 @@ describe('debouncing state changes', () => {
|
|
|
129
123
|
events.offline(new Event('offline'));
|
|
130
124
|
events.online(new Event('online'));
|
|
131
125
|
events.offline(new Event('offline'));
|
|
132
|
-
});
|
|
126
|
+
});
|
|
133
127
|
|
|
134
|
-
|
|
128
|
+
// Immediately, nothing should happen
|
|
129
|
+
expect(result.current.online).toBe(true);
|
|
135
130
|
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
// 50ms later, final "offline" event should finally resolve
|
|
132
|
+
await waitFor(() => {
|
|
133
|
+
expect(result.current.online).toBe(false);
|
|
138
134
|
});
|
|
139
|
-
expect(result.current.online).toBe(false);
|
|
140
135
|
});
|
|
141
136
|
it('can use a debounceDelay of 0 to skip debouncing', async () => {
|
|
142
137
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
143
138
|
const events = {};
|
|
144
139
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
145
140
|
const {
|
|
146
|
-
result
|
|
147
|
-
waitForNextUpdate
|
|
141
|
+
result
|
|
148
142
|
} = renderHook(function () {
|
|
149
143
|
return useOnlineStatus(...arguments);
|
|
150
144
|
}, {
|
|
@@ -156,14 +150,14 @@ describe('debouncing state changes', () => {
|
|
|
156
150
|
events.offline(new Event('offline'));
|
|
157
151
|
events.online(new Event('online'));
|
|
158
152
|
events.offline(new Event('offline'));
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
await waitForNextUpdate({
|
|
162
|
-
timeout: 0
|
|
163
|
-
}); // There should be no delay before status is offline
|
|
153
|
+
});
|
|
164
154
|
|
|
165
|
-
|
|
166
|
-
|
|
155
|
+
// await wait(0) didn't work here
|
|
156
|
+
await waitFor(() => {
|
|
157
|
+
// There should be no delay before status is offline
|
|
158
|
+
expect(result.current.online).toBe(false);
|
|
159
|
+
expect(result.current.offline).toBe(true);
|
|
160
|
+
});
|
|
167
161
|
});
|
|
168
162
|
it('can have the debounce delay changed during its lifecycle', async () => {
|
|
169
163
|
// Start with 150 ms debounce
|
|
@@ -172,7 +166,6 @@ describe('debouncing state changes', () => {
|
|
|
172
166
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
173
167
|
const {
|
|
174
168
|
result,
|
|
175
|
-
waitForNextUpdate,
|
|
176
169
|
rerender
|
|
177
170
|
} = renderHook(function () {
|
|
178
171
|
return useOnlineStatus(...arguments);
|
|
@@ -186,15 +179,16 @@ describe('debouncing state changes', () => {
|
|
|
186
179
|
events.offline(new Event('offline'));
|
|
187
180
|
events.online(new Event('online'));
|
|
188
181
|
events.offline(new Event('offline'));
|
|
189
|
-
});
|
|
182
|
+
});
|
|
190
183
|
|
|
191
|
-
|
|
184
|
+
// Immediately, nothing should happen
|
|
185
|
+
expect(result.current.online).toBe(true);
|
|
192
186
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
expect(result.current.online).toBe(false); // Change to 50 ms debounce
|
|
187
|
+
// 150ms later, final "offline" event should finally resolve
|
|
188
|
+
await wait(160);
|
|
189
|
+
expect(result.current.online).toBe(false);
|
|
197
190
|
|
|
191
|
+
// Change to 50 ms debounce
|
|
198
192
|
rerender({
|
|
199
193
|
debounceDelay: 50
|
|
200
194
|
});
|
|
@@ -203,20 +197,19 @@ describe('debouncing state changes', () => {
|
|
|
203
197
|
events.online(new Event('online'));
|
|
204
198
|
events.offline(new Event('offline'));
|
|
205
199
|
events.online(new Event('online'));
|
|
206
|
-
});
|
|
200
|
+
});
|
|
207
201
|
|
|
208
|
-
|
|
202
|
+
// Immediately, nothing should happen
|
|
203
|
+
expect(result.current.online).toBe(false);
|
|
209
204
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
});
|
|
205
|
+
// 50ms later, final "online" event should finally resolve
|
|
206
|
+
await wait(60);
|
|
213
207
|
expect(result.current.online).toBe(true);
|
|
214
208
|
});
|
|
215
209
|
it('handles debounced state change when parent component rerenders during a debounce delay', async () => {
|
|
216
210
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
217
211
|
const events = {};
|
|
218
212
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
219
|
-
|
|
220
213
|
const TestComponent = () => {
|
|
221
214
|
const {
|
|
222
215
|
online
|
|
@@ -227,10 +220,9 @@ describe('debouncing state changes', () => {
|
|
|
227
220
|
"data-testid": "status"
|
|
228
221
|
}, online ? 'on' : 'off');
|
|
229
222
|
};
|
|
230
|
-
|
|
231
223
|
const {
|
|
232
224
|
rerender
|
|
233
|
-
} = render(
|
|
225
|
+
} = render(/*#__PURE__*/React.createElement(TestComponent, null));
|
|
234
226
|
const {
|
|
235
227
|
getByTestId
|
|
236
228
|
} = screen;
|
|
@@ -240,20 +232,22 @@ describe('debouncing state changes', () => {
|
|
|
240
232
|
events.offline(new Event('offline'));
|
|
241
233
|
events.online(new Event('online'));
|
|
242
234
|
events.offline(new Event('offline'));
|
|
243
|
-
});
|
|
235
|
+
});
|
|
244
236
|
|
|
245
|
-
|
|
237
|
+
// Immediately, nothing should happen
|
|
238
|
+
expect(getByTestId('status')).toHaveTextContent('on');
|
|
246
239
|
|
|
247
|
-
|
|
240
|
+
// Rerender parent component
|
|
241
|
+
rerender(/*#__PURE__*/React.createElement(TestComponent, null));
|
|
248
242
|
|
|
243
|
+
// Final "offline" event should still resolve
|
|
249
244
|
await waitFor(() => expect(getByTestId('status')).toHaveTextContent('off'));
|
|
250
245
|
});
|
|
251
246
|
it('handles debounced state change when debounce delay is changed during a delay', async () => {
|
|
252
247
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
253
248
|
const events = {};
|
|
254
249
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
255
|
-
|
|
256
|
-
const TestComponent = (_ref) => {
|
|
250
|
+
const TestComponent = _ref => {
|
|
257
251
|
let {
|
|
258
252
|
options
|
|
259
253
|
} = _ref;
|
|
@@ -264,10 +258,9 @@ describe('debouncing state changes', () => {
|
|
|
264
258
|
"data-testid": "status"
|
|
265
259
|
}, online ? 'on' : 'off');
|
|
266
260
|
};
|
|
267
|
-
|
|
268
261
|
const {
|
|
269
262
|
rerender
|
|
270
|
-
} = render(
|
|
263
|
+
} = render(/*#__PURE__*/React.createElement(TestComponent, {
|
|
271
264
|
options: {
|
|
272
265
|
debounceDelay: 100
|
|
273
266
|
}
|
|
@@ -281,23 +274,25 @@ describe('debouncing state changes', () => {
|
|
|
281
274
|
events.offline(new Event('offline'));
|
|
282
275
|
events.online(new Event('online'));
|
|
283
276
|
events.offline(new Event('offline'));
|
|
284
|
-
});
|
|
277
|
+
});
|
|
285
278
|
|
|
286
|
-
|
|
279
|
+
// Immediately, nothing should happen
|
|
280
|
+
expect(getByTestId('status')).toHaveTextContent('on');
|
|
287
281
|
|
|
288
|
-
|
|
282
|
+
// Change debounce options
|
|
283
|
+
rerender(/*#__PURE__*/React.createElement(TestComponent, {
|
|
289
284
|
options: {
|
|
290
285
|
debounceDelay: 50
|
|
291
286
|
}
|
|
292
|
-
}));
|
|
287
|
+
}));
|
|
293
288
|
|
|
289
|
+
// Final "offline" event should still resolve
|
|
294
290
|
await waitFor(() => expect(getByTestId('status')).toHaveTextContent('off'));
|
|
295
291
|
});
|
|
296
292
|
it('debounces consistently across rerenders', async () => {
|
|
297
293
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
298
294
|
const events = {};
|
|
299
295
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
300
|
-
|
|
301
296
|
const TestComponent = () => {
|
|
302
297
|
const {
|
|
303
298
|
online
|
|
@@ -308,10 +303,9 @@ describe('debouncing state changes', () => {
|
|
|
308
303
|
"data-testid": "status"
|
|
309
304
|
}, online ? 'on' : 'off');
|
|
310
305
|
};
|
|
311
|
-
|
|
312
306
|
const {
|
|
313
307
|
rerender
|
|
314
|
-
} = render(
|
|
308
|
+
} = render(/*#__PURE__*/React.createElement(TestComponent, null));
|
|
315
309
|
const {
|
|
316
310
|
getByTestId
|
|
317
311
|
} = screen;
|
|
@@ -321,22 +315,27 @@ describe('debouncing state changes', () => {
|
|
|
321
315
|
events.offline(new Event('offline'));
|
|
322
316
|
events.online(new Event('online'));
|
|
323
317
|
events.offline(new Event('offline'));
|
|
324
|
-
});
|
|
318
|
+
});
|
|
325
319
|
|
|
320
|
+
// wait a little bit - not long enough for debounce to resolve
|
|
326
321
|
await wait(50);
|
|
327
|
-
expect(getByTestId('status')).toHaveTextContent('on');
|
|
322
|
+
expect(getByTestId('status')).toHaveTextContent('on');
|
|
328
323
|
|
|
329
|
-
|
|
324
|
+
// Rerender parent component
|
|
325
|
+
rerender(/*#__PURE__*/React.createElement(TestComponent, null));
|
|
330
326
|
|
|
327
|
+
// Trigger more events
|
|
331
328
|
await act(async () => {
|
|
332
329
|
events.online(new Event('online'));
|
|
333
330
|
events.offline(new Event('offline'));
|
|
334
|
-
});
|
|
335
|
-
// _would_ have resolved if there weren't the second set of events
|
|
331
|
+
});
|
|
336
332
|
|
|
333
|
+
// wait a little more - long enough that the first debounced callbacks
|
|
334
|
+
// _would_ have resolved if there weren't the second set of events
|
|
337
335
|
await wait(60);
|
|
338
|
-
expect(getByTestId('status')).toHaveTextContent('on');
|
|
336
|
+
expect(getByTestId('status')).toHaveTextContent('on');
|
|
339
337
|
|
|
338
|
+
// wait long enough for second set of callbacks to resolve
|
|
340
339
|
await waitFor(() => expect(getByTestId('status')).toHaveTextContent('off'));
|
|
341
340
|
});
|
|
342
341
|
});
|
|
@@ -345,43 +344,42 @@ describe('it updates the lastOnline value in local storage', () => {
|
|
|
345
344
|
const testDateString = 'Fri, 27 Aug 2021 19:53:06 GMT';
|
|
346
345
|
it('sets lastOnline in local storage when it goes offline', async () => {
|
|
347
346
|
var _result$current$lastO;
|
|
348
|
-
|
|
349
347
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
350
348
|
const events = {};
|
|
351
349
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
352
350
|
const {
|
|
353
|
-
result
|
|
354
|
-
waitForNextUpdate
|
|
351
|
+
result
|
|
355
352
|
} = renderHook(function () {
|
|
356
353
|
return useOnlineStatus(...arguments);
|
|
357
354
|
}, {
|
|
358
355
|
initialProps: {
|
|
359
356
|
debounceDelay: 0
|
|
360
357
|
}
|
|
361
|
-
});
|
|
358
|
+
});
|
|
362
359
|
|
|
360
|
+
// Correct initial state
|
|
363
361
|
expect(localStorage.getItem(lastOnlineKey)).toBe(null);
|
|
364
362
|
expect(result.current.lastOnline).toBe(null);
|
|
365
363
|
act(() => {
|
|
366
364
|
events.offline(new Event('offline'));
|
|
367
|
-
}); // Wait for debounce
|
|
368
|
-
|
|
369
|
-
await waitForNextUpdate({
|
|
370
|
-
timeout: 0
|
|
371
365
|
});
|
|
366
|
+
|
|
367
|
+
// Wait for debounce
|
|
368
|
+
await wait(500);
|
|
372
369
|
expect(result.current.online).toBe(false);
|
|
373
|
-
expect(result.current.offline).toBe(true);
|
|
370
|
+
expect(result.current.offline).toBe(true);
|
|
374
371
|
|
|
372
|
+
// Check localStorage for a stored date
|
|
375
373
|
const parsedDate = new Date(localStorage.getItem(lastOnlineKey));
|
|
376
|
-
expect(parsedDate.toString()).not.toBe('Invalid Date');
|
|
377
|
-
|
|
374
|
+
expect(parsedDate.toString()).not.toBe('Invalid Date');
|
|
375
|
+
// Check hook return value
|
|
378
376
|
expect(result.current.lastOnline).toBeInstanceOf(Date);
|
|
379
377
|
expect((_result$current$lastO = result.current.lastOnline) === null || _result$current$lastO === void 0 ? void 0 : _result$current$lastO.toUTCString()).toBe(localStorage.getItem(lastOnlineKey));
|
|
380
|
-
});
|
|
378
|
+
});
|
|
381
379
|
|
|
380
|
+
// not necessary
|
|
382
381
|
it.skip("sets lastOnline on mount if it's not set", () => {
|
|
383
382
|
var _result$current$lastO2;
|
|
384
|
-
|
|
385
383
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(false);
|
|
386
384
|
const events = {};
|
|
387
385
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
@@ -432,8 +430,7 @@ describe('it updates the lastOnline value in local storage', () => {
|
|
|
432
430
|
const events = {};
|
|
433
431
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
434
432
|
const {
|
|
435
|
-
result
|
|
436
|
-
waitForNextUpdate
|
|
433
|
+
result
|
|
437
434
|
} = renderHook(function () {
|
|
438
435
|
return useOnlineStatus(...arguments);
|
|
439
436
|
}, {
|
|
@@ -445,58 +442,52 @@ describe('it updates the lastOnline value in local storage', () => {
|
|
|
445
442
|
expect(result.current.lastOnline).toEqual(new Date(testDateString));
|
|
446
443
|
act(() => {
|
|
447
444
|
events.offline(new Event('online'));
|
|
448
|
-
}); // Wait for debounce
|
|
449
|
-
|
|
450
|
-
await waitForNextUpdate({
|
|
451
|
-
timeout: 0
|
|
452
445
|
});
|
|
446
|
+
|
|
447
|
+
// Wait for debounce
|
|
448
|
+
await wait(500);
|
|
453
449
|
expect(result.current.online).toBe(true);
|
|
454
|
-
expect(result.current.offline).toBe(false);
|
|
450
|
+
expect(result.current.offline).toBe(false);
|
|
455
451
|
|
|
452
|
+
// expect(localStorage.getItem(lastOnlineKey)).toBe(null)
|
|
456
453
|
expect(result.current.lastOnline).toBe(null);
|
|
457
454
|
});
|
|
458
455
|
it('tracks correctly when going offline and online', async () => {
|
|
459
456
|
var _result$current$lastO3, _result$current$lastO4;
|
|
460
|
-
|
|
461
457
|
jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true);
|
|
462
458
|
const events = {};
|
|
463
459
|
window.addEventListener = jest.fn((event, cb) => events[event] = cb);
|
|
464
460
|
const {
|
|
465
|
-
result
|
|
466
|
-
waitForNextUpdate
|
|
461
|
+
result
|
|
467
462
|
} = renderHook(function () {
|
|
468
463
|
return useOnlineStatus(...arguments);
|
|
469
464
|
}, {
|
|
470
465
|
initialProps: {
|
|
471
466
|
debounceDelay: 0
|
|
472
467
|
}
|
|
473
|
-
});
|
|
468
|
+
});
|
|
474
469
|
|
|
470
|
+
// Correct initial state
|
|
475
471
|
expect(localStorage.getItem(lastOnlineKey)).toBe(null);
|
|
476
472
|
expect(result.current.lastOnline).toBe(null);
|
|
477
473
|
act(() => {
|
|
478
474
|
events.offline(new Event('offline'));
|
|
479
475
|
});
|
|
480
|
-
await
|
|
481
|
-
timeout: 0
|
|
482
|
-
});
|
|
476
|
+
await waitFor(() => undefined);
|
|
483
477
|
const firstDate = new Date(localStorage.getItem(lastOnlineKey));
|
|
484
478
|
const firstValue = (_result$current$lastO3 = result.current.lastOnline) === null || _result$current$lastO3 === void 0 ? void 0 : _result$current$lastO3.valueOf();
|
|
485
479
|
act(() => {
|
|
486
480
|
events.offline(new Event('online'));
|
|
487
481
|
});
|
|
488
|
-
await
|
|
489
|
-
|
|
490
|
-
});
|
|
491
|
-
expect(result.current.lastOnline).toBe(null); // todo: this is an error from UTC strings' imprecision
|
|
482
|
+
await wait(500);
|
|
483
|
+
expect(result.current.lastOnline).toBe(null);
|
|
492
484
|
|
|
493
|
-
|
|
485
|
+
// todo: this is an error from UTC strings' imprecision
|
|
486
|
+
await wait(500);
|
|
494
487
|
act(() => {
|
|
495
488
|
events.offline(new Event('offline'));
|
|
496
489
|
});
|
|
497
|
-
await
|
|
498
|
-
timeout: 0
|
|
499
|
-
});
|
|
490
|
+
await wait(500);
|
|
500
491
|
expect(new Date(localStorage.getItem(lastOnlineKey))).not.toEqual(firstDate);
|
|
501
492
|
expect((_result$current$lastO4 = result.current.lastOnline) === null || _result$current$lastO4 === void 0 ? void 0 : _result$current$lastO4.valueOf()).not.toEqual(firstValue);
|
|
502
493
|
});
|
|
@@ -3,32 +3,31 @@ import React from 'react';
|
|
|
3
3
|
import { mockOfflineInterface } from '../../utils/test-mocks';
|
|
4
4
|
import { useCacheableSection, CacheableSection } from '../cacheable-section';
|
|
5
5
|
import { useCachedSections } from '../cacheable-section-state';
|
|
6
|
-
import { OfflineProvider } from '../offline-provider';
|
|
6
|
+
import { OfflineProvider } from '../offline-provider';
|
|
7
7
|
|
|
8
|
+
// Suppress 'act' warning for these tests
|
|
8
9
|
const originalError = console.error;
|
|
9
10
|
beforeEach(() => {
|
|
10
11
|
jest.spyOn(console, 'error').mockImplementation(function () {
|
|
11
12
|
const pattern = /Warning: An update to .* inside a test was not wrapped in act/;
|
|
12
|
-
|
|
13
13
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
14
14
|
args[_key] = arguments[_key];
|
|
15
15
|
}
|
|
16
|
-
|
|
17
16
|
if (typeof args[0] === 'string' && pattern.test(args[0])) {
|
|
18
17
|
return;
|
|
19
18
|
}
|
|
20
|
-
|
|
21
19
|
return originalError.call(console, ...args);
|
|
22
20
|
});
|
|
23
21
|
});
|
|
24
22
|
afterEach(() => {
|
|
25
|
-
jest.clearAllMocks()
|
|
23
|
+
jest.clearAllMocks()
|
|
24
|
+
// syntax needed to appease typescript
|
|
26
25
|
;
|
|
27
26
|
console.error.mockRestore();
|
|
28
27
|
});
|
|
29
28
|
describe('Testing offline provider', () => {
|
|
30
29
|
it('Should render without failing', () => {
|
|
31
|
-
render(
|
|
30
|
+
render(/*#__PURE__*/React.createElement(OfflineProvider, {
|
|
32
31
|
offlineInterface: mockOfflineInterface
|
|
33
32
|
}, /*#__PURE__*/React.createElement("div", {
|
|
34
33
|
"data-testid": "test-div"
|
|
@@ -36,7 +35,8 @@ describe('Testing offline provider', () => {
|
|
|
36
35
|
expect(screen.getByTestId('test-div')).toBeInTheDocument();
|
|
37
36
|
});
|
|
38
37
|
it('Should sync cached sections with indexedDB', async () => {
|
|
39
|
-
const testOfflineInterface = {
|
|
38
|
+
const testOfflineInterface = {
|
|
39
|
+
...mockOfflineInterface,
|
|
40
40
|
getCachedSections: jest.fn().mockResolvedValue([{
|
|
41
41
|
sectionId: '1',
|
|
42
42
|
lastUpdated: 'date1'
|
|
@@ -45,7 +45,6 @@ describe('Testing offline provider', () => {
|
|
|
45
45
|
lastUpdated: 'date2'
|
|
46
46
|
}])
|
|
47
47
|
};
|
|
48
|
-
|
|
49
48
|
const CachedSections = () => {
|
|
50
49
|
const {
|
|
51
50
|
cachedSections
|
|
@@ -54,8 +53,7 @@ describe('Testing offline provider', () => {
|
|
|
54
53
|
"data-testid": "sections"
|
|
55
54
|
}, JSON.stringify(cachedSections));
|
|
56
55
|
};
|
|
57
|
-
|
|
58
|
-
render( /*#__PURE__*/React.createElement(OfflineProvider, {
|
|
56
|
+
render(/*#__PURE__*/React.createElement(OfflineProvider, {
|
|
59
57
|
offlineInterface: testOfflineInterface
|
|
60
58
|
}, /*#__PURE__*/React.createElement(CachedSections, null)));
|
|
61
59
|
const {
|
|
@@ -83,23 +81,23 @@ describe('Testing offline provider', () => {
|
|
|
83
81
|
"data-testid": "test-div"
|
|
84
82
|
}));
|
|
85
83
|
};
|
|
86
|
-
|
|
87
|
-
render( /*#__PURE__*/React.createElement(OfflineProvider, {
|
|
84
|
+
render(/*#__PURE__*/React.createElement(OfflineProvider, {
|
|
88
85
|
offlineInterface: mockOfflineInterface
|
|
89
86
|
}, /*#__PURE__*/React.createElement(TestConsumer, null)));
|
|
90
87
|
expect(screen.getByTestId('test-div')).toBeInTheDocument();
|
|
91
88
|
});
|
|
92
89
|
it('Should render without failing when no offlineInterface is provided', () => {
|
|
93
|
-
render(
|
|
90
|
+
render(/*#__PURE__*/React.createElement(OfflineProvider, null, /*#__PURE__*/React.createElement("div", {
|
|
94
91
|
"data-testid": "test-div"
|
|
95
92
|
})));
|
|
96
93
|
expect(screen.getByTestId('test-div')).toBeInTheDocument();
|
|
97
94
|
});
|
|
98
95
|
it('Should render without failing if PWA is not enabled', () => {
|
|
99
|
-
const testOfflineInterface = {
|
|
96
|
+
const testOfflineInterface = {
|
|
97
|
+
...mockOfflineInterface,
|
|
100
98
|
pwaEnabled: false
|
|
101
99
|
};
|
|
102
|
-
render(
|
|
100
|
+
render(/*#__PURE__*/React.createElement(OfflineProvider, {
|
|
103
101
|
offlineInterface: testOfflineInterface
|
|
104
102
|
}, /*#__PURE__*/React.createElement("div", {
|
|
105
103
|
"data-testid": "test-div"
|