@dhis2/app-service-offline
Advanced tools
Comparing version 3.8.0 to 3.9.0
@@ -25,6 +25,7 @@ "use strict"; | ||
const TestControls = ({ | ||
id, | ||
makeRecordingHandler = identity | ||
}) => { | ||
const TestControls = (_ref) => { | ||
let { | ||
id, | ||
makeRecordingHandler = identity | ||
} = _ref; | ||
const { | ||
@@ -38,9 +39,9 @@ startRecording, | ||
return /*#__PURE__*/_react2.default.createElement(_react2.default.Fragment, null, /*#__PURE__*/_react2.default.createElement(_renderCounter.RenderCounter, { | ||
id: "controls-rc-".concat(id), | ||
id: `controls-rc-${id}`, | ||
countsObj: renderCounts | ||
}), /*#__PURE__*/_react2.default.createElement("button", { | ||
"data-testid": "start-recording-".concat(id), | ||
"data-testid": `start-recording-${id}`, | ||
onClick: makeRecordingHandler(startRecording) | ||
}), /*#__PURE__*/_react2.default.createElement("button", { | ||
"data-testid": "remove-".concat(id), | ||
"data-testid": `remove-${id}`, | ||
onClick: () => { | ||
@@ -50,22 +51,25 @@ remove(); | ||
}), /*#__PURE__*/_react2.default.createElement("div", { | ||
"data-testid": "is-cached-".concat(id) | ||
"data-testid": `is-cached-${id}` | ||
}, isCached ? 'yes' : 'no'), /*#__PURE__*/_react2.default.createElement("div", { | ||
"data-testid": "last-updated-".concat(id) | ||
"data-testid": `last-updated-${id}` | ||
}, lastUpdated || 'never'), /*#__PURE__*/_react2.default.createElement("div", { | ||
"data-testid": "recording-state-".concat(id) | ||
"data-testid": `recording-state-${id}` | ||
}, recordingState)); | ||
}; | ||
const TestSection = ({ | ||
id, | ||
children | ||
}) => /*#__PURE__*/_react2.default.createElement(_cacheableSection.CacheableSection, { | ||
id: id, | ||
loadingMask: /*#__PURE__*/_react2.default.createElement("div", { | ||
"data-testid": "loading-mask-".concat(id) | ||
}) | ||
}, /*#__PURE__*/_react2.default.createElement(_renderCounter.RenderCounter, { | ||
id: "section-rc-".concat(id), | ||
countsObj: renderCounts | ||
}), children); | ||
const TestSection = (_ref2) => { | ||
let { | ||
id, | ||
children | ||
} = _ref2; | ||
return /*#__PURE__*/_react2.default.createElement(_cacheableSection.CacheableSection, { | ||
id: id, | ||
loadingMask: /*#__PURE__*/_react2.default.createElement("div", { | ||
"data-testid": `loading-mask-${id}` | ||
}) | ||
}, /*#__PURE__*/_react2.default.createElement(_renderCounter.RenderCounter, { | ||
id: `section-rc-${id}`, | ||
countsObj: renderCounts | ||
}), children); | ||
}; | ||
@@ -88,5 +92,9 @@ const TestSingleSection = props => { | ||
// spy on console.error | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const pattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -157,5 +165,10 @@ return; | ||
// Suppress the expected error from console (in addition to 'act' warning) | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const actPattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
const errPattern = /Error during recording/; | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
const matchesPattern = actPattern.test(args[0]) || errPattern.test(args[0]); | ||
@@ -162,0 +175,0 @@ |
@@ -6,2 +6,8 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "CacheableSection", { | ||
enumerable: true, | ||
get: function () { | ||
return _cacheableSection.CacheableSection; | ||
} | ||
}); | ||
Object.defineProperty(exports, "OfflineProvider", { | ||
@@ -13,6 +19,6 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(exports, "CacheableSection", { | ||
Object.defineProperty(exports, "clearSensitiveCaches", { | ||
enumerable: true, | ||
get: function () { | ||
return _cacheableSection.CacheableSection; | ||
return _clearSensitiveCaches.clearSensitiveCaches; | ||
} | ||
@@ -32,18 +38,18 @@ }); | ||
}); | ||
Object.defineProperty(exports, "useOnlineStatus", { | ||
Object.defineProperty(exports, "useDhis2ConnectionStatus", { | ||
enumerable: true, | ||
get: function () { | ||
return _onlineStatus.useOnlineStatus; | ||
return _dhis2ConnectionStatus.useDhis2ConnectionStatus; | ||
} | ||
}); | ||
Object.defineProperty(exports, "useOnlineStatusMessage", { | ||
Object.defineProperty(exports, "useOnlineStatus", { | ||
enumerable: true, | ||
get: function () { | ||
return _onlineStatusMessage.useOnlineStatusMessage; | ||
return _networkStatus.useNetworkStatus; | ||
} | ||
}); | ||
Object.defineProperty(exports, "clearSensitiveCaches", { | ||
Object.defineProperty(exports, "useOnlineStatusMessage", { | ||
enumerable: true, | ||
get: function () { | ||
return _clearSensitiveCaches.clearSensitiveCaches; | ||
return _onlineStatusMessage.useOnlineStatusMessage; | ||
} | ||
@@ -58,6 +64,8 @@ }); | ||
var _onlineStatus = require("./lib/online-status"); | ||
var _networkStatus = require("./lib/network-status"); | ||
var _onlineStatusMessage = require("./lib/online-status-message"); | ||
var _clearSensitiveCaches = require("./lib/clear-sensitive-caches"); | ||
var _clearSensitiveCaches = require("./lib/clear-sensitive-caches"); | ||
var _dhis2ConnectionStatus = require("./lib/dhis2-connection-status"); |
@@ -37,5 +37,9 @@ "use strict"; | ||
beforeAll(() => { | ||
jest.spyOn(console, 'debug').mockImplementation((...args) => { | ||
jest.spyOn(console, 'debug').mockImplementation(function () { | ||
const pattern = /Clearing sensitive caches/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -42,0 +46,0 @@ return; |
@@ -20,5 +20,9 @@ "use strict"; | ||
beforeEach(() => { | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const pattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -25,0 +29,0 @@ return; |
"use strict"; | ||
var _appServiceAlerts = require("@dhis2/app-service-alerts"); | ||
var _reactHooks = require("@testing-library/react-hooks"); | ||
@@ -20,5 +18,9 @@ | ||
beforeEach(() => { | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const pattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -37,10 +39,15 @@ return; | ||
it('renders in the default state initially', () => { | ||
const wrapper = (_ref) => { | ||
let { | ||
children | ||
} = _ref; | ||
return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: _testMocks.mockOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
result | ||
} = (0, _reactHooks.renderHook)(() => (0, _cacheableSection.useCacheableSection)('one'), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: _testMocks.mockOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -59,2 +66,12 @@ expect(result.current.recordingState).toBe('default'); | ||
}; | ||
const wrapper = (_ref2) => { | ||
let { | ||
children | ||
} = _ref2; | ||
return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
@@ -64,7 +81,3 @@ result, | ||
} = (0, _reactHooks.renderHook)(() => (0, _cacheableSection.useCacheableSection)(sectionId), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -108,5 +121,10 @@ | ||
// Suppress the expected error from console (in addition to 'act' warning) | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const actPattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
const errPattern = /Error during recording/; | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
const matchesPattern = actPattern.test(args[0]) || errPattern.test(args[0]); | ||
@@ -123,10 +141,16 @@ | ||
}; | ||
const wrapper = (_ref3) => { | ||
let { | ||
children | ||
} = _ref3; | ||
return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
result | ||
} = (0, _reactHooks.renderHook)(() => (0, _cacheableSection.useCacheableSection)('one'), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -164,10 +188,16 @@ | ||
}; | ||
const wrapper = (_ref4) => { | ||
let { | ||
children | ||
} = _ref4; | ||
return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
result | ||
} = (0, _reactHooks.renderHook)(() => (0, _cacheableSection.useCacheableSection)('err'), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -185,2 +215,12 @@ await expect(result.current.startRecording()).rejects.toThrow('Failed message' // from failedMessageRecordingMock | ||
}; | ||
const wrapper = (_ref5) => { | ||
let { | ||
children | ||
} = _ref5; | ||
return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
@@ -190,7 +230,3 @@ result, | ||
} = (0, _reactHooks.renderHook)(() => (0, _cacheableSection.useCacheableSection)(sectionId), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); // Wait for state to sync with indexedDB | ||
@@ -217,2 +253,12 @@ | ||
}; | ||
const wrapper = (_ref6) => { | ||
let { | ||
children | ||
} = _ref6; | ||
return /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
@@ -222,8 +268,4 @@ result, | ||
rerender | ||
} = (0, _reactHooks.renderHook)((...args) => (0, _cacheableSection.useCacheableSection)(...args), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(_appServiceAlerts.AlertsProvider, null, /*#__PURE__*/_react.default.createElement(_offlineProvider.OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)), | ||
} = (0, _reactHooks.renderHook)(id => (0, _cacheableSection.useCacheableSection)(id), { | ||
wrapper, | ||
initialProps: 'id-one' | ||
@@ -230,0 +272,0 @@ }); // Wait for state to sync with indexedDB |
@@ -6,7 +6,7 @@ "use strict"; | ||
}); | ||
exports.CacheableSectionProvider = CacheableSectionProvider; | ||
exports.createCacheableSectionStore = createCacheableSectionStore; | ||
exports.CacheableSectionProvider = CacheableSectionProvider; | ||
exports.useCachedSection = useCachedSection; | ||
exports.useCachedSections = useCachedSections; | ||
exports.useRecordingState = useRecordingState; | ||
exports.useCachedSections = useCachedSections; | ||
exports.useCachedSection = useCachedSection; | ||
@@ -31,10 +31,13 @@ var _propTypes = _interopRequireDefault(require("prop-types")); | ||
function getSectionsById(sectionsArray) { | ||
return sectionsArray.reduce((result, { | ||
sectionId, | ||
lastUpdated | ||
}) => ({ ...result, | ||
[sectionId]: { | ||
return sectionsArray.reduce((result, _ref) => { | ||
let { | ||
sectionId, | ||
lastUpdated | ||
} | ||
}), {}); | ||
} = _ref; | ||
return { ...result, | ||
[sectionId]: { | ||
lastUpdated | ||
} | ||
}; | ||
}, {}); | ||
} | ||
@@ -78,5 +81,6 @@ /** | ||
function CacheableSectionProvider({ | ||
children | ||
}) { | ||
function CacheableSectionProvider(_ref2) { | ||
let { | ||
children | ||
} = _ref2; | ||
const offlineInterface = (0, _offlineInterface.useOfflineInterface)(); | ||
@@ -83,0 +87,0 @@ const store = useConst(createCacheableSectionStore); // On load, get sections and add to store |
@@ -6,4 +6,4 @@ "use strict"; | ||
}); | ||
exports.CacheableSection = CacheableSection; | ||
exports.useCacheableSection = useCacheableSection; | ||
exports.CacheableSection = CacheableSection; | ||
@@ -67,8 +67,9 @@ var _propTypes = _interopRequireDefault(require("prop-types")); | ||
function startRecording({ | ||
recordingTimeoutDelay = 1000, | ||
onStarted, | ||
onCompleted, | ||
onError | ||
} = {}) { | ||
function startRecording() { | ||
let { | ||
recordingTimeoutDelay = 1000, | ||
onStarted, | ||
onCompleted, | ||
onError | ||
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// This promise resolving means that the message to the service worker | ||
@@ -131,7 +132,8 @@ // to start recording was successful. Waiting for resolution prevents | ||
*/ | ||
function CacheableSection({ | ||
id, | ||
loadingMask, | ||
children | ||
}) { | ||
function CacheableSection(_ref) { | ||
let { | ||
id, | ||
loadingMask, | ||
children | ||
} = _ref; | ||
// Accesses recording state that useCacheableSection controls | ||
@@ -138,0 +140,0 @@ const { |
@@ -6,4 +6,4 @@ "use strict"; | ||
}); | ||
exports.SECTIONS_STORE = exports.SECTIONS_DB = void 0; | ||
exports.clearSensitiveCaches = clearSensitiveCaches; | ||
exports.SECTIONS_STORE = exports.SECTIONS_DB = void 0; | ||
// IndexedDB names; should be the same as in @dhis2/pwa | ||
@@ -35,5 +35,8 @@ const SECTIONS_DB = 'sections-db'; | ||
if (!dbs.some(({ | ||
name | ||
}) => name === dbName)) { | ||
if (!dbs.some((_ref) => { | ||
let { | ||
name | ||
} = _ref; | ||
return name === dbName; | ||
})) { | ||
// Sections-db is not created; nothing to do here | ||
@@ -73,3 +76,4 @@ return; | ||
async function clearSensitiveCaches(dbName = SECTIONS_DB) { | ||
async function clearSensitiveCaches() { | ||
let dbName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : SECTIONS_DB; | ||
console.debug('Clearing sensitive caches'); | ||
@@ -76,0 +80,0 @@ let cacheKeys; // caches.keys can fail in insecure contexts, see: |
@@ -6,4 +6,4 @@ "use strict"; | ||
}); | ||
exports.useGlobalState = exports.createStore = exports.GlobalStateProvider = void 0; | ||
exports.useGlobalStateMutation = useGlobalStateMutation; | ||
exports.useGlobalState = exports.GlobalStateProvider = exports.createStore = void 0; | ||
@@ -27,3 +27,4 @@ var _isEqual = _interopRequireDefault(require("lodash/isEqual")); | ||
const createStore = (initialState = {}) => { | ||
const createStore = function () { | ||
let initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
const subscriptions = new Set(); | ||
@@ -55,8 +56,11 @@ let state = initialState; | ||
const GlobalStateProvider = ({ | ||
store, | ||
children | ||
}) => /*#__PURE__*/_react.default.createElement(GlobalStateContext.Provider, { | ||
value: store | ||
}, children); | ||
const GlobalStateProvider = (_ref) => { | ||
let { | ||
store, | ||
children | ||
} = _ref; | ||
return /*#__PURE__*/_react.default.createElement(GlobalStateContext.Provider, { | ||
value: store | ||
}, children); | ||
}; | ||
@@ -69,3 +73,4 @@ exports.GlobalStateProvider = GlobalStateProvider; | ||
const useGlobalState = (selector = identity) => { | ||
const useGlobalState = function () { | ||
let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : identity; | ||
const store = useGlobalStateStore(); | ||
@@ -98,5 +103,5 @@ const [selectedState, setSelectedState] = (0, _react.useState)(selector(store.getState())); | ||
const store = useGlobalStateStore(); | ||
return (0, _react.useCallback)((...args) => { | ||
store.mutate(mutationCreator(...args)); | ||
return (0, _react.useCallback)(function () { | ||
store.mutate(mutationCreator(...arguments)); | ||
}, [mutationCreator, store]); | ||
} |
@@ -22,2 +22,4 @@ "use strict"; | ||
pwaEnabled: false, | ||
latestIsConnected: false, | ||
subscribeToDhis2ConnectionStatus: () => () => undefined, | ||
startRecording: async () => undefined, | ||
@@ -37,6 +39,7 @@ getCachedSections: async () => [], | ||
*/ | ||
function OfflineInterfaceProvider({ | ||
offlineInterface, | ||
children | ||
}) { | ||
function OfflineInterfaceProvider(_ref) { | ||
let { | ||
offlineInterface, | ||
children | ||
} = _ref; | ||
return /*#__PURE__*/_react.default.createElement(OfflineInterfaceContext.Provider, { | ||
@@ -43,0 +46,0 @@ value: offlineInterface |
@@ -14,2 +14,4 @@ "use strict"; | ||
var _dhis2ConnectionStatus = require("./dhis2-connection-status"); | ||
var _offlineInterface = require("./offline-interface"); | ||
@@ -22,6 +24,8 @@ | ||
/** A context provider for all the relevant offline contexts */ | ||
function OfflineProvider({ | ||
offlineInterface, | ||
children | ||
}) { | ||
function OfflineProvider(_ref) { | ||
let { | ||
offlineInterface, | ||
children | ||
} = _ref; | ||
// If an offline interface is not provided, or if one is provided and PWA | ||
@@ -35,3 +39,3 @@ // is not enabled, skip adding context providers | ||
offlineInterface: offlineInterface | ||
}, /*#__PURE__*/_react.default.createElement(_cacheableSectionState.CacheableSectionProvider, null, /*#__PURE__*/_react.default.createElement(_onlineStatusMessage.OnlineStatusMessageProvider, null, children))); | ||
}, /*#__PURE__*/_react.default.createElement(_dhis2ConnectionStatus.Dhis2ConnectionStatusProvider, null, /*#__PURE__*/_react.default.createElement(_cacheableSectionState.CacheableSectionProvider, null, /*#__PURE__*/_react.default.createElement(_onlineStatusMessage.OnlineStatusMessageProvider, null, children)))); | ||
} | ||
@@ -38,0 +42,0 @@ |
@@ -6,3 +6,3 @@ "use strict"; | ||
}); | ||
exports.OnlineStatusMessageProvider = exports.useOnlineStatusMessage = void 0; | ||
exports.useOnlineStatusMessage = exports.OnlineStatusMessageProvider = void 0; | ||
@@ -35,5 +35,6 @@ var _react = _interopRequireWildcard(require("react")); | ||
const OnlineStatusMessageProvider = ({ | ||
children | ||
}) => { | ||
const OnlineStatusMessageProvider = (_ref) => { | ||
let { | ||
children | ||
} = _ref; | ||
const [onlineStatusMessage, setOnlineStatusMessage] = (0, _react.useState)(); | ||
@@ -40,0 +41,0 @@ return /*#__PURE__*/_react.default.createElement(OnlineStatusMessageContext.Provider, { |
@@ -12,6 +12,8 @@ "use strict"; | ||
const RenderCounter = ({ | ||
id, | ||
countsObj | ||
}) => { | ||
const RenderCounter = (_ref) => { | ||
let { | ||
id, | ||
countsObj | ||
} = _ref; | ||
if (!(id in countsObj)) { | ||
@@ -18,0 +20,0 @@ countsObj[id] = 0; |
@@ -6,7 +6,9 @@ "use strict"; | ||
}); | ||
exports.mockOfflineInterface = exports.failedMessageRecordingMock = exports.errorRecordingMock = exports.successfulRecordingMock = void 0; | ||
const successfulRecordingMock = jest.fn().mockImplementation(async ({ | ||
onStarted, | ||
onCompleted | ||
} = {}) => { | ||
exports.successfulRecordingMock = exports.mockOfflineInterface = exports.failedMessageRecordingMock = exports.errorRecordingMock = void 0; | ||
const successfulRecordingMock = jest.fn().mockImplementation(async function () { | ||
let { | ||
onStarted, | ||
onCompleted | ||
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// in 100ms, call 'onStarted' callback (allows 'pending' state) | ||
@@ -26,6 +28,8 @@ if (onStarted) { | ||
exports.successfulRecordingMock = successfulRecordingMock; | ||
const errorRecordingMock = jest.fn().mockImplementation(({ | ||
onStarted, | ||
onError | ||
} = {}) => { | ||
const errorRecordingMock = jest.fn().mockImplementation(function () { | ||
let { | ||
onStarted, | ||
onError | ||
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// in 100ms, call 'onStarted' callback (allows 'pending' state) | ||
@@ -46,6 +50,9 @@ if (onStarted) { | ||
pwaEnabled: true, | ||
latestIsConnected: true, | ||
startRecording: successfulRecordingMock, | ||
getCachedSections: jest.fn().mockResolvedValue([]), | ||
removeSection: jest.fn().mockResolvedValue(true) | ||
removeSection: jest.fn().mockResolvedValue(true), | ||
// returns an unsubscribe function | ||
subscribeToDhis2ConnectionStatus: jest.fn().mockReturnValue(() => undefined) | ||
}; | ||
exports.mockOfflineInterface = mockOfflineInterface; |
@@ -14,6 +14,7 @@ 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); } | ||
const TestControls = ({ | ||
id, | ||
makeRecordingHandler = identity | ||
}) => { | ||
const TestControls = (_ref) => { | ||
let { | ||
id, | ||
makeRecordingHandler = identity | ||
} = _ref; | ||
const { | ||
@@ -27,9 +28,9 @@ startRecording, | ||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(RenderCounter, { | ||
id: "controls-rc-".concat(id), | ||
id: `controls-rc-${id}`, | ||
countsObj: renderCounts | ||
}), /*#__PURE__*/React.createElement("button", { | ||
"data-testid": "start-recording-".concat(id), | ||
"data-testid": `start-recording-${id}`, | ||
onClick: makeRecordingHandler(startRecording) | ||
}), /*#__PURE__*/React.createElement("button", { | ||
"data-testid": "remove-".concat(id), | ||
"data-testid": `remove-${id}`, | ||
onClick: () => { | ||
@@ -39,22 +40,25 @@ remove(); | ||
}), /*#__PURE__*/React.createElement("div", { | ||
"data-testid": "is-cached-".concat(id) | ||
"data-testid": `is-cached-${id}` | ||
}, isCached ? 'yes' : 'no'), /*#__PURE__*/React.createElement("div", { | ||
"data-testid": "last-updated-".concat(id) | ||
"data-testid": `last-updated-${id}` | ||
}, lastUpdated || 'never'), /*#__PURE__*/React.createElement("div", { | ||
"data-testid": "recording-state-".concat(id) | ||
"data-testid": `recording-state-${id}` | ||
}, recordingState)); | ||
}; | ||
const TestSection = ({ | ||
id, | ||
children | ||
}) => /*#__PURE__*/React.createElement(CacheableSection, { | ||
id: id, | ||
loadingMask: /*#__PURE__*/React.createElement("div", { | ||
"data-testid": "loading-mask-".concat(id) | ||
}) | ||
}, /*#__PURE__*/React.createElement(RenderCounter, { | ||
id: "section-rc-".concat(id), | ||
countsObj: renderCounts | ||
}), children); | ||
const TestSection = (_ref2) => { | ||
let { | ||
id, | ||
children | ||
} = _ref2; | ||
return /*#__PURE__*/React.createElement(CacheableSection, { | ||
id: id, | ||
loadingMask: /*#__PURE__*/React.createElement("div", { | ||
"data-testid": `loading-mask-${id}` | ||
}) | ||
}, /*#__PURE__*/React.createElement(RenderCounter, { | ||
id: `section-rc-${id}`, | ||
countsObj: renderCounts | ||
}), children); | ||
}; | ||
@@ -77,5 +81,9 @@ const TestSingleSection = props => { | ||
// spy on console.error | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const pattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -146,5 +154,10 @@ return; | ||
// Suppress the expected error from console (in addition to 'act' warning) | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const actPattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
const errPattern = /Error during recording/; | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
const matchesPattern = actPattern.test(args[0]) || errPattern.test(args[0]); | ||
@@ -151,0 +164,0 @@ |
export { OfflineProvider } from './lib/offline-provider'; | ||
export { CacheableSection, useCacheableSection } from './lib/cacheable-section'; | ||
export { useCachedSections } from './lib/cacheable-section-state'; | ||
export { useOnlineStatus } from './lib/online-status'; | ||
export { useCachedSections } from './lib/cacheable-section-state'; // Use "useOnlineStatus" name for backwards compatibility | ||
export { useNetworkStatus as useOnlineStatus } from './lib/network-status'; | ||
export { useOnlineStatusMessage } from './lib/online-status-message'; | ||
export { clearSensitiveCaches } from './lib/clear-sensitive-caches'; | ||
export { clearSensitiveCaches } from './lib/clear-sensitive-caches'; | ||
export { useDhis2ConnectionStatus } from './lib/dhis2-connection-status'; |
@@ -29,5 +29,9 @@ import FDBFactory from 'fake-indexeddb/lib/FDBFactory'; | ||
beforeAll(() => { | ||
jest.spyOn(console, 'debug').mockImplementation((...args) => { | ||
jest.spyOn(console, 'debug').mockImplementation(function () { | ||
const pattern = /Clearing sensitive caches/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -34,0 +38,0 @@ return; |
@@ -10,5 +10,9 @@ import { render, screen, waitFor } from '@testing-library/react'; | ||
beforeEach(() => { | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const pattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -15,0 +19,0 @@ return; |
@@ -1,2 +0,1 @@ | ||
import { AlertsProvider } from '@dhis2/app-service-alerts'; | ||
import { renderHook, act } from '@testing-library/react-hooks'; | ||
@@ -10,5 +9,9 @@ import React from 'react'; | ||
beforeEach(() => { | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const pattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (typeof args[0] === 'string' && pattern.test(args[0])) { | ||
@@ -27,10 +30,15 @@ return; | ||
it('renders in the default state initially', () => { | ||
const wrapper = (_ref) => { | ||
let { | ||
children | ||
} = _ref; | ||
return /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: mockOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
result | ||
} = renderHook(() => useCacheableSection('one'), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/React.createElement(AlertsProvider, null, /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: mockOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -49,2 +57,12 @@ expect(result.current.recordingState).toBe('default'); | ||
}; | ||
const wrapper = (_ref2) => { | ||
let { | ||
children | ||
} = _ref2; | ||
return /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
@@ -54,7 +72,3 @@ result, | ||
} = renderHook(() => useCacheableSection(sectionId), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/React.createElement(AlertsProvider, null, /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -98,5 +112,10 @@ | ||
// Suppress the expected error from console (in addition to 'act' warning) | ||
jest.spyOn(console, 'error').mockImplementation((...args) => { | ||
jest.spyOn(console, 'error').mockImplementation(function () { | ||
const actPattern = /Warning: An update to .* inside a test was not wrapped in act/; | ||
const errPattern = /Error during recording/; | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
const matchesPattern = actPattern.test(args[0]) || errPattern.test(args[0]); | ||
@@ -113,10 +132,16 @@ | ||
}; | ||
const wrapper = (_ref3) => { | ||
let { | ||
children | ||
} = _ref3; | ||
return /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
result | ||
} = renderHook(() => useCacheableSection('one'), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/React.createElement(AlertsProvider, null, /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -154,10 +179,16 @@ | ||
}; | ||
const wrapper = (_ref4) => { | ||
let { | ||
children | ||
} = _ref4; | ||
return /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
result | ||
} = renderHook(() => useCacheableSection('err'), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/React.createElement(AlertsProvider, null, /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); | ||
@@ -175,2 +206,12 @@ await expect(result.current.startRecording()).rejects.toThrow('Failed message' // from failedMessageRecordingMock | ||
}; | ||
const wrapper = (_ref5) => { | ||
let { | ||
children | ||
} = _ref5; | ||
return /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
@@ -180,7 +221,3 @@ result, | ||
} = renderHook(() => useCacheableSection(sectionId), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/React.createElement(AlertsProvider, null, /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)) | ||
wrapper | ||
}); // Wait for state to sync with indexedDB | ||
@@ -207,2 +244,12 @@ | ||
}; | ||
const wrapper = (_ref6) => { | ||
let { | ||
children | ||
} = _ref6; | ||
return /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children); | ||
}; | ||
const { | ||
@@ -212,8 +259,4 @@ result, | ||
rerender | ||
} = renderHook((...args) => useCacheableSection(...args), { | ||
wrapper: ({ | ||
children | ||
}) => /*#__PURE__*/React.createElement(AlertsProvider, null, /*#__PURE__*/React.createElement(OfflineProvider, { | ||
offlineInterface: testOfflineInterface | ||
}, children)), | ||
} = renderHook(id => useCacheableSection(id), { | ||
wrapper, | ||
initialProps: 'id-one' | ||
@@ -220,0 +263,0 @@ }); // Wait for state to sync with indexedDB |
@@ -15,10 +15,13 @@ import PropTypes from 'prop-types'; | ||
function getSectionsById(sectionsArray) { | ||
return sectionsArray.reduce((result, { | ||
sectionId, | ||
lastUpdated | ||
}) => ({ ...result, | ||
[sectionId]: { | ||
return sectionsArray.reduce((result, _ref) => { | ||
let { | ||
sectionId, | ||
lastUpdated | ||
} | ||
}), {}); | ||
} = _ref; | ||
return { ...result, | ||
[sectionId]: { | ||
lastUpdated | ||
} | ||
}; | ||
}, {}); | ||
} | ||
@@ -61,5 +64,6 @@ /** | ||
export function CacheableSectionProvider({ | ||
children | ||
}) { | ||
export function CacheableSectionProvider(_ref2) { | ||
let { | ||
children | ||
} = _ref2; | ||
const offlineInterface = useOfflineInterface(); | ||
@@ -66,0 +70,0 @@ const store = useConst(createCacheableSectionStore); // On load, get sections and add to store |
@@ -48,8 +48,9 @@ import PropTypes from 'prop-types'; | ||
function startRecording({ | ||
recordingTimeoutDelay = 1000, | ||
onStarted, | ||
onCompleted, | ||
onError | ||
} = {}) { | ||
function startRecording() { | ||
let { | ||
recordingTimeoutDelay = 1000, | ||
onStarted, | ||
onCompleted, | ||
onError | ||
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// This promise resolving means that the message to the service worker | ||
@@ -112,7 +113,8 @@ // to start recording was successful. Waiting for resolution prevents | ||
*/ | ||
export function CacheableSection({ | ||
id, | ||
loadingMask, | ||
children | ||
}) { | ||
export function CacheableSection(_ref) { | ||
let { | ||
id, | ||
loadingMask, | ||
children | ||
} = _ref; | ||
// Accesses recording state that useCacheableSection controls | ||
@@ -119,0 +121,0 @@ const { |
@@ -25,5 +25,8 @@ // IndexedDB names; should be the same as in @dhis2/pwa | ||
if (!dbs.some(({ | ||
name | ||
}) => name === dbName)) { | ||
if (!dbs.some((_ref) => { | ||
let { | ||
name | ||
} = _ref; | ||
return name === dbName; | ||
})) { | ||
// Sections-db is not created; nothing to do here | ||
@@ -63,3 +66,4 @@ return; | ||
export async function clearSensitiveCaches(dbName = SECTIONS_DB) { | ||
export async function clearSensitiveCaches() { | ||
let dbName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : SECTIONS_DB; | ||
console.debug('Clearing sensitive caches'); | ||
@@ -66,0 +70,0 @@ let cacheKeys; // caches.keys can fail in insecure contexts, see: |
@@ -10,3 +10,4 @@ import isEqual from 'lodash/isEqual'; | ||
export const createStore = (initialState = {}) => { | ||
export const createStore = function () { | ||
let initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
const subscriptions = new Set(); | ||
@@ -35,8 +36,11 @@ let state = initialState; | ||
export const GlobalStateProvider = ({ | ||
store, | ||
children | ||
}) => /*#__PURE__*/React.createElement(GlobalStateContext.Provider, { | ||
value: store | ||
}, children); | ||
export const GlobalStateProvider = (_ref) => { | ||
let { | ||
store, | ||
children | ||
} = _ref; | ||
return /*#__PURE__*/React.createElement(GlobalStateContext.Provider, { | ||
value: store | ||
}, children); | ||
}; | ||
GlobalStateProvider.propTypes = { | ||
@@ -46,3 +50,4 @@ children: PropTypes.node, | ||
}; | ||
export const useGlobalState = (selector = identity) => { | ||
export const useGlobalState = function () { | ||
let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : identity; | ||
const store = useGlobalStateStore(); | ||
@@ -72,5 +77,5 @@ const [selectedState, setSelectedState] = useState(selector(store.getState())); | ||
const store = useGlobalStateStore(); | ||
return useCallback((...args) => { | ||
store.mutate(mutationCreator(...args)); | ||
return useCallback(function () { | ||
store.mutate(mutationCreator(...arguments)); | ||
}, [mutationCreator, store]); | ||
} |
@@ -6,2 +6,4 @@ import PropTypes from 'prop-types'; | ||
pwaEnabled: false, | ||
latestIsConnected: false, | ||
subscribeToDhis2ConnectionStatus: () => () => undefined, | ||
startRecording: async () => undefined, | ||
@@ -21,6 +23,7 @@ getCachedSections: async () => [], | ||
*/ | ||
export function OfflineInterfaceProvider({ | ||
offlineInterface, | ||
children | ||
}) { | ||
export function OfflineInterfaceProvider(_ref) { | ||
let { | ||
offlineInterface, | ||
children | ||
} = _ref; | ||
return /*#__PURE__*/React.createElement(OfflineInterfaceContext.Provider, { | ||
@@ -27,0 +30,0 @@ value: offlineInterface |
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import { CacheableSectionProvider } from './cacheable-section-state'; | ||
import { Dhis2ConnectionStatusProvider } from './dhis2-connection-status'; | ||
import { OfflineInterfaceProvider } from './offline-interface'; | ||
@@ -8,6 +9,8 @@ import { OnlineStatusMessageProvider } from './online-status-message'; | ||
/** A context provider for all the relevant offline contexts */ | ||
export function OfflineProvider({ | ||
offlineInterface, | ||
children | ||
}) { | ||
export function OfflineProvider(_ref) { | ||
let { | ||
offlineInterface, | ||
children | ||
} = _ref; | ||
// If an offline interface is not provided, or if one is provided and PWA | ||
@@ -21,3 +24,3 @@ // is not enabled, skip adding context providers | ||
offlineInterface: offlineInterface | ||
}, /*#__PURE__*/React.createElement(CacheableSectionProvider, null, /*#__PURE__*/React.createElement(OnlineStatusMessageProvider, null, children))); | ||
}, /*#__PURE__*/React.createElement(Dhis2ConnectionStatusProvider, null, /*#__PURE__*/React.createElement(CacheableSectionProvider, null, /*#__PURE__*/React.createElement(OnlineStatusMessageProvider, null, children)))); | ||
} | ||
@@ -24,0 +27,0 @@ OfflineProvider.propTypes = { |
@@ -17,5 +17,6 @@ import React, { useContext, useState } from 'react'; | ||
}; | ||
export const OnlineStatusMessageProvider = ({ | ||
children | ||
}) => { | ||
export const OnlineStatusMessageProvider = (_ref) => { | ||
let { | ||
children | ||
} = _ref; | ||
const [onlineStatusMessage, setOnlineStatusMessage] = useState(); | ||
@@ -22,0 +23,0 @@ return /*#__PURE__*/React.createElement(OnlineStatusMessageContext.Provider, { |
import React from 'react'; | ||
export const RenderCounter = ({ | ||
id, | ||
countsObj | ||
}) => { | ||
export const RenderCounter = (_ref) => { | ||
let { | ||
id, | ||
countsObj | ||
} = _ref; | ||
if (!(id in countsObj)) { | ||
@@ -7,0 +9,0 @@ countsObj[id] = 0; |
@@ -1,5 +0,7 @@ | ||
export const successfulRecordingMock = jest.fn().mockImplementation(async ({ | ||
onStarted, | ||
onCompleted | ||
} = {}) => { | ||
export const successfulRecordingMock = jest.fn().mockImplementation(async function () { | ||
let { | ||
onStarted, | ||
onCompleted | ||
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// in 100ms, call 'onStarted' callback (allows 'pending' state) | ||
@@ -18,6 +20,8 @@ if (onStarted) { | ||
}); | ||
export const errorRecordingMock = jest.fn().mockImplementation(({ | ||
onStarted, | ||
onError | ||
} = {}) => { | ||
export const errorRecordingMock = jest.fn().mockImplementation(function () { | ||
let { | ||
onStarted, | ||
onError | ||
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
// in 100ms, call 'onStarted' callback (allows 'pending' state) | ||
@@ -36,5 +40,8 @@ if (onStarted) { | ||
pwaEnabled: true, | ||
latestIsConnected: true, | ||
startRecording: successfulRecordingMock, | ||
getCachedSections: jest.fn().mockResolvedValue([]), | ||
removeSection: jest.fn().mockResolvedValue(true) | ||
removeSection: jest.fn().mockResolvedValue(true), | ||
// returns an unsubscribe function | ||
subscribeToDhis2ConnectionStatus: jest.fn().mockReturnValue(() => undefined) | ||
}; |
export { OfflineProvider } from './lib/offline-provider'; | ||
export { CacheableSection, useCacheableSection } from './lib/cacheable-section'; | ||
export { useCachedSections } from './lib/cacheable-section-state'; | ||
export { useOnlineStatus } from './lib/online-status'; | ||
export { useNetworkStatus as useOnlineStatus } from './lib/network-status'; | ||
export { useOnlineStatusMessage } from './lib/online-status-message'; | ||
export { clearSensitiveCaches } from './lib/clear-sensitive-caches'; | ||
export { useDhis2ConnectionStatus } from './lib/dhis2-connection-status'; |
@@ -37,2 +37,8 @@ import { ReactNode } from 'react'; | ||
readonly pwaEnabled: boolean; | ||
readonly latestIsConnected: boolean | null; | ||
subscribeToDhis2ConnectionStatus: ({ onUpdate, }: { | ||
onUpdate: ({ isConnected }: { | ||
isConnected: boolean; | ||
}) => void; | ||
}) => () => void; | ||
startRecording: StartRecording; | ||
@@ -39,0 +45,0 @@ getCachedSections: () => Promise<IndexedDBCachedSection[]>; |
@@ -7,5 +7,7 @@ /// <reference types="jest" /> | ||
pwaEnabled: boolean; | ||
latestIsConnected: boolean; | ||
startRecording: jest.Mock<any, any>; | ||
getCachedSections: jest.Mock<any, any>; | ||
removeSection: jest.Mock<any, any>; | ||
subscribeToDhis2ConnectionStatus: jest.Mock<any, any>; | ||
}; |
{ | ||
"name": "@dhis2/app-service-offline", | ||
"description": "A runtime service for online/offline detection and offline caching", | ||
"version": "3.8.0", | ||
"version": "3.9.0", | ||
"main": "./build/cjs/index.js", | ||
@@ -36,3 +36,3 @@ "module": "./build/es/index.js", | ||
"peerDependencies": { | ||
"@dhis2/app-service-alerts": "3.8.0", | ||
"@dhis2/app-service-config": "3.9.0", | ||
"prop-types": "^15.7.2", | ||
@@ -39,0 +39,0 @@ "react": "^16.8.6", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
278246
76
6788
2