diff --git a/lib/gui/app/app.js b/lib/gui/app/app.js index 89b886a6..0a7e41d2 100644 --- a/lib/gui/app/app.js +++ b/lib/gui/app/app.js @@ -90,7 +90,7 @@ const app = angular.module('Etcher', [ require('./components/safe-webview'), // Pages - require('./pages/main/main'), + require('./pages/main/main.ts').MODULE_NAME, require('./pages/finish/finish'), require('./components/settings/index.ts').MODULE_NAME, diff --git a/lib/gui/app/components/featured-project/index.js b/lib/gui/app/components/featured-project/index.js deleted file mode 100644 index 033edb9e..00000000 --- a/lib/gui/app/components/featured-project/index.js +++ /dev/null @@ -1,34 +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.Components.FeaturedProject - */ - -const angular = require('angular') -const { react2angular } = require('react2angular') - -const MODULE_NAME = 'Etcher.Components.FeaturedProject' -const FeaturedProject = angular.module(MODULE_NAME, []) - -FeaturedProject.component( - 'featuredProject', - react2angular(require('./featured-project.jsx')) -) - -module.exports = MODULE_NAME diff --git a/lib/gui/app/components/image-selector/image-selector.jsx b/lib/gui/app/components/image-selector/image-selector.jsx index 023b001a..a3bc561a 100644 --- a/lib/gui/app/components/image-selector/image-selector.jsx +++ b/lib/gui/app/components/image-selector/image-selector.jsx @@ -28,7 +28,6 @@ const messages = require('../../../../shared/messages') const supportedFormats = require('../../../../shared/supported-formats') const shared = require('../../../../shared/units') const selectionState = require('../../models/selection-state') -const settings = require('../../models/settings') const store = require('../../models/store') const analytics = require('../../modules/analytics') const exceptionReporter = require('../../modules/exception-reporter') @@ -41,8 +40,7 @@ const { Footer, Underline, DetailsText, - ChangeButton, - ThemedProvider + ChangeButton } = require('../../styled-components') const { Modal @@ -306,7 +304,7 @@ class ImageSelector extends React.Component { const imageSize = selectionState.getImageSize() return ( - +
{({ getRootProps, getInputProps }) => ( @@ -394,7 +392,7 @@ class ImageSelector extends React.Component { {selectionState.getImagePath()} )} - + ) } } diff --git a/lib/gui/app/components/image-selector/index.js b/lib/gui/app/components/image-selector/index.js deleted file mode 100644 index d9973467..00000000 --- a/lib/gui/app/components/image-selector/index.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2018 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' - -/* eslint-disable jsdoc/require-example */ - -/** - * @module Etcher.Components.ImageSelector - */ - -const angular = require('angular') -const { react2angular } = require('react2angular') - -const MODULE_NAME = 'Etcher.Components.ImageSelector' -const ImageSelector = angular.module(MODULE_NAME, []) - -ImageSelector.component( - 'imageSelector', - react2angular(require('./image-selector.jsx')), - [], - [ - 'WarningModalService' - ] -) -module.exports = MODULE_NAME diff --git a/lib/gui/app/components/reduced-flashing-infos/index.js b/lib/gui/app/components/reduced-flashing-infos/index.js deleted file mode 100644 index 4b1446e3..00000000 --- a/lib/gui/app/components/reduced-flashing-infos/index.js +++ /dev/null @@ -1,34 +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.Components.ReducedFlashingInfos - */ - -const angular = require('angular') -const { react2angular } = require('react2angular') - -const MODULE_NAME = 'Etcher.Components.ReducedFlashingInfos' -const ReducedFlashingInfos = angular.module(MODULE_NAME, []) - -ReducedFlashingInfos.component( - 'reducedFlashingInfos', - react2angular(require('./reduced-flashing-infos.jsx')) -) - -module.exports = MODULE_NAME diff --git a/lib/gui/app/pages/main/DriveSelector.jsx b/lib/gui/app/pages/main/DriveSelector.jsx index 7fcf482b..b7900c83 100644 --- a/lib/gui/app/pages/main/DriveSelector.jsx +++ b/lib/gui/app/pages/main/DriveSelector.jsx @@ -17,15 +17,11 @@ 'use strict' const _ = require('lodash') -const prettyBytes = require('pretty-bytes') const propTypes = require('prop-types') const React = require('react') -const { - ThemedProvider -} = require('../../styled-components') const driveConstraints = require('../../../../shared/drive-constraints') const utils = require('../../../../shared/utils') -const TargetSelector = require('../../components/drive-selector/target-selector') +const TargetSelector = require('../../components/drive-selector/target-selector.jsx') const SvgIcon = require('../../components/svg-icon/svg-icon.jsx') const selectionState = require('../../models/selection-state') const settings = require('../../models/settings') @@ -150,44 +146,42 @@ const DriveSelector = ({ const showStepConnectingLines = !webviewShowing || !flashing return ( - -
+
- {showStepConnectingLines && ( - -
-
-
- )} - -
- +
-
+ >
+
+ + )} -
- openDriveSelector(DriveSelectorService)} - reselectDrive={() => reselectDrive(DriveSelectorService)} - flashing={flashing} - constraints={driveConstraints} - targets={targets} - /> -
+
+
- + +
+ openDriveSelector(DriveSelectorService)} + reselectDrive={() => reselectDrive(DriveSelectorService)} + flashing={flashing} + constraints={driveConstraints} + targets={targets} + /> +
+
) } diff --git a/lib/gui/app/pages/main/Flash.jsx b/lib/gui/app/pages/main/Flash.jsx index 7b1ea719..3098004b 100644 --- a/lib/gui/app/pages/main/Flash.jsx +++ b/lib/gui/app/pages/main/Flash.jsx @@ -20,7 +20,6 @@ const React = require('react') const _ = require('lodash') const { Modal, Txt } = require('rendition') -const { ThemedProvider } = require('../../styled-components') const messages = require('../../../../shared/messages') const flashState = require('../../models/flash-state') const driveScanner = require('../../modules/drive-scanner') @@ -93,7 +92,7 @@ const flashImageToDrive = async ($timeout, $state) => { // otherwise Windows throws EPERM driveScanner.stop() - const iconPath = '../../../assets/icon.png' + const iconPath = '../../assets/icon.png' const basename = path.basename(image.path) try { await imageWriter.flash(image.path, drives) @@ -167,23 +166,13 @@ const Flash = ({ shouldFlashStepBeDisabled, lastFlashErrorCode, progressMessage, $timeout, $state, DriveSelectorService }) => { - // This is a hack to re-render the component whenever the global state changes. Remove once we get rid of angular and use redux correctly. - // eslint-disable-next-line no-magic-numbers - const setRefresh = React.useState(false)[1] const state = flashState.getFlashState() const isFlashing = flashState.isFlashing() - const isFlashStepDisabled = shouldFlashStepBeDisabled() const flashErrorCode = lastFlashErrorCode() const [ warningMessages, setWarningMessages ] = React.useState([]) const [ errorMessage, setErrorMessage ] = React.useState('') - React.useEffect(() => { - return store.observe(() => { - setRefresh((ref) => !ref) - }) - }, []) - const handleWarningResponse = async (shouldContinue) => { setWarningMessages([]) @@ -229,10 +218,10 @@ const Flash = ({ setErrorMessage(await flashImageToDrive($timeout, $state)) } - return + return
- +
@@ -242,7 +231,7 @@ const Flash = ({ active={isFlashing} percentage={state.percentage} label={getProgressButtonLabel()} - disabled={Boolean(flashErrorCode) || isFlashStepDisabled} + disabled={Boolean(flashErrorCode) || shouldFlashStepBeDisabled} callback={tryFlash}> @@ -300,7 +289,7 @@ const Flash = ({ } - + } module.exports = Flash diff --git a/lib/gui/app/pages/main/MainPage.tsx b/lib/gui/app/pages/main/MainPage.tsx new file mode 100644 index 00000000..b5afb878 --- /dev/null +++ b/lib/gui/app/pages/main/MainPage.tsx @@ -0,0 +1,142 @@ +/* + * Copyright 2019 balena.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. + */ + +import * as path from 'path'; +import * as React from 'react'; +import * as FeaturedProject from '../../components/featured-project/featured-project'; +import * as ImageSelector from '../../components/image-selector/image-selector'; +import * as ReducedFlashingInfos from '../../components/reduced-flashing-infos/reduced-flashing-infos'; +import * as flashState from '../../models/flash-state'; +import * as selectionState from '../../models/selection-state'; +import * as store from '../../models/store'; +import { ThemedProvider } from '../../styled-components'; +import * as middleEllipsis from '../../utils/middle-ellipsis'; + +import * as messages from '../../../../shared/messages'; +import { bytesToClosestUnit } from '../../../../shared/units'; + +import * as DriveSelector from './DriveSelector'; +import * as Flash from './Flash'; + +const getDrivesTitle = (selection: any) => { + const drives = selection.getSelectedDrives(); + + if (drives.length === 1) { + return drives[0].description || 'Untitled Device'; + } + + if (drives.length === 0) { + return 'No targets found'; + } + + return `${drives.length} Targets`; +}; + +const getImageBasename = (selection: any) => { + if (!selection.hasImage()) { + return ''; + } + + const selectionImageName = selection.getImageName(); + const imageBasename = path.basename(selection.getImagePath()); + return selectionImageName || imageBasename; +}; + +const MainPage = ({ DriveSelectorService, $timeout, $state }: any) => { + const setRefresh = React.useState(false)[1]; + const [isWebviewShowing, setIsWebviewShowing] = React.useState(false); + React.useEffect(() => { + return (store as any).observe(() => { + setRefresh(ref => !ref); + }); + }, []); + + const setWebviewShowing = (isShowing: boolean) => { + setIsWebviewShowing(isShowing); + store.dispatch({ + type: 'SET_WEBVIEW_SHOWING_STATUS', + data: Boolean(isShowing), + }); + }; + + const isFlashing = flashState.isFlashing(); + const shouldDriveStepBeDisabled = !selectionState.hasImage(); + const shouldFlashStepBeDisabled = + !selectionState.hasDrive() || shouldDriveStepBeDisabled; + const hasDrive = selectionState.hasDrive(); + const imageLogo = selectionState.getImageLogo(); + const imageSize = bytesToClosestUnit(selectionState.getImageSize()); + const imageName = middleEllipsis(getImageBasename(selectionState), 16); + const driveTitle = middleEllipsis(getDrivesTitle(selectionState), 16); + const shouldShowFlashingInfos = isFlashing && isWebviewShowing; + const lastFlashErrorCode = flashState.getLastFlashErrorCode; + const progressMessage = messages.progress; + + return ( + +
+
+ +
+ +
+ +
+ + {isFlashing && ( +
+ +
+ )} + +
+ +
+ +
+ +
+
+
+ ); +}; + +export default MainPage; diff --git a/lib/gui/app/pages/main/controllers/main.js b/lib/gui/app/pages/main/controllers/main.js deleted file mode 100644 index d3b7d027..00000000 --- a/lib/gui/app/pages/main/controllers/main.js +++ /dev/null @@ -1,165 +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' - -const path = require('path') -const store = require('../../../models/store') -const settings = require('../../../models/settings') -const flashState = require('../../../models/flash-state') -const availableDrives = require('../../../models/available-drives') -const selectionState = require('../../../models/selection-state') -const driveConstraints = require('../../../../../shared/drive-constraints') -const messages = require('../../../../../shared/messages') -const prettyBytes = require('pretty-bytes') - -module.exports = function ( - OSOpenExternalService, - $filter, - $scope -) { - // Expose several modules to the template for convenience - this.selection = selectionState - this.drives = availableDrives - this.state = flashState - this.settings = settings - this.external = OSOpenExternalService - this.constraints = driveConstraints - this.progressMessage = messages.progress - this.isWebviewShowing = Boolean(store.getState().toJS().isWebviewShowing) - - // Trigger an update if the store changes - store.observe(() => { - if (!$scope.$$phase) { - $scope.$apply() - } - }) - - /** - * @summary Determine if the drive step should be disabled - * @function - * @public - * - * @returns {Boolean} whether the drive step should be disabled - * - * @example - * if (MainController.shouldDriveStepBeDisabled()) { - * console.log('The drive step should be disabled'); - * } - */ - this.shouldDriveStepBeDisabled = () => { - return !selectionState.hasImage() - } - - /** - * @summary Determine if the flash step should be disabled - * @function - * @public - * - * @returns {Boolean} whether the flash step should be disabled - * - * @example - * if (MainController.shouldFlashStepBeDisabled()) { - * console.log('The flash step should be disabled'); - * } - */ - this.shouldFlashStepBeDisabled = () => { - return !selectionState.hasDrive() || this.shouldDriveStepBeDisabled() - } - - /** - * @summary Get drive title based on device quantity - * @function - * @public - * - * @returns {String} - drives title - * - * @example - * console.log(DriveSelectionController.getDrivesTitle()) - * > 'Multiple Drives (4)' - */ - this.getDrivesTitle = () => { - const drives = this.selection.getSelectedDrives() - - /* eslint-disable no-magic-numbers */ - if (drives.length === 1) { - return drives[0].description || 'Untitled Device' - } - /* eslint-enable no-magic-numbers */ - - // eslint-disable-next-line no-magic-numbers - if (drives.length === 0) { - return 'No targets found' - } - - return `${drives.length} Targets` - } - - /** - * @summary Get drive subtitle - * @function - * @public - * - * @returns {String} - drives subtitle - * - * @example - * console.log(MainController.getDrivesSubtitle()) - * > '32 GB' - */ - this.getDrivesSubtitle = () => { - const drive = this.selection.getCurrentDrive() - - if (drive) { - return prettyBytes(drive.size) - } - - return 'Please insert at least one target device' - } - - /** - * @summary Get the basename of the selected image - * @function - * @public - * - * @returns {String} basename of the selected image - * - * @example - * const imageBasename = ImageSelectionController.getImageBasename(); - */ - this.getImageBasename = () => { - if (!this.selection.hasImage()) { - return '' - } - - return path.basename(this.selection.getImagePath()) - } - - this.setWebviewShowing = (data) => { - this.isWebviewShowing = data - store.dispatch({ - type: 'SET_WEBVIEW_SHOWING_STATUS', - data: Boolean(data) - }) - } - - this.getDriveTitle = () => { - /* eslint-disable no-magic-numbers */ - const driveTitleRaw = (this.selection.getSelectedDevices().length === 1) - ? this.getDrivesSubtitle() - : `${this.selection.getSelectedDevices().length} Targets` - return $filter('middleEllipsis:20')(driveTitleRaw) - } -} diff --git a/lib/gui/app/pages/main/main.js b/lib/gui/app/pages/main/main.js deleted file mode 100644 index 2607e7c9..00000000 --- a/lib/gui/app/pages/main/main.js +++ /dev/null @@ -1,70 +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' - -/** - * This page represents the application main page. - * - * @module Etcher.Pages.Main - */ - -const angular = require('angular') -const { react2angular } = require('react2angular') -const MODULE_NAME = 'Etcher.Pages.Main' - -const MainPage = angular.module(MODULE_NAME, [ - require('angular-ui-router'), - - require('../../components/drive-selector/drive-selector'), - require('../../components/image-selector'), - require('../../components/featured-project'), - require('../../components/reduced-flashing-infos'), - require('../../components/flash-another'), - require('../../components/flash-results'), - require('../../components/drive-selector'), - - require('../../os/open-external/open-external'), - - require('../../utils/byte-size/byte-size'), - require('../../utils/middle-ellipsis/filter') -]) - -MainPage.controller('MainController', require('./controllers/main')) -MainPage.component('driveSelector', react2angular(require('./DriveSelector.jsx'), - [ - 'webviewShowing', - 'disabled', - 'nextStepDisabled', - 'hasDrive', - 'flashing' - ], - [ 'DriveSelectorService' ] -)) -MainPage.component('flash', react2angular(require('./Flash.jsx'), - [ 'shouldFlashStepBeDisabled', 'lastFlashErrorCode', 'progressMessage' ], - [ '$timeout', '$state', 'DriveSelectorService' ])) - -MainPage.config(($stateProvider) => { - $stateProvider - .state('main', { - url: '/main', - controller: 'MainController as main', - template: require('./templates/main.tpl.html') - }) -}) - -module.exports = MODULE_NAME diff --git a/lib/gui/app/pages/main/main.ts b/lib/gui/app/pages/main/main.ts new file mode 100644 index 00000000..3de9ed2c --- /dev/null +++ b/lib/gui/app/pages/main/main.ts @@ -0,0 +1,60 @@ +/* + * Copyright 2019 balena.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'; + +/** + * This page represents the application main page. + * + * @module Etcher.Pages.Main + */ + +import * as angular from 'angular'; +// @ts-ignore +import * as angularRouter from 'angular-ui-router'; +import { react2angular } from 'react2angular'; +import MainPage from './MainPage'; + +import * as driveSelector from '../../components/drive-selector'; +import * as driveSelectorService from '../../components/drive-selector/drive-selector'; +import * as flashAnother from '../../components/flash-another'; +import * as flashResults from '../../components/flash-results'; +import * as openExternal from '../../os/open-external/open-external'; +import * as byteSize from '../../utils/byte-size/byte-size'; + +export const MODULE_NAME = 'Etcher.Pages.Main'; + +const Main = angular.module(MODULE_NAME, [ + angularRouter, + driveSelectorService, + flashAnother, + flashResults, + driveSelector, + openExternal, + byteSize, +]); + +Main.component( + 'mainPage', + react2angular(MainPage, [], ['DriveSelectorService', '$timeout', '$state']), +); + +Main.config(($stateProvider: any) => { + $stateProvider.state('main', { + url: '/main', + template: '', + }); +}); diff --git a/lib/gui/app/pages/main/templates/main.tpl.html b/lib/gui/app/pages/main/templates/main.tpl.html deleted file mode 100644 index 87ce38c8..00000000 --- a/lib/gui/app/pages/main/templates/main.tpl.html +++ /dev/null @@ -1,46 +0,0 @@ -
-
- - -
- -
- -
- -
- -
- -
- -
- -
- -
-
diff --git a/lib/gui/app/utils/middle-ellipsis/filter.js b/lib/gui/app/utils/middle-ellipsis/filter.js deleted file mode 100644 index 0e72044e..00000000 --- a/lib/gui/app/utils/middle-ellipsis/filter.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016 Juan Cruz Viotti. https://github.com/jviotti - * Copyright 2018 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' - -/** - * The purpose of this module is to provide utilities - * to work with sizes in bytes. - * - * @module Etcher.Utils.MiddleEllipsis - */ - -const _ = require('lodash') -const angular = require('angular') -const middleEllipsis = require('../middle-ellipsis') - -const MODULE_NAME = 'Etcher.Utils.MiddleEllipsis' -const MiddleEllipsis = angular.module(MODULE_NAME, []) - -/* eslint-disable lodash/prefer-lodash-method */ - -MiddleEllipsis.filter('middleEllipsis', _.constant(middleEllipsis)) - -/* eslint-enable lodash/prefer-lodash-method */ - -module.exports = MODULE_NAME diff --git a/tests/gui/pages/main.spec.js b/tests/gui/pages/main.spec.js deleted file mode 100644 index 13fc794e..00000000 --- a/tests/gui/pages/main.spec.js +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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 m = require('mochainon') -const _ = require('lodash') -const fs = require('fs') -const angular = require('angular') -const availableDrives = require('../../../lib/gui/app/models/available-drives') -const selectionState = require('../../../lib/gui/app/models/selection-state') - -// Mock HTML requires by reading from the file-system -// eslint-disable-next-line node/no-deprecated-api -require.extensions['.html'] = (module, filename) => { - module.exports = fs.readFileSync(filename, { - encoding: 'utf8' - }) -} - -// NOTE(Shou): since we don't test React yet we just ignore JSX files -// eslint-disable-next-line node/no-deprecated-api -require.extensions['.jsx'] = _.constant(null) - -describe('Browser: MainPage', function () { - beforeEach(angular.mock.module( - require('../../../lib/gui/app/pages/main/main') - )) - - describe('MainController', function () { - let $controller - - beforeEach(angular.mock.inject(function (_$controller_) { - $controller = _$controller_ - })) - - describe('.shouldDriveStepBeDisabled()', function () { - it('should return true if there is no drive', function () { - const controller = $controller('MainController', { - $scope: { - $apply: _.noop - } - }) - - selectionState.clear() - - m.chai.expect(controller.shouldDriveStepBeDisabled()).to.be.true - }) - - it('should return false if there is a drive', function () { - const controller = $controller('MainController', { - $scope: { - $apply: _.noop - } - }) - - selectionState.selectImage({ - path: 'rpi.img', - extension: 'img', - size: 99999, - isSizeEstimated: false - }) - - m.chai.expect(controller.shouldDriveStepBeDisabled()).to.be.false - }) - }) - - describe('.shouldFlashStepBeDisabled()', function () { - it('should return true if there is no selected drive nor image', function () { - const controller = $controller('MainController', { - $scope: { - $apply: _.noop - } - }) - - selectionState.clear() - - m.chai.expect(controller.shouldFlashStepBeDisabled()).to.be.true - }) - - it('should return true if there is a selected image but no drive', function () { - const controller = $controller('MainController', { - $scope: { - $apply: _.noop - } - }) - - selectionState.clear() - selectionState.selectImage({ - path: 'rpi.img', - extension: 'img', - size: 99999, - isSizeEstimated: false - }) - - m.chai.expect(controller.shouldFlashStepBeDisabled()).to.be.true - }) - - it('should return true if there is a selected drive but no image', function () { - const controller = $controller('MainController', { - $scope: { - $apply: _.noop - } - }) - - availableDrives.setDrives([ - { - device: '/dev/disk2', - description: 'Foo', - size: 99999, - mountpoint: '/mnt/foo', - system: false - } - ]) - - selectionState.clear() - selectionState.selectDrive('/dev/disk2') - - m.chai.expect(controller.shouldFlashStepBeDisabled()).to.be.true - }) - - it('should return false if there is a selected drive and a selected image', function () { - const controller = $controller('MainController', { - $scope: { - $apply: _.noop - } - }) - - availableDrives.setDrives([ - { - device: '/dev/disk2', - description: 'Foo', - size: 99999, - mountpoint: '/mnt/foo', - system: false - } - ]) - - selectionState.clear() - selectionState.selectDrive('/dev/disk2') - - selectionState.selectImage({ - path: 'rpi.img', - extension: 'img', - size: 99999, - isSizeEstimated: false - }) - - m.chai.expect(controller.shouldFlashStepBeDisabled()).to.be.false - }) - }) - }) - - describe('page template', function () { - let $state - - beforeEach(angular.mock.inject(function (_$state_) { - $state = _$state_ - })) - - it('should match the file contents', function () { - const { - template - } = $state.get('main') - const contents = fs.readFileSync('lib/gui/app/pages/main/templates/main.tpl.html', { - encoding: 'utf-8' - }) - m.chai.expect(template).to.equal(contents) - }) - }) -})