Decompress images before flashing, remove trim setting, trim ext partitions

Changelog-entry: Decompress images before flashing, remove trim setting, trim ext partitions
Change-type: patch
This commit is contained in:
Alexis Svinartchouk 2020-04-23 17:06:21 +02:00
parent e6125b893d
commit ee62b9a4c7
16 changed files with 202 additions and 386 deletions

View File

@ -89,30 +89,43 @@ analytics.logEvent('Application start', {
applicationSessionUuid, applicationSessionUuid,
}); });
const debouncedLog = _.debounce(console.log, 1000, { maxWait: 1000 });
function pluralize(word: string, quantity: number) {
return `${quantity} ${word}${quantity === 1 ? '' : 's'}`;
}
observe(() => { observe(() => {
if (!flashState.isFlashing()) { if (!flashState.isFlashing()) {
return; return;
} }
const currentFlashState = flashState.getFlashState(); const currentFlashState = flashState.getFlashState();
const stateType = windowProgress.set(currentFlashState);
!currentFlashState.flashing && currentFlashState.verifying
? `Verifying ${currentFlashState.verifying}`
: `Flashing ${currentFlashState.flashing}`;
let eta = '';
if (currentFlashState.eta !== undefined) {
eta = `eta in ${currentFlashState.eta.toFixed(0)}s`;
}
let active = '';
if (currentFlashState.type !== 'decompressing') {
active = pluralize('device', currentFlashState.active);
}
// NOTE: There is usually a short time period between the `isFlashing()` // NOTE: 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
// might cause some non-sense flashing state logs including // might cause some non-sense flashing state logs including
// `undefined` values. // `undefined` values.
analytics.logDebug( debouncedLog(outdent({ newline: ' ' })`
`${stateType} devices, ` + ${_.capitalize(currentFlashState.type)}
`${currentFlashState.percentage}% at ${currentFlashState.speed} MB/s ` + ${active},
`(total ${currentFlashState.totalSpeed} MB/s) ` + ${currentFlashState.percentage}%
`eta in ${currentFlashState.eta}s ` + at
`with ${currentFlashState.failed} failed devices`, ${(currentFlashState.speed || 0).toFixed(2)}
); MB/s
(total ${(currentFlashState.speed * currentFlashState.active).toFixed(2)} MB/s)
windowProgress.set(currentFlashState); ${eta}
with
${pluralize('failed device', currentFlashState.failed)}
`);
}); });
/** /**

View File

@ -14,39 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
import * as Color from 'color';
import * as React from 'react'; import * as React from 'react';
import { ProgressBar } from 'rendition'; import { ProgressBar } from 'rendition';
import { css, default as styled, keyframes } from 'styled-components'; import { default as styled } from 'styled-components';
import { StepButton, StepSelection } from '../../styled-components'; import { StepButton } from '../../styled-components';
import { colors } from '../../theme';
const darkenForegroundStripes = 0.18;
const desaturateForegroundStripes = 0.2;
const progressButtonStripesForegroundColor = Color(colors.primary.background)
.darken(darkenForegroundStripes)
.desaturate(desaturateForegroundStripes)
.string();
const desaturateBackgroundStripes = 0.05;
const progressButtonStripesBackgroundColor = Color(colors.primary.background)
.desaturate(desaturateBackgroundStripes)
.string();
const ProgressButtonStripes = keyframes`
0% {
background-position: 0 0;
}
100% {
background-position: 20px 20px;
}
`;
const ProgressButtonStripesRule = css`
${ProgressButtonStripes} 1s linear infinite;
`;
const FlashProgressBar = styled(ProgressBar)` const FlashProgressBar = styled(ProgressBar)`
> div { > div {
@ -54,6 +26,10 @@ const FlashProgressBar = styled(ProgressBar)`
height: 48px; height: 48px;
color: white !important; color: white !important;
text-shadow: none !important; text-shadow: none !important;
transition-duration: 0s;
> div {
transition-duration: 0s;
}
} }
width: 200px; width: 200px;
@ -61,40 +37,11 @@ const FlashProgressBar = styled(ProgressBar)`
font-size: 16px; font-size: 16px;
line-height: 48px; line-height: 48px;
background: ${Color(colors.warning.background) background: #2f3033;
.darken(darkenForegroundStripes)
.string()};
`;
const FlashProgressBarValidating = styled(FlashProgressBar)`
// Notice that we add 0.01 to certain gradient stop positions.
// That workarounds a Chrome rendering issue where diagonal
// lines look spiky.
// See https://github.com/balena-io/etcher/issues/472
background-image: -webkit-gradient(
linear,
0 0,
100% 100%,
color-stop(0.25, ${progressButtonStripesForegroundColor}),
color-stop(0.26, ${progressButtonStripesBackgroundColor}),
color-stop(0.5, ${progressButtonStripesBackgroundColor}),
color-stop(0.51, ${progressButtonStripesForegroundColor}),
color-stop(0.75, ${progressButtonStripesForegroundColor}),
color-stop(0.76, ${progressButtonStripesBackgroundColor}),
to(${progressButtonStripesBackgroundColor})
);
background-color: white;
animation: ${ProgressButtonStripesRule};
overflow: hidden;
background-size: 20px 20px;
`; `;
interface ProgressButtonProps { interface ProgressButtonProps {
striped: boolean; type: 'decompressing' | 'flashing' | 'verifying';
active: boolean; active: boolean;
percentage: number; percentage: number;
label: string; label: string;
@ -102,45 +49,35 @@ interface ProgressButtonProps {
callback: () => any; callback: () => any;
} }
const colors = {
decompressing: '#00aeef',
flashing: '#da60ff',
verifying: '#1ac135',
} as const;
/** /**
* Progress Button component * Progress Button component
*/ */
export class ProgressButton extends React.Component<ProgressButtonProps> { export class ProgressButton extends React.Component<ProgressButtonProps> {
public render() { public render() {
if (this.props.active) { if (this.props.active) {
if (this.props.striped) {
return (
<StepSelection>
<FlashProgressBarValidating
primary
emphasized
value={this.props.percentage}
>
{this.props.label}
</FlashProgressBarValidating>
</StepSelection>
);
}
return ( return (
<StepSelection> <FlashProgressBar
<FlashProgressBar warning emphasized value={this.props.percentage}> background={colors[this.props.type]}
{this.props.label} value={this.props.percentage}
</FlashProgressBar>
</StepSelection>
);
}
return (
<StepSelection>
<StepButton
primary
onClick={this.props.callback}
disabled={this.props.disabled}
> >
{this.props.label} {this.props.label}
</StepButton> </FlashProgressBar>
</StepSelection> );
}
return (
<StepButton
primary
onClick={this.props.callback}
disabled={this.props.disabled}
>
{this.props.label}
</StepButton>
); );
} }
} }

View File

@ -87,10 +87,6 @@ const settingsList: Setting[] = [
name: 'validateWriteOnSuccess', name: 'validateWriteOnSuccess',
label: 'Validate write on success', label: 'Validate write on success',
}, },
{
name: 'trim',
label: 'Trim ext{2,3,4} partitions before writing (raw images only)',
},
{ {
name: 'updatesEnabled', name: 'updatesEnabled',
label: 'Auto-updates enabled', label: 'Auto-updates enabled',

View File

@ -375,7 +375,7 @@ export class SourceSelector extends React.Component<
analytics.logEvent('Unsupported protocol', { path: imagePath }); analytics.logEvent('Unsupported protocol', { path: imagePath });
return; return;
} }
source = new sourceDestination.Http(imagePath); source = new sourceDestination.Http({ url: imagePath });
} }
try { try {

View File

@ -85,13 +85,6 @@ export function setProgressState(
return _.round(bytesToMegabytes(state.speed), PRECISION); return _.round(bytesToMegabytes(state.speed), PRECISION);
} }
return null;
}),
totalSpeed: _.attempt(() => {
if (_.isFinite(state.totalSpeed)) {
return _.round(bytesToMegabytes(state.totalSpeed), PRECISION);
}
return null; return null;
}), }),
}); });

View File

@ -29,13 +29,14 @@ export const DEFAULT_SETTINGS: _.Dictionary<any> = {
errorReporting: true, errorReporting: true,
unmountOnSuccess: true, unmountOnSuccess: true,
validateWriteOnSuccess: true, validateWriteOnSuccess: true,
trim: false,
updatesEnabled: updatesEnabled:
packageJSON.updates.enabled && packageJSON.updates.enabled &&
!_.includes(['rpm', 'deb'], packageJSON.packageType), !_.includes(['rpm', 'deb'], packageJSON.packageType),
lastSleptUpdateNotifier: null, lastSleptUpdateNotifier: null,
lastSleptUpdateNotifierVersion: null, lastSleptUpdateNotifierVersion: null,
desktopNotifications: true, desktopNotifications: true,
autoBlockmapping: true,
decompressFirst: true,
}; };
let settings = _.cloneDeep(DEFAULT_SETTINGS); let settings = _.cloneDeep(DEFAULT_SETTINGS);

View File

@ -45,7 +45,7 @@ function verifyNoNilFields(
/** /**
* @summary FLASH_STATE fields that can't be nil * @summary FLASH_STATE fields that can't be nil
*/ */
const flashStateNoNilFields = ['speed', 'totalSpeed']; const flashStateNoNilFields = ['speed'];
/** /**
* @summary SELECT_IMAGE fields that can't be nil * @summary SELECT_IMAGE fields that can't be nil
@ -65,14 +65,11 @@ const DEFAULT_STATE = Immutable.fromJS({
isFlashing: false, isFlashing: false,
flashResults: {}, flashResults: {},
flashState: { flashState: {
flashing: 0, active: 0,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
speed: null, speed: null,
averageSpeed: null, averageSpeed: null,
totalSpeed: null,
}, },
lastAverageFlashingSpeed: null, lastAverageFlashingSpeed: null,
}); });
@ -234,17 +231,7 @@ function storeReducer(
verifyNoNilFields(action.data, flashStateNoNilFields, 'flash'); verifyNoNilFields(action.data, flashStateNoNilFields, 'flash');
if ( if (!_.every(_.pick(action.data, ['active', 'failed']), _.isFinite)) {
!_.every(
_.pick(action.data, [
'flashing',
'verifying',
'successful',
'failed',
]),
_.isFinite,
)
) {
throw errors.createError({ throw errors.createError({
title: 'State quantity field(s) not finite number', title: 'State quantity field(s) not finite number',
}); });
@ -266,7 +253,7 @@ function storeReducer(
} }
let ret = state.set('flashState', Immutable.fromJS(action.data)); let ret = state.set('flashState', Immutable.fromJS(action.data));
if (action.data.flashing) { if (action.data.type === 'flashing') {
ret = ret.set('lastAverageFlashingSpeed', action.data.averageSpeed); ret = ret.set('lastAverageFlashingSpeed', action.data.averageSpeed);
} }
return ret; return ret;

View File

@ -168,7 +168,6 @@ export function performWrite(
flashInstanceUuid: flashState.getFlashUuid(), flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'), validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
}; };
ipc.server.on('fail', ({ error }: { error: Error & { code: string } }) => { ipc.server.on('fail', ({ error }: { error: Error & { code: string } }) => {
@ -196,8 +195,9 @@ export function performWrite(
source, source,
SourceType: source.SourceType.name, SourceType: source.SourceType.name,
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'), validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'), autoBlockmapping: settings.get('autoBlockmapping'),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
decompressFirst: settings.get('decompressFirst'),
}); });
}); });
@ -273,7 +273,6 @@ export async function flash(
flashInstanceUuid: flashState.getFlashUuid(), flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'), validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid, applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid, flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
}; };
@ -318,6 +317,8 @@ export async function flash(
errors: results.errors, errors: results.errors,
devices: results.devices, devices: results.devices,
status: 'finished', status: 'finished',
bytesWritten: results.bytesWritten,
sourceMetadata: results.sourceMetadata,
}; };
analytics.logEvent('Done', eventData); analytics.logEvent('Done', eventData);
} }
@ -336,7 +337,6 @@ export function cancel() {
flashInstanceUuid: flashState.getFlashUuid(), flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess'), validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
trim: settings.get('trim'),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid, applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid, flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
status: 'cancel', status: 'cancel',

View File

@ -15,16 +15,15 @@
*/ */
import { bytesToClosestUnit } from '../../../shared/units'; import { bytesToClosestUnit } from '../../../shared/units';
import * as settings from '../models/settings'; // import * as settings from '../models/settings';
export interface FlashState { export interface FlashState {
flashing: number; active: number;
verifying: number;
successful: number;
failed: number; failed: number;
percentage?: number; percentage?: number;
speed: number; speed: number;
position: number; position: number;
type?: 'decompressing' | 'flashing' | 'verifying';
} }
/** /**
@ -36,45 +35,47 @@ export interface FlashState {
* *
* @example * @example
* const status = progressStatus.fromFlashState({ * const status = progressStatus.fromFlashState({
* flashing: 1, * type: 'flashing'
* verifying: 0, * active: 1,
* successful: 0,
* failed: 0, * failed: 0,
* percentage: 55, * percentage: 55,
* speed: 2049 * speed: 2049,
* }) * })
* *
* console.log(status) * console.log(status)
* // '55% Flashing' * // '55% Flashing'
*/ */
export function fromFlashState(state: FlashState): string { export function fromFlashState({
const isFlashing = Boolean(state.flashing); type,
const isValidating = !isFlashing && Boolean(state.verifying); percentage,
const shouldValidate = settings.get('validateWriteOnSuccess'); position,
const shouldUnmount = settings.get('unmountOnSuccess'); }: FlashState): string {
if (type === undefined) {
if (state.percentage === 0 && !state.speed) {
if (isValidating) {
return 'Validating...';
}
return 'Starting...'; return 'Starting...';
} else if (state.percentage === 100) { } else if (type === 'decompressing') {
if ((isValidating || !shouldValidate) && shouldUnmount) { if (percentage == null) {
return 'Unmounting...'; return 'Decompressing...';
} else {
return `${percentage}% Decompressing`;
} }
} else if (type === 'flashing') {
return 'Finishing...'; if (percentage != null) {
} else if (isFlashing) { if (percentage < 100) {
if (state.percentage != null) { return `${percentage}% Flashing`;
return `${state.percentage}% Flashing`; } else {
return 'Finishing...';
}
} else {
return `${bytesToClosestUnit(position)} flashed`;
}
} else if (type === 'verifying') {
if (percentage == null) {
return 'Validating...';
} else if (percentage < 100) {
return `${percentage}% Validating`;
} else {
return 'Finishing...';
} }
return `${bytesToClosestUnit(state.position)} flashed`;
} else if (isValidating) {
return `${state.percentage}% Validating`;
} else if (!isFlashing && !isValidating) {
return 'Failed';
} }
return 'Failed';
throw new Error(`Invalid state: ${JSON.stringify(state)}`);
} }

View File

@ -33,6 +33,7 @@ import { scanner as driveScanner } from '../../modules/drive-scanner';
import * as imageWriter from '../../modules/image-writer'; import * as imageWriter from '../../modules/image-writer';
import * as progressStatus from '../../modules/progress-status'; import * as progressStatus from '../../modules/progress-status';
import * as notification from '../../os/notification'; import * as notification from '../../os/notification';
import { StepSelection } from '../../styled-components';
const COMPLETED_PERCENTAGE = 100; const COMPLETED_PERCENTAGE = 100;
const SPEED_PRECISION = 2; const SPEED_PRECISION = 2;
@ -243,14 +244,16 @@ export const Flash = ({
</div> </div>
<div className="space-vertical-large"> <div className="space-vertical-large">
<ProgressButton <StepSelection>
striped={state.type === 'verifying'} <ProgressButton
active={isFlashing} type={state.type}
percentage={state.percentage} active={isFlashing}
label={getProgressButtonLabel()} percentage={state.percentage}
disabled={Boolean(flashErrorCode) || shouldFlashStepBeDisabled} label={getProgressButtonLabel()}
callback={tryFlash} disabled={Boolean(flashErrorCode) || shouldFlashStepBeDisabled}
></ProgressButton> callback={tryFlash}
/>
</StepSelection>
{isFlashing && ( {isFlashing && (
<button <button

View File

@ -17,6 +17,7 @@
import { delay } from 'bluebird'; import { delay } from 'bluebird';
import { Drive as DrivelistDrive } from 'drivelist'; import { Drive as DrivelistDrive } from 'drivelist';
import * as sdk from 'etcher-sdk'; import * as sdk from 'etcher-sdk';
import { cleanupTmpFiles } from 'etcher-sdk/build/tmp';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as ipc from 'node-ipc'; import * as ipc from 'node-ipc';
@ -77,6 +78,7 @@ interface WriteResult {
successful: number; successful: number;
}; };
errors: Array<Error & { device: string }>; errors: Array<Error & { device: string }>;
sourceMetadata: sdk.sourceDestination.Metadata;
} }
/** /**
@ -84,38 +86,42 @@ interface WriteResult {
* @param {SourceDestination} source - source * @param {SourceDestination} source - source
* @param {SourceDestination[]} destinations - destinations * @param {SourceDestination[]} destinations - destinations
* @param {Boolean} verify - whether to validate the writes or not * @param {Boolean} verify - whether to validate the writes or not
* @param {Boolean} trim - whether to trim ext partitions before writing * @param {Boolean} autoBlockmapping - whether to trim ext partitions before writing
* @param {Function} onProgress - function to call on progress * @param {Function} onProgress - function to call on progress
* @param {Function} onFail - function to call on fail * @param {Function} onFail - function to call on fail
* @returns {Promise<{ bytesWritten, devices, errors} >} * @returns {Promise<{ bytesWritten, devices, errors} >}
*/ */
async function writeAndValidate( async function writeAndValidate({
source: sdk.sourceDestination.SourceDestination, source,
destinations: sdk.sourceDestination.BlockDevice[], destinations,
verify: boolean, verify,
trim: boolean, autoBlockmapping,
onProgress: sdk.multiWrite.OnProgressFunction, decompressFirst,
onFail: sdk.multiWrite.OnFailFunction, onProgress,
): Promise<WriteResult> { onFail,
let innerSource: sdk.sourceDestination.SourceDestination = await source.getInnerSource(); }: {
if (trim && (await innerSource.canRead())) { source: sdk.sourceDestination.SourceDestination;
innerSource = new sdk.sourceDestination.ConfiguredSource({ destinations: sdk.sourceDestination.BlockDevice[];
source: innerSource, verify: boolean;
shouldTrimPartitions: trim, autoBlockmapping: boolean;
createStreamFromDisk: true, decompressFirst: boolean;
}); onProgress: sdk.multiWrite.OnProgressFunction;
} onFail: sdk.multiWrite.OnFailFunction;
}): Promise<WriteResult> {
const { const {
sourceMetadata,
failures, failures,
bytesWritten, bytesWritten,
} = await sdk.multiWrite.pipeSourceToDestinations( } = await sdk.multiWrite.decompressThenFlash({
innerSource, source,
destinations, destinations,
onFail, onFail,
onProgress, onProgress,
verify, verify,
32, trim: autoBlockmapping,
); numBuffers: 32,
decompressFirst,
});
const result: WriteResult = { const result: WriteResult = {
bytesWritten, bytesWritten,
devices: { devices: {
@ -123,6 +129,7 @@ async function writeAndValidate(
successful: destinations.length - failures.size, successful: destinations.length - failures.size,
}, },
errors: [], errors: [],
sourceMetadata,
}; };
for (const [destination, error] of failures) { for (const [destination, error] of failures) {
const err = error as Error & { device: string }; const err = error as Error & { device: string };
@ -137,12 +144,15 @@ interface WriteOptions {
destinations: DrivelistDrive[]; destinations: DrivelistDrive[];
unmountOnSuccess: boolean; unmountOnSuccess: boolean;
validateWriteOnSuccess: boolean; validateWriteOnSuccess: boolean;
trim: boolean; autoBlockmapping: boolean;
decompressFirst: boolean;
source: SourceOptions; source: SourceOptions;
SourceType: string; SourceType: string;
} }
ipc.connectTo(IPC_SERVER_ID, () => { ipc.connectTo(IPC_SERVER_ID, () => {
// Remove leftover tmp files older than 1 hour
cleanupTmpFiles(Date.now() - 60 * 60 * 1000);
process.once('uncaughtException', handleError); process.once('uncaughtException', handleError);
// Gracefully exit on the following cases. If the parent // Gracefully exit on the following cases. If the parent
@ -219,7 +229,8 @@ ipc.connectTo(IPC_SERVER_ID, () => {
log(`Devices: ${destinations.join(', ')}`); log(`Devices: ${destinations.join(', ')}`);
log(`Umount on success: ${options.unmountOnSuccess}`); log(`Umount on success: ${options.unmountOnSuccess}`);
log(`Validate on success: ${options.validateWriteOnSuccess}`); log(`Validate on success: ${options.validateWriteOnSuccess}`);
log(`Trim: ${options.trim}`); log(`Auto blockmapping: ${options.autoBlockmapping}`);
log(`Decompress first: ${options.decompressFirst}`);
const dests = _.map(options.destinations, destination => { const dests = _.map(options.destinations, destination => {
return new sdk.sourceDestination.BlockDevice({ return new sdk.sourceDestination.BlockDevice({
drive: destination, drive: destination,
@ -235,17 +246,18 @@ ipc.connectTo(IPC_SERVER_ID, () => {
path: options.imagePath, path: options.imagePath,
}); });
} else { } else {
source = new Http(options.imagePath); source = new Http({ url: options.imagePath });
} }
try { try {
const results = await writeAndValidate( const results = await writeAndValidate({
source, source,
dests, destinations: dests,
options.validateWriteOnSuccess, verify: options.validateWriteOnSuccess,
options.trim, autoBlockmapping: options.autoBlockmapping,
decompressFirst: options.decompressFirst,
onProgress, onProgress,
onFail, onFail,
); });
log(`Finish: ${results.bytesWritten}`); log(`Finish: ${results.bytesWritten}`);
results.errors = _.map(results.errors, error => { results.errors = _.map(results.errors, error => {
return toJSON(error); return toJSON(error);

58
npm-shrinkwrap.json generated
View File

@ -1600,12 +1600,11 @@
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
}, },
"axios": { "axios": {
"version": "0.18.1", "version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": { "requires": {
"follow-redirects": "1.5.10", "follow-redirects": "1.5.10"
"is-buffer": "^2.0.2"
} }
}, },
"babel-code-frame": { "babel-code-frame": {
@ -1860,9 +1859,9 @@
}, },
"dependencies": { "dependencies": {
"buffer": { "buffer": {
"version": "5.5.0", "version": "5.6.0",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.5.0.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
"integrity": "sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww==", "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
"requires": { "requires": {
"base64-js": "^1.0.2", "base64-js": "^1.0.2",
"ieee754": "^1.1.4" "ieee754": "^1.1.4"
@ -2469,6 +2468,11 @@
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
}, },
"check-disk-space": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-2.1.0.tgz",
"integrity": "sha512-f0nx9oJF/AVF8nhSYlF1EBvMNnO+CXyLwKhPvN1943iOMI9TWhQigLZm80jAf0wzQhwKkzA8XXjyvuVUeGGcVQ=="
},
"check-error": { "check-error": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
@ -2838,15 +2842,6 @@
"object-visit": "^1.0.0" "object-visit": "^1.0.0"
} }
}, },
"color": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz",
"integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==",
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
}
},
"color-convert": { "color-convert": {
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -5412,14 +5407,15 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
}, },
"etcher-sdk": { "etcher-sdk": {
"version": "3.0.1", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-3.0.1.tgz", "resolved": "https://registry.npmjs.org/etcher-sdk/-/etcher-sdk-4.0.0.tgz",
"integrity": "sha512-Jd30W0OfKNwbQZ4NdsNLCItyPYNP3hIugJrG/V5uzBtpL4R+gldMrUopkJ1L0x59d9NwWavQ/CqM6gxrv3tVlw==", "integrity": "sha512-yzvZEoZkGO+QnpSRF7VTsNAMxnXTgdWoPOUUg62DVRrCJSIFOBrRYHfCfSCih20qHNlQnFuWKjJgFiDdMjfKJA==",
"requires": { "requires": {
"@ronomon/direct-io": "^3.0.1", "@ronomon/direct-io": "^3.0.1",
"axios": "^0.18.0", "axios": "^0.19.2",
"blockmap": "^4.0.1", "blockmap": "^4.0.1",
"bluebird": "^3.5.1", "bluebird": "^3.5.1",
"check-disk-space": "^2.1.0",
"crc": "^3.8.0", "crc": "^3.8.0",
"debug": "^3.1.0", "debug": "^3.1.0",
"drivelist": "^8.0.4", "drivelist": "^8.0.4",
@ -8364,9 +8360,9 @@
} }
}, },
"lzma-native": { "lzma-native": {
"version": "6.0.0", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-6.0.0.tgz", "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-6.0.1.tgz",
"integrity": "sha512-rf5f4opPymsPHotgY2d0cUP3kbVxERSxWDGEbi2gnbnxuWGokFrBaQ02Oe9pssIwsgp0r0PnbSNg7VPY3AYe7w==", "integrity": "sha512-O6oWF0xe1AFvOCjU8uOZBZ/lhjaMNwHfVNaqVMqmoQXlRwBcFWpCAToiZOdXcKVMdo/5s/D0a2QgA5laMErxHQ==",
"requires": { "requires": {
"node-addon-api": "^1.6.0", "node-addon-api": "^1.6.0",
"node-pre-gyp": "^0.11.0", "node-pre-gyp": "^0.11.0",
@ -9320,9 +9316,9 @@
} }
}, },
"node-abi": { "node-abi": {
"version": "2.15.0", "version": "2.16.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.15.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz",
"integrity": "sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg==", "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
} }
@ -9503,9 +9499,9 @@
}, },
"dependencies": { "dependencies": {
"@types/node": { "@types/node": {
"version": "6.14.9", "version": "6.14.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.10.tgz",
"integrity": "sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w==" "integrity": "sha512-pF4HjZGSog75kGq7B1InK/wt/N08BuPATo+7HRfv7gZUzccebwv/fmWVGs/j6LvSiLWpCuGGhql51M/wcQsNzA=="
} }
} }
}, },
@ -14484,4 +14480,4 @@
} }
} }
} }
} }

View File

@ -57,11 +57,10 @@
"bindings": "^1.3.0", "bindings": "^1.3.0",
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"bootstrap-sass": "^3.3.6", "bootstrap-sass": "^3.3.6",
"color": "^2.0.1",
"d3": "^4.13.0", "d3": "^4.13.0",
"debug": "^3.1.0", "debug": "^3.1.0",
"electron-updater": "4.0.6", "electron-updater": "4.0.6",
"etcher-sdk": "^3.0.1", "etcher-sdk": "^4.0.0",
"flexboxgrid": "^6.3.0", "flexboxgrid": "^6.3.0",
"immutable": "^3.8.1", "immutable": "^3.8.1",
"inactivity-timer": "^1.0.0", "inactivity-timer": "^1.0.0",

View File

@ -28,16 +28,12 @@ describe('Model: flashState', function() {
it('should be able to reset the progress state', function() { it('should be able to reset the progress state', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
eta: 15, eta: 15,
speed: 100000000000, speed: 100000000000,
averageSpeed: 100000000000, averageSpeed: 100000000000,
totalSpeed: 200000000000,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -46,14 +42,11 @@ describe('Model: flashState', function() {
flashState.resetState(); flashState.resetState();
expect(flashState.getFlashState()).to.deep.equal({ expect(flashState.getFlashState()).to.deep.equal({
flashing: 0, active: 0,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
speed: null, speed: null,
averageSpeed: null, averageSpeed: null,
totalSpeed: null,
}); });
}); });
@ -100,16 +93,12 @@ describe('Model: flashState', function() {
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
eta: 15, eta: 15,
speed: 100000000000, speed: 100000000000,
averageSpeed: 100000000000, averageSpeed: 100000000000,
totalSpeed: 200000000000,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -121,16 +110,12 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 0, percentage: 0,
eta: 15, eta: 15,
speed: 100000000000, speed: 100000000000,
averageSpeed: 100000000000, averageSpeed: 100000000000,
totalSpeed: 200000000000,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -142,16 +127,12 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 101, percentage: 101,
eta: 15, eta: 15,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 1,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -163,16 +144,12 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: -1, percentage: -1,
eta: 15, eta: 15,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 1,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -184,16 +161,12 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
eta: 0, eta: 0,
speed: 100000000000, speed: 100000000000,
averageSpeed: 100000000000, averageSpeed: 100000000000,
totalSpeed: 200000000000,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -205,9 +178,6 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
@ -215,7 +185,6 @@ describe('Model: flashState', function() {
eta: '15', eta: '15',
speed: 100000000000, speed: 100000000000,
averageSpeed: 100000000000, averageSpeed: 100000000000,
totalSpeed: 200000000000,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -228,15 +197,11 @@ describe('Model: flashState', function() {
expect(function() { expect(function() {
// @ts-ignore // @ts-ignore
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
eta: 15, eta: 15,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 1,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -248,16 +213,12 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
expect(function() { expect(function() {
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
eta: 15, eta: 15,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 1,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -265,61 +226,15 @@ describe('Model: flashState', function() {
}).to.not.throw('Missing flash fields: speed'); }).to.not.throw('Missing flash fields: speed');
}); });
it('should throw if totalSpeed is missing', function() {
flashState.setFlashingFlag();
expect(function() {
// @ts-ignore
flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0,
type: 'flashing',
percentage: 50,
eta: 15,
speed: 1,
averageSpeed: 1,
bytes: 0,
position: 0,
active: 0,
});
}).to.throw('Missing flash fields: totalSpeed');
});
it('should not throw if totalSpeed is 0', function() {
flashState.setFlashingFlag();
expect(function() {
flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0,
type: 'flashing',
percentage: 50,
eta: 15,
speed: 0,
averageSpeed: 0,
totalSpeed: 0,
bytes: 0,
position: 0,
active: 0,
});
}).to.not.throw('Missing flash fields: totalSpeed');
});
it('should floor the percentage number', function() { it('should floor the percentage number', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50.253559459485, percentage: 50.253559459485,
eta: 15, eta: 15,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 1,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -344,7 +259,6 @@ describe('Model: flashState', function() {
eta: 0, eta: 0,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 0,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -357,15 +271,11 @@ describe('Model: flashState', function() {
expect(() => { expect(() => {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
flashState.setProgressState({ flashState.setProgressState({
flashing: 0,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
eta: 0, eta: 0,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 0,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -395,28 +305,21 @@ describe('Model: flashState', function() {
flashState.resetState(); flashState.resetState();
const currentFlashState = flashState.getFlashState(); const currentFlashState = flashState.getFlashState();
expect(currentFlashState).to.deep.equal({ expect(currentFlashState).to.deep.equal({
flashing: 0, active: 0,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
speed: null, speed: null,
averageSpeed: null, averageSpeed: null,
totalSpeed: null,
}); });
}); });
it('should return the current flash state', function() { it('should return the current flash state', function() {
const state = { const state = {
flashing: 1,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 50, percentage: 50,
eta: 15, eta: 15,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 0,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -427,15 +330,11 @@ describe('Model: flashState', function() {
flashState.setProgressState(state); flashState.setProgressState(state);
const currentFlashState = flashState.getFlashState(); const currentFlashState = flashState.getFlashState();
expect(currentFlashState).to.deep.equal({ expect(currentFlashState).to.deep.equal({
flashing: 1,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 50, percentage: 50,
eta: 15, eta: 15,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 0,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 0,
@ -532,30 +431,22 @@ describe('Model: flashState', function() {
flashState.setFlashingFlag(); flashState.setFlashingFlag();
flashState.setProgressState({ flashState.setProgressState({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
type: 'flashing', type: 'flashing',
percentage: 50, percentage: 50,
eta: 15, eta: 15,
speed: 100000000000, speed: 100000000000,
averageSpeed: 100000000000, averageSpeed: 100000000000,
totalSpeed: 200000000000,
bytes: 0, bytes: 0,
position: 0, position: 0,
active: 0, active: 2,
}); });
expect(flashState.getFlashState()).to.not.deep.equal({ expect(flashState.getFlashState()).to.not.deep.equal({
flashing: 2,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
speed: 0, speed: 0,
averageSpeed: 0, averageSpeed: 0,
totalSpeed: 0,
}); });
flashState.unsetFlashingFlag({ flashState.unsetFlashingFlag({
@ -564,14 +455,11 @@ describe('Model: flashState', function() {
}); });
expect(flashState.getFlashState()).to.deep.equal({ expect(flashState.getFlashState()).to.deep.equal({
flashing: 0, active: 0,
verifying: 0,
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
speed: null, speed: null,
averageSpeed: null, averageSpeed: null,
totalSpeed: null,
}); });
}); });

View File

@ -23,9 +23,8 @@ describe('Browser: progressStatus', function() {
describe('.fromFlashState()', function() { describe('.fromFlashState()', function() {
beforeEach(function() { beforeEach(function() {
this.state = { this.state = {
flashing: 1, active: 1,
verifying: 0, type: 'flashing',
successful: 0,
failed: 0, failed: 0,
percentage: 0, percentage: 0,
eta: 15, eta: 15,
@ -42,31 +41,29 @@ describe('Browser: progressStatus', function() {
it('should handle percentage == 0, flashing, unmountOnSuccess', function() { it('should handle percentage == 0, flashing, unmountOnSuccess', function() {
this.state.speed = 0; this.state.speed = 0;
expect(progressStatus.fromFlashState(this.state)).to.equal('Starting...'); expect(progressStatus.fromFlashState(this.state)).to.equal('0% Flashing');
}); });
it('should handle percentage == 0, flashing, !unmountOnSuccess', function() { it('should handle percentage == 0, flashing, !unmountOnSuccess', function() {
this.state.speed = 0; this.state.speed = 0;
settings.set('unmountOnSuccess', false); settings.set('unmountOnSuccess', false);
expect(progressStatus.fromFlashState(this.state)).to.equal('Starting...'); expect(progressStatus.fromFlashState(this.state)).to.equal('0% Flashing');
}); });
it('should handle percentage == 0, verifying, unmountOnSuccess', function() { it('should handle percentage == 0, verifying, unmountOnSuccess', function() {
this.state.speed = 0; this.state.speed = 0;
this.state.flashing = 0; this.state.type = 'verifying';
this.state.verifying = 1;
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(
'Validating...', '0% Validating',
); );
}); });
it('should handle percentage == 0, verifying, !unmountOnSuccess', function() { it('should handle percentage == 0, verifying, !unmountOnSuccess', function() {
this.state.speed = 0; this.state.speed = 0;
this.state.flashing = 0; this.state.type = 'verifying';
this.state.verifying = 1;
settings.set('unmountOnSuccess', false); settings.set('unmountOnSuccess', false);
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(
'Validating...', '0% Validating',
); );
}); });
@ -86,18 +83,16 @@ describe('Browser: progressStatus', function() {
}); });
it('should handle percentage == 50, verifying, unmountOnSuccess', function() { it('should handle percentage == 50, verifying, unmountOnSuccess', function() {
this.state.flashing = 0;
this.state.verifying = 1;
this.state.percentage = 50; this.state.percentage = 50;
this.state.type = 'verifying';
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(
'50% Validating', '50% Validating',
); );
}); });
it('should handle percentage == 50, verifying, !unmountOnSuccess', function() { it('should handle percentage == 50, verifying, !unmountOnSuccess', function() {
this.state.flashing = 0;
this.state.verifying = 1;
this.state.percentage = 50; this.state.percentage = 50;
this.state.type = 'verifying';
settings.set('unmountOnSuccess', false); settings.set('unmountOnSuccess', false);
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(
'50% Validating', '50% Validating',
@ -115,7 +110,7 @@ describe('Browser: progressStatus', function() {
this.state.percentage = 100; this.state.percentage = 100;
settings.set('validateWriteOnSuccess', false); settings.set('validateWriteOnSuccess', false);
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(
'Unmounting...', 'Finishing...',
); );
}); });
@ -129,17 +124,14 @@ describe('Browser: progressStatus', function() {
}); });
it('should handle percentage == 100, verifying, unmountOnSuccess', function() { it('should handle percentage == 100, verifying, unmountOnSuccess', function() {
this.state.flashing = 0;
this.state.verifying = 1;
this.state.percentage = 100; this.state.percentage = 100;
this.state.type = 'verifying';
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(
'Unmounting...', 'Finishing...',
); );
}); });
it('should handle percentage == 100, validatinf, !unmountOnSuccess', function() { it('should handle percentage == 100, validatinf, !unmountOnSuccess', function() {
this.state.flashing = 0;
this.state.verifying = 1;
this.state.percentage = 100; this.state.percentage = 100;
settings.set('unmountOnSuccess', false); settings.set('unmountOnSuccess', false);
expect(progressStatus.fromFlashState(this.state)).to.equal( expect(progressStatus.fromFlashState(this.state)).to.equal(

View File

@ -30,9 +30,8 @@ describe('Browser: WindowProgress', function() {
windowProgress.currentWindow.setTitle = this.setTitleSpy; windowProgress.currentWindow.setTitle = this.setTitleSpy;
this.state = { this.state = {
flashing: 1, active: 1,
verifying: 0, type: 'flashing',
successful: 0,
failed: 0, failed: 0,
percentage: 85, percentage: 85,
speed: 100, speed: 100,
@ -79,8 +78,7 @@ describe('Browser: WindowProgress', function() {
}); });
it('should set the verifying title', function() { it('should set the verifying title', function() {
this.state.flashing = 0; this.state.type = 'verifying';
this.state.verifying = 1;
windowProgress.set(this.state); windowProgress.set(this.state);
assert.calledWith(this.setTitleSpy, ' 85% Validating'); assert.calledWith(this.setTitleSpy, ' 85% Validating');
}); });
@ -89,7 +87,7 @@ describe('Browser: WindowProgress', function() {
this.state.percentage = 0; this.state.percentage = 0;
this.state.speed = 0; this.state.speed = 0;
windowProgress.set(this.state); windowProgress.set(this.state);
assert.calledWith(this.setTitleSpy, ' Starting...'); assert.calledWith(this.setTitleSpy, ' 0% Flashing');
}); });
it('should set the finishing title', function() { it('should set the finishing title', function() {