@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,28 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _appServiceAlerts = require("@dhis2/app-service-alerts");
|
|
4
|
-
|
|
5
4
|
var _react = require("@testing-library/react");
|
|
6
|
-
|
|
7
5
|
var _react2 = _interopRequireDefault(require("react"));
|
|
8
|
-
|
|
9
6
|
var _cacheableSection = require("../lib/cacheable-section");
|
|
10
|
-
|
|
11
7
|
var _offlineProvider = require("../lib/offline-provider");
|
|
12
|
-
|
|
13
8
|
var _renderCounter = require("../utils/render-counter");
|
|
14
|
-
|
|
15
9
|
var _testMocks = require("../utils/test-mocks");
|
|
16
|
-
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
20
|
-
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
21
12
|
const renderCounts = {};
|
|
22
|
-
|
|
23
13
|
const identity = arg => arg;
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
const TestControls = _ref => {
|
|
15
|
+
var _lastUpdated$toISOStr;
|
|
26
16
|
let {
|
|
27
17
|
id,
|
|
28
18
|
makeRecordingHandler = identity
|
|
@@ -49,12 +39,11 @@ const TestControls = (_ref) => {
|
|
|
49
39
|
"data-testid": `is-cached-${id}`
|
|
50
40
|
}, isCached ? 'yes' : 'no'), /*#__PURE__*/_react2.default.createElement("div", {
|
|
51
41
|
"data-testid": `last-updated-${id}`
|
|
52
|
-
}, lastUpdated || 'never'), /*#__PURE__*/_react2.default.createElement("div", {
|
|
42
|
+
}, (_lastUpdated$toISOStr = lastUpdated === null || lastUpdated === void 0 ? void 0 : lastUpdated.toISOString()) !== null && _lastUpdated$toISOStr !== void 0 ? _lastUpdated$toISOStr : 'never'), /*#__PURE__*/_react2.default.createElement("div", {
|
|
53
43
|
"data-testid": `recording-state-${id}`
|
|
54
44
|
}, recordingState));
|
|
55
45
|
};
|
|
56
|
-
|
|
57
|
-
const TestSection = (_ref2) => {
|
|
46
|
+
const TestSection = _ref2 => {
|
|
58
47
|
let {
|
|
59
48
|
id,
|
|
60
49
|
children
|
|
@@ -69,7 +58,6 @@ const TestSection = (_ref2) => {
|
|
|
69
58
|
countsObj: renderCounts
|
|
70
59
|
}), children);
|
|
71
60
|
};
|
|
72
|
-
|
|
73
61
|
const TestSingleSection = props => {
|
|
74
62
|
// Props are spread so they can be overwritten
|
|
75
63
|
return /*#__PURE__*/_react2.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, _extends({
|
|
@@ -79,36 +67,34 @@ const TestSingleSection = props => {
|
|
|
79
67
|
}, props)), /*#__PURE__*/_react2.default.createElement(TestSection, _extends({
|
|
80
68
|
id: '1'
|
|
81
69
|
}, props))));
|
|
82
|
-
};
|
|
83
|
-
|
|
70
|
+
};
|
|
84
71
|
|
|
72
|
+
// Suppress 'act' warning for these tests
|
|
85
73
|
const originalError = console.error;
|
|
86
74
|
beforeEach(() => {
|
|
87
75
|
// This is done before each because the 'recording error' test uses its own
|
|
88
76
|
// spy on console.error
|
|
89
77
|
jest.spyOn(console, 'error').mockImplementation(function () {
|
|
90
78
|
const pattern = /Warning: An update to .* inside a test was not wrapped in act/;
|
|
91
|
-
|
|
92
79
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
93
80
|
args[_key] = arguments[_key];
|
|
94
81
|
}
|
|
95
|
-
|
|
96
82
|
if (typeof args[0] === 'string' && pattern.test(args[0])) {
|
|
97
83
|
return;
|
|
98
84
|
}
|
|
99
|
-
|
|
100
85
|
return originalError.call(console, ...args);
|
|
101
86
|
});
|
|
102
87
|
});
|
|
103
88
|
afterEach(() => {
|
|
104
|
-
jest.clearAllMocks()
|
|
89
|
+
jest.clearAllMocks()
|
|
90
|
+
// This syntax appeases typescript:
|
|
105
91
|
;
|
|
106
92
|
console.error.mockRestore();
|
|
107
93
|
(0, _renderCounter.resetRenderCounts)(renderCounts);
|
|
108
94
|
});
|
|
109
95
|
describe('Coordination between useCacheableSection and CacheableSection', () => {
|
|
110
96
|
it('renders in the default state initially', async () => {
|
|
111
|
-
(0, _react.render)(
|
|
97
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(TestSingleSection, null));
|
|
112
98
|
const {
|
|
113
99
|
getByTestId
|
|
114
100
|
} = _react.screen;
|
|
@@ -123,35 +109,31 @@ describe('Coordination between useCacheableSection and CacheableSection', () =>
|
|
|
123
109
|
getByTestId,
|
|
124
110
|
queryByTestId
|
|
125
111
|
} = _react.screen;
|
|
126
|
-
|
|
127
112
|
const onStarted = () => {
|
|
128
113
|
expect(getByTestId(/recording-state/)).toHaveTextContent('recording');
|
|
129
114
|
expect(getByTestId(/loading-mask/)).toBeInTheDocument();
|
|
130
115
|
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
131
116
|
};
|
|
132
|
-
|
|
133
117
|
const onCompleted = () => {
|
|
134
118
|
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
135
119
|
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
|
|
136
120
|
done();
|
|
137
121
|
};
|
|
138
|
-
|
|
139
122
|
const recordingOptions = {
|
|
140
123
|
onStarted,
|
|
141
124
|
onCompleted
|
|
142
125
|
};
|
|
143
|
-
|
|
144
126
|
const makeRecordingHandler = startRecording => {
|
|
145
127
|
return () => startRecording(recordingOptions);
|
|
146
128
|
};
|
|
147
|
-
|
|
148
|
-
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(TestSingleSection, {
|
|
129
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(TestSingleSection, {
|
|
149
130
|
makeRecordingHandler: makeRecordingHandler
|
|
150
131
|
}));
|
|
151
132
|
await (0, _react.act)(async () => {
|
|
152
133
|
_react.fireEvent.click(getByTestId(/start-recording/));
|
|
153
|
-
});
|
|
134
|
+
});
|
|
154
135
|
|
|
136
|
+
// At this stage, should be pending
|
|
155
137
|
expect(getByTestId(/recording-state/)).toHaveTextContent('pending');
|
|
156
138
|
expect(queryByTestId(/section-rc/)).not.toBeInTheDocument();
|
|
157
139
|
expect.assertions(7);
|
|
@@ -161,41 +143,35 @@ describe('Coordination between useCacheableSection and CacheableSection', () =>
|
|
|
161
143
|
jest.spyOn(console, 'error').mockImplementation(function () {
|
|
162
144
|
const actPattern = /Warning: An update to .* inside a test was not wrapped in act/;
|
|
163
145
|
const errPattern = /Error during recording/;
|
|
164
|
-
|
|
165
146
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
166
147
|
args[_key2] = arguments[_key2];
|
|
167
148
|
}
|
|
168
|
-
|
|
169
149
|
const matchesPattern = actPattern.test(args[0]) || errPattern.test(args[0]);
|
|
170
|
-
|
|
171
150
|
if (typeof args[0] === 'string' && matchesPattern) {
|
|
172
151
|
return;
|
|
173
152
|
}
|
|
174
|
-
|
|
175
153
|
return originalError.call(console, ...args);
|
|
176
154
|
});
|
|
177
155
|
const {
|
|
178
156
|
getByTestId,
|
|
179
157
|
queryByTestId
|
|
180
158
|
} = _react.screen;
|
|
181
|
-
const testOfflineInterface = {
|
|
159
|
+
const testOfflineInterface = {
|
|
160
|
+
..._testMocks.mockOfflineInterface,
|
|
182
161
|
startRecording: _testMocks.errorRecordingMock
|
|
183
162
|
};
|
|
184
|
-
|
|
185
163
|
const onError = () => {
|
|
186
164
|
expect(getByTestId(/recording-state/)).toHaveTextContent('error');
|
|
187
165
|
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
|
|
188
166
|
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
189
167
|
done();
|
|
190
168
|
};
|
|
191
|
-
|
|
192
169
|
const makeRecordingHandler = startRecording => {
|
|
193
170
|
return () => startRecording({
|
|
194
171
|
onError
|
|
195
172
|
});
|
|
196
173
|
};
|
|
197
|
-
|
|
198
|
-
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(TestSingleSection, {
|
|
174
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(TestSingleSection, {
|
|
199
175
|
offlineInterface: testOfflineInterface,
|
|
200
176
|
makeRecordingHandler: makeRecordingHandler
|
|
201
177
|
}));
|
|
@@ -203,33 +179,31 @@ describe('Coordination between useCacheableSection and CacheableSection', () =>
|
|
|
203
179
|
_react.fireEvent.click(getByTestId(/start-recording/));
|
|
204
180
|
});
|
|
205
181
|
expect.assertions(3);
|
|
206
|
-
});
|
|
207
|
-
// ! causes the following ones to mysteriously fail 😤
|
|
182
|
+
});
|
|
208
183
|
|
|
184
|
+
// ! After bumping testing-library versions, something about this test
|
|
185
|
+
// ! causes the following ones to mysteriously fail 😤
|
|
209
186
|
it.skip('handles an error starting the recording', async done => {
|
|
210
187
|
const {
|
|
211
188
|
getByTestId
|
|
212
189
|
} = _react.screen;
|
|
213
|
-
const testOfflineInterface = {
|
|
190
|
+
const testOfflineInterface = {
|
|
191
|
+
..._testMocks.mockOfflineInterface,
|
|
214
192
|
startRecording: _testMocks.failedMessageRecordingMock
|
|
215
193
|
};
|
|
216
194
|
const onStarted = jest.fn();
|
|
217
|
-
|
|
218
195
|
const testErrCondition = err => {
|
|
219
196
|
expect(err.message).toBe('Failed message'); // from the mock
|
|
220
|
-
|
|
221
197
|
expect(onStarted).not.toHaveBeenCalled();
|
|
222
198
|
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
223
199
|
done();
|
|
224
200
|
};
|
|
225
|
-
|
|
226
201
|
const makeRecordingHandler = startRecording => {
|
|
227
202
|
return () => startRecording({
|
|
228
203
|
onStarted
|
|
229
204
|
}).catch(testErrCondition);
|
|
230
205
|
};
|
|
231
|
-
|
|
232
|
-
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(TestSingleSection, {
|
|
206
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(TestSingleSection, {
|
|
233
207
|
offlineInterface: testOfflineInterface,
|
|
234
208
|
makeRecordingHandler: makeRecordingHandler
|
|
235
209
|
}));
|
|
@@ -238,7 +212,6 @@ describe('Coordination between useCacheableSection and CacheableSection', () =>
|
|
|
238
212
|
});
|
|
239
213
|
});
|
|
240
214
|
});
|
|
241
|
-
|
|
242
215
|
const TwoTestSections = props =>
|
|
243
216
|
/*#__PURE__*/
|
|
244
217
|
// Props are spread so they can be overwritten (but only on one section)
|
|
@@ -252,44 +225,42 @@ _react2.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE_
|
|
|
252
225
|
id: '2'
|
|
253
226
|
}), /*#__PURE__*/_react2.default.createElement(TestSection, {
|
|
254
227
|
id: '2'
|
|
255
|
-
})));
|
|
256
|
-
|
|
228
|
+
})));
|
|
257
229
|
|
|
230
|
+
// test that other sections don't rerender when one section does
|
|
258
231
|
describe('Performant state management', () => {
|
|
259
232
|
it('establishes a pre-recording render count', () => {
|
|
260
|
-
(0, _react.render)(
|
|
233
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(TwoTestSections, null));
|
|
261
234
|
const {
|
|
262
235
|
getByTestId
|
|
263
|
-
} = _react.screen;
|
|
264
|
-
|
|
236
|
+
} = _react.screen;
|
|
237
|
+
// Two renders for controls: undefined and 'default' states
|
|
265
238
|
expect(getByTestId('controls-rc-1')).toHaveTextContent('2');
|
|
266
|
-
expect(getByTestId('controls-rc-2')).toHaveTextContent('2');
|
|
267
|
-
|
|
239
|
+
expect(getByTestId('controls-rc-2')).toHaveTextContent('2');
|
|
240
|
+
// Just one render for sections
|
|
268
241
|
expect(getByTestId('section-rc-1')).toHaveTextContent('1');
|
|
269
242
|
expect(getByTestId('section-rc-2')).toHaveTextContent('1');
|
|
270
243
|
});
|
|
271
244
|
it('isolates rerenders from other consumers', async done => {
|
|
272
245
|
const {
|
|
273
246
|
getByTestId
|
|
274
|
-
} = _react.screen;
|
|
275
|
-
|
|
247
|
+
} = _react.screen;
|
|
248
|
+
// Make assertions
|
|
276
249
|
const onCompleted = () => {
|
|
277
250
|
// Before refactor: controls components have 6 renders EACH, and
|
|
278
251
|
// sections 1 and 2 have 2 and 1 renders, respectively
|
|
279
252
|
// After refactor, render counts for section that recorded:
|
|
280
253
|
expect(getByTestId('controls-rc-1')).toHaveTextContent('5');
|
|
281
|
-
expect(getByTestId('section-rc-1')).toHaveTextContent('2');
|
|
282
|
-
|
|
254
|
+
expect(getByTestId('section-rc-1')).toHaveTextContent('2');
|
|
255
|
+
// Section that did not record (should be same as pre-recording):
|
|
283
256
|
expect(getByTestId('controls-rc-2')).toHaveTextContent('2');
|
|
284
257
|
expect(getByTestId('section-rc-2')).toHaveTextContent('1');
|
|
285
258
|
done();
|
|
286
259
|
};
|
|
287
|
-
|
|
288
260
|
const makeRecordingHandler = startRecording => () => startRecording({
|
|
289
261
|
onCompleted
|
|
290
262
|
});
|
|
291
|
-
|
|
292
|
-
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(TwoTestSections, {
|
|
263
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(TwoTestSections, {
|
|
293
264
|
makeRecordingHandler: makeRecordingHandler
|
|
294
265
|
}));
|
|
295
266
|
await (0, _react.act)(async () => {
|
|
@@ -309,44 +280,42 @@ describe('useCacheableSection can be used inside a child of CacheableSection', (
|
|
|
309
280
|
id: '1'
|
|
310
281
|
}, props)))));
|
|
311
282
|
};
|
|
312
|
-
|
|
313
283
|
it('handles a successful recording', async done => {
|
|
314
284
|
const {
|
|
315
285
|
getByTestId,
|
|
316
286
|
queryByTestId
|
|
317
287
|
} = _react.screen;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
288
|
+
const onStarted = async () => {
|
|
289
|
+
await (0, _react.waitFor)(() => {
|
|
290
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('recording');
|
|
291
|
+
expect(getByTestId(/loading-mask/)).toBeInTheDocument();
|
|
292
|
+
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
293
|
+
});
|
|
323
294
|
};
|
|
324
|
-
|
|
325
295
|
const onCompleted = () => {
|
|
326
296
|
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
327
297
|
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
|
|
328
298
|
done();
|
|
329
299
|
};
|
|
330
|
-
|
|
331
300
|
const recordingOptions = {
|
|
332
301
|
onStarted,
|
|
333
302
|
onCompleted
|
|
334
303
|
};
|
|
335
|
-
|
|
336
304
|
const makeRecordingHandler = startRecording => {
|
|
337
305
|
return () => startRecording(recordingOptions);
|
|
338
306
|
};
|
|
339
|
-
|
|
340
|
-
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(ChildTest, {
|
|
307
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(ChildTest, {
|
|
341
308
|
makeRecordingHandler: makeRecordingHandler
|
|
342
309
|
}));
|
|
343
310
|
await (0, _react.act)(async () => {
|
|
344
|
-
_react.fireEvent.click(getByTestId(/start-recording/));
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
311
|
+
await _react.fireEvent.click(getByTestId(/start-recording/));
|
|
312
|
+
});
|
|
313
|
+
await (0, _react.waitFor)(() => {
|
|
314
|
+
// At this stage, should be pending
|
|
315
|
+
// - In this test case, 'controls' should not be rendered
|
|
316
|
+
expect(queryByTestId(/recording-state/)).not.toBeInTheDocument();
|
|
317
|
+
expect(queryByTestId(/section-rc/)).not.toBeInTheDocument();
|
|
318
|
+
expect.assertions(7);
|
|
319
|
+
});
|
|
351
320
|
});
|
|
352
321
|
});
|
package/build/cjs/index.js
CHANGED
|
@@ -63,17 +63,10 @@ Object.defineProperty(exports, "useSetOnlineStatusMessage", {
|
|
|
63
63
|
return _onlineStatusMessage.useSetOnlineStatusMessage;
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
-
|
|
67
66
|
var _offlineProvider = require("./lib/offline-provider");
|
|
68
|
-
|
|
69
67
|
var _cacheableSection = require("./lib/cacheable-section");
|
|
70
|
-
|
|
71
68
|
var _cacheableSectionState = require("./lib/cacheable-section-state");
|
|
72
|
-
|
|
73
69
|
var _networkStatus = require("./lib/network-status");
|
|
74
|
-
|
|
75
70
|
var _onlineStatusMessage = require("./lib/online-status-message");
|
|
76
|
-
|
|
77
71
|
var _clearSensitiveCaches = require("./lib/clear-sensitive-caches");
|
|
78
|
-
|
|
79
72
|
var _dhis2ConnectionStatus = require("./lib/dhis2-connection-status");
|
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
var _react = _interopRequireDefault(require("react"));
|
|
6
|
-
|
|
3
|
+
var _react = require("@testing-library/react");
|
|
4
|
+
var _react2 = _interopRequireDefault(require("react"));
|
|
7
5
|
var _testMocks = require("../../utils/test-mocks");
|
|
8
|
-
|
|
9
6
|
var _cacheableSectionState = require("../cacheable-section-state");
|
|
10
|
-
|
|
11
7
|
var _offlineProvider = require("../offline-provider");
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const wrapper = (_ref) => {
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
const wrapper = _ref => {
|
|
16
10
|
let {
|
|
17
11
|
children
|
|
18
12
|
} = _ref;
|
|
19
|
-
return /*#__PURE__*/
|
|
13
|
+
return /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, {
|
|
20
14
|
offlineInterface: _testMocks.mockOfflineInterface
|
|
21
15
|
}, children);
|
|
22
16
|
};
|
|
23
|
-
|
|
24
17
|
test('useRecordingState has stable references', () => {
|
|
25
18
|
const {
|
|
26
19
|
result,
|
|
27
20
|
rerender
|
|
28
|
-
} = (0,
|
|
21
|
+
} = (0, _react.renderHook)(() => (0, _cacheableSectionState.useRecordingState)('one'), {
|
|
29
22
|
wrapper
|
|
30
23
|
});
|
|
31
24
|
const origRecordingState = result.current.recordingState;
|
|
@@ -40,7 +33,7 @@ test('useCachedSection has stable references', () => {
|
|
|
40
33
|
const {
|
|
41
34
|
result,
|
|
42
35
|
rerender
|
|
43
|
-
} = (0,
|
|
36
|
+
} = (0, _react.renderHook)(() => (0, _cacheableSectionState.useCachedSection)('one'), {
|
|
44
37
|
wrapper
|
|
45
38
|
});
|
|
46
39
|
const origIsCached = result.current.isCached;
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _FDBFactory = _interopRequireDefault(require("fake-indexeddb/lib/FDBFactory"));
|
|
4
|
-
|
|
5
4
|
var _idb = require("idb");
|
|
6
|
-
|
|
7
5
|
require("fake-indexeddb/auto");
|
|
8
|
-
|
|
9
6
|
var _clearSensitiveCaches = require("../clear-sensitive-caches");
|
|
10
|
-
|
|
11
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
-
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
8
|
// Mocks for CacheStorage API
|
|
9
|
+
|
|
14
10
|
// Returns true if an existing cache is deleted
|
|
15
11
|
const makeCachesDeleteMock = keys => {
|
|
16
12
|
return jest.fn().mockImplementation(key => Promise.resolve(keys.includes(key)));
|
|
17
13
|
};
|
|
18
|
-
|
|
19
14
|
const keysMockDefault = jest.fn().mockImplementation(async () => []);
|
|
20
15
|
const deleteMockDefault = makeCachesDeleteMock([]);
|
|
21
16
|
const cachesDefault = {
|
|
@@ -30,21 +25,19 @@ window.caches = cachesDefault;
|
|
|
30
25
|
afterEach(() => {
|
|
31
26
|
window.caches = cachesDefault;
|
|
32
27
|
jest.clearAllMocks();
|
|
33
|
-
});
|
|
28
|
+
});
|
|
34
29
|
|
|
30
|
+
// silence debug logs for these tests
|
|
35
31
|
const originalDebug = console.debug;
|
|
36
32
|
beforeAll(() => {
|
|
37
33
|
jest.spyOn(console, 'debug').mockImplementation(function () {
|
|
38
34
|
const pattern = /Clearing sensitive caches/;
|
|
39
|
-
|
|
40
35
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
41
36
|
args[_key] = arguments[_key];
|
|
42
37
|
}
|
|
43
|
-
|
|
44
38
|
if (typeof args[0] === 'string' && pattern.test(args[0])) {
|
|
45
39
|
return;
|
|
46
40
|
}
|
|
47
|
-
|
|
48
41
|
return originalDebug.call(console, ...args);
|
|
49
42
|
});
|
|
50
43
|
});
|
|
@@ -59,7 +52,8 @@ it('returns false if caches.keys throws', async () => {
|
|
|
59
52
|
const spy = jest.fn(() => {
|
|
60
53
|
throw new Error('Security Error');
|
|
61
54
|
});
|
|
62
|
-
window.caches = {
|
|
55
|
+
window.caches = {
|
|
56
|
+
...cachesDefault,
|
|
63
57
|
keys: spy
|
|
64
58
|
};
|
|
65
59
|
const result = await (0, _clearSensitiveCaches.clearSensitiveCaches)();
|
|
@@ -70,7 +64,8 @@ it('clears potentially sensitive caches', async () => {
|
|
|
70
64
|
const testKeys = ['cache1', 'cache2', 'app-shell', 'other-assets'];
|
|
71
65
|
const keysMock = jest.fn().mockImplementation(() => Promise.resolve(testKeys));
|
|
72
66
|
const deleteMock = makeCachesDeleteMock(testKeys);
|
|
73
|
-
window.caches = {
|
|
67
|
+
window.caches = {
|
|
68
|
+
...cachesDefault,
|
|
74
69
|
keys: keysMock,
|
|
75
70
|
delete: deleteMock
|
|
76
71
|
};
|
|
@@ -84,7 +79,8 @@ it('clears potentially sensitive caches', async () => {
|
|
|
84
79
|
});
|
|
85
80
|
it('preserves keepable caches', async () => {
|
|
86
81
|
const keysMock = jest.fn().mockImplementation(async () => ['cache1', 'cache2', 'app-shell', 'other-assets', 'workbox-precache-v2-https://hey.howareya.now/']);
|
|
87
|
-
window.caches = {
|
|
82
|
+
window.caches = {
|
|
83
|
+
...cachesDefault,
|
|
88
84
|
keys: keysMock
|
|
89
85
|
};
|
|
90
86
|
await (0, _clearSensitiveCaches.clearSensitiveCaches)();
|
|
@@ -105,10 +101,8 @@ describe('clears sections-db', () => {
|
|
|
105
101
|
keyPath: 'sectionId'
|
|
106
102
|
});
|
|
107
103
|
}
|
|
108
|
-
|
|
109
104
|
});
|
|
110
105
|
}
|
|
111
|
-
|
|
112
106
|
afterEach(() => {
|
|
113
107
|
// reset indexedDB state
|
|
114
108
|
window.indexedDB = new _FDBFactory.default();
|
|
@@ -126,8 +120,9 @@ describe('clears sections-db', () => {
|
|
|
126
120
|
lastUpdated: new Date(),
|
|
127
121
|
requests: 3
|
|
128
122
|
});
|
|
129
|
-
await (0, _clearSensitiveCaches.clearSensitiveCaches)();
|
|
123
|
+
await (0, _clearSensitiveCaches.clearSensitiveCaches)();
|
|
130
124
|
|
|
125
|
+
// Sections-db should be cleared
|
|
131
126
|
const allSections = await db.getAll(_clearSensitiveCaches.SECTIONS_STORE);
|
|
132
127
|
expect(allSections).toHaveLength(0);
|
|
133
128
|
});
|
|
@@ -144,16 +139,18 @@ describe('clears sections-db', () => {
|
|
|
144
139
|
// if 'databases' property exists
|
|
145
140
|
await openTestDB(_clearSensitiveCaches.SECTIONS_DB);
|
|
146
141
|
const openMock = jest.fn();
|
|
147
|
-
window.indexedDB.open = openMock;
|
|
148
|
-
// (simulates Firefox environment)
|
|
142
|
+
window.indexedDB.open = openMock;
|
|
149
143
|
|
|
144
|
+
// Remove 'databases' from indexedDB prototype for this test
|
|
145
|
+
// (simulates Firefox environment)
|
|
150
146
|
const idbProto = Object.getPrototypeOf(window.indexedDB);
|
|
151
147
|
const databases = idbProto.databases;
|
|
152
148
|
delete idbProto.databases;
|
|
153
149
|
expect('databases' in window.indexedDB).toBe(false);
|
|
154
150
|
await expect((0, _clearSensitiveCaches.clearSensitiveCaches)()).resolves.toBeDefined();
|
|
155
|
-
expect(openMock).not.toHaveBeenCalled();
|
|
151
|
+
expect(openMock).not.toHaveBeenCalled();
|
|
156
152
|
|
|
153
|
+
// Restore indexedDB prototype for later tests
|
|
157
154
|
idbProto.databases = databases;
|
|
158
155
|
expect('databases' in window.indexedDB).toBe(true);
|
|
159
156
|
});
|