refactor(GUI): move SupportedFormatsModel to lib/shared (#1251)

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
Juan Cruz Viotti 2017-04-13 14:38:30 -04:00 committed by GitHub
parent 64c8eb594b
commit 0890b1e369
9 changed files with 312 additions and 327 deletions

View File

@ -1,154 +0,0 @@
/*
* 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.SupportedFormats
*/
const angular = require('angular');
const _ = require('lodash');
const path = require('path');
const imageStream = require('../../image-stream');
const MODULE_NAME = 'Etcher.Models.SupportedFormats';
const SupportedFormats = angular.module(MODULE_NAME, []);
SupportedFormats.service('SupportedFormatsModel', function() {
/**
* @summary Build an extension list getter from a type
* @function
* @private
*
* @param {String} type - file type
* @returns {Function} extension list getter
*
* @example
* const extensions = getExtensionsFromTypeGetter('archive')();
*/
const getExtensionsFromTypeGetter = (type) => {
return () => {
return _.map(_.filter(imageStream.supportedFileTypes, {
type
}), 'extension');
};
};
/**
* @summary Get compressed extensions
* @function
* @public
*
* @returns {String[]} compressed extensions
*
* SupportedFormatsModel.getCompressedExtensions().forEach((extension) => {
* console.log('We support the ' + extension + ' compressed file format');
* });
*/
this.getCompressedExtensions = getExtensionsFromTypeGetter('compressed');
/**
* @summary Get non compressed extensions
* @function
* @public
*
* @returns {String[]} no compressed extensions
*
* SupportedFormatsModel.getNonCompressedExtensions().forEach((extension) => {
* console.log('We support the ' + extension + ' file format');
* });
*/
this.getNonCompressedExtensions = getExtensionsFromTypeGetter('image');
/**
* @summary Get archive extensions
* @function
* @public
*
* @returns {String[]} archive extensions
*
* SupportedFormatsModel.getArchiveExtensions().forEach((extension) => {
* console.log('We support the ' + extension + ' file format');
* });
*/
this.getArchiveExtensions = getExtensionsFromTypeGetter('archive');
/**
* @summary Get all supported extensions
* @function
* @public
*
* @returns {String[]} extensions
*
* SupportedFormatsModel.getAllExtensions().forEach((extension) => {
* console.log('We support the ' + extension + ' format');
* });
*/
this.getAllExtensions = () => {
return _.map(imageStream.supportedFileTypes, 'extension');
};
/**
* @summary Check if an image is supported
* @function
* @public
*
* @param {String} imagePath - image path
* @returns {Boolean} whether the image is supported
*
* if (SupportedFormatsModel.isSupportedImage('foo.iso.bz2')) {
* console.log('The image is supported!');
* }
*/
this.isSupportedImage = (imagePath) => {
const extension = _.toLower(_.replace(path.extname(imagePath), '.', ''));
if (_.some([
_.includes(this.getNonCompressedExtensions(), extension),
_.includes(this.getArchiveExtensions(), extension)
])) {
return true;
}
if (!_.includes(this.getCompressedExtensions(), extension)) {
return false;
}
return this.isSupportedImage(path.basename(imagePath, `.${extension}`));
};
/**
* @summary Check if an image seems to be a Windows image
* @function
* @public
*
* @param {String} imagePath - image path
* @returns {Boolean} whether the image seems to be a Windows image
*
* @example
* if (SupportedFormatsModel.looksLikeWindowsImage('path/to/en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso')) {
* console.log('Looks like a Windows image');
* }
*/
this.looksLikeWindowsImage = (imagePath) => {
const regex = /windows|win7|win8|win10|winxp/i;
return regex.test(path.basename(imagePath));
};
});
module.exports = MODULE_NAME;

View File

@ -25,9 +25,7 @@
const angular = require('angular');
const MODULE_NAME = 'Etcher.OS.Dialog';
const OSDialog = angular.module(MODULE_NAME, [
require('../../models/supported-formats')
]);
const OSDialog = angular.module(MODULE_NAME, []);
OSDialog.service('OSDialogService', require('./services/dialog'));

View File

@ -19,8 +19,9 @@
const _ = require('lodash');
const electron = require('electron');
const errors = require('../../../../shared/errors');
const supportedFormats = require('../../../../shared/supported-formats');
module.exports = function($q, SupportedFormatsModel) {
module.exports = function($q) {
/**
* @summary Current renderer BrowserWindow instance
@ -64,7 +65,7 @@ module.exports = function($q, SupportedFormatsModel) {
filters: [
{
name: 'OS Images',
extensions: _.sortBy(SupportedFormatsModel.getAllExtensions())
extensions: _.sortBy(supportedFormats.getAllExtensions())
}
]
}, (files) => {

View File

@ -22,9 +22,9 @@ const path = require('path');
const messages = require('../../../../shared/messages');
const errors = require('../../../../shared/errors');
const imageStream = require('../../../../image-stream');
const supportedFormats = require('../../../../shared/supported-formats');
module.exports = function(
SupportedFormatsModel,
SelectionStateModel,
AnalyticsService,
ErrorService,
@ -42,7 +42,7 @@ module.exports = function(
'img',
'iso',
'zip'
], SupportedFormatsModel.getAllExtensions());
], supportedFormats.getAllExtensions());
/**
* @summary Extra supported extensions
@ -51,7 +51,7 @@ module.exports = function(
* @public
*/
this.extraSupportedExtensions = _.difference(
SupportedFormatsModel.getAllExtensions(),
supportedFormats.getAllExtensions(),
this.mainSupportedExtensions
).sort();
@ -67,7 +67,7 @@ module.exports = function(
* .then(ImageSelectionController.selectImage);
*/
this.selectImage = (image) => {
if (!SupportedFormatsModel.isSupportedImage(image.path)) {
if (!supportedFormats.isSupportedImage(image.path)) {
const invalidImageError = errors.createUserError('Invalid image', messages.error.invalidImage({
image
}));
@ -78,7 +78,7 @@ module.exports = function(
}
Bluebird.try(() => {
if (!SupportedFormatsModel.looksLikeWindowsImage(image.path)) {
if (!supportedFormats.looksLikeWindowsImage(image.path)) {
return false;
}

View File

@ -49,7 +49,6 @@ const MainPage = angular.module(MODULE_NAME, [
require('../../modules/analytics'),
require('../../modules/error'),
require('../../models/selection-state'),
require('../../models/supported-formats'),
require('../../models/drives'),
require('../../utils/byte-size/byte-size')

View File

@ -0,0 +1,141 @@
/*
* 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';
const _ = require('lodash');
const path = require('path');
const imageStream = require('../image-stream');
/**
* @summary Build an extension list getter from a type
* @function
* @private
*
* @param {String} type - file type
* @returns {Function} extension list getter
*
* @example
* const extensions = getExtensionsFromTypeGetter('archive')();
*/
const getExtensionsFromTypeGetter = (type) => {
return () => {
return _.map(_.filter(imageStream.supportedFileTypes, {
type
}), 'extension');
};
};
/**
* @summary Get compressed extensions
* @function
* @public
*
* @returns {String[]} compressed extensions
*
* _.each(supportedFormats.getCompressedExtensions(), (extension) => {
* console.log('We support the ' + extension + ' compressed file format');
* });
*/
exports.getCompressedExtensions = getExtensionsFromTypeGetter('compressed');
/**
* @summary Get non compressed extensions
* @function
* @public
*
* @returns {String[]} no compressed extensions
*
* _.each(supportedFormats.getNonCompressedExtensions(), (extension) => {
* console.log('We support the ' + extension + ' file format');
* });
*/
exports.getNonCompressedExtensions = getExtensionsFromTypeGetter('image');
/**
* @summary Get archive extensions
* @function
* @public
*
* @returns {String[]} archive extensions
*
* _.each(supportedFormats.getArchiveExtensions(), (extension) => {
* console.log('We support the ' + extension + ' file format');
* });
*/
exports.getArchiveExtensions = getExtensionsFromTypeGetter('archive');
/**
* @summary Get all supported extensions
* @function
* @public
*
* @returns {String[]} extensions
*
* _.each(supportedFormats.getAllExtensions(), (extension) => {
* console.log('We support the ' + extension + ' format');
* });
*/
exports.getAllExtensions = () => {
return _.map(imageStream.supportedFileTypes, 'extension');
};
/**
* @summary Check if an image is supported
* @function
* @public
*
* @param {String} imagePath - image path
* @returns {Boolean} whether the image is supported
*
* if (supportedFormats.isSupportedImage('foo.iso.bz2')) {
* console.log('The image is supported!');
* }
*/
exports.isSupportedImage = (imagePath) => {
const extension = _.toLower(_.replace(path.extname(imagePath), '.', ''));
if (_.some([
_.includes(exports.getNonCompressedExtensions(), extension),
_.includes(exports.getArchiveExtensions(), extension)
])) {
return true;
}
if (!_.includes(exports.getCompressedExtensions(), extension)) {
return false;
}
return exports.isSupportedImage(path.basename(imagePath, `.${extension}`));
};
/**
* @summary Check if an image seems to be a Windows image
* @function
* @public
*
* @param {String} imagePath - image path
* @returns {Boolean} whether the image seems to be a Windows image
*
* @example
* if (supportedFormats.looksLikeWindowsImage('path/to/en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso')) {
* console.log('Looks like a Windows image');
* }
*/
exports.looksLikeWindowsImage = (imagePath) => {
const regex = /windows|win7|win8|win10|winxp/i;
return regex.test(path.basename(imagePath));
};

View File

@ -1,158 +0,0 @@
'use strict';
const m = require('mochainon');
const _ = require('lodash');
const angular = require('angular');
require('angular-mocks');
describe('Browser: SupportedFormats', function() {
beforeEach(angular.mock.module(
require('../../../lib/gui/models/supported-formats')
));
describe('SupportedFormatsModel', function() {
let SupportedFormatsModel;
beforeEach(angular.mock.inject(function(_SupportedFormatsModel_) {
SupportedFormatsModel = _SupportedFormatsModel_;
}));
describe('.getCompressedExtensions()', function() {
it('should return the supported compressed extensions', function() {
const extensions = SupportedFormatsModel.getCompressedExtensions();
m.chai.expect(extensions).to.deep.equal([ 'gz', 'bz2', 'xz', 'dmg' ]);
});
});
describe('.getNonCompressedExtensions()', function() {
it('should return the supported non compressed extensions', function() {
const extensions = SupportedFormatsModel.getNonCompressedExtensions();
m.chai.expect(extensions).to.deep.equal([ 'img', 'iso', 'dsk', 'hddimg', 'raw' ]);
});
});
describe('.getArchiveExtensions()', function() {
it('should return the supported archive extensions', function() {
const extensions = SupportedFormatsModel.getArchiveExtensions();
m.chai.expect(extensions).to.deep.equal([ 'zip', 'etch' ]);
});
});
describe('.getAllExtensions()', function() {
it('should return the union of all compressed, uncompressed, and archive extensions', function() {
const archiveExtensions = SupportedFormatsModel.getArchiveExtensions();
const compressedExtensions = SupportedFormatsModel.getCompressedExtensions();
const nonCompressedExtensions = SupportedFormatsModel.getNonCompressedExtensions();
const expected = _.union(archiveExtensions, compressedExtensions, nonCompressedExtensions);
const extensions = SupportedFormatsModel.getAllExtensions();
m.chai.expect(extensions).to.deep.equal(expected);
});
});
describe('.isSupportedImage()', function() {
it('should return false if the file has no extension', function() {
const isSupported = SupportedFormatsModel.isSupportedImage('/path/to/foo');
m.chai.expect(isSupported).to.be.false;
});
it('should return false if the extension is not included in .getAllExtensions()', function() {
const isSupported = SupportedFormatsModel.isSupportedImage('/path/to/foo.jpg');
m.chai.expect(isSupported).to.be.false;
});
it('should return true if the extension is included in .getAllExtensions()', function() {
const nonCompressedExtension = _.first(SupportedFormatsModel.getNonCompressedExtensions());
const imagePath = `/path/to/foo.${nonCompressedExtension}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should ignore casing when determining extension validity', function() {
const nonCompressedExtension = _.first(SupportedFormatsModel.getNonCompressedExtensions());
const imagePath = `/path/to/foo.${_.toUpper(nonCompressedExtension)}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should not consider an extension before a non compressed extension', function() {
const nonCompressedExtension = _.first(SupportedFormatsModel.getNonCompressedExtensions());
const imagePath = `/path/to/foo.1234.${nonCompressedExtension}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return true if the extension is supported and the file name includes dots', function() {
const nonCompressedExtension = _.first(SupportedFormatsModel.getNonCompressedExtensions());
const imagePath = `/path/to/foo.1.2.3-bar.${nonCompressedExtension}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return true if the extension is only a supported archive extension', function() {
const archiveExtension = _.first(SupportedFormatsModel.getArchiveExtensions());
const imagePath = `/path/to/foo.${archiveExtension}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return true if the extension is a supported one plus a supported compressed extensions', function() {
const nonCompressedExtension = _.first(SupportedFormatsModel.getNonCompressedExtensions());
const compressedExtension = _.first(SupportedFormatsModel.getCompressedExtensions());
const imagePath = `/path/to/foo.${nonCompressedExtension}.${compressedExtension}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return false if the extension is an unsupported one plus a supported compressed extensions', function() {
const compressedExtension = _.first(SupportedFormatsModel.getCompressedExtensions());
const imagePath = `/path/to/foo.jpg.${compressedExtension}`;
const isSupported = SupportedFormatsModel.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.false;
});
});
describe('.looksLikeWindowsImage()', function() {
_.each([
'C:\\path\\to\\en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso',
'/path/to/en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso',
'/path/to/Win10_1607_SingleLang_English_x32.iso',
'/path/to/en_winxp_pro_x86_build2600_iso.img'
], (imagePath) => {
it(`should return true if filename is ${imagePath}`, function() {
const looksLikeWindowsImage = SupportedFormatsModel.looksLikeWindowsImage(imagePath);
m.chai.expect(looksLikeWindowsImage).to.be.true;
});
});
_.each([
'C:\\path\\to\\2017-01-11-raspbian-jessie.img',
'/path/to/2017-01-11-raspbian-jessie.img'
], (imagePath) => {
it(`should return false if filename is ${imagePath}`, function() {
const looksLikeWindowsImage = SupportedFormatsModel.looksLikeWindowsImage(imagePath);
m.chai.expect(looksLikeWindowsImage).to.be.false;
});
});
});
});
});

View File

@ -3,6 +3,7 @@
const m = require('mochainon');
const _ = require('lodash');
const path = require('path');
const supportedFormats = require('../../../lib/shared/supported-formats');
const angular = require('angular');
const settings = require('../../../lib/gui/models/settings');
const flashState = require('../../../lib/gui/models/flash-state');
@ -151,12 +152,10 @@ describe('Browser: MainPage', function() {
describe('ImageSelectionController', function() {
let $controller;
let SupportedFormatsModel;
let SelectionStateModel;
beforeEach(angular.mock.inject(function(_$controller_, _SupportedFormatsModel_, _SelectionStateModel_) {
beforeEach(angular.mock.inject(function(_$controller_, _SelectionStateModel_) {
$controller = _$controller_;
SupportedFormatsModel = _SupportedFormatsModel_;
SelectionStateModel = _SelectionStateModel_;
}));
@ -167,7 +166,7 @@ describe('Browser: MainPage', function() {
});
const extensions = controller.mainSupportedExtensions.concat(controller.extraSupportedExtensions);
m.chai.expect(_.sortBy(extensions)).to.deep.equal(_.sortBy(SupportedFormatsModel.getAllExtensions()));
m.chai.expect(_.sortBy(extensions)).to.deep.equal(_.sortBy(supportedFormats.getAllExtensions()));
});
describe('.getImageBasename()', function() {

View File

@ -0,0 +1,159 @@
/*
* 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';
const m = require('mochainon');
const _ = require('lodash');
const supportedFormats = require('../../lib/shared/supported-formats');
describe('Shared: SupportedFormats', function() {
describe('.getCompressedExtensions()', function() {
it('should return the supported compressed extensions', function() {
const extensions = supportedFormats.getCompressedExtensions();
m.chai.expect(extensions).to.deep.equal([ 'gz', 'bz2', 'xz', 'dmg' ]);
});
});
describe('.getNonCompressedExtensions()', function() {
it('should return the supported non compressed extensions', function() {
const extensions = supportedFormats.getNonCompressedExtensions();
m.chai.expect(extensions).to.deep.equal([ 'img', 'iso', 'dsk', 'hddimg', 'raw' ]);
});
});
describe('.getArchiveExtensions()', function() {
it('should return the supported archive extensions', function() {
const extensions = supportedFormats.getArchiveExtensions();
m.chai.expect(extensions).to.deep.equal([ 'zip', 'etch' ]);
});
});
describe('.getAllExtensions()', function() {
it('should return the union of all compressed, uncompressed, and archive extensions', function() {
const archiveExtensions = supportedFormats.getArchiveExtensions();
const compressedExtensions = supportedFormats.getCompressedExtensions();
const nonCompressedExtensions = supportedFormats.getNonCompressedExtensions();
const expected = _.union(archiveExtensions, compressedExtensions, nonCompressedExtensions);
const extensions = supportedFormats.getAllExtensions();
m.chai.expect(extensions).to.deep.equal(expected);
});
});
describe('.isSupportedImage()', function() {
it('should return false if the file has no extension', function() {
const isSupported = supportedFormats.isSupportedImage('/path/to/foo');
m.chai.expect(isSupported).to.be.false;
});
it('should return false if the extension is not included in .getAllExtensions()', function() {
const isSupported = supportedFormats.isSupportedImage('/path/to/foo.jpg');
m.chai.expect(isSupported).to.be.false;
});
it('should return true if the extension is included in .getAllExtensions()', function() {
const nonCompressedExtension = _.first(supportedFormats.getNonCompressedExtensions());
const imagePath = `/path/to/foo.${nonCompressedExtension}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should ignore casing when determining extension validity', function() {
const nonCompressedExtension = _.first(supportedFormats.getNonCompressedExtensions());
const imagePath = `/path/to/foo.${_.toUpper(nonCompressedExtension)}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should not consider an extension before a non compressed extension', function() {
const nonCompressedExtension = _.first(supportedFormats.getNonCompressedExtensions());
const imagePath = `/path/to/foo.1234.${nonCompressedExtension}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return true if the extension is supported and the file name includes dots', function() {
const nonCompressedExtension = _.first(supportedFormats.getNonCompressedExtensions());
const imagePath = `/path/to/foo.1.2.3-bar.${nonCompressedExtension}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return true if the extension is only a supported archive extension', function() {
const archiveExtension = _.first(supportedFormats.getArchiveExtensions());
const imagePath = `/path/to/foo.${archiveExtension}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return true if the extension is a supported one plus a supported compressed extensions', function() {
const nonCompressedExtension = _.first(supportedFormats.getNonCompressedExtensions());
const compressedExtension = _.first(supportedFormats.getCompressedExtensions());
const imagePath = `/path/to/foo.${nonCompressedExtension}.${compressedExtension}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.true;
});
it('should return false if the extension is an unsupported one plus a supported compressed extensions', function() {
const compressedExtension = _.first(supportedFormats.getCompressedExtensions());
const imagePath = `/path/to/foo.jpg.${compressedExtension}`;
const isSupported = supportedFormats.isSupportedImage(imagePath);
m.chai.expect(isSupported).to.be.false;
});
});
describe('.looksLikeWindowsImage()', function() {
_.each([
'C:\\path\\to\\en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso',
'/path/to/en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso',
'/path/to/Win10_1607_SingleLang_English_x32.iso',
'/path/to/en_winxp_pro_x86_build2600_iso.img'
], (imagePath) => {
it(`should return true if filename is ${imagePath}`, function() {
const looksLikeWindowsImage = supportedFormats.looksLikeWindowsImage(imagePath);
m.chai.expect(looksLikeWindowsImage).to.be.true;
});
});
_.each([
'C:\\path\\to\\2017-01-11-raspbian-jessie.img',
'/path/to/2017-01-11-raspbian-jessie.img'
], (imagePath) => {
it(`should return false if filename is ${imagePath}`, function() {
const looksLikeWindowsImage = supportedFormats.looksLikeWindowsImage(imagePath);
m.chai.expect(looksLikeWindowsImage).to.be.false;
});
});
});
});