mirror of
https://github.com/balena-io/etcher.git
synced 2025-04-24 07:17:18 +00:00
feat(GUI): support new "pending" drive flag (#1709)
We recently added a "pending" flag to all drives that represents whether the drive is ready for selection or not. This flag will be used by the "usbboot" flashing adaptor, which will emit various "pending" USB devices while it converts them to block devices that can actually be flashed. In terms of the GUI, the following visible changes were made: - Drives with a `pending: true` property will be disabled in the drive selector window - Drives with a `pending: true` property have a "PENDING" red badge See: https://github.com/resin-io/etcher/pull/1707 See: https://github.com/resin-io/etcher/pull/1686 Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
This commit is contained in:
parent
f3c8ec496a
commit
7b791d622f
@ -168,7 +168,29 @@ exports.isDriveLargeEnough = (drive, image) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Check if a drive is is valid, i.e. not locked and large enough for an image
|
||||
* @summary Check if a drive is pending (i.e. not ready for selection)
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @param {Object} drive - drive
|
||||
* @returns {Boolean} whether the drive is pending
|
||||
*
|
||||
* @example
|
||||
* if (constraints.isDrivePending({
|
||||
* device: '/dev/disk2',
|
||||
* name: 'My Drive',
|
||||
* size: 1000000000,
|
||||
* pending: true
|
||||
* })) {
|
||||
* console.log('The drive is pending');
|
||||
* }
|
||||
*/
|
||||
exports.isDrivePending = (drive) => {
|
||||
return _.get(drive, [ 'pending' ], false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Check if a drive is valid, i.e. not locked and large enough for an image
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
@ -194,7 +216,8 @@ exports.isDriveValid = (drive, image) => {
|
||||
return _.every([
|
||||
!this.isDriveLocked(drive),
|
||||
this.isDriveLargeEnough(drive, image),
|
||||
!this.isSourceDrive(drive, image)
|
||||
!this.isSourceDrive(drive, image),
|
||||
!this.isDrivePending(drive)
|
||||
])
|
||||
}
|
||||
|
||||
@ -278,6 +301,15 @@ exports.COMPATIBILITY_STATUS_MESSAGES = {
|
||||
*/
|
||||
SYSTEM: 'System Drive',
|
||||
|
||||
/**
|
||||
* @property {String} PENDING
|
||||
* @memberof COMPATIBILITY_STATUS_MESSAGES
|
||||
*
|
||||
* @description
|
||||
* The drive is not fully loaded.
|
||||
*/
|
||||
PENDING: 'Pending',
|
||||
|
||||
/**
|
||||
* @property {String} CONTAINS_IMAGE
|
||||
* @memberof COMPATIBILITY_STATUS_MESSAGES
|
||||
@ -342,7 +374,12 @@ exports.getDriveImageCompatibilityStatuses = (drive, image) => {
|
||||
const statusList = []
|
||||
|
||||
// Mind the order of the if-statements if you modify.
|
||||
if (exports.isSourceDrive(drive, image)) {
|
||||
if (exports.isDrivePending(drive)) {
|
||||
statusList.push({
|
||||
type: exports.COMPATIBILITY_STATUS_TYPES.ERROR,
|
||||
message: exports.COMPATIBILITY_STATUS_MESSAGES.PENDING
|
||||
})
|
||||
} else if (exports.isSourceDrive(drive, image)) {
|
||||
statusList.push({
|
||||
type: exports.COMPATIBILITY_STATUS_TYPES.ERROR,
|
||||
message: exports.COMPATIBILITY_STATUS_MESSAGES.CONTAINS_IMAGE
|
||||
|
@ -527,6 +527,43 @@ describe('Shared: DriveConstraints', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('.isDrivePending()', function () {
|
||||
it('should return true if the drive is pending', function () {
|
||||
const result = constraints.isDrivePending({
|
||||
device: '/dev/disk1',
|
||||
name: 'USB Drive',
|
||||
size: 1000000000,
|
||||
protected: false,
|
||||
pending: true
|
||||
})
|
||||
|
||||
m.chai.expect(result).to.be.true
|
||||
})
|
||||
|
||||
it('should return false if the drive is not pending', function () {
|
||||
const result = constraints.isDrivePending({
|
||||
device: '/dev/disk1',
|
||||
name: 'USB Drive',
|
||||
size: 1000000000,
|
||||
protected: false,
|
||||
pending: false
|
||||
})
|
||||
|
||||
m.chai.expect(result).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if "pending" is undefined', function () {
|
||||
const result = constraints.isDrivePending({
|
||||
device: '/dev/disk1',
|
||||
name: 'USB Drive',
|
||||
size: 1000000000,
|
||||
protected: false
|
||||
})
|
||||
|
||||
m.chai.expect(result).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
describe('.isDriveSizeRecommended()', function () {
|
||||
it('should return true if the drive size is greater than the recommended size ', function () {
|
||||
const result = constraints.isDriveSizeRecommended({
|
||||
@ -639,56 +676,120 @@ describe('Shared: DriveConstraints', function () {
|
||||
this.drive.protected = true
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
describe('given the drive is pending', function () {
|
||||
beforeEach(function () {
|
||||
this.drive.pending = true
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
describe('given the drive is not pending', function () {
|
||||
beforeEach(function () {
|
||||
this.drive.pending = false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
it('should return false if the drive is not large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
it('should return false if the drive is not large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -697,56 +798,120 @@ describe('Shared: DriveConstraints', function () {
|
||||
this.drive.protected = false
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
describe('given the drive is pending', function () {
|
||||
beforeEach(function () {
|
||||
this.drive.pending = true
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
it('should return false if the drive is not large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
describe('given the drive is not pending', function () {
|
||||
beforeEach(function () {
|
||||
this.drive.pending = false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
it('should return false if the drive is not large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return true if the drive is large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
it('should return false if the drive is not large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 5000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 5000000000
|
||||
}
|
||||
}
|
||||
}
|
||||
})).to.be.true
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return false if the drive is large enough and is a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.join(this.mountpoint, 'rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.false
|
||||
})
|
||||
|
||||
it('should return true if the drive is large enough and is not a source drive', function () {
|
||||
m.chai.expect(constraints.isDriveValid(this.drive, {
|
||||
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
|
||||
size: {
|
||||
original: 2000000000,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: 2000000000
|
||||
}
|
||||
}
|
||||
})).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -766,6 +931,7 @@ describe('Shared: DriveConstraints', function () {
|
||||
name: 'My Drive',
|
||||
protected: false,
|
||||
system: false,
|
||||
pending: false,
|
||||
mountpoints: [
|
||||
{
|
||||
path: this.mountpoint
|
||||
@ -809,6 +975,19 @@ describe('Shared: DriveConstraints', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('given the drive is pending', () => {
|
||||
it('should return an empty list', function () {
|
||||
this.drive.pending = true
|
||||
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, {
|
||||
path: '/mnt/disk2/rpi.img',
|
||||
size: 1000000000
|
||||
})
|
||||
|
||||
const expectedTuples = [ [ 'ERROR', 'PENDING' ] ]
|
||||
expectStatusTypesAndMessagesToBe(result, expectedTuples)
|
||||
})
|
||||
})
|
||||
|
||||
describe('given the drive contains the image', () => {
|
||||
it('should return the contains-image error', function () {
|
||||
this.image.path = path.join(this.mountpoint, 'rpi.img')
|
||||
|
Loading…
x
Reference in New Issue
Block a user