@dhis2/app-service-offline 2.10.0 → 2.12.0
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 +337 -0
- package/build/cjs/index.js +39 -1
- package/build/cjs/lib/__tests__/clear-sensitive-caches.test.js +131 -0
- package/build/cjs/lib/__tests__/offline-provider.test.js +127 -0
- package/build/cjs/lib/__tests__/use-cacheable-section.test.js +227 -0
- package/build/cjs/lib/cacheable-section-state.js +218 -0
- package/build/cjs/lib/cacheable-section.js +156 -0
- package/build/cjs/lib/clear-sensitive-caches.js +87 -0
- package/build/cjs/lib/global-state-service.js +95 -0
- package/build/cjs/lib/offline-interface.js +86 -0
- package/build/cjs/lib/offline-provider.js +53 -0
- package/build/cjs/types.js +0 -1
- package/build/cjs/utils/__tests__/render-counter.test.js +55 -0
- package/build/cjs/utils/render-counter.js +26 -0
- package/build/cjs/utils/test-mocks.js +40 -0
- package/build/es/__tests__/integration.test.js +327 -0
- package/build/es/index.js +5 -1
- package/build/es/lib/__tests__/clear-sensitive-caches.test.js +123 -0
- package/build/es/lib/__tests__/offline-provider.test.js +117 -0
- package/build/es/lib/__tests__/use-cacheable-section.test.js +218 -0
- package/build/es/lib/cacheable-section-state.js +199 -0
- package/build/es/lib/cacheable-section.js +137 -0
- package/build/es/lib/clear-sensitive-caches.js +78 -0
- package/build/es/lib/global-state-service.js +70 -0
- package/build/es/lib/offline-interface.js +65 -0
- package/build/es/lib/offline-provider.js +40 -0
- package/build/es/types.js +0 -1
- package/build/es/utils/__tests__/render-counter.test.js +40 -0
- package/build/es/utils/render-counter.js +11 -0
- package/build/es/utils/test-mocks.js +30 -0
- package/build/types/index.d.ts +4 -0
- package/build/types/lib/cacheable-section-state.d.ts +66 -0
- package/build/types/lib/cacheable-section.d.ts +52 -0
- package/build/types/lib/clear-sensitive-caches.d.ts +16 -0
- package/build/types/lib/global-state-service.d.ts +16 -0
- package/build/types/lib/offline-interface.d.ts +26 -0
- package/build/types/lib/offline-provider.d.ts +19 -0
- package/build/types/types.d.ts +50 -0
- package/build/types/utils/render-counter.d.ts +10 -0
- package/build/types/utils/test-mocks.d.ts +11 -0
- package/package.json +2 -2
package/build/cjs/types.js
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Rerenderer = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("@testing-library/react");
|
|
9
|
+
|
|
10
|
+
var _react2 = _interopRequireDefault(require("react"));
|
|
11
|
+
|
|
12
|
+
var _renderCounter = require("../render-counter");
|
|
13
|
+
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
|
|
16
|
+
const renderCounts = {};
|
|
17
|
+
|
|
18
|
+
const Rerenderer = () => {
|
|
19
|
+
const [, setState] = _react2.default.useState(true);
|
|
20
|
+
|
|
21
|
+
const toggleState = () => setState(prevState => !prevState);
|
|
22
|
+
|
|
23
|
+
return /*#__PURE__*/_react2.default.createElement(_react2.default.Fragment, null, /*#__PURE__*/_react2.default.createElement("button", {
|
|
24
|
+
onClick: toggleState,
|
|
25
|
+
role: "button"
|
|
26
|
+
}), /*#__PURE__*/_react2.default.createElement(_renderCounter.RenderCounter, {
|
|
27
|
+
id: 'rc1',
|
|
28
|
+
countsObj: renderCounts
|
|
29
|
+
}));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.Rerenderer = Rerenderer;
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
(0, _renderCounter.resetRenderCounts)(renderCounts);
|
|
35
|
+
});
|
|
36
|
+
it('increments the counter when rerendered', () => {
|
|
37
|
+
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(Rerenderer, null));
|
|
38
|
+
const {
|
|
39
|
+
getByTestId,
|
|
40
|
+
getByRole
|
|
41
|
+
} = _react.screen;
|
|
42
|
+
expect(getByTestId('rc1')).toHaveTextContent('1');
|
|
43
|
+
(0, _react.act)(() => {
|
|
44
|
+
_react.fireEvent.click(getByRole('button'));
|
|
45
|
+
});
|
|
46
|
+
expect(getByTestId('rc1')).toHaveTextContent('2');
|
|
47
|
+
(0, _react.act)(() => {
|
|
48
|
+
_react.fireEvent.click(getByRole('button'));
|
|
49
|
+
});
|
|
50
|
+
expect(getByTestId('rc1')).toHaveTextContent('3');
|
|
51
|
+
});
|
|
52
|
+
it('resets the render counter successfully', () => {
|
|
53
|
+
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(Rerenderer, null));
|
|
54
|
+
expect(_react.screen.getByTestId('rc1')).toHaveTextContent('1');
|
|
55
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.resetRenderCounts = exports.RenderCounter = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
|
|
12
|
+
const RenderCounter = ({
|
|
13
|
+
id,
|
|
14
|
+
countsObj
|
|
15
|
+
}) => {
|
|
16
|
+
if (!(id in countsObj)) countsObj[id] = 0;
|
|
17
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
18
|
+
"data-testid": id
|
|
19
|
+
}, ++countsObj[id]);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
exports.RenderCounter = RenderCounter;
|
|
23
|
+
|
|
24
|
+
const resetRenderCounts = renderCounts => Object.keys(renderCounts).forEach(key => renderCounts[key] = 0);
|
|
25
|
+
|
|
26
|
+
exports.resetRenderCounts = resetRenderCounts;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.mockOfflineInterface = exports.failedMessageRecordingMock = exports.errorRecordingMock = exports.successfulRecordingMock = void 0;
|
|
7
|
+
const successfulRecordingMock = jest.fn().mockImplementation(async ({
|
|
8
|
+
onStarted,
|
|
9
|
+
onCompleted
|
|
10
|
+
} = {}) => {
|
|
11
|
+
// in 100ms, call 'onStarted' callback (allows 'pending' state)
|
|
12
|
+
if (onStarted) setTimeout(onStarted, 100); // in 200ms, call 'onCompleted' callback
|
|
13
|
+
|
|
14
|
+
if (onCompleted) setTimeout(onCompleted, 200); // resolve
|
|
15
|
+
|
|
16
|
+
return Promise.resolve();
|
|
17
|
+
});
|
|
18
|
+
exports.successfulRecordingMock = successfulRecordingMock;
|
|
19
|
+
const errorRecordingMock = jest.fn().mockImplementation(({
|
|
20
|
+
onStarted,
|
|
21
|
+
onError
|
|
22
|
+
} = {}) => {
|
|
23
|
+
// in 100ms, call 'onStarted' callback (allows 'pending' state)
|
|
24
|
+
if (onStarted) setTimeout(onStarted, 100); // in 200ms, call 'onError'
|
|
25
|
+
|
|
26
|
+
setTimeout(() => onError(new Error('test err')), 200); // resolve to signal successful initiation
|
|
27
|
+
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
});
|
|
30
|
+
exports.errorRecordingMock = errorRecordingMock;
|
|
31
|
+
const failedMessageRecordingMock = jest.fn().mockRejectedValue(new Error('Failed message'));
|
|
32
|
+
exports.failedMessageRecordingMock = failedMessageRecordingMock;
|
|
33
|
+
const mockOfflineInterface = {
|
|
34
|
+
pwaEnabled: true,
|
|
35
|
+
init: jest.fn(),
|
|
36
|
+
startRecording: successfulRecordingMock,
|
|
37
|
+
getCachedSections: jest.fn().mockResolvedValue([]),
|
|
38
|
+
removeSection: jest.fn().mockResolvedValue(true)
|
|
39
|
+
};
|
|
40
|
+
exports.mockOfflineInterface = mockOfflineInterface;
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
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); }
|
|
2
|
+
|
|
3
|
+
import { act, fireEvent, render, screen } from '@testing-library/react';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { useCacheableSection, CacheableSection } from '../lib/cacheable-section';
|
|
6
|
+
import { OfflineProvider } from '../lib/offline-provider';
|
|
7
|
+
import { RenderCounter, resetRenderCounts } from '../utils/render-counter';
|
|
8
|
+
import { errorRecordingMock, failedMessageRecordingMock, mockOfflineInterface } from '../utils/test-mocks';
|
|
9
|
+
const renderCounts = {};
|
|
10
|
+
|
|
11
|
+
const identity = arg => arg;
|
|
12
|
+
|
|
13
|
+
const TestControls = ({
|
|
14
|
+
id,
|
|
15
|
+
makeRecordingHandler = identity
|
|
16
|
+
}) => {
|
|
17
|
+
const {
|
|
18
|
+
startRecording,
|
|
19
|
+
remove,
|
|
20
|
+
isCached,
|
|
21
|
+
lastUpdated,
|
|
22
|
+
recordingState
|
|
23
|
+
} = useCacheableSection(id);
|
|
24
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(RenderCounter, {
|
|
25
|
+
id: "controls-rc-".concat(id),
|
|
26
|
+
countsObj: renderCounts
|
|
27
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
28
|
+
"data-testid": "start-recording-".concat(id),
|
|
29
|
+
onClick: makeRecordingHandler(startRecording)
|
|
30
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
31
|
+
"data-testid": "remove-".concat(id),
|
|
32
|
+
onClick: () => {
|
|
33
|
+
remove();
|
|
34
|
+
}
|
|
35
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
36
|
+
"data-testid": "is-cached-".concat(id)
|
|
37
|
+
}, isCached ? 'yes' : 'no'), /*#__PURE__*/React.createElement("div", {
|
|
38
|
+
"data-testid": "last-updated-".concat(id)
|
|
39
|
+
}, lastUpdated || 'never'), /*#__PURE__*/React.createElement("div", {
|
|
40
|
+
"data-testid": "recording-state-".concat(id)
|
|
41
|
+
}, recordingState));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const TestSection = ({
|
|
45
|
+
id,
|
|
46
|
+
children
|
|
47
|
+
}) => /*#__PURE__*/React.createElement(CacheableSection, {
|
|
48
|
+
id: id,
|
|
49
|
+
loadingMask: /*#__PURE__*/React.createElement("div", {
|
|
50
|
+
"data-testid": "loading-mask-".concat(id)
|
|
51
|
+
})
|
|
52
|
+
}, /*#__PURE__*/React.createElement(RenderCounter, {
|
|
53
|
+
id: "section-rc-".concat(id),
|
|
54
|
+
countsObj: renderCounts
|
|
55
|
+
}), children);
|
|
56
|
+
|
|
57
|
+
const TestSingleSection = props => {
|
|
58
|
+
// Props are spread so they can be overwritten
|
|
59
|
+
return /*#__PURE__*/React.createElement(OfflineProvider, _extends({
|
|
60
|
+
offlineInterface: mockOfflineInterface
|
|
61
|
+
}, props), /*#__PURE__*/React.createElement(TestControls, _extends({
|
|
62
|
+
id: '1'
|
|
63
|
+
}, props)), /*#__PURE__*/React.createElement(TestSection, _extends({
|
|
64
|
+
id: '1'
|
|
65
|
+
}, props)));
|
|
66
|
+
}; // Suppress 'act' warning for these tests
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
const originalError = console.error;
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
// This is done before each because the 'recording error' test uses its own
|
|
72
|
+
// spy on console.error
|
|
73
|
+
jest.spyOn(console, 'error').mockImplementation((...args) => {
|
|
74
|
+
const pattern = /Warning: An update to .* inside a test was not wrapped in act/;
|
|
75
|
+
|
|
76
|
+
if (typeof args[0] === 'string' && pattern.test(args[0])) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return originalError.call(console, ...args);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
afterEach(() => {
|
|
84
|
+
jest.clearAllMocks() // This syntax appeases typescript:
|
|
85
|
+
;
|
|
86
|
+
console.error.mockRestore();
|
|
87
|
+
resetRenderCounts(renderCounts);
|
|
88
|
+
});
|
|
89
|
+
describe('Coordination between useCacheableSection and CacheableSection', () => {
|
|
90
|
+
it('renders in the default state initially', async () => {
|
|
91
|
+
render( /*#__PURE__*/React.createElement(TestSingleSection, null));
|
|
92
|
+
const {
|
|
93
|
+
getByTestId
|
|
94
|
+
} = screen;
|
|
95
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
96
|
+
expect(getByTestId(/is-cached/)).toHaveTextContent('no');
|
|
97
|
+
expect(getByTestId(/last-updated/)).toHaveTextContent('never');
|
|
98
|
+
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
99
|
+
expect(getByTestId(/controls-rc/)).toBeInTheDocument();
|
|
100
|
+
});
|
|
101
|
+
it('handles a successful recording', async done => {
|
|
102
|
+
const {
|
|
103
|
+
getByTestId,
|
|
104
|
+
queryByTestId
|
|
105
|
+
} = screen;
|
|
106
|
+
|
|
107
|
+
const onStarted = () => {
|
|
108
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('recording');
|
|
109
|
+
expect(getByTestId(/loading-mask/)).toBeInTheDocument();
|
|
110
|
+
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const onCompleted = () => {
|
|
114
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
115
|
+
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
|
|
116
|
+
done();
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const recordingOptions = {
|
|
120
|
+
onStarted,
|
|
121
|
+
onCompleted
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const makeRecordingHandler = startRecording => {
|
|
125
|
+
return () => startRecording(recordingOptions);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
render( /*#__PURE__*/React.createElement(TestSingleSection, {
|
|
129
|
+
makeRecordingHandler: makeRecordingHandler
|
|
130
|
+
}));
|
|
131
|
+
await act(async () => {
|
|
132
|
+
fireEvent.click(getByTestId(/start-recording/));
|
|
133
|
+
}); // At this stage, should be pending
|
|
134
|
+
|
|
135
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('pending');
|
|
136
|
+
expect(queryByTestId(/section-rc/)).not.toBeInTheDocument();
|
|
137
|
+
expect.assertions(7);
|
|
138
|
+
});
|
|
139
|
+
it('handles a recording that encounters an error', async done => {
|
|
140
|
+
// Suppress the expected error from console (in addition to 'act' warning)
|
|
141
|
+
jest.spyOn(console, 'error').mockImplementation((...args) => {
|
|
142
|
+
const actPattern = /Warning: An update to .* inside a test was not wrapped in act/;
|
|
143
|
+
const errPattern = /Error during recording/;
|
|
144
|
+
const matchesPattern = actPattern.test(args[0]) || errPattern.test(args[0]);
|
|
145
|
+
|
|
146
|
+
if (typeof args[0] === 'string' && matchesPattern) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return originalError.call(console, ...args);
|
|
151
|
+
});
|
|
152
|
+
const {
|
|
153
|
+
getByTestId,
|
|
154
|
+
queryByTestId
|
|
155
|
+
} = screen;
|
|
156
|
+
const testOfflineInterface = { ...mockOfflineInterface,
|
|
157
|
+
startRecording: errorRecordingMock
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const onError = () => {
|
|
161
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('error');
|
|
162
|
+
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
|
|
163
|
+
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
164
|
+
done();
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const makeRecordingHandler = startRecording => {
|
|
168
|
+
return () => startRecording({
|
|
169
|
+
onError
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
render( /*#__PURE__*/React.createElement(TestSingleSection, {
|
|
174
|
+
offlineInterface: testOfflineInterface,
|
|
175
|
+
makeRecordingHandler: makeRecordingHandler
|
|
176
|
+
}));
|
|
177
|
+
await act(async () => {
|
|
178
|
+
fireEvent.click(getByTestId(/start-recording/));
|
|
179
|
+
});
|
|
180
|
+
expect.assertions(3);
|
|
181
|
+
}); // ! After bumping testing-library versions, something about this test
|
|
182
|
+
// ! causes the following ones to mysteriously fail 😤
|
|
183
|
+
|
|
184
|
+
it.skip('handles an error starting the recording', async done => {
|
|
185
|
+
const {
|
|
186
|
+
getByTestId
|
|
187
|
+
} = screen;
|
|
188
|
+
const testOfflineInterface = { ...mockOfflineInterface,
|
|
189
|
+
startRecording: failedMessageRecordingMock
|
|
190
|
+
};
|
|
191
|
+
const onStarted = jest.fn();
|
|
192
|
+
|
|
193
|
+
const testErrCondition = err => {
|
|
194
|
+
expect(err.message).toBe('Failed message'); // from the mock
|
|
195
|
+
|
|
196
|
+
expect(onStarted).not.toHaveBeenCalled();
|
|
197
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
198
|
+
done();
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const makeRecordingHandler = startRecording => {
|
|
202
|
+
return () => startRecording({
|
|
203
|
+
onStarted
|
|
204
|
+
}).catch(testErrCondition);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
render( /*#__PURE__*/React.createElement(TestSingleSection, {
|
|
208
|
+
offlineInterface: testOfflineInterface,
|
|
209
|
+
makeRecordingHandler: makeRecordingHandler
|
|
210
|
+
}));
|
|
211
|
+
await act(async () => {
|
|
212
|
+
fireEvent.click(getByTestId(/start-recording/));
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const TwoTestSections = props =>
|
|
218
|
+
/*#__PURE__*/
|
|
219
|
+
// Props are spread so they can be overwritten (but only on one section)
|
|
220
|
+
React.createElement(OfflineProvider, _extends({
|
|
221
|
+
offlineInterface: mockOfflineInterface
|
|
222
|
+
}, props), /*#__PURE__*/React.createElement(TestControls, _extends({
|
|
223
|
+
id: '1'
|
|
224
|
+
}, props)), /*#__PURE__*/React.createElement(TestSection, _extends({
|
|
225
|
+
id: '1'
|
|
226
|
+
}, props)), /*#__PURE__*/React.createElement(TestControls, {
|
|
227
|
+
id: '2'
|
|
228
|
+
}), /*#__PURE__*/React.createElement(TestSection, {
|
|
229
|
+
id: '2'
|
|
230
|
+
})); // test that other sections don't rerender when one section does
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
describe('Performant state management', () => {
|
|
234
|
+
it('establishes a pre-recording render count', () => {
|
|
235
|
+
render( /*#__PURE__*/React.createElement(TwoTestSections, null));
|
|
236
|
+
const {
|
|
237
|
+
getByTestId
|
|
238
|
+
} = screen; // Two renders for controls: undefined and 'default' states
|
|
239
|
+
|
|
240
|
+
expect(getByTestId('controls-rc-1')).toHaveTextContent('2');
|
|
241
|
+
expect(getByTestId('controls-rc-2')).toHaveTextContent('2'); // Just one render for sections
|
|
242
|
+
|
|
243
|
+
expect(getByTestId('section-rc-1')).toHaveTextContent('1');
|
|
244
|
+
expect(getByTestId('section-rc-2')).toHaveTextContent('1');
|
|
245
|
+
});
|
|
246
|
+
it('isolates rerenders from other consumers', async done => {
|
|
247
|
+
const {
|
|
248
|
+
getByTestId
|
|
249
|
+
} = screen; // Make assertions
|
|
250
|
+
|
|
251
|
+
const onCompleted = () => {
|
|
252
|
+
// Before refactor: controls components have 6 renders EACH, and
|
|
253
|
+
// sections 1 and 2 have 2 and 1 renders, respectively
|
|
254
|
+
// After refactor, render counts for section that recorded:
|
|
255
|
+
expect(getByTestId('controls-rc-1')).toHaveTextContent('5');
|
|
256
|
+
expect(getByTestId('section-rc-1')).toHaveTextContent('2'); // Section that did not record (should be same as pre-recording):
|
|
257
|
+
|
|
258
|
+
expect(getByTestId('controls-rc-2')).toHaveTextContent('2');
|
|
259
|
+
expect(getByTestId('section-rc-2')).toHaveTextContent('1');
|
|
260
|
+
done();
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const makeRecordingHandler = startRecording => () => startRecording({
|
|
264
|
+
onCompleted
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
render( /*#__PURE__*/React.createElement(TwoTestSections, {
|
|
268
|
+
makeRecordingHandler: makeRecordingHandler
|
|
269
|
+
}));
|
|
270
|
+
await act(async () => {
|
|
271
|
+
fireEvent.click(getByTestId('start-recording-1'));
|
|
272
|
+
});
|
|
273
|
+
expect.assertions(4);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
describe('useCacheableSection can be used inside a child of CacheableSection', () => {
|
|
277
|
+
const ChildTest = props => {
|
|
278
|
+
// Props are spread so they can be overwritten
|
|
279
|
+
return /*#__PURE__*/React.createElement(OfflineProvider, _extends({
|
|
280
|
+
offlineInterface: mockOfflineInterface
|
|
281
|
+
}, props), /*#__PURE__*/React.createElement(TestSection, _extends({
|
|
282
|
+
id: '1'
|
|
283
|
+
}, props), /*#__PURE__*/React.createElement(TestControls, _extends({
|
|
284
|
+
id: '1'
|
|
285
|
+
}, props))));
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
it('handles a successful recording', async done => {
|
|
289
|
+
const {
|
|
290
|
+
getByTestId,
|
|
291
|
+
queryByTestId
|
|
292
|
+
} = screen;
|
|
293
|
+
|
|
294
|
+
const onStarted = () => {
|
|
295
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('recording');
|
|
296
|
+
expect(getByTestId(/loading-mask/)).toBeInTheDocument();
|
|
297
|
+
expect(getByTestId(/section-rc/)).toBeInTheDocument();
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const onCompleted = () => {
|
|
301
|
+
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
|
|
302
|
+
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
|
|
303
|
+
done();
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const recordingOptions = {
|
|
307
|
+
onStarted,
|
|
308
|
+
onCompleted
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
const makeRecordingHandler = startRecording => {
|
|
312
|
+
return () => startRecording(recordingOptions);
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
render( /*#__PURE__*/React.createElement(ChildTest, {
|
|
316
|
+
makeRecordingHandler: makeRecordingHandler
|
|
317
|
+
}));
|
|
318
|
+
await act(async () => {
|
|
319
|
+
fireEvent.click(getByTestId(/start-recording/));
|
|
320
|
+
}); // At this stage, should be pending
|
|
321
|
+
// - In this test case, 'controls' should not be rendered
|
|
322
|
+
|
|
323
|
+
expect(queryByTestId(/recording-state/)).not.toBeInTheDocument();
|
|
324
|
+
expect(queryByTestId(/section-rc/)).not.toBeInTheDocument();
|
|
325
|
+
expect.assertions(7);
|
|
326
|
+
});
|
|
327
|
+
});
|