From 67daf086a2c923b4d41fcfff3584fc685cecd49f Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Fri, 8 Apr 2016 12:17:36 -0400 Subject: [PATCH] Detect removal of selected drive (#264) Suppose you plug a device, select it in Etcher, but then eject it from your computer. Etcher will keep the selection thinking the drive is still there. With this PR, the selected drive, if any, is ensured its still inside the array of available drives, otherwise the selected is cleared. Fixes: https://github.com/resin-io/etcher/issues/254 Signed-off-by: Juan Cruz Viotti --- lib/browser/app.js | 5 ++ lib/browser/models/selection-state.js | 24 ++++++ tests/browser/models/selection-state.spec.js | 85 ++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/lib/browser/app.js b/lib/browser/app.js index f0d44458..c931f4fd 100644 --- a/lib/browser/app.js +++ b/lib/browser/app.js @@ -124,6 +124,11 @@ app.controller('AppController', function( this.scanner.start(2000).on('error', dialog.showError).on('scan', function(drives) { + // Cover the case where you select a drive, but then eject it. + if (self.selection.hasDrive() && !_.find(drives, self.selection.isCurrentDrive)) { + self.selection.removeDrive(); + } + // Notice we only autoselect the drive if there is an image, // which means that the first step was completed successfully, // otherwise the drive is selected while the drive step is disabled diff --git a/lib/browser/models/selection-state.js b/lib/browser/models/selection-state.js index 7d7d8a5c..96acf8ec 100644 --- a/lib/browser/models/selection-state.js +++ b/lib/browser/models/selection-state.js @@ -166,4 +166,28 @@ SelectionStateModel.service('SelectionStateModel', function() { } }; + /** + * @summary Check if a drive is the current drive + * @function + * @public + * + * @param {Object} drive - drive + * @returns {Boolean} whether the drive is the current drive + * + * @example + * if (SelectionStateModel.isCurrentDrive({ + * device: '/dev/sdb', + * description: 'DataTraveler 2.0', + * size: '7.3G', + * mountpoint: '/media/UNTITLED', + * name: '/dev/sdb', + * system: false + * })) { + * console.log('This is the current drive!'); + * } + */ + this.isCurrentDrive = function(drive) { + return angular.equals(self.getDrive(), drive); + }; + }); diff --git a/tests/browser/models/selection-state.spec.js b/tests/browser/models/selection-state.spec.js index cfdcc29e..b89796d0 100644 --- a/tests/browser/models/selection-state.spec.js +++ b/tests/browser/models/selection-state.spec.js @@ -218,6 +218,91 @@ describe('Browser: SelectionState', function() { }); + describe('.isCurrentDrive()', function() { + + describe('given a selected drive', function() { + + beforeEach(function() { + SelectionStateModel.setDrive({ + device: '/dev/sdb', + description: 'DataTraveler 2.0', + size: '7.3G', + mountpoint: '/media/UNTITLED', + name: '/dev/sdb', + system: false + }); + }); + + it('should return true given the exact same drive', function() { + m.chai.expect(SelectionStateModel.isCurrentDrive({ + device: '/dev/sdb', + description: 'DataTraveler 2.0', + size: '7.3G', + mountpoint: '/media/UNTITLED', + name: '/dev/sdb', + system: false + })).to.be.true; + }); + + it('should return true given the exact same drive with a $$hashKey', function() { + m.chai.expect(SelectionStateModel.isCurrentDrive({ + device: '/dev/sdb', + description: 'DataTraveler 2.0', + size: '7.3G', + mountpoint: '/media/UNTITLED', + name: '/dev/sdb', + system: false, + $$hashKey: 1234 + })).to.be.true; + }); + + it('should return false if the device changes', function() { + m.chai.expect(SelectionStateModel.isCurrentDrive({ + device: '/dev/sdc', + description: 'DataTraveler 2.0', + size: '7.3G', + mountpoint: '/media/UNTITLED', + name: '/dev/sdb', + system: false + })).to.be.false; + }); + + it('should return false if the description changes', function() { + m.chai.expect(SelectionStateModel.isCurrentDrive({ + device: '/dev/sdb', + description: 'DataTraveler 3.0', + size: '7.3G', + mountpoint: '/media/UNTITLED', + name: '/dev/sdb', + system: false + })).to.be.false; + }); + + }); + + describe('given no selected drive', function() { + + beforeEach(function() { + SelectionStateModel.removeDrive(); + }); + + it('should return false for anything', function() { + + m.chai.expect(SelectionStateModel.isCurrentDrive({ + device: '/dev/sdb', + description: 'DataTraveler 2.0', + size: '7.3G', + mountpoint: '/media/UNTITLED', + name: '/dev/sdb', + system: false + })).to.be.false; + + }); + + }); + + }); + }); });