From 4108979b653a57a03149c8590d1d9b79689c928a Mon Sep 17 00:00:00 2001 From: Jonas Hermsmeier Date: Tue, 24 Oct 2017 22:43:54 +0200 Subject: [PATCH] feat(gui): Display image size when drive too small This adds a display of the determined image size to the drive label when the drive has been determined to be too small. Change-Type: patch Changelog-Entry: Display image size for comparison if drive is too small --- lib/shared/drive-constraints.js | 82 ++++---------------------- lib/shared/messages.js | 35 +++++++++++ tests/shared/drive-constraints.spec.js | 41 ++++++++----- 3 files changed, 71 insertions(+), 87 deletions(-) diff --git a/lib/shared/drive-constraints.js b/lib/shared/drive-constraints.js index 98314d0f..ce7fe907 100644 --- a/lib/shared/drive-constraints.js +++ b/lib/shared/drive-constraints.js @@ -18,6 +18,8 @@ const _ = require('lodash') const pathIsInside = require('path-is-inside') +const prettyBytes = require('pretty-bytes') +const messages = require('./messages') /** * @summary The default unknown size for things such as images and drives @@ -299,72 +301,6 @@ exports.isDriveSizeLarge = (drive) => { return _.get(drive, [ 'size' ], UNKNOWN_SIZE) > exports.LARGE_DRIVE_SIZE } -/** - * @summary Drive/image compatibility status messages. - * @public - * @type {Object} - * - * @description - * Status messages intended to be shown to the user. - */ -exports.COMPATIBILITY_STATUS_MESSAGES = { - - /** - * @property {String} SIZE_NOT_RECOMMENDED - * @memberof COMPATIBILITY_STATUS_MESSAGES - * - * @description - * The image and drive compatibility is not recommended; happens when the - * actual drive size is smaller than the image's recommended drive size. - */ - SIZE_NOT_RECOMMENDED: 'Not Recommended', - - /** - * @property {String} TOO_SMALL - * @memberof COMPATIBILITY_STATUS_MESSAGES - * - * @description - * The drive is too small for the image. - */ - TOO_SMALL: 'Too Small For Image', - - /** - * @property {String} LOCKED - * @memberof COMPATIBILITY_STATUS_MESSAGES - * - * @description - * The drive is locked (e.g. the lock-tab on SD cards) and cannot be written to. - */ - LOCKED: 'Locked', - - /** - * @property {String} SYSTEM - * @memberof COMPATIBILITY_STATUS_MESSAGES - * - * @description - * The drive is a system drive and should not be written to. - */ - SYSTEM: 'System Drive', - - /** - * @property {String} CONTAINS_IMAGE - * @memberof COMPATIBILITY_STATUS_MESSAGES - * - * @description - * The drive contains the image and therefore cannot be written to. - */ - CONTAINS_IMAGE: 'Drive Contains Image', - - /** - * @property {String} LARGE_DRIVE - * @memberof COMPATIBILITY_STATUS_MESSAGES - * - * @description - * The drive is large and therefore likely not a medium you want to write to. - */ - LARGE_DRIVE: 'Large Drive' -} - /** * @summary Drive/image compatibility status types. * @public @@ -428,37 +364,39 @@ exports.getDriveImageCompatibilityStatuses = (drive, image) => { if (exports.isSourceDrive(drive, image)) { statusList.push({ type: exports.COMPATIBILITY_STATUS_TYPES.ERROR, - message: exports.COMPATIBILITY_STATUS_MESSAGES.CONTAINS_IMAGE + message: messages.compatibility.containsImage() }) } else if (exports.isDriveLocked(drive)) { statusList.push({ type: exports.COMPATIBILITY_STATUS_TYPES.ERROR, - message: exports.COMPATIBILITY_STATUS_MESSAGES.LOCKED + message: messages.compatibility.locked() }) } else if (!_.isNil(drive) && !_.isNil(drive.size) && !exports.isDriveLargeEnough(drive, image)) { + const imageSize = _.get(image, [ 'size', 'final', 'estimation' ]) ? image.size.original : image.size.final.value + const relativeBytes = imageSize - drive.size statusList.push({ type: exports.COMPATIBILITY_STATUS_TYPES.ERROR, - message: exports.COMPATIBILITY_STATUS_MESSAGES.TOO_SMALL + message: messages.compatibility.tooSmall(prettyBytes(relativeBytes)) }) } else { if (exports.isSystemDrive(drive)) { statusList.push({ type: exports.COMPATIBILITY_STATUS_TYPES.WARNING, - message: exports.COMPATIBILITY_STATUS_MESSAGES.SYSTEM + message: messages.compatibility.system() }) } if (exports.isDriveSizeLarge(drive)) { statusList.push({ type: exports.COMPATIBILITY_STATUS_TYPES.WARNING, - message: exports.COMPATIBILITY_STATUS_MESSAGES.LARGE_DRIVE + message: messages.compatibility.largeDrive() }) } if (!_.isNil(drive) && !exports.isDriveSizeRecommended(drive, image)) { statusList.push({ type: exports.COMPATIBILITY_STATUS_TYPES.WARNING, - message: exports.COMPATIBILITY_STATUS_MESSAGES.SIZE_NOT_RECOMMENDED + message: messages.compatibility.sizeNotRecommended() }) } } diff --git a/lib/shared/messages.js b/lib/shared/messages.js index 72bf6d3f..ceefab59 100644 --- a/lib/shared/messages.js +++ b/lib/shared/messages.js @@ -62,6 +62,41 @@ module.exports = { `${drive.description} (${drive.displayName})` ].join(' ') } + + }, + + /** + * @summary Drive compatibility messages + * @namespace compatibility + * @memberof messages + */ + compatibility: { + + sizeNotRecommended () { + return 'Not Recommended' + }, + + tooSmall (additionalSpace) { + return `Insufficient space, additional ${additionalSpace} required` + }, + + locked () { + return 'Locked' + }, + + system () { + return 'System Drive' + }, + + containsImage () { + return 'Drive Contains Image' + }, + + // The drive is large and therefore likely not a medium you want to write to. + largeDrive () { + return 'Large Drive' + } + }, /** diff --git a/tests/shared/drive-constraints.spec.js b/tests/shared/drive-constraints.spec.js index 1425ca63..33912ba9 100644 --- a/tests/shared/drive-constraints.spec.js +++ b/tests/shared/drive-constraints.spec.js @@ -20,6 +20,7 @@ const m = require('mochainon') const _ = require('lodash') const path = require('path') const constraints = require('../../lib/shared/drive-constraints') +const messages = require('../../lib/shared/messages') describe('Shared: DriveConstraints', function () { describe('.isDriveLocked()', function () { @@ -1029,7 +1030,7 @@ describe('Shared: DriveConstraints', function () { const expectedTuplesSorted = _.sortBy(_.map(expectedTuples, (tuple) => { return { type: constraints.COMPATIBILITY_STATUS_TYPES[tuple[0]], - message: constraints.COMPATIBILITY_STATUS_MESSAGES[tuple[1]] + message: messages.compatibility[tuple[1]]() } }), [ 'message' ]) const resultTuplesSorted = _.sortBy(resultList, [ 'message' ]) @@ -1060,7 +1061,7 @@ describe('Shared: DriveConstraints', function () { this.image.path = path.join(this.mountpoint, 'rpi.img') const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'ERROR', 'CONTAINS_IMAGE' ] ] + const expectedTuples = [ [ 'ERROR', 'containsImage' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1071,7 +1072,7 @@ describe('Shared: DriveConstraints', function () { this.drive.isSystem = true const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'WARNING', 'SYSTEM' ] ] + const expectedTuples = [ [ 'WARNING', 'system' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1082,9 +1083,14 @@ describe('Shared: DriveConstraints', function () { this.image.size.final.value = this.drive.size + 1 const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'ERROR', 'TOO_SMALL' ] ] + const expected = [ + { + message: messages.compatibility.tooSmall('1 B'), + type: constraints.COMPATIBILITY_STATUS_TYPES.ERROR + } + ] - expectStatusTypesAndMessagesToBe(result, expectedTuples) + m.chai.expect(result).to.deep.equal(expected) }) }) @@ -1105,7 +1111,7 @@ describe('Shared: DriveConstraints', function () { this.drive.isReadOnly = true const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'ERROR', 'LOCKED' ] ] + const expectedTuples = [ [ 'ERROR', 'locked' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1116,7 +1122,7 @@ describe('Shared: DriveConstraints', function () { this.image.recommendedDriveSize = this.drive.size + 1 const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'WARNING', 'SIZE_NOT_RECOMMENDED' ] ] + const expectedTuples = [ [ 'WARNING', 'sizeNotRecommended' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1127,7 +1133,7 @@ describe('Shared: DriveConstraints', function () { this.drive.size = constraints.LARGE_DRIVE_SIZE + 1 const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'WARNING', 'LARGE_DRIVE' ] ] + const expectedTuples = [ [ 'WARNING', 'largeDrive' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1154,7 +1160,7 @@ describe('Shared: DriveConstraints', function () { this.drive.isReadOnly = true const result = constraints.getDriveImageCompatibilityStatuses(this.drive, null) - const expectedTuples = [ [ 'ERROR', 'LOCKED' ] ] + const expectedTuples = [ [ 'ERROR', 'locked' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1165,7 +1171,7 @@ describe('Shared: DriveConstraints', function () { this.drive.isSystem = true const result = constraints.getDriveImageCompatibilityStatuses(this.drive, null) - const expectedTuples = [ [ 'WARNING', 'SYSTEM' ] ] + const expectedTuples = [ [ 'WARNING', 'system' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1177,7 +1183,7 @@ describe('Shared: DriveConstraints', function () { this.image.path = path.join(this.mountpoint, 'rpi.img') const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'ERROR', 'CONTAINS_IMAGE' ] ] + const expectedTuples = [ [ 'ERROR', 'containsImage' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1188,7 +1194,7 @@ describe('Shared: DriveConstraints', function () { this.drive.isReadOnly = true const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'ERROR', 'LOCKED' ] ] + const expectedTuples = [ [ 'ERROR', 'locked' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) }) @@ -1200,9 +1206,14 @@ describe('Shared: DriveConstraints', function () { this.drive.isSystem = true const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'ERROR', 'TOO_SMALL' ] ] + const expected = [ + { + message: messages.compatibility.tooSmall('1 B'), + type: constraints.COMPATIBILITY_STATUS_TYPES.ERROR + } + ] - expectStatusTypesAndMessagesToBe(result, expectedTuples) + m.chai.expect(result).to.deep.equal(expected) }) }) @@ -1212,7 +1223,7 @@ describe('Shared: DriveConstraints', function () { this.image.recommendedDriveSize = this.drive.size + 1 const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image) - const expectedTuples = [ [ 'WARNING', 'SIZE_NOT_RECOMMENDED' ], [ 'WARNING', 'SYSTEM' ] ] + const expectedTuples = [ [ 'WARNING', 'sizeNotRecommended' ], [ 'WARNING', 'system' ] ] expectStatusTypesAndMessagesToBe(result, expectedTuples) })