mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-25 20:26:36 +00:00
refactor(GUI): extract FlashStateModel from ImageWriterService (#606)
`ImageWriterService` currently has two responsibilities. It contains logic to start and manage a flash process, and provides an API to interact with the current flash state. To honour the single responsibility principle, we extract `FlashStateModel` from `ImageWriterService`. Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
parent
70fe34b591
commit
1febeda04e
@ -47,6 +47,7 @@ const app = angular.module('Etcher', [
|
|||||||
require('./models/settings'),
|
require('./models/settings'),
|
||||||
require('./models/supported-formats'),
|
require('./models/supported-formats'),
|
||||||
require('./models/drives'),
|
require('./models/drives'),
|
||||||
|
require('./models/flash-state'),
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
require('./components/progress-button/progress-button'),
|
require('./components/progress-button/progress-button'),
|
||||||
@ -95,9 +96,9 @@ app.run((AnalyticsService, UpdateNotifierService, SelectionStateModel) => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.run((AnalyticsService, OSWindowProgressService, ImageWriterService) => {
|
app.run((AnalyticsService, OSWindowProgressService, FlashStateModel) => {
|
||||||
Store.subscribe(() => {
|
Store.subscribe(() => {
|
||||||
const flashState = ImageWriterService.getFlashState();
|
const flashState = FlashStateModel.getFlashState();
|
||||||
|
|
||||||
// There is usually a short time period between the `isFlashing()`
|
// There is usually a short time period between the `isFlashing()`
|
||||||
// property being set, and the flashing actually starting, which
|
// property being set, and the flashing actually starting, which
|
||||||
@ -106,7 +107,7 @@ app.run((AnalyticsService, OSWindowProgressService, ImageWriterService) => {
|
|||||||
//
|
//
|
||||||
// We use the presence of `.eta` to determine that the actual
|
// We use the presence of `.eta` to determine that the actual
|
||||||
// writing started.
|
// writing started.
|
||||||
if (!ImageWriterService.isFlashing() || !flashState.eta) {
|
if (!FlashStateModel.isFlashing() || !flashState.eta) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +136,7 @@ app.controller('AppController', function(
|
|||||||
$state,
|
$state,
|
||||||
DriveScannerService,
|
DriveScannerService,
|
||||||
SelectionStateModel,
|
SelectionStateModel,
|
||||||
|
FlashStateModel,
|
||||||
SettingsModel,
|
SettingsModel,
|
||||||
SupportedFormatsModel,
|
SupportedFormatsModel,
|
||||||
DrivesModel,
|
DrivesModel,
|
||||||
@ -152,6 +154,7 @@ app.controller('AppController', function(
|
|||||||
this.selection = SelectionStateModel;
|
this.selection = SelectionStateModel;
|
||||||
this.drives = DrivesModel;
|
this.drives = DrivesModel;
|
||||||
this.writer = ImageWriterService;
|
this.writer = ImageWriterService;
|
||||||
|
this.state = FlashStateModel;
|
||||||
this.settings = SettingsModel;
|
this.settings = SettingsModel;
|
||||||
this.tooltipModal = TooltipModalService;
|
this.tooltipModal = TooltipModalService;
|
||||||
|
|
||||||
@ -174,7 +177,7 @@ app.controller('AppController', function(
|
|||||||
// This catches the case where the user enters
|
// This catches the case where the user enters
|
||||||
// the settings screen when a flash finished
|
// the settings screen when a flash finished
|
||||||
// and goes back to the main screen with the back button.
|
// and goes back to the main screen with the back button.
|
||||||
if (!this.writer.isFlashing()) {
|
if (!FlashStateModel.isFlashing()) {
|
||||||
|
|
||||||
this.selection.clear({
|
this.selection.clear({
|
||||||
|
|
||||||
@ -248,7 +251,7 @@ app.controller('AppController', function(
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.reselectImage = () => {
|
this.reselectImage = () => {
|
||||||
if (this.writer.isFlashing()) {
|
if (FlashStateModel.isFlashing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +266,7 @@ app.controller('AppController', function(
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.reselectDrive = () => {
|
this.reselectDrive = () => {
|
||||||
if (this.writer.isFlashing()) {
|
if (FlashStateModel.isFlashing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,12 +279,12 @@ app.controller('AppController', function(
|
|||||||
preserveImage: true
|
preserveImage: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this.writer.resetState();
|
FlashStateModel.resetState();
|
||||||
AnalyticsService.logEvent('Restart after failure');
|
AnalyticsService.logEvent('Restart after failure');
|
||||||
};
|
};
|
||||||
|
|
||||||
this.wasLastFlashSuccessful = () => {
|
this.wasLastFlashSuccessful = () => {
|
||||||
const flashResults = this.writer.getFlashResults();
|
const flashResults = FlashStateModel.getFlashResults();
|
||||||
|
|
||||||
if (_.get(flashResults, 'cancelled', false)) {
|
if (_.get(flashResults, 'cancelled', false)) {
|
||||||
return true;
|
return true;
|
||||||
@ -292,7 +295,7 @@ app.controller('AppController', function(
|
|||||||
|
|
||||||
this.flash = (image, drive) => {
|
this.flash = (image, drive) => {
|
||||||
|
|
||||||
if (this.writer.isFlashing()) {
|
if (FlashStateModel.isFlashing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +309,7 @@ app.controller('AppController', function(
|
|||||||
});
|
});
|
||||||
|
|
||||||
return this.writer.flash(image, drive).then(() => {
|
return this.writer.flash(image, drive).then(() => {
|
||||||
const results = ImageWriterService.getFlashResults();
|
const results = FlashStateModel.getFlashResults();
|
||||||
|
|
||||||
if (results.cancelled) {
|
if (results.cancelled) {
|
||||||
return;
|
return;
|
||||||
|
175
lib/gui/models/flash-state.js
Normal file
175
lib/gui/models/flash-state.js
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Resin.io
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module Etcher.Models.FlashState
|
||||||
|
*/
|
||||||
|
|
||||||
|
const angular = require('angular');
|
||||||
|
const _ = require('lodash');
|
||||||
|
const Store = require('./store');
|
||||||
|
const MODULE_NAME = 'Etcher.Models.FlashState';
|
||||||
|
const FlashState = angular.module(MODULE_NAME, []);
|
||||||
|
|
||||||
|
FlashState.service('FlashStateModel', function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Reset flash state
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* FlashStateModel.resetState();
|
||||||
|
*/
|
||||||
|
this.resetState = () => {
|
||||||
|
Store.dispatch({
|
||||||
|
type: Store.Actions.RESET_FLASH_STATE
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Check if currently flashing
|
||||||
|
* @function
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @returns {Boolean} whether is flashing or not
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* if (FlashStateModel.isFlashing()) {
|
||||||
|
* console.log('We\'re currently flashing');
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
this.isFlashing = () => {
|
||||||
|
return Store.getState().toJS().isFlashing;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Set the flashing flag
|
||||||
|
* @function
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* This function is extracted for testing purposes.
|
||||||
|
*
|
||||||
|
* The flag is used to signify that we're going to
|
||||||
|
* start a flash process.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* FlashStateModel.setFlashingFlag();
|
||||||
|
*/
|
||||||
|
this.setFlashingFlag = () => {
|
||||||
|
Store.dispatch({
|
||||||
|
type: Store.Actions.SET_FLASHING_FLAG
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Unset the flashing flag
|
||||||
|
* @function
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* This function is extracted for testing purposes.
|
||||||
|
*
|
||||||
|
* The flag is used to signify that the write process ended.
|
||||||
|
*
|
||||||
|
* @param {Object} results - flash results
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* FlashStateModel.unsetFlashingFlag({
|
||||||
|
* passedValidation: true,
|
||||||
|
* cancelled: false,
|
||||||
|
* sourceChecksum: 'a1b45d'
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
this.unsetFlashingFlag = (results) => {
|
||||||
|
Store.dispatch({
|
||||||
|
type: Store.Actions.UNSET_FLASHING_FLAG,
|
||||||
|
data: results
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Set the flashing state
|
||||||
|
* @function
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* This function is extracted for testing purposes.
|
||||||
|
*
|
||||||
|
* @param {Object} state - flashing state
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* FlashStateModel.setProgressState({
|
||||||
|
* type: 'write',
|
||||||
|
* percentage: 50,
|
||||||
|
* eta: 15,
|
||||||
|
* speed: 100000000000
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
this.setProgressState = (state) => {
|
||||||
|
Store.dispatch({
|
||||||
|
type: Store.Actions.SET_FLASH_STATE,
|
||||||
|
data: {
|
||||||
|
type: state.type,
|
||||||
|
percentage: state.percentage,
|
||||||
|
eta: state.eta,
|
||||||
|
|
||||||
|
speed: _.attempt(() => {
|
||||||
|
if (_.isNumber(state.speed) && !_.isNaN(state.speed)) {
|
||||||
|
|
||||||
|
// Transform bytes to megabytes preserving only two decimal places
|
||||||
|
return Math.floor(state.speed / 1e+6 * 100) / 100;
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get the flash results
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @returns {Object} flash results
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const results = FlashStateModel.getFlashResults();
|
||||||
|
*/
|
||||||
|
this.getFlashResults = () => {
|
||||||
|
return Store.getState().toJS().flashResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get the current flash state
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @returns {Object} flash state
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const flashState = FlashStateModel.getFlashState();
|
||||||
|
*/
|
||||||
|
this.getFlashState = () => {
|
||||||
|
return Store.getState().get('flashState').toJS();
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = MODULE_NAME;
|
@ -22,157 +22,15 @@
|
|||||||
|
|
||||||
const angular = require('angular');
|
const angular = require('angular');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const Store = require('../models/store');
|
|
||||||
const childWriter = require('../../src/child-writer');
|
const childWriter = require('../../src/child-writer');
|
||||||
|
|
||||||
const MODULE_NAME = 'Etcher.Modules.ImageWriter';
|
const MODULE_NAME = 'Etcher.Modules.ImageWriter';
|
||||||
const imageWriter = angular.module(MODULE_NAME, [
|
const imageWriter = angular.module(MODULE_NAME, [
|
||||||
require('../models/settings')
|
require('../models/settings'),
|
||||||
|
require('../models/flash-state')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel) {
|
imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel, FlashStateModel) {
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Reset flash state
|
|
||||||
* @function
|
|
||||||
* @public
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ImageWriterService.resetState();
|
|
||||||
*/
|
|
||||||
this.resetState = () => {
|
|
||||||
Store.dispatch({
|
|
||||||
type: Store.Actions.RESET_FLASH_STATE
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Check if currently flashing
|
|
||||||
* @function
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @returns {Boolean} whether is flashing or not
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* if (ImageWriterService.isFlashing()) {
|
|
||||||
* console.log('We\'re currently flashing');
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
this.isFlashing = () => {
|
|
||||||
return Store.getState().toJS().isFlashing;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Set the flashing flag
|
|
||||||
* @function
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* This function is extracted for testing purposes.
|
|
||||||
*
|
|
||||||
* The flag is used to signify that we're going to
|
|
||||||
* start a flash process.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ImageWriterService.setFlashingFlag();
|
|
||||||
*/
|
|
||||||
this.setFlashingFlag = () => {
|
|
||||||
Store.dispatch({
|
|
||||||
type: Store.Actions.SET_FLASHING_FLAG
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Unset the flashing flag
|
|
||||||
* @function
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* This function is extracted for testing purposes.
|
|
||||||
*
|
|
||||||
* The flag is used to signify that the write process ended.
|
|
||||||
*
|
|
||||||
* @param {Object} results - flash results
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ImageWriterService.unsetFlashingFlag({
|
|
||||||
* passedValidation: true,
|
|
||||||
* cancelled: false,
|
|
||||||
* sourceChecksum: 'a1b45d'
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
this.unsetFlashingFlag = (results) => {
|
|
||||||
Store.dispatch({
|
|
||||||
type: Store.Actions.UNSET_FLASHING_FLAG,
|
|
||||||
data: results
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Set the flashing state
|
|
||||||
* @function
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* This function is extracted for testing purposes.
|
|
||||||
*
|
|
||||||
* @param {Object} state - flashing state
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ImageWriterService.setProgressState({
|
|
||||||
* type: 'write',
|
|
||||||
* percentage: 50,
|
|
||||||
* eta: 15,
|
|
||||||
* speed: 100000000000
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
this.setProgressState = (state) => {
|
|
||||||
Store.dispatch({
|
|
||||||
type: Store.Actions.SET_FLASH_STATE,
|
|
||||||
data: {
|
|
||||||
type: state.type,
|
|
||||||
percentage: state.percentage,
|
|
||||||
eta: state.eta,
|
|
||||||
|
|
||||||
speed: _.attempt(() => {
|
|
||||||
if (_.isNumber(state.speed) && !_.isNaN(state.speed)) {
|
|
||||||
|
|
||||||
// Transform bytes to megabytes preserving only two decimal places
|
|
||||||
return Math.floor(state.speed / 1e+6 * 100) / 100;
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Get the flash results
|
|
||||||
* @function
|
|
||||||
* @public
|
|
||||||
*
|
|
||||||
* @returns {Object} flash results
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const results = ImageWriterService.getFlashResults();
|
|
||||||
*/
|
|
||||||
this.getFlashResults = () => {
|
|
||||||
return Store.getState().toJS().flashResults;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Get the current flash state
|
|
||||||
* @function
|
|
||||||
* @public
|
|
||||||
*
|
|
||||||
* @returns {Object} flash state
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const flashState = ImageWriterService.getFlashState();
|
|
||||||
*/
|
|
||||||
this.getFlashState = () => {
|
|
||||||
return Store.getState().get('flashState').toJS();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Perform write operation
|
* @summary Perform write operation
|
||||||
@ -228,11 +86,11 @@ imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel
|
|||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
this.flash = (image, drive) => {
|
this.flash = (image, drive) => {
|
||||||
if (this.isFlashing()) {
|
if (FlashStateModel.isFlashing()) {
|
||||||
return $q.reject(new Error('There is already a flash in progress'));
|
return $q.reject(new Error('There is already a flash in progress'));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setFlashingFlag();
|
FlashStateModel.setFlashingFlag();
|
||||||
|
|
||||||
return this.performWrite(image, drive, (state) => {
|
return this.performWrite(image, drive, (state) => {
|
||||||
|
|
||||||
@ -241,7 +99,7 @@ imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel
|
|||||||
// `.getFlashState()` will not return
|
// `.getFlashState()` will not return
|
||||||
// the latest updated progress state.
|
// the latest updated progress state.
|
||||||
$rootScope.$apply(() => {
|
$rootScope.$apply(() => {
|
||||||
this.setProgressState(state);
|
FlashStateModel.setProgressState(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
}).then((results) => {
|
}).then((results) => {
|
||||||
@ -253,9 +111,9 @@ imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel
|
|||||||
passedValidation: false
|
passedValidation: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this.unsetFlashingFlag(results);
|
FlashStateModel.unsetFlashingFlag(results);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.unsetFlashingFlag({
|
FlashStateModel.unsetFlashingFlag({
|
||||||
cancelled: false,
|
cancelled: false,
|
||||||
passedValidation: false,
|
passedValidation: false,
|
||||||
errorCode: error.code
|
errorCode: error.code
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = function($state, ImageWriterService, SelectionStateModel, AnalyticsService, SettingsModel) {
|
module.exports = function($state, FlashStateModel, SelectionStateModel, AnalyticsService, SettingsModel) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Settings model
|
* @summary Settings model
|
||||||
@ -30,7 +30,7 @@ module.exports = function($state, ImageWriterService, SelectionStateModel, Analy
|
|||||||
* @type String
|
* @type String
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
this.checksum = ImageWriterService.getFlashResults().sourceChecksum;
|
this.checksum = FlashStateModel.getFlashResults().sourceChecksum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Restart the flashing process
|
* @summary Restart the flashing process
|
||||||
|
@ -31,7 +31,7 @@ const MODULE_NAME = 'Etcher.Pages.Finish';
|
|||||||
const FinishPage = angular.module(MODULE_NAME, [
|
const FinishPage = angular.module(MODULE_NAME, [
|
||||||
require('angular-ui-router'),
|
require('angular-ui-router'),
|
||||||
require('../../modules/analytics'),
|
require('../../modules/analytics'),
|
||||||
require('../../modules/image-writer'),
|
require('../../models/flash-state'),
|
||||||
require('../../models/selection-state'),
|
require('../../models/selection-state'),
|
||||||
require('../../models/settings')
|
require('../../models/settings')
|
||||||
]);
|
]);
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<button class="btn btn-link step-footer"
|
<button class="btn btn-link step-footer"
|
||||||
ng-click="app.reselectImage()"
|
ng-click="app.reselectImage()"
|
||||||
ng-hide="app.writer.isFlashing()">Change</button>
|
ng-hide="app.state.isFlashing()">Change</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -66,7 +66,7 @@
|
|||||||
}">{{ app.selection.getDrive().name }} - {{ app.selection.getDrive().size | gigabyte | number:1 }} GB</div>
|
}">{{ app.selection.getDrive().name }} - {{ app.selection.getDrive().size | gigabyte | number:1 }} GB</div>
|
||||||
<button class="btn btn-link step-footer"
|
<button class="btn btn-link step-footer"
|
||||||
ng-click="app.reselectDrive()"
|
ng-click="app.reselectDrive()"
|
||||||
ng-hide="app.writer.isFlashing()">Change</button>
|
ng-hide="app.state.isFlashing()">Change</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -84,30 +84,30 @@
|
|||||||
|
|
||||||
<div class="space-vertical-large">
|
<div class="space-vertical-large">
|
||||||
<progress-button class="btn-brick"
|
<progress-button class="btn-brick"
|
||||||
percentage="app.writer.getFlashState().percentage"
|
percentage="app.state.getFlashState().percentage"
|
||||||
striped="{{ app.writer.getFlashState().type == 'check' }}"
|
striped="{{ app.state.getFlashState().type == 'check' }}"
|
||||||
ng-attr-active="{{ app.writer.isFlashing() }}"
|
ng-attr-active="{{ app.state.isFlashing() }}"
|
||||||
ng-show="app.wasLastFlashSuccessful()"
|
ng-show="app.wasLastFlashSuccessful()"
|
||||||
ng-click="app.flash(app.selection.getImagePath(), app.selection.getDrive())"
|
ng-click="app.flash(app.selection.getImagePath(), app.selection.getDrive())"
|
||||||
ng-disabled="!app.selection.hasImage() || !app.selection.hasDrive()">
|
ng-disabled="!app.selection.hasImage() || !app.selection.hasDrive()">
|
||||||
<span ng-show="app.writer.getFlashState().percentage == 100 && app.writer.isFlashing()">Finishing...</span>
|
<span ng-show="app.state.getFlashState().percentage == 100 && app.state.isFlashing()">Finishing...</span>
|
||||||
<span ng-show="app.writer.getFlashState().percentage == 0 && !app.writer.isFlashing()">Flash!</span>
|
<span ng-show="app.state.getFlashState().percentage == 0 && !app.state.isFlashing()">Flash!</span>
|
||||||
<span ng-show="app.writer.getFlashState().percentage == 0 && app.writer.isFlashing() && !app.writer.getFlashState().speed">Starting...</span>
|
<span ng-show="app.state.getFlashState().percentage == 0 && app.state.isFlashing() && !app.state.getFlashState().speed">Starting...</span>
|
||||||
<span ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100 && app.writer.getFlashState().type != 'check'"
|
<span ng-show="app.state.getFlashState().speed && app.state.getFlashState().percentage != 100 && app.state.getFlashState().type != 'check'"
|
||||||
ng-bind="app.writer.getFlashState().percentage + '% '"></span>
|
ng-bind="app.state.getFlashState().percentage + '% '"></span>
|
||||||
<span ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100 && app.writer.getFlashState().type == 'check'"
|
<span ng-show="app.state.getFlashState().speed && app.state.getFlashState().percentage != 100 && app.state.getFlashState().type == 'check'"
|
||||||
ng-bind="app.writer.getFlashState().percentage + '% Validating...'"></span>
|
ng-bind="app.state.getFlashState().percentage + '% Validating...'"></span>
|
||||||
</progress-button>
|
</progress-button>
|
||||||
|
|
||||||
<div class="alert-ribbon alert-warning" ng-class="{ 'alert-ribbon--open': !app.wasLastFlashSuccessful() }">
|
<div class="alert-ribbon alert-warning" ng-class="{ 'alert-ribbon--open': !app.wasLastFlashSuccessful() }">
|
||||||
<span class="glyphicon glyphicon-warning-sign"></span>
|
<span class="glyphicon glyphicon-warning-sign"></span>
|
||||||
<span ng-show="app.writer.getFlashResults().errorCode === 'ENOSPC'">
|
<span ng-show="app.state.getFlashResults().errorCode === 'ENOSPC'">
|
||||||
Not enough space on the drive.<br>Please insert larger one and <button class="btn btn-link" ng-click="app.restartAfterFailure()">try again</button>
|
Not enough space on the drive.<br>Please insert larger one and <button class="btn btn-link" ng-click="app.restartAfterFailure()">try again</button>
|
||||||
</span>
|
</span>
|
||||||
<span ng-show="app.writer.getFlashResults().errorCode !== 'ENOSPC' && app.settings.get('validateWriteOnSuccess')">
|
<span ng-show="app.state.getFlashResults().errorCode !== 'ENOSPC' && app.settings.get('validateWriteOnSuccess')">
|
||||||
Your removable drive may be corrupted.<br>Try inserting a different one and <button class="btn btn-link" ng-click="app.restartAfterFailure()">press "retry"</button>
|
Your removable drive may be corrupted.<br>Try inserting a different one and <button class="btn btn-link" ng-click="app.restartAfterFailure()">press "retry"</button>
|
||||||
</span>
|
</span>
|
||||||
<span ng-show="app.writer.getFlashResults().errorCode !== 'ENOSPC' && !app.settings.get('validateWriteOnSuccess')">
|
<span ng-show="app.state.getFlashResults().errorCode !== 'ENOSPC' && !app.settings.get('validateWriteOnSuccess')">
|
||||||
Oops, seems something went wrong. Click <button class="btn btn-link" ng-click="app.restartAfterFailure()">here</button> to retry
|
Oops, seems something went wrong. Click <button class="btn btn-link" ng-click="app.restartAfterFailure()">here</button> to retry
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -116,9 +116,9 @@
|
|||||||
<span class="glyphicon glyphicon-repeat"></span> Retry
|
<span class="glyphicon glyphicon-repeat"></span> Retry
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p class="step-footer step-footer-split" ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100">
|
<p class="step-footer step-footer-split" ng-show="app.state.getFlashState().speed && app.state.getFlashState().percentage != 100">
|
||||||
<span>ETA: {{ app.writer.getFlashState().eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
|
<span>ETA: {{ app.state.getFlashState().eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
|
||||||
<span ng-bind="app.writer.getFlashState().speed.toFixed(2) + ' MB/s'"></span>
|
<span ng-bind="app.state.getFlashState().speed.toFixed(2) + ' MB/s'"></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
407
tests/gui/models/flash-state.spec.js
Normal file
407
tests/gui/models/flash-state.spec.js
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const m = require('mochainon');
|
||||||
|
const angular = require('angular');
|
||||||
|
require('angular-mocks');
|
||||||
|
|
||||||
|
describe('Browser: FlashStateModel', function() {
|
||||||
|
|
||||||
|
beforeEach(angular.mock.module(
|
||||||
|
require('../../../lib/gui/models/flash-state')
|
||||||
|
));
|
||||||
|
|
||||||
|
describe('FlashStateModel', function() {
|
||||||
|
|
||||||
|
let FlashStateModel;
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(function(_FlashStateModel_) {
|
||||||
|
FlashStateModel = _FlashStateModel_;
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('.resetState()', function() {
|
||||||
|
|
||||||
|
it('should be able to reset the progress state', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
|
||||||
|
FlashStateModel.resetState();
|
||||||
|
|
||||||
|
m.chai.expect(FlashStateModel.getFlashState()).to.deep.equal({
|
||||||
|
percentage: 0,
|
||||||
|
speed: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to reset the progress state', function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
|
||||||
|
FlashStateModel.resetState();
|
||||||
|
m.chai.expect(FlashStateModel.getFlashResults()).to.deep.equal({});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.isFlashing()', function() {
|
||||||
|
|
||||||
|
it('should return false by default', function() {
|
||||||
|
m.chai.expect(FlashStateModel.isFlashing()).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if flashing', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(FlashStateModel.isFlashing()).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.setProgressState()', function() {
|
||||||
|
|
||||||
|
it('should not allow setting the state if flashing is false', function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Can\'t set the flashing state when not flashing');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if type is missing', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Missing state type');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if type is not a string', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 1234,
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid state type: 1234');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw if percentage is 0', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 0,
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.not.throw('Missing state percentage');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if percentage is missing', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Missing state percentage');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if percentage is not a number', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: '50',
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid state percentage: 50');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if eta is missing', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Missing state eta');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw if eta is equal to zero', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 0,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.not.throw('Missing state eta');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if eta is not a number', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: '15',
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid state eta: 15');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if speed is missing', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15
|
||||||
|
});
|
||||||
|
}).to.throw('Missing state speed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw if speed is 0', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 0
|
||||||
|
});
|
||||||
|
}).to.not.throw('Missing state speed');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.getFlashResults()', function() {
|
||||||
|
|
||||||
|
it('should get the flash results', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
|
||||||
|
const expectedResults = {
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
};
|
||||||
|
|
||||||
|
FlashStateModel.unsetFlashingFlag(expectedResults);
|
||||||
|
const results = FlashStateModel.getFlashResults();
|
||||||
|
m.chai.expect(results).to.deep.equal(expectedResults);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.getFlashState()', function() {
|
||||||
|
|
||||||
|
it('should initially return an empty state', function() {
|
||||||
|
FlashStateModel.resetState();
|
||||||
|
const flashState = FlashStateModel.getFlashState();
|
||||||
|
m.chai.expect(flashState).to.deep.equal({
|
||||||
|
percentage: 0,
|
||||||
|
speed: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the current flash state', function() {
|
||||||
|
const state = {
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
FlashStateModel.setProgressState(state);
|
||||||
|
const flashState = FlashStateModel.getFlashState();
|
||||||
|
m.chai.expect(flashState).to.deep.equal(state);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.unsetFlashingFlag()', function() {
|
||||||
|
|
||||||
|
it('should throw if no flashing results', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag();
|
||||||
|
}).to.throw('Missing results');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if errorCode is defined but it is not a number', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234',
|
||||||
|
errorCode: 123
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid results errorCode: 123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if no passedValidation', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
}).to.throw('Missing results passedValidation');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if passedValidation is not boolean', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: 'true',
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid results passedValidation: true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if no cancelled', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
}).to.throw('Missing results cancelled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if cancelled is not boolean', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: 'false',
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid results cancelled: false');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if passedValidation is true and sourceChecksum does not exist', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false
|
||||||
|
});
|
||||||
|
}).to.throw('Missing results sourceChecksum');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if passedValidation is true and sourceChecksum is not a string', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: 12345
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid results sourceChecksum: 12345');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if cancelled is true and sourceChecksum exists', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: false,
|
||||||
|
cancelled: true,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
}).to.throw('The sourceChecksum value can\'t exist if the flashing was cancelled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if cancelled is true and passedValidation is true', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: true
|
||||||
|
});
|
||||||
|
}).to.throw('The passedValidation value can\'t be true if the flashing was cancelled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to set flashing to false', function() {
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
|
||||||
|
m.chai.expect(FlashStateModel.isFlashing()).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset the flashing state', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
|
||||||
|
FlashStateModel.setProgressState({
|
||||||
|
type: 'write',
|
||||||
|
percentage: 50,
|
||||||
|
eta: 15,
|
||||||
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
|
||||||
|
m.chai.expect(FlashStateModel.getFlashState()).to.not.deep.equal({
|
||||||
|
percentage: 0,
|
||||||
|
speed: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
FlashStateModel.unsetFlashingFlag({
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
});
|
||||||
|
|
||||||
|
m.chai.expect(FlashStateModel.getFlashState()).to.deep.equal({
|
||||||
|
percentage: 0,
|
||||||
|
speed: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.setFlashingFlag()', function() {
|
||||||
|
|
||||||
|
it('should be able to set flashing to true', function() {
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(FlashStateModel.isFlashing()).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset the flash results', function() {
|
||||||
|
const expectedResults = {
|
||||||
|
passedValidation: true,
|
||||||
|
cancelled: false,
|
||||||
|
sourceChecksum: '1234'
|
||||||
|
};
|
||||||
|
|
||||||
|
FlashStateModel.unsetFlashingFlag(expectedResults);
|
||||||
|
const results = FlashStateModel.getFlashResults();
|
||||||
|
m.chai.expect(results).to.deep.equal(expectedResults);
|
||||||
|
FlashStateModel.setFlashingFlag();
|
||||||
|
m.chai.expect(FlashStateModel.getFlashResults()).to.deep.equal({});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -10,402 +10,24 @@ describe('Browser: ImageWriter', function() {
|
|||||||
require('../../../lib/gui/modules/image-writer')
|
require('../../../lib/gui/modules/image-writer')
|
||||||
));
|
));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.module(
|
||||||
|
require('../../../lib/gui/models/flash-state')
|
||||||
|
));
|
||||||
|
|
||||||
describe('ImageWriterService', function() {
|
describe('ImageWriterService', function() {
|
||||||
|
|
||||||
let $q;
|
let $q;
|
||||||
let $rootScope;
|
let $rootScope;
|
||||||
let ImageWriterService;
|
let ImageWriterService;
|
||||||
|
let FlashStateModel;
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _ImageWriterService_) {
|
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _ImageWriterService_, _FlashStateModel_) {
|
||||||
$q = _$q_;
|
$q = _$q_;
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
ImageWriterService = _ImageWriterService_;
|
ImageWriterService = _ImageWriterService_;
|
||||||
|
FlashStateModel = _FlashStateModel_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('.resetState()', function() {
|
|
||||||
|
|
||||||
it('should be able to reset the progress state', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
|
|
||||||
ImageWriterService.resetState();
|
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.getFlashState()).to.deep.equal({
|
|
||||||
percentage: 0,
|
|
||||||
speed: 0
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to reset the progress state', function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
|
|
||||||
ImageWriterService.resetState();
|
|
||||||
m.chai.expect(ImageWriterService.getFlashResults()).to.deep.equal({});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.isFlashing()', function() {
|
|
||||||
|
|
||||||
it('should return false by default', function() {
|
|
||||||
m.chai.expect(ImageWriterService.isFlashing()).to.be.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if flashing', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(ImageWriterService.isFlashing()).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.setProgressState()', function() {
|
|
||||||
|
|
||||||
it('should not allow setting the state if flashing is false', function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Can\'t set the flashing state when not flashing');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if type is missing', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Missing state type');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if type is not a string', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 1234,
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid state type: 1234');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not throw if percentage is 0', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 0,
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.not.throw('Missing state percentage');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if percentage is missing', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Missing state percentage');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if percentage is not a number', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: '50',
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid state percentage: 50');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if eta is missing', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Missing state eta');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not throw if eta is equal to zero', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 0,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.not.throw('Missing state eta');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if eta is not a number', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: '15',
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid state eta: 15');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if speed is missing', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15
|
|
||||||
});
|
|
||||||
}).to.throw('Missing state speed');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not throw if speed is 0', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 0
|
|
||||||
});
|
|
||||||
}).to.not.throw('Missing state speed');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.getFlashResults()', function() {
|
|
||||||
|
|
||||||
it('should get the flash results', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
|
|
||||||
const expectedResults = {
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
};
|
|
||||||
|
|
||||||
ImageWriterService.unsetFlashingFlag(expectedResults);
|
|
||||||
const results = ImageWriterService.getFlashResults();
|
|
||||||
m.chai.expect(results).to.deep.equal(expectedResults);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.getFlashState()', function() {
|
|
||||||
|
|
||||||
it('should initially return an empty state', function() {
|
|
||||||
ImageWriterService.resetState();
|
|
||||||
const flashState = ImageWriterService.getFlashState();
|
|
||||||
m.chai.expect(flashState).to.deep.equal({
|
|
||||||
percentage: 0,
|
|
||||||
speed: 0
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the current flash state', function() {
|
|
||||||
const state = {
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
ImageWriterService.setProgressState(state);
|
|
||||||
const flashState = ImageWriterService.getFlashState();
|
|
||||||
m.chai.expect(flashState).to.deep.equal(state);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.unsetFlashingFlag()', function() {
|
|
||||||
|
|
||||||
it('should throw if no flashing results', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag();
|
|
||||||
}).to.throw('Missing results');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if errorCode is defined but it is not a number', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234',
|
|
||||||
errorCode: 123
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid results errorCode: 123');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if no passedValidation', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
}).to.throw('Missing results passedValidation');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if passedValidation is not boolean', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: 'true',
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid results passedValidation: true');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if no cancelled', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
}).to.throw('Missing results cancelled');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if cancelled is not boolean', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: 'false',
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid results cancelled: false');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if passedValidation is true and sourceChecksum does not exist', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false
|
|
||||||
});
|
|
||||||
}).to.throw('Missing results sourceChecksum');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if passedValidation is true and sourceChecksum is not a string', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: 12345
|
|
||||||
});
|
|
||||||
}).to.throw('Invalid results sourceChecksum: 12345');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if cancelled is true and sourceChecksum exists', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: false,
|
|
||||||
cancelled: true,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
}).to.throw('The sourceChecksum value can\'t exist if the flashing was cancelled');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if cancelled is true and passedValidation is true', function() {
|
|
||||||
m.chai.expect(function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: true
|
|
||||||
});
|
|
||||||
}).to.throw('The passedValidation value can\'t be true if the flashing was cancelled');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to set flashing to false', function() {
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.isFlashing()).to.be.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset the flashing state', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
|
|
||||||
ImageWriterService.setProgressState({
|
|
||||||
type: 'write',
|
|
||||||
percentage: 50,
|
|
||||||
eta: 15,
|
|
||||||
speed: 100000000000
|
|
||||||
});
|
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.getFlashState()).to.not.deep.equal({
|
|
||||||
percentage: 0,
|
|
||||||
speed: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
ImageWriterService.unsetFlashingFlag({
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
});
|
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.getFlashState()).to.deep.equal({
|
|
||||||
percentage: 0,
|
|
||||||
speed: 0
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.setFlashingFlag()', function() {
|
|
||||||
|
|
||||||
it('should be able to set flashing to true', function() {
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(ImageWriterService.isFlashing()).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset the flash results', function() {
|
|
||||||
const expectedResults = {
|
|
||||||
passedValidation: true,
|
|
||||||
cancelled: false,
|
|
||||||
sourceChecksum: '1234'
|
|
||||||
};
|
|
||||||
|
|
||||||
ImageWriterService.unsetFlashingFlag(expectedResults);
|
|
||||||
const results = ImageWriterService.getFlashResults();
|
|
||||||
m.chai.expect(results).to.deep.equal(expectedResults);
|
|
||||||
ImageWriterService.setFlashingFlag();
|
|
||||||
m.chai.expect(ImageWriterService.getFlashResults()).to.deep.equal({});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('.flash()', function() {
|
describe('.flash()', function() {
|
||||||
|
|
||||||
describe('given a succesful write', function() {
|
describe('given a succesful write', function() {
|
||||||
@ -424,7 +46,7 @@ describe('Browser: ImageWriter', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should set flashing to false when done', function() {
|
it('should set flashing to false when done', function() {
|
||||||
ImageWriterService.unsetFlashingFlag({
|
FlashStateModel.unsetFlashingFlag({
|
||||||
passedValidation: true,
|
passedValidation: true,
|
||||||
cancelled: false,
|
cancelled: false,
|
||||||
sourceChecksum: '1234'
|
sourceChecksum: '1234'
|
||||||
@ -432,11 +54,11 @@ describe('Browser: ImageWriter', function() {
|
|||||||
|
|
||||||
ImageWriterService.flash('foo.img', '/dev/disk2');
|
ImageWriterService.flash('foo.img', '/dev/disk2');
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
m.chai.expect(ImageWriterService.isFlashing()).to.be.false;
|
m.chai.expect(FlashStateModel.isFlashing()).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prevent writing more than once', function() {
|
it('should prevent writing more than once', function() {
|
||||||
ImageWriterService.unsetFlashingFlag({
|
FlashStateModel.unsetFlashingFlag({
|
||||||
passedValidation: true,
|
passedValidation: true,
|
||||||
cancelled: false,
|
cancelled: false,
|
||||||
sourceChecksum: '1234'
|
sourceChecksum: '1234'
|
||||||
@ -480,18 +102,18 @@ describe('Browser: ImageWriter', function() {
|
|||||||
it('should set flashing to false when done', function() {
|
it('should set flashing to false when done', function() {
|
||||||
ImageWriterService.flash('foo.img', '/dev/disk2');
|
ImageWriterService.flash('foo.img', '/dev/disk2');
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
m.chai.expect(ImageWriterService.isFlashing()).to.be.false;
|
m.chai.expect(FlashStateModel.isFlashing()).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the error code in the flash results', function() {
|
it('should set the error code in the flash results', function() {
|
||||||
ImageWriterService.flash('foo.img', '/dev/disk2');
|
ImageWriterService.flash('foo.img', '/dev/disk2');
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
const flashResults = ImageWriterService.getFlashResults();
|
const flashResults = FlashStateModel.getFlashResults();
|
||||||
m.chai.expect(flashResults.errorCode).to.equal('FOO');
|
m.chai.expect(flashResults.errorCode).to.equal('FOO');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be rejected with the error', function() {
|
it('should be rejected with the error', function() {
|
||||||
ImageWriterService.unsetFlashingFlag({
|
FlashStateModel.unsetFlashingFlag({
|
||||||
passedValidation: true,
|
passedValidation: true,
|
||||||
cancelled: false,
|
cancelled: false,
|
||||||
sourceChecksum: '1234'
|
sourceChecksum: '1234'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user