mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-23 19:26:33 +00:00
feat(GUI): collect archive and image extension in analytics (#1343)
Change-Type: patch
This commit is contained in:
parent
9e7e5de63a
commit
1fe87d8883
@ -23,6 +23,7 @@ const persistState = require('redux-localstorage');
|
|||||||
const uuidV4 = require('uuid/v4');
|
const uuidV4 = require('uuid/v4');
|
||||||
const constraints = require('../../shared/drive-constraints');
|
const constraints = require('../../shared/drive-constraints');
|
||||||
const errors = require('../../shared/errors');
|
const errors = require('../../shared/errors');
|
||||||
|
const fileExtensions = require('../../shared/file-extensions');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Application default state
|
* @summary Application default state
|
||||||
@ -331,6 +332,32 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!action.data.extension) {
|
||||||
|
throw errors.createError({
|
||||||
|
title: 'Missing image extension'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isString(action.data.extension)) {
|
||||||
|
throw errors.createError({
|
||||||
|
title: `Invalid image extension: ${action.data.extension}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileExtensions.getLastFileExtension(action.data.path) !== action.data.extension) {
|
||||||
|
if (!action.data.archiveExtension) {
|
||||||
|
throw errors.createError({
|
||||||
|
title: 'Missing image archive extension'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isString(action.data.archiveExtension)) {
|
||||||
|
throw errors.createError({
|
||||||
|
title: `Invalid image archive extension: ${action.data.archiveExtension}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!action.data.size) {
|
if (!action.data.size) {
|
||||||
throw errors.createError({
|
throw errors.createError({
|
||||||
title: 'Missing image size'
|
title: 'Missing image size'
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
const Bluebird = require('bluebird');
|
const Bluebird = require('bluebird');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const PassThroughStream = require('stream').PassThrough;
|
const PassThroughStream = require('stream').PassThrough;
|
||||||
const supportedFileTypes = require('./supported');
|
const supportedFileTypes = require('./supported');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const errors = require('../shared/errors');
|
const errors = require('../shared/errors');
|
||||||
|
const fileExtensions = require('../shared/file-extensions');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Archive metadata base path
|
* @summary Archive metadata base path
|
||||||
@ -172,8 +172,7 @@ exports.extractImage = (archive, hooks) => {
|
|||||||
return hooks.getEntries(archive).then((entries) => {
|
return hooks.getEntries(archive).then((entries) => {
|
||||||
|
|
||||||
const imageEntries = _.filter(entries, (entry) => {
|
const imageEntries = _.filter(entries, (entry) => {
|
||||||
const extension = _.toLower(_.replace(path.extname(entry.name), '.', ''));
|
return _.includes(IMAGE_EXTENSIONS, fileExtensions.getLastFileExtension(entry.name));
|
||||||
return _.includes(IMAGE_EXTENSIONS, extension);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const VALID_NUMBER_OF_IMAGE_ENTRIES = 1;
|
const VALID_NUMBER_OF_IMAGE_ENTRIES = 1;
|
||||||
@ -205,6 +204,9 @@ exports.extractImage = (archive, hooks) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
results.metadata.extension = fileExtensions.getLastFileExtension(imageEntry.name);
|
||||||
|
results.metadata.archiveExtension = fileExtensions.getLastFileExtension(archive);
|
||||||
|
|
||||||
return results.metadata;
|
return results.metadata;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -26,6 +26,7 @@ const gzip = require('./gzip');
|
|||||||
const udif = Bluebird.promisifyAll(require('udif'));
|
const udif = Bluebird.promisifyAll(require('udif'));
|
||||||
const archive = require('./archive');
|
const archive = require('./archive');
|
||||||
const zipArchiveHooks = require('./archive-hooks/zip');
|
const zipArchiveHooks = require('./archive-hooks/zip');
|
||||||
|
const fileExtensions = require('../shared/file-extensions');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Image handlers
|
* @summary Image handlers
|
||||||
@ -50,6 +51,8 @@ module.exports = {
|
|||||||
'application/x-bzip2': (file, options) => {
|
'application/x-bzip2': (file, options) => {
|
||||||
return Bluebird.props({
|
return Bluebird.props({
|
||||||
path: file,
|
path: file,
|
||||||
|
archiveExtension: fileExtensions.getLastFileExtension(file),
|
||||||
|
extension: fileExtensions.getPenultimateFileExtension(file),
|
||||||
stream: fs.createReadStream(file),
|
stream: fs.createReadStream(file),
|
||||||
size: {
|
size: {
|
||||||
original: options.size,
|
original: options.size,
|
||||||
@ -79,6 +82,8 @@ module.exports = {
|
|||||||
return gzip.getUncompressedSize(file).then((uncompressedSize) => {
|
return gzip.getUncompressedSize(file).then((uncompressedSize) => {
|
||||||
return Bluebird.props({
|
return Bluebird.props({
|
||||||
path: file,
|
path: file,
|
||||||
|
archiveExtension: fileExtensions.getLastFileExtension(file),
|
||||||
|
extension: fileExtensions.getPenultimateFileExtension(file),
|
||||||
stream: fs.createReadStream(file),
|
stream: fs.createReadStream(file),
|
||||||
size: {
|
size: {
|
||||||
original: options.size,
|
original: options.size,
|
||||||
@ -113,6 +118,8 @@ module.exports = {
|
|||||||
}).then((metadata) => {
|
}).then((metadata) => {
|
||||||
return {
|
return {
|
||||||
path: file,
|
path: file,
|
||||||
|
archiveExtension: fileExtensions.getLastFileExtension(file),
|
||||||
|
extension: fileExtensions.getPenultimateFileExtension(file),
|
||||||
stream: fs.createReadStream(file),
|
stream: fs.createReadStream(file),
|
||||||
size: {
|
size: {
|
||||||
original: options.size,
|
original: options.size,
|
||||||
@ -143,6 +150,7 @@ module.exports = {
|
|||||||
return udif.getUncompressedSizeAsync(file).then((size) => {
|
return udif.getUncompressedSizeAsync(file).then((size) => {
|
||||||
return {
|
return {
|
||||||
path: file,
|
path: file,
|
||||||
|
extension: fileExtensions.getLastFileExtension(file),
|
||||||
stream: udif.createReadStream(file),
|
stream: udif.createReadStream(file),
|
||||||
size: {
|
size: {
|
||||||
original: options.size,
|
original: options.size,
|
||||||
@ -186,6 +194,7 @@ module.exports = {
|
|||||||
'application/octet-stream': (file, options) => {
|
'application/octet-stream': (file, options) => {
|
||||||
return Bluebird.props({
|
return Bluebird.props({
|
||||||
path: file,
|
path: file,
|
||||||
|
extension: fileExtensions.getLastFileExtension(file),
|
||||||
stream: fs.createReadStream(file),
|
stream: fs.createReadStream(file),
|
||||||
size: {
|
size: {
|
||||||
original: options.size,
|
original: options.size,
|
||||||
|
74
lib/shared/file-extensions.js
Normal file
74
lib/shared/file-extensions.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 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');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get the extensions of a file
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @param {String} filePath - file path
|
||||||
|
* @returns {String[]} extensions
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const extensions = fileExtensions.getFileExtensions('path/to/foo.img.gz');
|
||||||
|
* console.log(extensions);
|
||||||
|
* > [ 'img', 'gz' ]
|
||||||
|
*/
|
||||||
|
exports.getFileExtensions = (filePath) => {
|
||||||
|
return _.chain(filePath)
|
||||||
|
.split('.')
|
||||||
|
.tail()
|
||||||
|
.map(_.toLower)
|
||||||
|
.value();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get the last file extension
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @param {String} filePath - file path
|
||||||
|
* @returns {(String|Undefined)} last extension
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const extension = fileExtensions.getLastFileExtension('path/to/foo.img.gz');
|
||||||
|
* console.log(extension);
|
||||||
|
* > [ 'gz' ]
|
||||||
|
*/
|
||||||
|
exports.getLastFileExtension = (filePath) => {
|
||||||
|
return _.last(exports.getFileExtensions(filePath));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Get the penultimate file extension
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @param {String} filePath - file path
|
||||||
|
* @returns {(String|Undefined)} penultimate extension
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const extension = fileExtensions.getLastFileExtension('path/to/foo.img.gz');
|
||||||
|
* console.log(extension);
|
||||||
|
* > [ 'img' ]
|
||||||
|
*/
|
||||||
|
exports.getPenultimateFileExtension = (filePath) => {
|
||||||
|
return _.last(_.initial(exports.getFileExtensions(filePath)));
|
||||||
|
};
|
@ -19,6 +19,7 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const imageStream = require('../image-stream');
|
const imageStream = require('../image-stream');
|
||||||
|
const fileExtensions = require('./file-extensions');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Build an extension list getter from a type
|
* @summary Build an extension list getter from a type
|
||||||
@ -106,20 +107,20 @@ exports.getAllExtensions = () => {
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
exports.isSupportedImage = (imagePath) => {
|
exports.isSupportedImage = (imagePath) => {
|
||||||
const extension = _.toLower(_.replace(path.extname(imagePath), '.', ''));
|
const lastExtension = fileExtensions.getLastFileExtension(imagePath);
|
||||||
|
const penultimateExtension = fileExtensions.getPenultimateFileExtension(imagePath);
|
||||||
|
|
||||||
if (_.some([
|
if (_.some([
|
||||||
_.includes(exports.getNonCompressedExtensions(), extension),
|
_.includes(exports.getNonCompressedExtensions(), lastExtension),
|
||||||
_.includes(exports.getArchiveExtensions(), extension)
|
_.includes(exports.getArchiveExtensions(), lastExtension)
|
||||||
])) {
|
])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.includes(exports.getCompressedExtensions(), extension)) {
|
return _.every([
|
||||||
return false;
|
_.includes(exports.getCompressedExtensions(), lastExtension),
|
||||||
}
|
_.includes(exports.getNonCompressedExtensions(), penultimateExtension)
|
||||||
|
]);
|
||||||
return exports.isSupportedImage(path.basename(imagePath, `.${extension}`));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,6 +118,7 @@ describe('Browser: DrivesModel', function() {
|
|||||||
SelectionStateModel.removeDrive();
|
SelectionStateModel.removeDrive();
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: this.imagePath,
|
path: this.imagePath,
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
|
@ -221,6 +221,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.image = {
|
this.image = {
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -342,6 +343,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
it('should override the image', function() {
|
it('should override the image', function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'bar.img',
|
path: 'bar.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -381,6 +383,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
it('should be able to set an image', function() {
|
it('should be able to set an image', function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -396,9 +399,28 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(imageSize).to.equal(999999999);
|
m.chai.expect(imageSize).to.equal(999999999);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to set an image with an archive extension', function() {
|
||||||
|
SelectionStateModel.setImage({
|
||||||
|
path: 'foo.zip',
|
||||||
|
extension: 'img',
|
||||||
|
archiveExtension: 'zip',
|
||||||
|
size: {
|
||||||
|
original: 999999999,
|
||||||
|
final: {
|
||||||
|
estimation: false,
|
||||||
|
value: 999999999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const imagePath = SelectionStateModel.getImagePath();
|
||||||
|
m.chai.expect(imagePath).to.equal('foo.zip');
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw if no path', function() {
|
it('should throw if no path', function() {
|
||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -414,6 +436,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 123,
|
path: 123,
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -425,10 +448,75 @@ describe('Browser: SelectionState', function() {
|
|||||||
}).to.throw('Invalid image path: 123');
|
}).to.throw('Invalid image path: 123');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw if no extension', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
SelectionStateModel.setImage({
|
||||||
|
path: 'foo.img',
|
||||||
|
size: {
|
||||||
|
original: 999999999,
|
||||||
|
final: {
|
||||||
|
estimation: false,
|
||||||
|
value: 999999999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).to.throw('Missing image extension');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if extension is not a string', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
SelectionStateModel.setImage({
|
||||||
|
path: 'foo.img',
|
||||||
|
extension: 1,
|
||||||
|
size: {
|
||||||
|
original: 999999999,
|
||||||
|
final: {
|
||||||
|
estimation: false,
|
||||||
|
value: 999999999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid image extension: 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if the extension doesn\'t match the path and there is no archive extension', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
SelectionStateModel.setImage({
|
||||||
|
path: 'foo.img',
|
||||||
|
extension: 'iso',
|
||||||
|
size: {
|
||||||
|
original: 999999999,
|
||||||
|
final: {
|
||||||
|
estimation: false,
|
||||||
|
value: 999999999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).to.throw('Missing image archive extension');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if the extension doesn\'t match the path and the archive extension is not a string', function() {
|
||||||
|
m.chai.expect(function() {
|
||||||
|
SelectionStateModel.setImage({
|
||||||
|
path: 'foo.img',
|
||||||
|
extension: 'iso',
|
||||||
|
archiveExtension: 1,
|
||||||
|
size: {
|
||||||
|
original: 999999999,
|
||||||
|
final: {
|
||||||
|
estimation: false,
|
||||||
|
value: 999999999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).to.throw('Invalid image archive extension: 1');
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw if no size', function() {
|
it('should throw if no size', function() {
|
||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img'
|
path: 'foo.img',
|
||||||
|
extension: 'img'
|
||||||
});
|
});
|
||||||
}).to.throw('Missing image size');
|
}).to.throw('Missing image size');
|
||||||
});
|
});
|
||||||
@ -437,6 +525,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: 999999999
|
size: 999999999
|
||||||
});
|
});
|
||||||
}).to.throw('Invalid image size: 999999999');
|
}).to.throw('Invalid image size: 999999999');
|
||||||
@ -446,6 +535,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: '999999999',
|
original: '999999999',
|
||||||
final: {
|
final: {
|
||||||
@ -461,6 +551,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999.999,
|
original: 999999999.999,
|
||||||
final: {
|
final: {
|
||||||
@ -476,6 +567,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: -1,
|
original: -1,
|
||||||
final: {
|
final: {
|
||||||
@ -491,6 +583,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -506,6 +599,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -521,6 +615,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -536,6 +631,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -551,6 +647,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -567,6 +664,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -583,6 +681,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -610,6 +709,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 9999999999,
|
original: 9999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -638,6 +738,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -680,6 +781,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: imagePath,
|
path: imagePath,
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
@ -713,6 +815,7 @@ describe('Browser: SelectionState', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'foo.img',
|
path: 'foo.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
|
@ -46,6 +46,7 @@ describe('Browser: MainPage', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'rpi.img',
|
path: 'rpi.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 99999,
|
original: 99999,
|
||||||
final: {
|
final: {
|
||||||
@ -80,6 +81,7 @@ describe('Browser: MainPage', function() {
|
|||||||
SelectionStateModel.clear();
|
SelectionStateModel.clear();
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'rpi.img',
|
path: 'rpi.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 99999,
|
original: 99999,
|
||||||
final: {
|
final: {
|
||||||
@ -133,6 +135,7 @@ describe('Browser: MainPage', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: 'rpi.img',
|
path: 'rpi.img',
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 99999,
|
original: 99999,
|
||||||
final: {
|
final: {
|
||||||
@ -178,6 +181,7 @@ describe('Browser: MainPage', function() {
|
|||||||
|
|
||||||
SelectionStateModel.setImage({
|
SelectionStateModel.setImage({
|
||||||
path: path.join(__dirname, 'foo', 'bar.img'),
|
path: path.join(__dirname, 'foo', 'bar.img'),
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: 999999999,
|
original: 999999999,
|
||||||
final: {
|
final: {
|
||||||
|
@ -48,6 +48,8 @@ describe('ImageStream: BZ2', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'img',
|
||||||
|
archiveExtension: 'bz2',
|
||||||
size: {
|
size: {
|
||||||
original: expectedSize,
|
original: expectedSize,
|
||||||
final: {
|
final: {
|
||||||
|
@ -51,6 +51,7 @@ describe('ImageStream: DMG', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'dmg',
|
||||||
size: {
|
size: {
|
||||||
original: compressedSize,
|
original: compressedSize,
|
||||||
final: {
|
final: {
|
||||||
@ -88,6 +89,7 @@ describe('ImageStream: DMG', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'dmg',
|
||||||
size: {
|
size: {
|
||||||
original: compressedSize,
|
original: compressedSize,
|
||||||
final: {
|
final: {
|
||||||
|
@ -49,6 +49,8 @@ describe('ImageStream: GZ', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'img',
|
||||||
|
archiveExtension: 'gz',
|
||||||
size: {
|
size: {
|
||||||
original: compressedSize,
|
original: compressedSize,
|
||||||
final: {
|
final: {
|
||||||
|
@ -47,6 +47,7 @@ describe('ImageStream: IMG', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'img',
|
||||||
size: {
|
size: {
|
||||||
original: expectedSize,
|
original: expectedSize,
|
||||||
final: {
|
final: {
|
||||||
|
@ -47,6 +47,7 @@ describe('ImageStream: ISO', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'iso',
|
||||||
size: {
|
size: {
|
||||||
original: expectedSize,
|
original: expectedSize,
|
||||||
final: {
|
final: {
|
||||||
|
@ -60,6 +60,8 @@ exports.extractFromFilePath = function(file, image) {
|
|||||||
|
|
||||||
return imageStream.getFromFilePath(file).then(function(results) {
|
return imageStream.getFromFilePath(file).then(function(results) {
|
||||||
m.chai.expect(results.path).to.equal(file);
|
m.chai.expect(results.path).to.equal(file);
|
||||||
|
m.chai.expect(_.isString(results.extension)).to.be.true;
|
||||||
|
m.chai.expect(_.isEmpty(_.trim(results.extension))).to.be.false;
|
||||||
|
|
||||||
if (!_.some([
|
if (!_.some([
|
||||||
results.size.original === fs.statSync(file).size,
|
results.size.original === fs.statSync(file).size,
|
||||||
|
@ -49,6 +49,8 @@ describe('ImageStream: XZ', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'img',
|
||||||
|
archiveExtension: 'xz',
|
||||||
size: {
|
size: {
|
||||||
original: compressedSize,
|
original: compressedSize,
|
||||||
final: {
|
final: {
|
||||||
|
@ -72,6 +72,8 @@ describe('ImageStream: ZIP', function() {
|
|||||||
return imageStream.getImageMetadata(image).then((metadata) => {
|
return imageStream.getImageMetadata(image).then((metadata) => {
|
||||||
m.chai.expect(metadata).to.deep.equal({
|
m.chai.expect(metadata).to.deep.equal({
|
||||||
path: image,
|
path: image,
|
||||||
|
extension: 'img',
|
||||||
|
archiveExtension: 'zip',
|
||||||
size: {
|
size: {
|
||||||
original: expectedSize,
|
original: expectedSize,
|
||||||
final: {
|
final: {
|
||||||
|
141
tests/shared/file-extensions.spec.js
Normal file
141
tests/shared/file-extensions.spec.js
Normal 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 m = require('mochainon');
|
||||||
|
const _ = require('lodash');
|
||||||
|
const fileExtensions = require('../../lib/shared/file-extensions');
|
||||||
|
|
||||||
|
describe('Shared: fileExtensions', function() {
|
||||||
|
|
||||||
|
describe('.getFileExtensions()', function() {
|
||||||
|
|
||||||
|
_.forEach([
|
||||||
|
|
||||||
|
// No extension
|
||||||
|
{
|
||||||
|
file: 'path/to/filename',
|
||||||
|
extension: []
|
||||||
|
},
|
||||||
|
|
||||||
|
// Type: 'archive'
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.zip',
|
||||||
|
extension: [ 'zip' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.etch',
|
||||||
|
extension: [ 'etch' ]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Type: 'compressed'
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.img.gz',
|
||||||
|
extension: [ 'img', 'gz' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.img.bz2',
|
||||||
|
extension: [ 'img', 'bz2' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.img.xz',
|
||||||
|
extension: [ 'img', 'xz' ]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Type: 'image'
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.img',
|
||||||
|
extension: [ 'img' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.iso',
|
||||||
|
extension: [ 'iso' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.dsk',
|
||||||
|
extension: [ 'dsk' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.hddimg',
|
||||||
|
extension: [ 'hddimg' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.raw',
|
||||||
|
extension: [ 'raw' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'path/to/filename.dmg',
|
||||||
|
extension: [ 'dmg' ]
|
||||||
|
}
|
||||||
|
|
||||||
|
], (testCase) => {
|
||||||
|
it(`should return ${testCase.extension} for ${testCase.file}`, function() {
|
||||||
|
m.chai.expect(fileExtensions.getFileExtensions(testCase.file)).to.deep.equal(testCase.extension);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always return lowercase extensions', function() {
|
||||||
|
const filePath = 'foo.IMG.gZ';
|
||||||
|
m.chai.expect(fileExtensions.getFileExtensions(filePath)).to.deep.equal([
|
||||||
|
'img',
|
||||||
|
'gz'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.getLastFileExtension()', function() {
|
||||||
|
|
||||||
|
it('should return undefined in the file path has no extension', function() {
|
||||||
|
m.chai.expect(fileExtensions.getLastFileExtension('foo')).to.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the extension if there is only one extension', function() {
|
||||||
|
m.chai.expect(fileExtensions.getLastFileExtension('foo.img')).to.equal('img');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the last extension if there two extensions', function() {
|
||||||
|
m.chai.expect(fileExtensions.getLastFileExtension('foo.img.gz')).to.equal('gz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the last extension if there are three extensions', function() {
|
||||||
|
m.chai.expect(fileExtensions.getLastFileExtension('foo.bar.img.gz')).to.equal('gz');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('.getPenultimateFileExtension()', function() {
|
||||||
|
|
||||||
|
it('should return undefined in the file path has no extension', function() {
|
||||||
|
m.chai.expect(fileExtensions.getPenultimateFileExtension('foo')).to.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return undefined if there is only one extension', function() {
|
||||||
|
m.chai.expect(fileExtensions.getPenultimateFileExtension('foo.img')).to.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the first extension if there are two extensions', function() {
|
||||||
|
m.chai.expect(fileExtensions.getPenultimateFileExtension('foo.img.gz')).to.equal('img');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the penultimate extension if there are three extensions', function() {
|
||||||
|
m.chai.expect(fileExtensions.getPenultimateFileExtension('foo.bar.img.gz')).to.equal('img');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user