@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.
Files changed (60) hide show
  1. package/build/cjs/__tests__/integration.test.js +51 -82
  2. package/build/cjs/index.js +0 -7
  3. package/build/cjs/lib/__tests__/cacheable-section-state.test.js +7 -14
  4. package/build/cjs/lib/__tests__/clear-sensitive-caches.test.js +17 -20
  5. package/build/cjs/lib/__tests__/network-status.test.js +135 -148
  6. package/build/cjs/lib/__tests__/offline-provider.test.js +12 -22
  7. package/build/cjs/lib/__tests__/use-cacheable-section.test.js +87 -98
  8. package/build/cjs/lib/__tests__/use-online-status-message.test.js +7 -14
  9. package/build/cjs/lib/cacheable-section-state.js +27 -38
  10. package/build/cjs/lib/cacheable-section.js +26 -27
  11. package/build/cjs/lib/clear-sensitive-caches.js +14 -24
  12. package/build/cjs/lib/dhis2-connection-status/dev-debug-log.js +1 -3
  13. package/build/cjs/lib/dhis2-connection-status/dhis2-connection-status.js +27 -58
  14. package/build/cjs/lib/dhis2-connection-status/dhis2-connection-status.test.js +287 -230
  15. package/build/cjs/lib/dhis2-connection-status/index.js +0 -1
  16. package/build/cjs/lib/dhis2-connection-status/is-ping-available.js +0 -6
  17. package/build/cjs/lib/dhis2-connection-status/is-ping-available.test.js +0 -1
  18. package/build/cjs/lib/dhis2-connection-status/smart-interval.js +35 -49
  19. package/build/cjs/lib/dhis2-connection-status/use-ping-query.js +4 -5
  20. package/build/cjs/lib/global-state-service.js +9 -27
  21. package/build/cjs/lib/network-status.js +10 -13
  22. package/build/cjs/lib/offline-interface.js +3 -14
  23. package/build/cjs/lib/offline-provider.js +1 -12
  24. package/build/cjs/lib/online-status-message.js +5 -17
  25. package/build/cjs/setupRTL.js +1 -1
  26. package/build/cjs/utils/__tests__/render-counter.test.js +3 -12
  27. package/build/cjs/utils/render-counter.js +2 -10
  28. package/build/cjs/utils/test-mocks.js +13 -18
  29. package/build/es/__tests__/integration.test.js +51 -74
  30. package/build/es/index.js +2 -2
  31. package/build/es/lib/__tests__/cacheable-section-state.test.js +2 -4
  32. package/build/es/lib/__tests__/clear-sensitive-caches.test.js +19 -16
  33. package/build/es/lib/__tests__/network-status.test.js +105 -114
  34. package/build/es/lib/__tests__/offline-provider.test.js +13 -15
  35. package/build/es/lib/__tests__/use-cacheable-section.test.js +69 -73
  36. package/build/es/lib/__tests__/use-online-status-message.test.js +2 -3
  37. package/build/es/lib/cacheable-section-state.js +25 -26
  38. package/build/es/lib/cacheable-section.js +23 -15
  39. package/build/es/lib/clear-sensitive-caches.js +13 -21
  40. package/build/es/lib/dhis2-connection-status/dev-debug-log.js +1 -3
  41. package/build/es/lib/dhis2-connection-status/dhis2-connection-status.js +26 -37
  42. package/build/es/lib/dhis2-connection-status/dhis2-connection-status.test.js +223 -159
  43. package/build/es/lib/dhis2-connection-status/is-ping-available.js +0 -5
  44. package/build/es/lib/dhis2-connection-status/smart-interval.js +34 -42
  45. package/build/es/lib/dhis2-connection-status/use-ping-query.js +6 -3
  46. package/build/es/lib/global-state-service.js +6 -12
  47. package/build/es/lib/network-status.js +10 -9
  48. package/build/es/lib/offline-interface.js +0 -3
  49. package/build/es/lib/offline-provider.js +0 -3
  50. package/build/es/lib/online-status-message.js +3 -2
  51. package/build/es/setupRTL.js +1 -1
  52. package/build/es/utils/__tests__/render-counter.test.js +2 -4
  53. package/build/es/utils/render-counter.js +1 -3
  54. package/build/es/utils/test-mocks.js +8 -9
  55. package/build/types/lib/cacheable-section.d.ts +1 -1
  56. package/build/types/lib/dhis2-connection-status/dhis2-connection-status.d.ts +1 -1
  57. package/build/types/lib/network-status.d.ts +1 -1
  58. package/build/types/lib/online-status-message.d.ts +1 -1
  59. package/build/types/types.d.ts +1 -1
  60. package/package.json +4 -4
@@ -1,49 +1,41 @@
1
1
  "use strict";
2
2
 
3
3
  var _appServiceConfig = require("@dhis2/app-service-config");
4
-
5
- var _reactHooks = require("@testing-library/react-hooks");
6
-
7
- var _react = _interopRequireDefault(require("react"));
8
-
4
+ var _react = require("@testing-library/react");
5
+ var _react2 = _interopRequireDefault(require("react"));
9
6
  var _testMocks = require("../../utils/test-mocks");
10
-
11
7
  var _offlineProvider = require("../offline-provider");
12
-
13
8
  var _dhis2ConnectionStatus = require("./dhis2-connection-status");
14
-
15
9
  var _smartInterval = require("./smart-interval");
16
-
17
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
12
 
19
13
  // important that this name starts with 'mock' to be hoisted correctly
20
14
  const mockPing = jest.fn().mockImplementation(() => Promise.resolve());
21
15
  jest.mock('./use-ping-query.ts', () => ({
22
16
  usePingQuery: () => mockPing
23
17
  }));
24
-
25
18
  const failedPing = () => Promise.reject({
26
19
  message: 'this is a network error',
27
20
  type: 'network'
28
21
  });
29
-
30
22
  const FIRST_INTERVAL_MS = _smartInterval.DEFAULT_INITIAL_DELAY_MS;
31
23
  const SECOND_INTERVAL_MS = FIRST_INTERVAL_MS * _smartInterval.DEFAULT_INCREMENT_FACTOR;
32
24
  const THIRD_INTERVAL_MS = SECOND_INTERVAL_MS * _smartInterval.DEFAULT_INCREMENT_FACTOR;
33
- const FOURTH_INTERVAL_MS = THIRD_INTERVAL_MS * _smartInterval.DEFAULT_INCREMENT_FACTOR; // Explanation: The length of the Nth interval is:
25
+ const FOURTH_INTERVAL_MS = THIRD_INTERVAL_MS * _smartInterval.DEFAULT_INCREMENT_FACTOR;
26
+
27
+ // Explanation: The length of the Nth interval is:
34
28
  // initialDelay * incrementFactor ^ (N - 1)
35
29
  // Using some algebra and the law of logs, the Nth interval
36
30
  // which is longer than the max delay is:
37
31
  // N >= (ln (maxDelay / initialDelay) / ln (incrementFactor)) + 1
38
32
  // => then use Math.ceil to handle the 'greater than' effect
39
-
40
33
  const INTERVALS_TO_REACH_MAX_DELAY = Math.ceil(Math.log(_smartInterval.DEFAULT_MAX_DELAY_MS / _smartInterval.DEFAULT_INITIAL_DELAY_MS) / Math.log(_smartInterval.DEFAULT_INCREMENT_FACTOR) + 1);
41
-
42
- const wrapper = (_ref) => {
34
+ const wrapper = _ref => {
43
35
  let {
44
36
  children
45
37
  } = _ref;
46
- return /*#__PURE__*/_react.default.createElement(_appServiceConfig.ConfigProvider, {
38
+ return /*#__PURE__*/_react2.default.createElement(_appServiceConfig.ConfigProvider, {
47
39
  config: {
48
40
  baseUrl: '..',
49
41
  apiVersion: 42,
@@ -55,10 +47,11 @@ const wrapper = (_ref) => {
55
47
  full: 'n/a'
56
48
  }
57
49
  }
58
- }, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
50
+ }, /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
59
51
  offlineInterface: _testMocks.mockOfflineInterface
60
52
  }, children));
61
53
  };
54
+
62
55
  /**
63
56
  * Assert on the delay of the last time setTimeoutSpy was called with
64
57
  * the `callbackAndRestart()` function in smartInterval.
@@ -68,11 +61,8 @@ const wrapper = (_ref) => {
68
61
  * an assertion like:
69
62
  * `expect(setTimeoutSpy).toHaveBeenLastCalledWith(..., expectedDelay)`
70
63
  */
71
-
72
-
73
64
  const assertLastDelay = (setTimeoutSpy, expectedDelay) => {
74
65
  const calls = setTimeoutSpy.mock.calls;
75
-
76
66
  for (let i = calls.length - 1; i >= 0; i--) {
77
67
  if (calls[i][0].name === 'callbackAndRestart') {
78
68
  expect(calls[i][1]).toBe(expectedDelay);
@@ -80,7 +70,6 @@ const assertLastDelay = (setTimeoutSpy, expectedDelay) => {
80
70
  }
81
71
  }
82
72
  };
83
-
84
73
  const testCurrentDate = new Date('Fri, 03 Feb 2023 13:52:31 GMT');
85
74
  beforeAll(() => {
86
75
  jest.useFakeTimers();
@@ -92,8 +81,8 @@ beforeEach(() => {
92
81
  jest.spyOn(document, 'hasFocus').mockReturnValue(true);
93
82
  });
94
83
  afterEach(() => {
95
- jest.clearAllMocks(); // for lastConnected:
96
-
84
+ jest.clearAllMocks();
85
+ // for lastConnected:
97
86
  localStorage.clear();
98
87
  });
99
88
  afterAll(() => {
@@ -104,7 +93,7 @@ describe('initialization to the right values based on offline interface', () =>
104
93
  test('when latestIsConnected is true', () => {
105
94
  const {
106
95
  result
107
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
96
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
108
97
  wrapper: wrapper
109
98
  });
110
99
  expect(result.current.isConnected).toBe(true);
@@ -112,54 +101,53 @@ describe('initialization to the right values based on offline interface', () =>
112
101
  expect(result.current.lastConnected).toBe(null);
113
102
  });
114
103
  test('when latestIsConnected is false', () => {
115
- const customMockOfflineInterface = { ..._testMocks.mockOfflineInterface,
104
+ const customMockOfflineInterface = {
105
+ ..._testMocks.mockOfflineInterface,
116
106
  latestIsConnected: false
117
107
  };
118
-
119
- const customWrapper = (_ref2) => {
108
+ const customWrapper = _ref2 => {
120
109
  let {
121
110
  children
122
111
  } = _ref2;
123
- return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
112
+ return /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
124
113
  offlineInterface: customMockOfflineInterface
125
114
  }, children);
126
115
  };
127
-
128
116
  const {
129
117
  result
130
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
118
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
131
119
  wrapper: customWrapper
132
120
  });
133
121
  expect(result.current.isConnected).toBe(false);
134
- expect(result.current.isDisconnected).toBe(true); // If localStorage is clear, sets 'lastConnected' to `now` as a best
122
+ expect(result.current.isDisconnected).toBe(true);
123
+ // If localStorage is clear, sets 'lastConnected' to `now` as a best
135
124
  // effort to provide useful information.
136
125
  // There will be more detailed testing of lastConnected below
137
-
138
126
  expect(result.current.lastConnected).toEqual(testCurrentDate);
139
- }); // This might happen in the unlikely circumstance that the provider
127
+ });
128
+
129
+ // This might happen in the unlikely circumstance that the provider
140
130
  // renders before the offlineInterface has received a value for
141
131
  // lastIsConnected. Normally, the ServerVersionProvider in the app
142
132
  // adapter delays rendering the App Runtime provider (including the
143
133
  // OfflineProvider) until the offline interface is ready, which should
144
134
  // avoid this case.
145
-
146
135
  test('when latestIsConnected is null', () => {
147
- const customMockOfflineInterface = { ..._testMocks.mockOfflineInterface,
136
+ const customMockOfflineInterface = {
137
+ ..._testMocks.mockOfflineInterface,
148
138
  latestIsConnected: null
149
139
  };
150
-
151
- const customWrapper = (_ref3) => {
140
+ const customWrapper = _ref3 => {
152
141
  let {
153
142
  children
154
143
  } = _ref3;
155
- return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
144
+ return /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
156
145
  offlineInterface: customMockOfflineInterface
157
146
  }, children);
158
147
  };
159
-
160
148
  const {
161
149
  result
162
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
150
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
163
151
  wrapper: customWrapper
164
152
  });
165
153
  expect(result.current.isConnected).toBe(true);
@@ -172,111 +160,124 @@ describe('interval behavior', () => {
172
160
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
173
161
  const {
174
162
  result
175
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
163
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
176
164
  wrapper: wrapper
177
165
  });
178
166
  expect(result.current.isConnected).toBe(true);
179
167
  expect(mockPing).not.toHaveBeenCalled();
180
- assertLastDelay(setTimeoutSpy, FIRST_INTERVAL_MS); // 500ms before first interval
168
+ assertLastDelay(setTimeoutSpy, FIRST_INTERVAL_MS);
181
169
 
170
+ // 500ms before first interval
182
171
  jest.advanceTimersByTime(FIRST_INTERVAL_MS - 500);
183
- expect(mockPing).not.toHaveBeenCalled(); // 500ms after first interval
184
-
172
+ expect(mockPing).not.toHaveBeenCalled();
173
+ // 500ms after first interval
185
174
  jest.advanceTimersByTime(1000);
186
175
  expect(mockPing).toHaveBeenCalledTimes(1);
187
- assertLastDelay(setTimeoutSpy, SECOND_INTERVAL_MS); // 500ms before second interval
176
+ assertLastDelay(setTimeoutSpy, SECOND_INTERVAL_MS);
188
177
 
178
+ // 500ms before second interval
189
179
  jest.advanceTimersByTime(SECOND_INTERVAL_MS - 1000);
190
- expect(mockPing).toHaveBeenCalledTimes(1); // 500ms after second interval
191
-
180
+ expect(mockPing).toHaveBeenCalledTimes(1);
181
+ // 500ms after second interval
192
182
  jest.advanceTimersByTime(1000);
193
183
  expect(mockPing).toHaveBeenCalledTimes(2);
194
- assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS); // 500ms before third interval
184
+ assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
195
185
 
186
+ // 500ms before third interval
196
187
  jest.advanceTimersByTime(THIRD_INTERVAL_MS - 1000);
197
- expect(mockPing).toHaveBeenCalledTimes(2); // 500ms after third interval
198
-
188
+ expect(mockPing).toHaveBeenCalledTimes(2);
189
+ // 500ms after third interval
199
190
  jest.advanceTimersByTime(1000);
200
191
  expect(mockPing).toHaveBeenCalledTimes(3);
201
- assertLastDelay(setTimeoutSpy, FOURTH_INTERVAL_MS); // Run a number of intervals to reach the max delay -
192
+ assertLastDelay(setTimeoutSpy, FOURTH_INTERVAL_MS);
193
+
194
+ // Run a number of intervals to reach the max delay -
202
195
  // this number is calculated above to work for any default values.
203
196
  // Since three have already elapsed, there will be some extra too
204
-
205
197
  for (let i = 0; i < INTERVALS_TO_REACH_MAX_DELAY; i++) {
206
198
  // Wrap in act to await async side effects of interval execution
207
199
  // and pings
208
- await (0, _reactHooks.act)(async () => {
200
+ await (0, _react.act)(async () => {
209
201
  jest.runOnlyPendingTimers();
210
202
  });
211
- } // Timeout should no longer be incrementing; max has been reached
212
-
203
+ }
213
204
 
205
+ // Timeout should no longer be incrementing; max has been reached
214
206
  expect(mockPing).toHaveBeenCalledTimes(3 + INTERVALS_TO_REACH_MAX_DELAY);
215
- assertLastDelay(setTimeoutSpy, _smartInterval.DEFAULT_MAX_DELAY_MS); // Run a few more intervals to make sure it stays at max
207
+ assertLastDelay(setTimeoutSpy, _smartInterval.DEFAULT_MAX_DELAY_MS);
216
208
 
209
+ // Run a few more intervals to make sure it stays at max
217
210
  for (let i = 0; i < 3; i++) {
218
- await (0, _reactHooks.act)(async () => {
211
+ await (0, _react.act)(async () => {
219
212
  jest.runOnlyPendingTimers();
220
213
  });
221
- } // Expect continued use of the max delay
222
-
214
+ }
223
215
 
216
+ // Expect continued use of the max delay
224
217
  expect(mockPing).toHaveBeenCalledTimes(6 + INTERVALS_TO_REACH_MAX_DELAY);
225
218
  assertLastDelay(setTimeoutSpy, _smartInterval.DEFAULT_MAX_DELAY_MS);
226
219
  });
227
220
  describe('pings are delayed when offlineInterface sends status updates', () => {
228
221
  test('updates postpone pings', () => {
229
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
222
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
230
223
  wrapper: wrapper
231
- }); // get onUpdate function passed to mockOfflineInterface
224
+ });
232
225
 
226
+ // get onUpdate function passed to mockOfflineInterface
233
227
  const {
234
228
  onUpdate
235
- } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0]; // invoke it at a few intervals, before pings are scheduled
229
+ } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0];
236
230
 
231
+ // invoke it at a few intervals, before pings are scheduled
237
232
  for (let i = 0; i < 3; i++) {
238
233
  jest.advanceTimersByTime(_smartInterval.DEFAULT_INITIAL_DELAY_MS - 2000);
239
234
  onUpdate({
240
235
  isConnected: true
241
236
  });
242
- } // expect ping mock not to have been called
243
-
237
+ }
244
238
 
239
+ // expect ping mock not to have been called
245
240
  expect(mockPing).not.toHaveBeenCalled;
246
241
  });
247
242
  test('if the status is the same, the ping delay is reset to the current', () => {
248
243
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
249
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
244
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
250
245
  wrapper
251
- }); // get onUpdate function passed to mockOfflineInterface
246
+ });
252
247
 
248
+ // get onUpdate function passed to mockOfflineInterface
253
249
  const {
254
250
  onUpdate
255
- } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0]; // let two intervals pass to allow delay to increase
251
+ } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0];
256
252
 
253
+ // let two intervals pass to allow delay to increase
257
254
  jest.advanceTimersByTime(FIRST_INTERVAL_MS + 50);
258
- jest.advanceTimersByTime(SECOND_INTERVAL_MS); // ...delay should now be 'THIRD_INTERVAL_MS'
255
+ jest.advanceTimersByTime(SECOND_INTERVAL_MS);
259
256
 
257
+ // ...delay should now be 'THIRD_INTERVAL_MS'
260
258
  assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
261
- expect(mockPing).toHaveBeenCalledTimes(2); // simulate updates from the SW/offline interface several times
262
- // invoke it at a few intervals, before pings are scheduled
259
+ expect(mockPing).toHaveBeenCalledTimes(2);
263
260
 
261
+ // simulate updates from the SW/offline interface several times
262
+ // invoke it at a few intervals, before pings are scheduled
264
263
  for (let i = 0; i < 3; i++) {
265
264
  jest.advanceTimersByTime(THIRD_INTERVAL_MS - 2000);
266
265
  onUpdate({
267
266
  isConnected: true
268
267
  });
269
- } // ping mock should STILL only have been called twice
268
+ }
270
269
 
270
+ // ping mock should STILL only have been called twice
271
+ expect(mockPing).toHaveBeenCalledTimes(2);
271
272
 
272
- expect(mockPing).toHaveBeenCalledTimes(2); // the delay should still be THIRD_INTERVAL_MS
273
+ // the delay should still be THIRD_INTERVAL_MS
274
+ assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
273
275
 
274
- assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS); // The timer works as normal for the next tick --
276
+ // The timer works as normal for the next tick --
275
277
  // 500ms before the fourth interval:
276
-
277
278
  jest.advanceTimersByTime(THIRD_INTERVAL_MS - 500);
278
- expect(mockPing).toHaveBeenCalledTimes(2); // 500ms after the fourth interval
279
-
279
+ expect(mockPing).toHaveBeenCalledTimes(2);
280
+ // 500ms after the fourth interval
280
281
  jest.advanceTimersByTime(1000);
281
282
  expect(mockPing).toHaveBeenCalledTimes(3);
282
283
  });
@@ -286,42 +287,47 @@ describe('interval behavior', () => {
286
287
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
287
288
  const {
288
289
  result
289
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
290
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
290
291
  wrapper: wrapper
291
- }); // get onUpdate function passed to mockOfflineInterface
292
-
292
+ });
293
+ // get onUpdate function passed to mockOfflineInterface
293
294
  const {
294
295
  onUpdate
295
296
  } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0];
296
- expect(result.current.isConnected).toBe(true); // Get to third interval
297
- // (Wrap in `act` to await async side effects of the executions)
297
+ expect(result.current.isConnected).toBe(true);
298
298
 
299
- await (0, _reactHooks.act)(async () => {
299
+ // Get to third interval
300
+ // (Wrap in `act` to await async side effects of the executions)
301
+ await (0, _react.act)(async () => {
300
302
  jest.runOnlyPendingTimers();
301
303
  jest.runOnlyPendingTimers();
302
304
  });
303
305
  expect(mockPing).toHaveBeenCalledTimes(2);
304
- assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS); // Trigger connection status change from offline interface
306
+ assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
305
307
 
306
- await (0, _reactHooks.act)(async () => {
308
+ // Trigger connection status change from offline interface
309
+ await (0, _react.act)(async () => {
307
310
  onUpdate({
308
311
  isConnected: false
309
312
  });
310
- }); // Expect "first interval delay" to be set up
313
+ });
311
314
 
315
+ // Expect "first interval delay" to be set up
312
316
  assertLastDelay(setTimeoutSpy, FIRST_INTERVAL_MS);
313
- expect(result.current.isConnected).toBe(false); // Mock an error for the next ping to maintain `isConnected: false`
317
+ expect(result.current.isConnected).toBe(false);
314
318
 
319
+ // Mock an error for the next ping to maintain `isConnected: false`
315
320
  mockPing.mockImplementationOnce(() => Promise.reject({
316
321
  message: 'this is a network error',
317
322
  type: 'network'
318
- })); // Advance past "first interval" -- make sure incrementing resumes
323
+ }));
324
+ // Advance past "first interval" -- make sure incrementing resumes
319
325
  // while still 'isConnected: false'
320
-
321
- await (0, _reactHooks.act)(async () => {
326
+ await (0, _react.act)(async () => {
322
327
  jest.advanceTimersByTime(FIRST_INTERVAL_MS + 50);
323
- }); // Expect another execution with the incremented interval
328
+ });
324
329
 
330
+ // Expect another execution with the incremented interval
325
331
  expect(mockPing).toHaveBeenCalledTimes(3);
326
332
  assertLastDelay(setTimeoutSpy, SECOND_INTERVAL_MS);
327
333
  });
@@ -329,21 +335,23 @@ describe('interval behavior', () => {
329
335
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
330
336
  const {
331
337
  result
332
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
338
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
333
339
  wrapper: wrapper
334
340
  });
335
- expect(result.current.isConnected).toBe(true); // Get to third interval
341
+ expect(result.current.isConnected).toBe(true);
336
342
 
343
+ // Get to third interval
337
344
  jest.runOnlyPendingTimers();
338
345
  jest.runOnlyPendingTimers();
339
346
  expect(mockPing).toHaveBeenCalledTimes(2);
340
- assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS); // Mock a network error
347
+ assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
341
348
 
349
+ // Mock a network error
342
350
  mockPing.mockImplementationOnce(() => Promise.reject({
343
351
  message: 'this is a network error',
344
352
  type: 'network'
345
353
  }));
346
- await (0, _reactHooks.act)(async () => {
354
+ await (0, _react.act)(async () => {
347
355
  jest.advanceTimersByTime(THIRD_INTERVAL_MS + 50);
348
356
  });
349
357
  expect(result.current.isConnected).toBe(false);
@@ -354,111 +362,126 @@ describe('interval behavior', () => {
354
362
  });
355
363
  describe('pings aren\'t sent when the app is not focused; "standby behavior"', () => {
356
364
  test("it doesn't ping when the app loses focus and is never refocused", () => {
357
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
365
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
358
366
  wrapper
359
367
  });
360
- window.dispatchEvent(new Event('blur')); // This recursively executes all timers -- if it's not in standby,
361
- // it will enter a loop
368
+ window.dispatchEvent(new Event('blur'));
362
369
 
370
+ // This recursively executes all timers -- if it's not in standby,
371
+ // it will enter a loop
363
372
  jest.runAllTimers();
364
373
  expect(mockPing).not.toHaveBeenCalled();
365
374
  });
366
375
  test("it doesn't ping if the app is never focused (even upon startup)", () => {
367
376
  jest.spyOn(document, 'hasFocus').mockReturnValue(false);
368
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
377
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
369
378
  wrapper
370
- }); // This recursively executes all timers
379
+ });
371
380
 
381
+ // This recursively executes all timers
372
382
  jest.runAllTimers();
373
383
  expect(mockPing).not.toHaveBeenCalled();
374
384
  });
375
385
  test('if the app is defocused and refocused between two pings, pings happen normally', () => {
376
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
386
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
377
387
  wrapper
378
388
  });
379
- window.dispatchEvent(new Event('blur')); // wait half of the first interval
380
-
389
+ window.dispatchEvent(new Event('blur'));
390
+ // wait half of the first interval
381
391
  jest.advanceTimersByTime(FIRST_INTERVAL_MS / 2);
382
- window.dispatchEvent(new Event('focus')); // wait for just over the second half of the first interval
392
+ window.dispatchEvent(new Event('focus'));
383
393
 
384
- jest.advanceTimersByTime(FIRST_INTERVAL_MS / 2 + 50); // ping should execute normally
394
+ // wait for just over the second half of the first interval
395
+ jest.advanceTimersByTime(FIRST_INTERVAL_MS / 2 + 50);
385
396
 
397
+ // ping should execute normally
386
398
  expect(mockPing).toHaveBeenCalledTimes(1);
387
399
  });
388
400
  test('if the app is defocused until after a scheduled ping, that ping is not sent until the app is refocused', () => {
389
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
401
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
390
402
  wrapper
391
403
  });
392
- window.dispatchEvent(new Event('blur')); // wait for twice the first interval
404
+ window.dispatchEvent(new Event('blur'));
393
405
 
394
- jest.advanceTimersByTime(FIRST_INTERVAL_MS * 2); // no pings should be sent since it's in standby
406
+ // wait for twice the first interval
407
+ jest.advanceTimersByTime(FIRST_INTERVAL_MS * 2);
395
408
 
396
- expect(mockPing).not.toHaveBeenCalled(); // refocus the page
409
+ // no pings should be sent since it's in standby
410
+ expect(mockPing).not.toHaveBeenCalled();
397
411
 
398
- window.dispatchEvent(new Event('focus')); // ping should execute immediately
412
+ // refocus the page
413
+ window.dispatchEvent(new Event('focus'));
399
414
 
415
+ // ping should execute immediately
400
416
  expect(mockPing).toHaveBeenCalledTimes(1);
401
417
  });
402
418
  });
403
419
  describe('it pings when an offline event is detected', () => {
404
420
  test('if the app is focused, it pings immediately', () => {
405
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
421
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
406
422
  wrapper
407
423
  });
408
- window.dispatchEvent(new Event('offline')); // ping should execute immediately
424
+ window.dispatchEvent(new Event('offline'));
409
425
 
426
+ // ping should execute immediately
410
427
  expect(mockPing).toHaveBeenCalledTimes(1);
411
428
  });
412
429
  test('if the app is not focused, it does not ping immediately, but pings immediately when refocused', () => {
413
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
430
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
414
431
  wrapper
415
432
  });
416
433
  window.dispatchEvent(new Event('blur'));
417
- window.dispatchEvent(new Event('offline')); // ping should not execute, but should be queued for refocus
434
+ window.dispatchEvent(new Event('offline'));
418
435
 
419
- expect(mockPing).toHaveBeenCalledTimes(0); // upon refocus, the ping should execute immediately
420
- // despite a full interval not elapsing
436
+ // ping should not execute, but should be queued for refocus
437
+ expect(mockPing).toHaveBeenCalledTimes(0);
421
438
 
439
+ // upon refocus, the ping should execute immediately
440
+ // despite a full interval not elapsing
422
441
  window.dispatchEvent(new Event('focus'));
423
442
  expect(mockPing).toHaveBeenCalledTimes(1);
424
443
  });
425
444
  describe('interval handling when pinging upon refocusing after offline event is detected while not focused', () => {
426
445
  test('if the app is refocused before the next "scheduled" ping, the timeout to the next ping is not increased', () => {
427
446
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
428
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
447
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
429
448
  wrapper
430
449
  });
431
450
  window.dispatchEvent(new Event('blur'));
432
451
  window.dispatchEvent(new Event('offline'));
433
- window.dispatchEvent(new Event('focus')); // upon refocus, the ping should execute immediately
452
+ window.dispatchEvent(new Event('focus'));
453
+ // upon refocus, the ping should execute immediately
434
454
  // despite a full interval not elapsing
455
+ expect(mockPing).toHaveBeenCalledTimes(1);
435
456
 
436
- expect(mockPing).toHaveBeenCalledTimes(1); // The delay should be the initial again -- it shouldn't increment
437
-
457
+ // The delay should be the initial again -- it shouldn't increment
438
458
  assertLastDelay(setTimeoutSpy, FIRST_INTERVAL_MS);
439
459
  });
440
460
  test('same as previous, but interval is reset if status changes', async () => {
441
461
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
442
462
  const {
443
463
  result
444
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
464
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
445
465
  wrapper: wrapper
446
466
  });
447
- expect(result.current.isConnected).toBe(true); // Get to third interval
467
+ expect(result.current.isConnected).toBe(true);
448
468
 
469
+ // Get to third interval
449
470
  jest.runOnlyPendingTimers();
450
471
  jest.runOnlyPendingTimers();
451
472
  expect(mockPing).toHaveBeenCalledTimes(2);
452
- assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS); // Mock a network error
473
+ assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
453
474
 
475
+ // Mock a network error
454
476
  mockPing.mockImplementationOnce(() => Promise.reject({
455
477
  message: 'this is a network error',
456
478
  type: 'network'
457
- })); // Blur, trigger 'offline' event, and refocus to trigger a ping
479
+ }));
458
480
 
481
+ // Blur, trigger 'offline' event, and refocus to trigger a ping
459
482
  window.dispatchEvent(new Event('blur'));
460
483
  window.dispatchEvent(new Event('offline'));
461
- await (0, _reactHooks.act)(async () => {
484
+ await (0, _react.act)(async () => {
462
485
  window.dispatchEvent(new Event('focus'));
463
486
  });
464
487
  expect(result.current.isConnected).toBe(false);
@@ -467,46 +490,53 @@ describe('it pings when an offline event is detected', () => {
467
490
  });
468
491
  test('if the app is refocused after the next "scheduled" ping, increase the interval to the next ping if the status hasn\'t changed', () => {
469
492
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
470
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
493
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
471
494
  wrapper
472
495
  });
473
496
  window.dispatchEvent(new Event('blur'));
474
- window.dispatchEvent(new Event('offline')); // Elapse twice one interval - it should enter full standby
497
+ window.dispatchEvent(new Event('offline'));
475
498
 
499
+ // Elapse twice one interval - it should enter full standby
476
500
  jest.advanceTimersByTime(FIRST_INTERVAL_MS * 2);
477
- expect(mockPing).toHaveBeenCalledTimes(0); // Refocusing should trigger a ping from the full standby,
478
- // not just the offline event
501
+ expect(mockPing).toHaveBeenCalledTimes(0);
479
502
 
503
+ // Refocusing should trigger a ping from the full standby,
504
+ // not just the offline event
480
505
  window.dispatchEvent(new Event('focus'));
481
- expect(mockPing).toHaveBeenCalledTimes(1); // The delay should increment this time, as it would from normal standby
506
+ expect(mockPing).toHaveBeenCalledTimes(1);
482
507
 
508
+ // The delay should increment this time, as it would from normal standby
483
509
  assertLastDelay(setTimeoutSpy, SECOND_INTERVAL_MS);
484
510
  });
485
511
  test('the same as previous, but the interval is reset if status has changed', async () => {
486
512
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
487
513
  const {
488
514
  result
489
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
515
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
490
516
  wrapper: wrapper
491
517
  });
492
- expect(result.current.isConnected).toBe(true); // Get to third interval
518
+ expect(result.current.isConnected).toBe(true);
493
519
 
520
+ // Get to third interval
494
521
  jest.runOnlyPendingTimers();
495
522
  jest.runOnlyPendingTimers();
496
523
  expect(mockPing).toHaveBeenCalledTimes(2);
497
- assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS); // Blur and elapse twice the third interval --
498
- // it should enter full standby
524
+ assertLastDelay(setTimeoutSpy, THIRD_INTERVAL_MS);
499
525
 
526
+ // Blur and elapse twice the third interval --
527
+ // it should enter full standby
500
528
  window.dispatchEvent(new Event('blur'));
501
529
  window.dispatchEvent(new Event('offline'));
502
- jest.advanceTimersByTime(THIRD_INTERVAL_MS * 2); // Mock a network error for the next ping
530
+ jest.advanceTimersByTime(THIRD_INTERVAL_MS * 2);
503
531
 
532
+ // Mock a network error for the next ping
504
533
  mockPing.mockImplementationOnce(() => Promise.reject({
505
534
  message: 'this is a network error',
506
535
  type: 'network'
507
- })); // Trigger a ping by refocusing
536
+ }));
508
537
 
509
- await (0, _reactHooks.act)(async () => {
538
+ // Trigger a ping by refocusing
539
+ await (0, _react.act)(async () => {
510
540
  window.dispatchEvent(new Event('focus'));
511
541
  });
512
542
  expect(result.current.isConnected).toBe(false);
@@ -517,7 +547,7 @@ describe('it pings when an offline event is detected', () => {
517
547
  });
518
548
  describe('it pings when an online event is detected', () => {
519
549
  test('if the app is focused, it pings immediately', () => {
520
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
550
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
521
551
  wrapper
522
552
  });
523
553
  window.dispatchEvent(new Event('offline'));
@@ -526,63 +556,73 @@ describe('it pings when an online event is detected', () => {
526
556
  expect(mockPing).toHaveBeenCalledTimes(2);
527
557
  });
528
558
  test('pings are throttled', () => {
529
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
559
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
530
560
  wrapper
531
561
  });
532
562
  window.dispatchEvent(new Event('offline'));
533
563
  window.dispatchEvent(new Event('online'));
534
564
  window.dispatchEvent(new Event('offline'));
535
565
  expect(mockPing).toHaveBeenCalledTimes(3);
536
- window.dispatchEvent(new Event('online')); // Another ping should NOT be sent immediately after this latest
566
+ window.dispatchEvent(new Event('online'));
567
+ // Another ping should NOT be sent immediately after this latest
537
568
  // online event
538
-
539
- expect(mockPing).toHaveBeenCalledTimes(3); // (Not testing throttle time here because further pings may interfere)
569
+ expect(mockPing).toHaveBeenCalledTimes(3);
570
+ // (Not testing throttle time here because further pings may interfere)
540
571
  });
541
572
  });
542
573
  describe('lastConnected status', () => {
543
574
  test('it sets lastConnected in localStorage when it becomes disconnected', async () => {
544
575
  const {
545
576
  result
546
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
577
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
547
578
  wrapper: wrapper
548
579
  });
549
- expect(result.current.isConnected).toBe(true); // Mock a network error for the next ping
580
+ expect(result.current.isConnected).toBe(true);
550
581
 
551
- mockPing.mockImplementationOnce(failedPing); // Trigger a ping (to fail and switch to disconnected)
582
+ // Mock a network error for the next ping
583
+ mockPing.mockImplementationOnce(failedPing);
552
584
 
553
- await (0, _reactHooks.act)(async () => {
585
+ // Trigger a ping (to fail and switch to disconnected)
586
+ await (0, _react.act)(async () => {
554
587
  jest.runOnlyPendingTimers();
555
588
  });
556
- expect(mockPing).toHaveBeenCalledTimes(1); // Expect 'disconnected' status now
589
+ expect(mockPing).toHaveBeenCalledTimes(1);
557
590
 
591
+ // Expect 'disconnected' status now
558
592
  expect(result.current.isConnected).toBe(false);
559
- expect(result.current.isDisconnected).toBe(true); // Check localStorage for the dummy date
593
+ expect(result.current.isDisconnected).toBe(true);
560
594
 
595
+ // Check localStorage for the dummy date
561
596
  const localStorageDate = localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)());
562
- expect(localStorageDate).toBe(testCurrentDate.toUTCString()); // Check hook return value
597
+ expect(localStorageDate).toBe(testCurrentDate.toUTCString());
563
598
 
599
+ // Check hook return value
564
600
  expect(result.current.lastConnected).toBeInstanceOf(Date);
565
601
  expect(result.current.lastConnected).toEqual(testCurrentDate);
566
602
  });
567
603
  test('lastConnected becomes null when it becomes connected again', async () => {
568
604
  const {
569
605
  result
570
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
606
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
571
607
  wrapper: wrapper
572
608
  });
573
- expect(result.current.isConnected).toBe(true); // Mock a network error for the next ping
609
+ expect(result.current.isConnected).toBe(true);
574
610
 
575
- mockPing.mockImplementationOnce(failedPing); // Trigger an immediate ping (to fail and switch to disconnected)
611
+ // Mock a network error for the next ping
612
+ mockPing.mockImplementationOnce(failedPing);
576
613
 
577
- await (0, _reactHooks.act)(async () => {
614
+ // Trigger an immediate ping (to fail and switch to disconnected)
615
+ await (0, _react.act)(async () => {
578
616
  jest.runOnlyPendingTimers();
579
617
  });
580
- expect(mockPing).toHaveBeenCalledTimes(1); // Verify hook return value
618
+ expect(mockPing).toHaveBeenCalledTimes(1);
581
619
 
620
+ // Verify hook return value
582
621
  expect(result.current.isConnected).toBe(false);
583
- expect(result.current.lastConnected).toEqual(testCurrentDate); // Trigger a successful ping to go back online
622
+ expect(result.current.lastConnected).toEqual(testCurrentDate);
584
623
 
585
- await (0, _reactHooks.act)(async () => {
624
+ // Trigger a successful ping to go back online
625
+ await (0, _react.act)(async () => {
586
626
  jest.runOnlyPendingTimers();
587
627
  });
588
628
  expect(mockPing).toHaveBeenCalledTimes(2);
@@ -593,18 +633,21 @@ describe('lastConnected status', () => {
593
633
  const {
594
634
  result,
595
635
  unmount
596
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
636
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
597
637
  wrapper: wrapper
598
- }); // Mock a network error for the next ping to trigger 'disconnected'
638
+ });
599
639
 
640
+ // Mock a network error for the next ping to trigger 'disconnected'
600
641
  mockPing.mockImplementationOnce(failedPing);
601
- await (0, _reactHooks.act)(async () => {
642
+ await (0, _react.act)(async () => {
602
643
  jest.runOnlyPendingTimers();
603
644
  });
604
- expect(result.current.isConnected).toBe(false); // Unmount
645
+ expect(result.current.isConnected).toBe(false);
605
646
 
606
- unmount(); // Expect value to persist in localStorage
647
+ // Unmount
648
+ unmount();
607
649
 
650
+ // Expect value to persist in localStorage
608
651
  const localStorageDate = localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)());
609
652
  expect(localStorageDate).toBe(testCurrentDate.toUTCString());
610
653
  });
@@ -612,25 +655,29 @@ describe('lastConnected status', () => {
612
655
  const {
613
656
  result,
614
657
  unmount
615
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
658
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
616
659
  wrapper
617
660
  });
618
- expect(result.current.isConnected).toBe(true); // Mock a network error for the next ping to trigger disconnected
661
+ expect(result.current.isConnected).toBe(true);
619
662
 
663
+ // Mock a network error for the next ping to trigger disconnected
620
664
  mockPing.mockImplementationOnce(failedPing);
621
- await (0, _reactHooks.act)(async () => {
665
+ await (0, _react.act)(async () => {
622
666
  jest.runOnlyPendingTimers();
623
667
  });
624
- expect(result.current.isConnected).toBe(false); // Check localStorage for the dummy date
668
+ expect(result.current.isConnected).toBe(false);
625
669
 
670
+ // Check localStorage for the dummy date
626
671
  const localStorageDate = localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)());
627
- expect(localStorageDate).toBe(testCurrentDate.toUTCString()); // Trigger another ping to go back to connected
672
+ expect(localStorageDate).toBe(testCurrentDate.toUTCString());
628
673
 
629
- await (0, _reactHooks.act)(async () => {
674
+ // Trigger another ping to go back to connected
675
+ await (0, _react.act)(async () => {
630
676
  jest.runOnlyPendingTimers();
631
677
  });
632
- expect(result.current.isConnected).toBe(true); // Unmount and expect localStorage to be clear for next session
678
+ expect(result.current.isConnected).toBe(true);
633
679
 
680
+ // Unmount and expect localStorage to be clear for next session
634
681
  unmount();
635
682
  expect(localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)())).toBe(null);
636
683
  });
@@ -638,70 +685,73 @@ describe('lastConnected status', () => {
638
685
  test('it sets lastConnected to `now` if nothing is found in localStorage', async () => {
639
686
  // use a custom offlineInterface with `latestIsConnected: false`
640
687
  // to initialize the `isConnected` state to false
641
- const customMockOfflineInterface = { ..._testMocks.mockOfflineInterface,
688
+ const customMockOfflineInterface = {
689
+ ..._testMocks.mockOfflineInterface,
642
690
  latestIsConnected: false
643
691
  };
644
-
645
- const customWrapper = (_ref4) => {
692
+ const customWrapper = _ref4 => {
646
693
  let {
647
694
  children
648
695
  } = _ref4;
649
- return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
696
+ return /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
650
697
  offlineInterface: customMockOfflineInterface
651
698
  }, children);
652
- }; // render hook with custom wrapper
653
-
699
+ };
654
700
 
655
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
701
+ // render hook with custom wrapper
702
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
656
703
  wrapper: customWrapper
657
- }); // expect correct lastConnected time (mocked Date.now())
704
+ });
658
705
 
706
+ // expect correct lastConnected time (mocked Date.now())
659
707
  expect(localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)())).toBe(testCurrentDate.toUTCString());
660
708
  });
661
709
  test('if a value is already in localStorage, it uses that without overwriting', async () => {
662
710
  // seed localStorage with an imaginary 'lastConnected' value from last session
663
711
  const testPreviousDate = new Date('2023-01-01');
664
- localStorage.setItem((0, _dhis2ConnectionStatus.getLastConnectedKey)(), testPreviousDate.toUTCString()); // render hook with custom wrapper
712
+ localStorage.setItem((0, _dhis2ConnectionStatus.getLastConnectedKey)(), testPreviousDate.toUTCString());
665
713
 
666
- const customMockOfflineInterface = { ..._testMocks.mockOfflineInterface,
714
+ // render hook with custom wrapper
715
+ const customMockOfflineInterface = {
716
+ ..._testMocks.mockOfflineInterface,
667
717
  latestIsConnected: false
668
718
  };
669
-
670
- const customWrapper = (_ref5) => {
719
+ const customWrapper = _ref5 => {
671
720
  let {
672
721
  children
673
722
  } = _ref5;
674
- return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
723
+ return /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
675
724
  offlineInterface: customMockOfflineInterface
676
725
  }, children);
677
726
  };
678
-
679
727
  const {
680
728
  result
681
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
729
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
682
730
  wrapper: customWrapper
683
- }); // On render, the hook should retain last connected
731
+ });
684
732
 
733
+ // On render, the hook should retain last connected
685
734
  expect(result.current.lastConnected).not.toBe(null);
686
- expect(result.current.lastConnected).toEqual(testPreviousDate); // should be the same in localStorage too
687
-
735
+ expect(result.current.lastConnected).toEqual(testPreviousDate);
736
+ // should be the same in localStorage too
688
737
  expect(localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)())).toBe(testPreviousDate.toUTCString());
689
738
  });
690
739
  });
691
740
  test("it doesn't change lastConnected if already disconnected", async () => {
692
741
  // seed localStorage with an imaginary 'lastConnected' value from last session
693
742
  const testPreviousDate = new Date('2023-01-01');
694
- localStorage.setItem((0, _dhis2ConnectionStatus.getLastConnectedKey)(), testPreviousDate.toUTCString()); // render hook with custom wrapper
743
+ localStorage.setItem((0, _dhis2ConnectionStatus.getLastConnectedKey)(), testPreviousDate.toUTCString());
695
744
 
696
- const customMockOfflineInterface = { ..._testMocks.mockOfflineInterface,
745
+ // render hook with custom wrapper
746
+ const customMockOfflineInterface = {
747
+ ..._testMocks.mockOfflineInterface,
697
748
  latestIsConnected: false
698
749
  };
699
-
700
- const customWrapper = (_ref6) => {
750
+ const customWrapper = _ref6 => {
701
751
  let {
702
752
  children
703
753
  } = _ref6;
704
- return /*#__PURE__*/_react.default.createElement(_appServiceConfig.ConfigProvider, {
754
+ return /*#__PURE__*/_react2.default.createElement(_appServiceConfig.ConfigProvider, {
705
755
  config: {
706
756
  baseUrl: '..',
707
757
  apiVersion: 42,
@@ -712,39 +762,43 @@ describe('lastConnected status', () => {
712
762
  full: 'n/a'
713
763
  }
714
764
  }
715
- }, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
765
+ }, /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
716
766
  offlineInterface: customMockOfflineInterface
717
767
  }, children));
718
768
  };
719
-
720
769
  const {
721
770
  result
722
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
771
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
723
772
  wrapper: customWrapper
724
- }); // As in previous test, the hook should retain last connected
773
+ });
725
774
 
726
- expect(result.current.lastConnected).toEqual(testPreviousDate); // Mock a network error for the next ping and trigger
775
+ // As in previous test, the hook should retain last connected
776
+ expect(result.current.lastConnected).toEqual(testPreviousDate);
727
777
 
778
+ // Mock a network error for the next ping and trigger
728
779
  mockPing.mockImplementationOnce(failedPing);
729
- await (0, _reactHooks.act)(async () => {
780
+ await (0, _react.act)(async () => {
730
781
  jest.runOnlyPendingTimers();
731
782
  });
732
- expect(mockPing).toHaveBeenCalledTimes(1); // Expect the same lastConnected as before
783
+ expect(mockPing).toHaveBeenCalledTimes(1);
733
784
 
734
- expect(result.current.lastConnected).toEqual(testPreviousDate); // should be the same in localStorage too
785
+ // Expect the same lastConnected as before
786
+ expect(result.current.lastConnected).toEqual(testPreviousDate);
787
+ // should be the same in localStorage too
788
+ expect(localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)())).toBe(testPreviousDate.toUTCString());
735
789
 
736
- expect(localStorage.getItem((0, _dhis2ConnectionStatus.getLastConnectedKey)())).toBe(testPreviousDate.toUTCString()); // Verify the same with a signal from the service worker
790
+ // Verify the same with a signal from the service worker
737
791
  // get onUpdate function passed to mockOfflineInterface
738
-
739
792
  const {
740
793
  onUpdate
741
794
  } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0];
742
- await (0, _reactHooks.act)(async () => {
795
+ await (0, _react.act)(async () => {
743
796
  onUpdate({
744
797
  isConnected: false
745
798
  });
746
- }); // Expect the same lastConnected as before
799
+ });
747
800
 
801
+ // Expect the same lastConnected as before
748
802
  expect(result.current.lastConnected).toEqual(testPreviousDate);
749
803
  });
750
804
  test('lastConnected is saved specifically to an app if a name is provided', async () => {
@@ -752,17 +806,18 @@ describe('lastConnected status', () => {
752
806
  const testAppName = 'test-app-name';
753
807
  const lastConnectedKey = (0, _dhis2ConnectionStatus.getLastConnectedKey)(testAppName);
754
808
  const testPreviousDate = new Date('2023-01-01');
755
- localStorage.setItem(lastConnectedKey, testPreviousDate.toUTCString()); // render hook with custom wrapper to start disconnected with app name
809
+ localStorage.setItem(lastConnectedKey, testPreviousDate.toUTCString());
756
810
 
757
- const customMockOfflineInterface = { ..._testMocks.mockOfflineInterface,
811
+ // render hook with custom wrapper to start disconnected with app name
812
+ const customMockOfflineInterface = {
813
+ ..._testMocks.mockOfflineInterface,
758
814
  latestIsConnected: false
759
815
  };
760
-
761
- const customWrapper = (_ref7) => {
816
+ const customWrapper = _ref7 => {
762
817
  let {
763
818
  children
764
819
  } = _ref7;
765
- return /*#__PURE__*/_react.default.createElement(_appServiceConfig.ConfigProvider, {
820
+ return /*#__PURE__*/_react2.default.createElement(_appServiceConfig.ConfigProvider, {
766
821
  config: {
767
822
  baseUrl: '..',
768
823
  apiVersion: 42,
@@ -774,42 +829,44 @@ describe('lastConnected status', () => {
774
829
  full: 'n/a'
775
830
  }
776
831
  }
777
- }, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
832
+ }, /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
778
833
  offlineInterface: customMockOfflineInterface
779
834
  }, children));
780
835
  };
781
-
782
836
  const {
783
837
  result
784
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
838
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
785
839
  wrapper: customWrapper
786
- }); // Expect previous value to be read correctly
840
+ });
787
841
 
788
- expect(result.current.lastConnected).toEqual(testPreviousDate); // Go to connected then disconnected again to generate a new date
842
+ // Expect previous value to be read correctly
843
+ expect(result.current.lastConnected).toEqual(testPreviousDate);
789
844
 
790
- await (0, _reactHooks.act)(async () => {
845
+ // Go to connected then disconnected again to generate a new date
846
+ await (0, _react.act)(async () => {
791
847
  jest.runOnlyPendingTimers();
792
848
  });
793
849
  expect(result.current.isConnected).toBe(true);
794
850
  expect(result.current.lastConnected).toBe(null);
795
851
  expect(localStorage.getItem(lastConnectedKey)).toBe(null);
796
852
  mockPing.mockImplementationOnce(failedPing);
797
- await (0, _reactHooks.act)(async () => {
853
+ await (0, _react.act)(async () => {
798
854
  jest.runOnlyPendingTimers();
799
855
  });
800
- expect(result.current.isConnected).toBe(false); // Note the new date:
801
-
802
- expect(result.current.lastConnected).toEqual(testCurrentDate); // Verify localStorage
856
+ expect(result.current.isConnected).toBe(false);
857
+ // Note the new date:
858
+ expect(result.current.lastConnected).toEqual(testCurrentDate);
803
859
 
860
+ // Verify localStorage
804
861
  expect(localStorage.getItem(lastConnectedKey)).toBe(testCurrentDate.toUTCString());
805
862
  });
806
863
  });
807
864
  describe("when the /api/ping endpoint isn't supported", () => {
808
- const customWrapper = (_ref8) => {
865
+ const customWrapper = _ref8 => {
809
866
  let {
810
867
  children
811
868
  } = _ref8;
812
- return /*#__PURE__*/_react.default.createElement(_appServiceConfig.ConfigProvider, {
869
+ return /*#__PURE__*/_react2.default.createElement(_appServiceConfig.ConfigProvider, {
813
870
  config: {
814
871
  baseUrl: '..',
815
872
  apiVersion: 42,
@@ -821,17 +878,16 @@ describe("when the /api/ping endpoint isn't supported", () => {
821
878
  full: 'n/a'
822
879
  }
823
880
  }
824
- }, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, {
881
+ }, /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
825
882
  offlineInterface: _testMocks.mockOfflineInterface
826
883
  }, children));
827
884
  };
828
-
829
885
  test("pings aren't sent", async () => {
830
886
  const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
831
- (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
887
+ (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
832
888
  wrapper: customWrapper
833
889
  });
834
- await (0, _reactHooks.act)(async () => {
890
+ await (0, _react.act)(async () => {
835
891
  jest.runAllTimers();
836
892
  });
837
893
  expect(mockPing).not.toHaveBeenCalled();
@@ -840,22 +896,23 @@ describe("when the /api/ping endpoint isn't supported", () => {
840
896
  test('service worker updates still work', async () => {
841
897
  const {
842
898
  result
843
- } = (0, _reactHooks.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
899
+ } = (0, _react.renderHook)(() => (0, _dhis2ConnectionStatus.useDhis2ConnectionStatus)(), {
844
900
  wrapper: wrapper
845
- }); // get onUpdate function passed to mockOfflineInterface
846
-
901
+ });
902
+ // get onUpdate function passed to mockOfflineInterface
847
903
  const {
848
904
  onUpdate
849
905
  } = _testMocks.mockOfflineInterface.subscribeToDhis2ConnectionStatus.mock.calls[0][0];
850
- expect(result.current.isConnected).toBe(true); // Trigger connection status change from offline interface
906
+ expect(result.current.isConnected).toBe(true);
851
907
 
852
- await (0, _reactHooks.act)(async () => {
908
+ // Trigger connection status change from offline interface
909
+ await (0, _react.act)(async () => {
853
910
  onUpdate({
854
911
  isConnected: false
855
912
  });
856
913
  });
857
914
  expect(result.current.isConnected).toBe(false);
858
- await (0, _reactHooks.act)(async () => {
915
+ await (0, _react.act)(async () => {
859
916
  onUpdate({
860
917
  isConnected: true
861
918
  });