diff --git a/docs/state/StateTreeGlossary.md b/docs/state/StateTreeGlossary.md index 20d70d35c6..9809de77b4 100644 --- a/docs/state/StateTreeGlossary.md +++ b/docs/state/StateTreeGlossary.md @@ -116,12 +116,6 @@ Since the Tidepool Uploader is a Chrome App that runs *outside* of the browser e To ensure the highest possible standards of data quality, it is very important for us at Tidepool to prevent uploaders that have been succeeded by newer versions from uploading to the Tidepool cloud. To this end, we have implemented an "info" endpoint on our data ingestion API that responds with (among other things) the minimum version of the Tidepool Uploader that the data ingestion API will accept data from. -#### `version` - -*The property `version` encodes the current version of the uploader in [semver](http://semver.org/).* - -While we use semver at Tidepool, the Chrome Store does not support patch-level version increments, so the minimum - and typical - version number increase that will appear in the Tidepool Uploader is a minor version bump. As a way of distinguishing major releases, on occasion we will choose an arbitrary increase of the minor version number - e.g., skipping from 0.122.0 to 0.150.0 for a major feature release in 0.150.0. - #### `working` *The `working` property is an object with a small handful of keys that record the app's current state with respect to certain asynchronous actions.* diff --git a/lib/containers/App.js b/lib/containers/App.js index 1c5626c102..0eeab07f44 100644 --- a/lib/containers/App.js +++ b/lib/containers/App.js @@ -316,7 +316,6 @@ export default connect( os: state.os, page: state.page, targetUsersForUpload: state.targetUsersForUpload, - version: state.version, unsupported: state.unsupported, uploadIsInProgress: state.working.uploading, uploadsByUser: state.uploadsByUser, diff --git a/lib/containers/root/Root.dev.js b/lib/containers/root/Root.dev.js index 43e63092d3..5fa29d739a 100644 --- a/lib/containers/root/Root.dev.js +++ b/lib/containers/root/Root.dev.js @@ -23,14 +23,14 @@ import configureStore from '../../redux/store/configureStore'; import App from '../App'; import DevTools from '../../components/DevTools'; -const { store, api } = configureStore(); +const { api, store, version } = configureStore(); export default class Root extends Component { render() { return (
- +
diff --git a/lib/containers/root/Root.prod.js b/lib/containers/root/Root.prod.js index 5bf79fbf43..ea55dde3a1 100644 --- a/lib/containers/root/Root.prod.js +++ b/lib/containers/root/Root.prod.js @@ -22,13 +22,13 @@ import configureStore from '../../redux/store/configureStore'; import App from '../App'; -const { store, api } = configureStore(); +const { api, store, version } = configureStore(); export default class Root extends Component { render() { return ( - + ); } diff --git a/lib/redux/actions/async.js b/lib/redux/actions/async.js index 897e212d1c..2f0d117da9 100644 --- a/lib/redux/actions/async.js +++ b/lib/redux/actions/async.js @@ -41,7 +41,6 @@ let daysForCareLink = null; export function doAppInit(config, servicesToInit) { return (dispatch, getState) => { - dispatch(syncActions.setVersion(config.version)); services = servicesToInit; versionInfo.semver = config.version; versionInfo.name = config.namedVersion; @@ -191,7 +190,8 @@ export function doLogout() { export function doCareLinkUpload(deviceKey, creds, utc) { return (dispatch, getState) => { const { api, carelink } = services; - const { devices, targetTimezones, uploadTargetUser, version } = getState(); + const version = versionInfo.semver; + const { devices, targetTimezones, uploadTargetUser } = getState(); const targetDevice = devices[deviceKey]; @@ -240,7 +240,8 @@ export function doCareLinkUpload(deviceKey, creds, utc) { export function doDeviceUpload(driverId, utc) { return (dispatch, getState) => { const { device } = services; - const { devices, os, targetTimezones, uploadTargetUser, version } = getState(); + const version = versionInfo.semver; + const { devices, os, targetTimezones, uploadTargetUser } = getState(); const targetDevice = _.findWhere(devices, {source: {driverId: driverId}}); dispatch(syncActions.deviceDetectRequest()); const opts = { @@ -305,7 +306,7 @@ export function doUpload(deviceKey, opts, utc) { return (dispatch, getState) => { dispatch(syncActions.versionCheckRequest()); const { api } = services; - let { version } = getState(); + const version = versionInfo.semver; api.upload.getVersions((err, versions) => { if (err) { dispatch(syncActions.versionCheckFailure(err)); @@ -355,7 +356,7 @@ export function readFile(userId, deviceKey, file, extension) { return; } dispatch(syncActions.choosingFile(userId, deviceKey)); - const { version } = getState(); + const version = versionInfo.semver; if (file.name.slice(-extension.length) !== extension) { let err = new Error(errorText.E_FILE_EXT + extension); @@ -396,7 +397,7 @@ export function doVersionCheck() { return (dispatch, getState) => { dispatch(syncActions.versionCheckRequest()); const { api } = services; - let { version } = getState(); + const version = versionInfo.semver; api.upload.getVersions((err, versions) => { if (err) { return dispatch(syncActions.versionCheckFailure(err)); diff --git a/lib/redux/actions/sync.js b/lib/redux/actions/sync.js index 61f541e795..b1bc61265e 100644 --- a/lib/redux/actions/sync.js +++ b/lib/redux/actions/sync.js @@ -136,14 +136,6 @@ export function setUploadTargetUser(userId) { }; } -export function setVersion(version) { - return { - type: actionTypes.SET_VERSION, - payload: { version }, - meta: {source: actionSources[actionTypes.SET_VERSION]} - }; -} - export function toggleDropdown(previous, actionSource = actionSources[actionTypes.TOGGLE_DROPDOWN]) { return { type: actionTypes.TOGGLE_DROPDOWN, diff --git a/lib/redux/reducers/misc.js b/lib/redux/reducers/misc.js index c333fceecc..84e01654af 100644 --- a/lib/redux/reducers/misc.js +++ b/lib/redux/reducers/misc.js @@ -109,15 +109,6 @@ export function blipUrls(state = {}, action) { } } -export function version(state = null, action) { - switch (action.type) { - case actionTypes.SET_VERSION: - return action.payload.version; - default: - return state; - } -} - function checkingVersion(state = false, action) { switch (action.type) { case actionTypes.VERSION_CHECK_FAILURE: diff --git a/lib/redux/store/configureStore.js b/lib/redux/store/configureStore.js index ebcc31c7d5..e02791de82 100644 --- a/lib/redux/store/configureStore.js +++ b/lib/redux/store/configureStore.js @@ -56,5 +56,5 @@ else { export default function configureStore(initialState) { const store = finalCreateStore(uploader, initialState); - return { api, store }; + return { api, store, version: config.version}; } diff --git a/test/browser/redux/actions/async.test.js b/test/browser/redux/actions/async.test.js index 1129bff46f..a7e1403111 100644 --- a/test/browser/redux/actions/async.test.js +++ b/test/browser/redux/actions/async.test.js @@ -84,11 +84,6 @@ describe('Asynchronous Actions', () => { log: _.noop }; const expectedActions = [ - { - type: actionTypes.SET_VERSION, - payload: {version: config.version}, - meta: {source: actionSources[actionTypes.SET_VERSION]} - }, { type: actionTypes.INIT_APP_REQUEST, meta: {source: actionSources[actionTypes.INIT_APP_REQUEST]} @@ -131,7 +126,10 @@ describe('Asynchronous Actions', () => { meta: {source: actionSources[actionTypes.VERSION_CHECK_SUCCESS]} } ]; - const store = mockStore({version: config.version}, expectedActions, done); + asyncActions.__Rewire__('versionInfo', { + semver: config.version + }); + const store = mockStore({}, expectedActions, done); store.dispatch(asyncActions.doAppInit(config, servicesToInit)); }); }); @@ -172,11 +170,6 @@ describe('Asynchronous Actions', () => { log: _.noop }; const expectedActions = [ - { - type: actionTypes.SET_VERSION, - payload: {version: config.version}, - meta: {source: actionSources[actionTypes.SET_VERSION]} - }, { type: actionTypes.INIT_APP_REQUEST, meta: {source: actionSources[actionTypes.INIT_APP_REQUEST]} @@ -233,9 +226,11 @@ describe('Asynchronous Actions', () => { meta: {source: actionSources[actionTypes.SET_PAGE]} } ]; + asyncActions.__Rewire__('versionInfo', { + semver: config.version + }); const state = { - uploadTargetUser: pwd.user.userid, - version: config.version + uploadTargetUser: pwd.user.userid }; const store = mockStore(state, expectedActions, done); store.dispatch(asyncActions.doAppInit(config, servicesToInit)); @@ -269,11 +264,6 @@ describe('Asynchronous Actions', () => { log: _.noop }; const expectedActions = [ - { - type: actionTypes.SET_VERSION, - payload: {version: '0.100.0'}, - meta: {source: actionSources[actionTypes.SET_VERSION]} - }, { type: actionTypes.INIT_APP_REQUEST, meta: {source: actionSources[actionTypes.INIT_APP_REQUEST]} @@ -295,6 +285,9 @@ describe('Asynchronous Actions', () => { meta: {source: actionSources[actionTypes.INIT_APP_FAILURE]} } ]; + asyncActions.__Rewire__('versionInfo', { + semver: config.version + }); const store = mockStore({}, expectedActions, done); store.dispatch(asyncActions.doAppInit(config, servicesToInit)); }); @@ -441,9 +434,7 @@ describe('Asynchronous Actions', () => { describe('doUpload [upload aborted b/c version check failed]', () => { it('should dispatch VERSION_CHECK_REQUEST, VERSION_CHECK_FAILURE, UPLOAD_ABORTED', (done) => { const requiredVersion = '0.99.0'; - const initialState = { - version: '0.50.0' - }; + const currentVersion = '0.50.0'; asyncActions.__Rewire__('services', { api: { upload: { @@ -459,7 +450,7 @@ describe('Asynchronous Actions', () => { { type: actionTypes.VERSION_CHECK_FAILURE, error: true, - payload: new UnsupportedError(initialState.version, requiredVersion), + payload: new UnsupportedError(currentVersion, requiredVersion), meta: { source: actionSources[actionTypes.VERSION_CHECK_FAILURE], metric: { @@ -475,7 +466,10 @@ describe('Asynchronous Actions', () => { meta: {source: actionSources[actionTypes.UPLOAD_ABORTED]} } ]; - const store = mockStore(initialState, expectedActions, done); + asyncActions.__Rewire__('versionInfo', { + semver: currentVersion + }); + const store = mockStore({}, expectedActions, done); store.dispatch(asyncActions.doUpload()); }); }); @@ -483,7 +477,6 @@ describe('Asynchronous Actions', () => { describe('doUpload [upload aborted b/c another upload already in progress]', () => { it('should dispatch VERSION_CHECK_REQUEST, VERSION_CHECK_SUCCESS, UPLOAD_ABORTED', (done) => { const initialState = { - version: '0.100.0', working: {uploading: true} }; asyncActions.__Rewire__('services', { @@ -509,6 +502,9 @@ describe('Asynchronous Actions', () => { meta: {source: actionSources[actionTypes.UPLOAD_ABORTED]} } ]; + asyncActions.__Rewire__('versionInfo', { + semver: '0.100.0' + }); const store = mockStore(initialState, expectedActions, done); store.dispatch(asyncActions.doUpload()); }); @@ -1538,10 +1534,10 @@ describe('Asynchronous Actions', () => { } } }); - const state = { - version: currentVersion - }; - const store = mockStore(state, expectedActions, done); + asyncActions.__Rewire__('versionInfo', { + semver: currentVersion + }); + const store = mockStore({}, expectedActions, done); store.dispatch(asyncActions.doVersionCheck()); }); }); @@ -1566,10 +1562,10 @@ describe('Asynchronous Actions', () => { } } }); - const state = { - version: currentVersion - }; - const store = mockStore(state, expectedActions, done); + asyncActions.__Rewire__('versionInfo', { + semver: currentVersion + }); + const store = mockStore({}, expectedActions, done); store.dispatch(asyncActions.doVersionCheck()); }); }); diff --git a/test/browser/redux/actions/sync.test.js b/test/browser/redux/actions/sync.test.js index 2085098d03..091bcb157f 100644 --- a/test/browser/redux/actions/sync.test.js +++ b/test/browser/redux/actions/sync.test.js @@ -278,24 +278,6 @@ describe('Synchronous Actions', () => { }); }); - describe('setVersion', () => { - const VERSION = '0.100.0'; - it('should be an FSA', () => { - let action = syncActions.setVersion(VERSION); - - expect(isFSA(action)).to.be.true; - }); - - it('should create an action to set the uploader version', () => { - const expectedAction = { - type: actionTypes.SET_VERSION, - payload: {version: VERSION}, - meta: {source: actionSources[actionTypes.SET_VERSION]} - }; - expect(syncActions.setVersion(VERSION)).to.deep.equal(expectedAction); - }); - }); - describe('toggleDropdown', () => { const DROPDOWN_PREVIOUS_STATE = true; it('should be an FSA', () => { diff --git a/test/browser/redux/reducers/misc.test.js b/test/browser/redux/reducers/misc.test.js index c321b67bb6..29d962e7cd 100644 --- a/test/browser/redux/reducers/misc.test.js +++ b/test/browser/redux/reducers/misc.test.js @@ -230,19 +230,6 @@ describe('misc reducers', () => { }); }); - describe('version', () => { - it('should return the initial state', () => { - expect(misc.version(undefined, {})).to.be.null; - }); - - it('should handle SET_VERSION', () => { - expect(misc.version(undefined, { - type: actionTypes.SET_VERSION, - payload: {version: '0.100.0'} - })).to.deep.equal('0.100.0'); - }); - }); - describe('working', () => { it('should return the initial state', () => { expect(misc.working(undefined, {})).to.deep.equal({