From b7da4dfeda55ff058694d5b0fa0115810260ff14 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 18 Jan 2016 13:46:29 -0400 Subject: [PATCH 1/4] Autoselect the drive if only one drive is present --- build/browser/app.js | 6 ++++++ lib/browser/app.js | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/build/browser/app.js b/build/browser/app.js index b0e36ba4..fdf6f09f 100644 --- a/build/browser/app.js +++ b/build/browser/app.js @@ -53,6 +53,12 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState this.selection.clear(); this.writer.setProgress(0); this.scanner.start(2000); + + this.scanner.scan().then(function (res) { + if(res.length === 1){ + self.selectDrive(res[0]); + } + }); }; this.restart(); diff --git a/lib/browser/app.js b/lib/browser/app.js index 264ab437..82c366ac 100644 --- a/lib/browser/app.js +++ b/lib/browser/app.js @@ -52,6 +52,12 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState this.selection.clear(); this.writer.setProgress(0); this.scanner.start(2000); + + this.scanner.scan().then(function (res) { + if(res.length === 1){ + self.selectDrive(res[0]); + } + }); }; this.restart(); From 491a0ae9c91c55ab148b49edf2c60da0c992e5b4 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 18 Jan 2016 13:23:50 -0400 Subject: [PATCH 2/4] Trigger drive scans after slight delays This allows unit tests to easily capture the first run, as otherwise happens too fast. --- build/browser/app.js | 13 ++++++++++--- lib/browser/modules/drive-scanner.js | 13 ++++++++++--- tests/browser/modules/drive-scanner.spec.js | 11 +++++++++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/build/browser/app.js b/build/browser/app.js index fdf6f09f..ed79871c 100644 --- a/build/browser/app.js +++ b/build/browser/app.js @@ -131,7 +131,7 @@ if (window.mocha) { var driveScanner = angular.module('ResinEtcher.drive-scanner', []); -driveScanner.service('DriveScannerRefreshService', function($interval) { +driveScanner.service('DriveScannerRefreshService', function($interval, $timeout) { 'use strict'; var interval = null; @@ -150,8 +150,15 @@ driveScanner.service('DriveScannerRefreshService', function($interval) { * }, 2000); */ this.every = function(fn, ms) { - fn(); - interval = $interval(fn, ms); + + // Call fn after in the next process tick + // to be able to capture the first run + // in unit tests. + $timeout(function() { + fn(); + interval = $interval(fn, ms); + }); + }; /** diff --git a/lib/browser/modules/drive-scanner.js b/lib/browser/modules/drive-scanner.js index 65fd9351..549a4bcb 100644 --- a/lib/browser/modules/drive-scanner.js +++ b/lib/browser/modules/drive-scanner.js @@ -34,7 +34,7 @@ if (window.mocha) { var driveScanner = angular.module('ResinEtcher.drive-scanner', []); -driveScanner.service('DriveScannerRefreshService', function($interval) { +driveScanner.service('DriveScannerRefreshService', function($interval, $timeout) { 'use strict'; var interval = null; @@ -53,8 +53,15 @@ driveScanner.service('DriveScannerRefreshService', function($interval) { * }, 2000); */ this.every = function(fn, ms) { - fn(); - interval = $interval(fn, ms); + + // Call fn after in the next process tick + // to be able to capture the first run + // in unit tests. + $timeout(function() { + fn(); + interval = $interval(fn, ms); + }); + }; /** diff --git a/tests/browser/modules/drive-scanner.spec.js b/tests/browser/modules/drive-scanner.spec.js index 8cabbec1..2d2cedeb 100644 --- a/tests/browser/modules/drive-scanner.spec.js +++ b/tests/browser/modules/drive-scanner.spec.js @@ -12,9 +12,11 @@ describe('Browser: DriveScanner', function() { var DriveScannerRefreshService; var $interval; + var $timeout; - beforeEach(angular.mock.inject(function(_$interval_, _DriveScannerRefreshService_) { + beforeEach(angular.mock.inject(function(_$interval_, _$timeout_, _DriveScannerRefreshService_) { $interval = _$interval_; + $timeout = _$timeout_; DriveScannerRefreshService = _DriveScannerRefreshService_; })); @@ -23,6 +25,7 @@ describe('Browser: DriveScanner', function() { it('should call the function right away', function() { var spy = m.sinon.spy(); DriveScannerRefreshService.every(spy, 1000); + $timeout.flush(); DriveScannerRefreshService.stop(); m.chai.expect(spy).to.have.been.calledOnce; }); @@ -30,6 +33,7 @@ describe('Browser: DriveScanner', function() { it('should call the function in an interval', function() { var spy = m.sinon.spy(); DriveScannerRefreshService.every(spy, 100); + $timeout.flush(); // 400ms = 100ms / 4 + 1 (the initial call) $interval.flush(400); @@ -45,11 +49,13 @@ describe('Browser: DriveScanner', function() { describe('DriveScannerService', function() { var $interval; + var $timeout; var $q; var DriveScannerService; - beforeEach(angular.mock.inject(function(_$interval_, _$q_, _DriveScannerService_) { + beforeEach(angular.mock.inject(function(_$interval_, _$timeout_, _$q_, _DriveScannerService_) { $interval = _$interval_; + $timeout = _$timeout_; $q = _$q_; DriveScannerService = _DriveScannerService_; })); @@ -169,6 +175,7 @@ describe('Browser: DriveScanner', function() { it('should set the drives to the scanned ones', function() { DriveScannerService.start(200); + $timeout.flush(); $interval.flush(400); m.chai.expect(DriveScannerService.drives).to.deep.equal(this.drives); DriveScannerService.stop(); From f218cc1b5994d215cfcdffa642986532b88d92f0 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 18 Jan 2016 13:27:27 -0400 Subject: [PATCH 3/4] Make DriveScanner.start() return an EventEmitter instance --- build/browser/app.js | 22 +++++++++++++++++++-- lib/browser/modules/drive-scanner.js | 22 +++++++++++++++++++-- tests/browser/modules/drive-scanner.spec.js | 15 ++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/build/browser/app.js b/build/browser/app.js index ed79871c..31fa1ef9 100644 --- a/build/browser/app.js +++ b/build/browser/app.js @@ -117,6 +117,7 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState var angular = require('angular'); var _ = require('lodash'); +var EventEmitter = require('events').EventEmitter; var remote = window.require('remote'); if (window.mocha) { @@ -247,15 +248,32 @@ driveScanner.service('DriveScannerService', function($q, DriveScannerRefreshServ * @function * @public * + * @description + * This function returns an event emitter instance + * that emits a `scan` event everything it scans + * the drives successfully. + * * @param {Number} ms - interval milliseconds + * @returns {EventEmitter} event emitter instance * * @example - * DriveScannerService.start(2000); + * var emitter = DriveScannerService.start(2000); + * + * emitter.on('scan', function(drives) { + * console.log(drives); + * }); */ this.start = function(ms) { + var emitter = new EventEmitter(); + DriveScannerRefreshService.every(function() { - return self.scan().then(self.setDrives); + return self.scan().then(function(drives) { + emitter.emit('scan', drives); + self.setDrives(drives); + }); }, ms); + + return emitter; }; /** diff --git a/lib/browser/modules/drive-scanner.js b/lib/browser/modules/drive-scanner.js index 549a4bcb..bd3b6763 100644 --- a/lib/browser/modules/drive-scanner.js +++ b/lib/browser/modules/drive-scanner.js @@ -20,6 +20,7 @@ var angular = require('angular'); var _ = require('lodash'); +var EventEmitter = require('events').EventEmitter; var remote = window.require('remote'); if (window.mocha) { @@ -150,15 +151,32 @@ driveScanner.service('DriveScannerService', function($q, DriveScannerRefreshServ * @function * @public * + * @description + * This function returns an event emitter instance + * that emits a `scan` event everything it scans + * the drives successfully. + * * @param {Number} ms - interval milliseconds + * @returns {EventEmitter} event emitter instance * * @example - * DriveScannerService.start(2000); + * var emitter = DriveScannerService.start(2000); + * + * emitter.on('scan', function(drives) { + * console.log(drives); + * }); */ this.start = function(ms) { + var emitter = new EventEmitter(); + DriveScannerRefreshService.every(function() { - return self.scan().then(self.setDrives); + return self.scan().then(function(drives) { + emitter.emit('scan', drives); + self.setDrives(drives); + }); }, ms); + + return emitter; }; /** diff --git a/tests/browser/modules/drive-scanner.spec.js b/tests/browser/modules/drive-scanner.spec.js index 2d2cedeb..8f4c1dc4 100644 --- a/tests/browser/modules/drive-scanner.spec.js +++ b/tests/browser/modules/drive-scanner.spec.js @@ -181,6 +181,21 @@ describe('Browser: DriveScanner', function() { DriveScannerService.stop(); }); + describe('.start()', function() { + + it('should emit a `scan` event with the drives', function() { + var emitter = DriveScannerService.start(2000); + var scanSpy = m.sinon.spy(); + emitter.on('scan', scanSpy); + $timeout.flush(); + $interval.flush(1000); + m.chai.expect(scanSpy).to.have.been.calledOnce; + m.chai.expect(scanSpy).to.have.been.calledWith(this.drives); + DriveScannerService.stop(); + }); + + }); + }); }); From 9ffc6427842ba08c4d0287f695175efda03d287d Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 18 Jan 2016 13:39:07 -0400 Subject: [PATCH 4/4] Autoselect a single drive by using DriveScanner `scan` event - The autoselection only happens once the user has selected an image to prevent weird behaviour. - The autoselection happens only if the current selected drive is different from the new drive in order to avoid selecting the same driver over and over again if it still is the only one. --- build/browser/app.js | 23 +++++++++++++++++++---- lib/browser/app.js | 23 +++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/build/browser/app.js b/build/browser/app.js index 31fa1ef9..70d07b0e 100644 --- a/build/browser/app.js +++ b/build/browser/app.js @@ -20,6 +20,7 @@ */ var angular = require('angular'); +var _ = require('lodash'); var remote = window.require('remote'); var shell = remote.require('shell'); var dialog = remote.require('./src/dialog'); @@ -52,12 +53,26 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState console.debug('Restarting'); this.selection.clear(); this.writer.setProgress(0); - this.scanner.start(2000); + this.scanner.start(2000).on('scan', function(drives) { + + // 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 + // which looks very weird. + if (drives.length === 1 && self.selection.hasImage()) { + var drive = _.first(drives); + + // Do not autoselect the same drive over and over again + // and fill the logs unnecessary. + // `angular.equals` is used instead of `_.isEqual` to + // cope with `$$hashKey`. + if (!angular.equals(self.selection.getDrive(), drive)) { + console.debug('Autoselecting drive: ' + drive.device); + self.selectDrive(drive); + } - this.scanner.scan().then(function (res) { - if(res.length === 1){ - self.selectDrive(res[0]); } + }); }; diff --git a/lib/browser/app.js b/lib/browser/app.js index 82c366ac..556949d4 100644 --- a/lib/browser/app.js +++ b/lib/browser/app.js @@ -19,6 +19,7 @@ */ var angular = require('angular'); +var _ = require('lodash'); var remote = window.require('remote'); var shell = remote.require('shell'); var dialog = remote.require('./src/dialog'); @@ -51,12 +52,26 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState console.debug('Restarting'); this.selection.clear(); this.writer.setProgress(0); - this.scanner.start(2000); + this.scanner.start(2000).on('scan', function(drives) { + + // 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 + // which looks very weird. + if (drives.length === 1 && self.selection.hasImage()) { + var drive = _.first(drives); + + // Do not autoselect the same drive over and over again + // and fill the logs unnecessary. + // `angular.equals` is used instead of `_.isEqual` to + // cope with `$$hashKey`. + if (!angular.equals(self.selection.getDrive(), drive)) { + console.debug('Autoselecting drive: ' + drive.device); + self.selectDrive(drive); + } - this.scanner.scan().then(function (res) { - if(res.length === 1){ - self.selectDrive(res[0]); } + }); };