-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* actionRecordMiddleware, session store state actions * downloadHelpers, helpers, download strings as files
- Loading branch information
Showing
10 changed files
with
261 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
src/common/__tests__/__snapshots__/downloadHelpers.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`DownloadHelpers should attempt to download data: data download 1`] = ` | ||
Object { | ||
"data": "", | ||
"fileName": "download.txt", | ||
} | ||
`; | ||
|
||
exports[`DownloadHelpers should have specific functions: helpers 1`] = ` | ||
Object { | ||
"debugLog": [Function], | ||
"downloadData": [Function], | ||
} | ||
`; | ||
|
||
exports[`DownloadHelpers should throw an error attempting to access a log: access error 1`] = `[Error: debuglog error, URL.createObjectURL is not a function]`; | ||
|
||
exports[`DownloadHelpers should throw an error attempting to download data: download error 1`] = `[TypeError: URL.createObjectURL is not a function]`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { downloadHelpers } from '../downloadHelpers'; | ||
|
||
/** | ||
* ToDo: evaluate the clearing of timers with pending and real | ||
* It's unclear if this is actively helping/necessary... | ||
*/ | ||
describe('DownloadHelpers', () => { | ||
beforeEach(() => { | ||
jest.useFakeTimers(); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.runOnlyPendingTimers(); | ||
jest.useRealTimers(); | ||
}); | ||
|
||
it('should have specific functions', () => { | ||
expect(downloadHelpers).toMatchSnapshot('helpers'); | ||
}); | ||
|
||
it('should throw an error attempting to download data', done => { | ||
downloadHelpers.downloadData().catch(error => { | ||
expect(error).toMatchSnapshot('download error'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should throw an error attempting to access a log', done => { | ||
downloadHelpers.debugLog().catch(error => { | ||
expect(error).toMatchSnapshot('access error'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should attempt to download data', done => { | ||
window.URL = { | ||
createObjectURL: jest.fn(), | ||
revokeObjectURL: jest.fn() | ||
}; | ||
|
||
downloadHelpers.downloadData().then(value => { | ||
expect(value).toMatchSnapshot('data download'); | ||
done(); | ||
}); | ||
|
||
jest.runAllTimers(); | ||
|
||
window.URL = { | ||
createObjectURL: undefined, | ||
revokeObjectURL: undefined | ||
}; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import moment from 'moment/moment'; | ||
import { helpers } from './helpers'; | ||
import { dateHelpers } from './dateHelpers'; | ||
|
||
/** | ||
* Download data to a file | ||
* | ||
* @param {object} options | ||
* @param {string} options.data | ||
* @param {string} options.fileName | ||
* @param {string} options.fileType | ||
* @returns {Promise} | ||
*/ | ||
const downloadData = options => { | ||
const { data = '', fileName = 'download.txt', fileType = 'text/plain' } = options || {}; | ||
return new Promise((resolve, reject) => { | ||
try { | ||
const { document, navigator, URL } = window; | ||
const blob = new Blob([data], { type: fileType }); | ||
|
||
if (navigator?.msSaveBlob) { | ||
navigator.msSaveBlob(blob, fileName); | ||
resolve({ fileName, data }); | ||
} else { | ||
const anchorTag = document.createElement('a'); | ||
|
||
anchorTag.href = URL.createObjectURL(blob); | ||
anchorTag.style.display = 'none'; | ||
anchorTag.download = fileName; | ||
|
||
document.body.appendChild(anchorTag); | ||
|
||
anchorTag.click(); | ||
|
||
setTimeout(() => { | ||
document.body.removeChild(anchorTag); | ||
URL.revokeObjectURL(blob); | ||
resolve({ fileName, data }); | ||
}, 250); | ||
} | ||
} catch (error) { | ||
reject(error); | ||
} | ||
}); | ||
}; | ||
|
||
/** | ||
* Download the debug log file. | ||
*/ | ||
const debugLog = async () => { | ||
try { | ||
const { sessionStorage } = window; | ||
const fileName = `${helpers.UI_LOGGER_FILE}`.replace( | ||
'{0}', | ||
moment(dateHelpers.getCurrentDate()).format('YYYYMMDD_HHmmss') | ||
); | ||
const data = JSON.stringify(JSON.parse(sessionStorage.getItem(`${helpers.UI_LOGGER_ID}`)), null, 2); | ||
|
||
await downloadData({ data, fileName, fileType: 'application/json' }); | ||
} catch (e) { | ||
throw new Error(`debuglog error, ${e.message}`); | ||
} | ||
}; | ||
|
||
const downloadHelpers = { | ||
downloadData, | ||
debugLog | ||
}; | ||
|
||
helpers.browserExpose({ debugLog }, { limit: false }); | ||
|
||
export { downloadHelpers as default, downloadHelpers, downloadData, debugLog }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { helpers } from './helpers'; | ||
import { dateHelpers } from './dateHelpers'; | ||
import { downloadHelpers } from './downloadHelpers'; | ||
|
||
export { helpers as default, helpers, dateHelpers }; | ||
export { helpers as default, helpers, dateHelpers, downloadHelpers }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/** | ||
* Modify actions for privacy. | ||
* | ||
* @param {object} action | ||
* @param {string} action.type | ||
* @param {object} action.payload | ||
* @returns {object} | ||
*/ | ||
const sanitizeActionHeaders = ({ type, payload, ...action }) => { | ||
if (payload) { | ||
let updatedPayload = { ...payload, headers: {} }; | ||
|
||
if (Array.isArray(payload)) { | ||
updatedPayload = payload.map(({ headers, ...obj }) => ({ ...obj, headers: {} })); | ||
} | ||
|
||
return { type, payload: updatedPayload, ...action }; | ||
} | ||
|
||
return { type, ...action }; | ||
}; | ||
|
||
/** | ||
* Return existing sessionStorage log. | ||
* | ||
* @param {string} id | ||
* @param {number} limit | ||
* @returns {Array} | ||
*/ | ||
const getActions = (id, limit) => { | ||
const { sessionStorage } = window; | ||
const item = sessionStorage.getItem(id); | ||
let parsedItems = (item && (JSON.parse(item) || {})?.actions) || null; | ||
|
||
if (parsedItems?.length && limit > 0) { | ||
parsedItems = parsedItems.slice(limit * -1); | ||
} | ||
|
||
return parsedItems; | ||
}; | ||
|
||
/** | ||
* Store actions against an id in sessionStorage. | ||
* | ||
* @param {object} action | ||
* @param {object} config | ||
* @param {number} config.id | ||
* @param {number} config.limit | ||
*/ | ||
const recordAction = (action, { id, limit, ...config }) => { | ||
const { navigator, sessionStorage } = window; | ||
const items = getActions(id, limit) || []; | ||
const priorItem = items[items.length - 1]; | ||
const updatedAction = sanitizeActionHeaders(action); | ||
const actionObj = { | ||
diff: 0, | ||
timestamp: Date.now(), | ||
action: updatedAction | ||
}; | ||
|
||
if (priorItem && priorItem.timestamp) { | ||
actionObj.diff = actionObj.timestamp - priorItem.timestamp; | ||
} | ||
|
||
items.push(actionObj); | ||
sessionStorage.setItem( | ||
id, | ||
JSON.stringify({ | ||
browser: navigator.userAgent, | ||
timestamp: new Date(), | ||
...config, | ||
actions: items | ||
}) | ||
); | ||
}; | ||
|
||
/** | ||
* Expose settings and record middleware. | ||
* | ||
* @param {object} config | ||
* @returns {Function} | ||
*/ | ||
const actionRecordMiddleware = (config = {}) => { | ||
return () => next => action => { | ||
recordAction(action, { | ||
id: 'actionRecordMiddleware/v1', | ||
limitResults: 100, | ||
...config | ||
}); | ||
|
||
return next(action); | ||
}; | ||
}; | ||
|
||
export { actionRecordMiddleware as default, actionRecordMiddleware }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters