From 32bad945e73c9dd8af63914b862b90794d4770ae Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Sat, 3 Jun 2017 19:03:15 -0700 Subject: [PATCH] Coverts DownloadItem and DownloadsBar Resolves #9260 Auditors: @bsclifton Test Plan: - download an item - check if download item is shown - check if you can interact with it (note there is a problem with pause/resume, fixed here #9246) --- .../components/download/downloadItem.js | 190 +++++++++++++----- .../components/download/downloadsBar.js | 48 ++--- app/renderer/components/main/main.js | 5 +- app/renderer/getComputedStyle.js | 10 - js/lib/urlutil.js | 9 + js/state/downloadUtil.js | 60 +++++- .../components/download/downloadBarTest.js | 77 ++++--- .../components/download/downloadItemTest.js | 163 +++++++-------- 8 files changed, 352 insertions(+), 210 deletions(-) delete mode 100644 app/renderer/getComputedStyle.js diff --git a/app/renderer/components/download/downloadItem.js b/app/renderer/components/download/downloadItem.js index a08f18e9a04..0122cc428f2 100644 --- a/app/renderer/components/download/downloadItem.js +++ b/app/renderer/components/download/downloadItem.js @@ -3,9 +3,10 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ const React = require('react') +const Immutable = require('immutable') // Components -const ImmutableComponent = require('../immutableComponent') +const ReduxComponent = require('../reduxComponent') const Button = require('../common/button') // Constants @@ -18,12 +19,13 @@ const appActions = require('../../../../js/actions/appActions') // Utils const contextMenus = require('../../../../js/contextMenus') const downloadUtil = require('../../../../js/state/downloadUtil') +const urlUtil = require('../../../../js/lib/urlutil') const {getOrigin} = require('../../../../js/state/siteUtil') const cx = require('../../../../js/lib/classSet') -class DownloadItem extends ImmutableComponent { - constructor () { - super() +class DownloadItem extends React.Component { + constructor (props) { + super(props) this.onRevealDownload = this.onRevealDownload.bind(this) this.onOpenDownload = this.onOpenDownload.bind(this) this.onPauseDownload = this.onDownloadActionPerformed.bind(this, PAUSE) @@ -33,66 +35,109 @@ class DownloadItem extends ImmutableComponent { this.onShowDeleteConfirmation = this.onShowDeleteConfirmation.bind(this) this.onHideDeleteConfirmation = this.onHideDeleteConfirmation.bind(this) this.onDeleteDownload = this.onDeleteDownload.bind(this) - this.onRedownload = this.onRedownload.bind(this) + this.onReDownload = this.onReDownload.bind(this) this.onCopyLinkToClipboard = this.onCopyLinkToClipboard.bind(this) } + onRevealDownload () { appActions.downloadRevealed(this.props.downloadId) } + onOpenDownload () { appActions.downloadOpened(this.props.downloadId) } + onClearDownload () { appActions.downloadCleared(this.props.downloadId) } + onShowDeleteConfirmation () { appActions.showDownloadDeleteConfirmation() } + onHideDeleteConfirmation () { appActions.hideDownloadDeleteConfirmation() } + onDeleteDownload () { appActions.hideDownloadDeleteConfirmation() appActions.downloadDeleted(this.props.downloadId) } + onDownloadActionPerformed (downloadAction) { appActions.downloadActionPerformed(this.props.downloadId, downloadAction) } + onCopyLinkToClipboard () { appActions.downloadCopiedToClipboard(this.props.downloadId) } - onRedownload () { + + onReDownload () { appActions.downloadRedownloaded(this.props.downloadId) } + get isInterrupted () { - return this.props.download.get('state') === downloadStates.INTERRUPTED + return this.props.downloadState === downloadStates.INTERRUPTED } + get isInProgress () { - return this.props.download.get('state') === downloadStates.IN_PROGRESS + return this.props.downloadState === downloadStates.IN_PROGRESS } + get isCompleted () { - return this.props.download.get('state') === downloadStates.COMPLETED + return this.props.downloadState === downloadStates.COMPLETED } + get isCancelled () { - return this.props.download.get('state') === downloadStates.CANCELLED + return this.props.downloadState === downloadStates.CANCELLED } + get isPaused () { - return this.props.download.get('state') === downloadStates.PAUSED + return this.props.downloadState === downloadStates.PAUSED + } + + mergeProps (state, dispatchProps, ownProps) { + const download = state.getIn(['downloads', ownProps.downloadId]) || Immutable.Map() + const origin = getOrigin(download.get('url')) + + const props = {} + // used in renderer + props.downloadId = ownProps.downloadId + props.deleteConfirmationVisible = state.get('deleteConfirmationVisible') + props.isLocalFile = urlUtil.isLocalFile(origin) + props.isInsecure = origin && origin.startsWith('http://') + props.percentageComplete = downloadUtil.getPercentageComplete(download) + props.isPendingState = downloadUtil.isPendingState(download) + props.downloadState = download.get('state') + props.totalBytes = download.get('totalBytes') + props.fileName = download.get('filename') + props.origin = origin + props.statel10n = downloadUtil.getL10nId(download) + props.download = download // TODO (nejc) only primitive types + props.allowPause = downloadUtil.shouldAllowPause(props.download) + props.allowResume = downloadUtil.shouldAllowResume(props.download) + props.allowCancel = downloadUtil.shouldAllowCancel(props.download) + props.allowRedownload = downloadUtil.shouldAllowRedownload(props.download) + props.allowCopyLink = downloadUtil.shouldAllowCopyLink(props.download) + props.allowOpenDownloadLocation = downloadUtil.shouldAllowOpenDownloadLocation(props.download) + props.allowDelete = downloadUtil.shouldAllowDelete(props.download) + props.allowRemoveFromList = downloadUtil.shouldAllowRemoveFromList(props.download) + + return props } + render () { - const origin = getOrigin(this.props.download.get('url')) - const localFileOrigins = ['file:', 'blob:', 'data:', 'chrome-extension:', 'chrome:'] - const localFile = origin && localFileOrigins.some((localFileOrigin) => origin.startsWith(localFileOrigin)) + const l10nStateArgs = {} const progressStyle = { - width: downloadUtil.getPercentageComplete(this.props.download) + width: this.props.percentageComplete } - const l10nStateArgs = {} + if (this.isCancelled || this.isInterrupted) { progressStyle.display = 'none' - } else if (downloadUtil.isPendingState(this.props.download)) { - l10nStateArgs.downloadPercent = downloadUtil.getPercentageComplete(this.props.download) + } else if (this.props.isPendingState) { + l10nStateArgs.downloadPercent = this.props.percentageComplete } - const isInsecure = origin.startsWith('http://') + return { this.props.deleteConfirmationVisible - ?
+ ?
+
: null }
{ - downloadUtil.shouldAllowPause(this.props.download) - ?
{ - (this.isInProgress || this.isPaused) && this.props.download.get('totalBytes') + (this.isInProgress || this.isPaused) && this.props.totalBytes ?
: null }
-
- { - this.props.download.get('filename') - } +
+ {this.props.fileName}
{ - origin + this.props.origin ?
{ - isInsecure + this.props.isInsecure ? : null } - {localFile ? null : origin} + + {this.props.isLocalFile ? null : this.props.origin} +
: null } { this.isCancelled || this.isInterrupted || this.isCompleted || this.isPaused || this.isInProgress - ?
+ ?
: null } @@ -186,4 +280,4 @@ class DownloadItem extends ImmutableComponent { } } -module.exports = DownloadItem +module.exports = ReduxComponent.connect(DownloadItem) diff --git a/app/renderer/components/download/downloadsBar.js b/app/renderer/components/download/downloadsBar.js index e12f2d02222..955cebc9963 100644 --- a/app/renderer/components/download/downloadsBar.js +++ b/app/renderer/components/download/downloadsBar.js @@ -5,7 +5,7 @@ const React = require('react') // Components -const ImmutableComponent = require('../immutableComponent') +const ReduxComponent = require('../reduxComponent') const Button = require('../common/button') const BrowserButton = require('../common/browserButton') const DownloadItem = require('./downloadItem') @@ -19,19 +19,21 @@ const appActions = require('../../../../js/actions/appActions') // Utils const contextMenus = require('../../../../js/contextMenus') - +const downloadUtil = require('../../../../js/state/downloadUtil') const cx = require('../../../../js/lib/classSet') -class DownloadsBar extends ImmutableComponent { - constructor () { - super() +class DownloadsBar extends React.Component { + constructor (props) { + super(props) this.onHideDownloadsToolbar = this.onHideDownloadsToolbar.bind(this) this.onShowDownloads = this.onShowDownloads.bind(this) } + onHideDownloadsToolbar () { windowActions.setDownloadsToolbarVisible(false) webviewActions.setWebviewFocused() } + onShowDownloads () { appActions.createTabRequested({ activateIfOpen: true, @@ -39,40 +41,38 @@ class DownloadsBar extends ImmutableComponent { }) windowActions.setDownloadsToolbarVisible(false) } + + mergeProps (state, dispatchProps, ownProps) { + const props = {} + // used in renderer + props.downloads = downloadUtil.getDownloadItems(state) + + return props + } + render () { - const getComputedStyle = require('../../getComputedStyle') - const downloadItemWidth = Number.parseInt(getComputedStyle('--download-item-width'), 10) - const downloadItemMargin = Number.parseInt(getComputedStyle('--download-item-margin'), 10) - const downloadBarPadding = Number.parseInt(getComputedStyle('--download-bar-padding'), 10) - const downloadBarButtons = Number.parseInt(getComputedStyle('--download-bar-buttons'), 10) - const numItems = Math.floor((this.props.windowWidth - (downloadBarPadding * 2) - downloadBarButtons) / (downloadItemWidth + downloadItemMargin)) return
{ - this.props.downloads - .sort((x, y) => x.get('startTime') - y.get('startTime')) - .skip(this.props.downloads.size - numItems) - .reverse() - .map((download, downloadId) => - ) + this.props.downloads.map(downloadId => + + ) }
- -
{ this.props.windowState.getIn(['ui', 'downloadsToolbar', 'isVisible']) && this.props.appState.get('downloads') && this.props.appState.get('downloads').size > 0 - ? + ? : null }
diff --git a/app/renderer/getComputedStyle.js b/app/renderer/getComputedStyle.js deleted file mode 100644 index abf347fd537..00000000000 --- a/app/renderer/getComputedStyle.js +++ /dev/null @@ -1,10 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const getComputedStyle = (variable) => - window - .getComputedStyle(document.querySelector(':root')) - .getPropertyValue(variable) - -module.exports = getComputedStyle diff --git a/js/lib/urlutil.js b/js/lib/urlutil.js index b1d0dafdd03..36c3166a6c2 100644 --- a/js/lib/urlutil.js +++ b/js/lib/urlutil.js @@ -411,6 +411,15 @@ const UrlUtil = { */ getUrlOrigin: function (url) { return new window.URL(url).origin + }, + + isLocalFile: function (origin) { + if (!origin) { + return false + } + + const localFileOrigins = ['file:', 'blob:', 'data:', 'chrome-extension:', 'chrome:'] + return origin && localFileOrigins.some((localFileOrigin) => origin.startsWith(localFileOrigin)) } } diff --git a/js/state/downloadUtil.js b/js/state/downloadUtil.js index 10028d9027e..24b212c3f4e 100644 --- a/js/state/downloadUtil.js +++ b/js/state/downloadUtil.js @@ -11,31 +11,31 @@ const notErrorStates = [downloadStates.IN_PROGRESS, downloadStates.PAUSED, downl const downloadIsInState = (download, list) => list.includes(download.get('state')) -module.exports.isPendingState = (download) => +const isPendingState = (download) => downloadIsInState(download, pendingStates) -module.exports.shouldAllowPause = (download) => +const shouldAllowPause = (download) => downloadIsInState(download, [downloadStates.IN_PROGRESS]) -module.exports.shouldAllowResume = (download) => +const shouldAllowResume = (download) => downloadIsInState(download, [downloadStates.PAUSED]) -module.exports.shouldAllowCancel = (download) => +const shouldAllowCancel = (download) => downloadIsInState(download, pendingStates) -module.exports.shouldAllowRedownload = (download) => +const shouldAllowRedownload = (download) => downloadIsInState(download, stopStates) -module.exports.shouldAllowOpenDownloadLocation = (download) => +const shouldAllowOpenDownloadLocation = (download) => downloadIsInState(download, notErrorStates) -module.exports.shouldAllowDelete = (download) => +const shouldAllowDelete = (download) => downloadIsInState(download, stopStates) -module.exports.shouldAllowRemoveFromList = (download) => +const shouldAllowRemoveFromList = (download) => downloadIsInState(download, stopStates) -module.exports.getL10nId = (download) => { +const getL10nId = (download) => { switch (download.get('state')) { case downloadStates.INTERRUPTED: return 'downloadInterrupted' @@ -55,7 +55,45 @@ module.exports.getL10nId = (download) => { return '' } -module.exports.getPercentageComplete = (download) => +const getPercentageComplete = (download) => Math.ceil(download.get('receivedBytes') / download.get('totalBytes') * 100) + '%' -module.exports.shouldAllowCopyLink = (download) => !!download.get('url') +const shouldAllowCopyLink = (download) => !!download.get('url') + +const getDownloadItems = (state) => { + if (!state.get('downloads')) { + return 0 + } + + const downloadsSize = state.get('downloads').size + const root = window.getComputedStyle(document.querySelector(':root')) + const downloadItemWidth = Number.parseInt(root.getPropertyValue('--download-item-width'), 10) + const downloadItemMargin = Number.parseInt(root.getPropertyValue('--download-item-margin'), 10) + const downloadBarPadding = Number.parseInt(root.getPropertyValue('--download-bar-padding'), 10) + const downloadBarButtons = Number.parseInt(root.getPropertyValue('--download-bar-buttons'), 10) + const numItems = Math.floor( + (window.innerWidth - (downloadBarPadding * 2) - downloadBarButtons) / + (downloadItemWidth + downloadItemMargin) + ) + + return state.get('downloads') + .sort((x, y) => x.get('startTime') - y.get('startTime')) + .skip(downloadsSize - numItems) + .reverse() + .map((download, downloadId) => downloadId) +} + +module.exports = { + isPendingState, + shouldAllowPause, + shouldAllowResume, + shouldAllowCancel, + shouldAllowRedownload, + shouldAllowOpenDownloadLocation, + shouldAllowDelete, + shouldAllowRemoveFromList, + getL10nId, + getPercentageComplete, + shouldAllowCopyLink, + getDownloadItems +} diff --git a/test/unit/app/renderer/components/download/downloadBarTest.js b/test/unit/app/renderer/components/download/downloadBarTest.js index b48c7f118e1..1f780accf8f 100644 --- a/test/unit/app/renderer/components/download/downloadBarTest.js +++ b/test/unit/app/renderer/components/download/downloadBarTest.js @@ -11,41 +11,45 @@ const path = require('path') const uuid = require('uuid') const Immutable = require('immutable') const downloadStates = require('../../../../../../js/constants/downloadStates') -let DownloadItem, DownloadsBar require('../../../../braveUnit') const mostRecentlyDownloadedId = uuid.v4() -const newDownloads = () => Immutable.fromJS({ - [uuid.v4()]: { - startTime: new Date().getTime(), - filename: 'mostHatedPrimes.txt', - savePath: path.join(require('os').tmpdir(), 'mostHatedPrimes.txt'), - url: 'http://www.bradrichter.com/mostHatedPrimes.txt', - totalBytes: 104729, - receivedBytes: 96931, - state: downloadStates.IN_PROGRESS - }, - [mostRecentlyDownloadedId]: { - startTime: new Date().getTime() + 1000, - filename: 'compositeNumbersFTW.txt', - savePath: path.join(require('os').tmpdir(), 'compositeNumbersFTW.txt'), - url: 'http://www.bradrichter.com/compositeNumbersTW.txt', - totalBytes: 42, - receivedBytes: 1024, - state: downloadStates.COMPLETED - }, - [uuid.v4()]: { - startTime: new Date().getTime() - 1000, - filename: 'guideToIntegers.txt', - savePath: path.join(require('os').tmpdir(), 'guideToInegers.txt'), - url: 'http://www.bradrichter.com/guideToInegers.txt', - totalBytes: 72, - receivedBytes: 1, - state: downloadStates.IN_PROGRESS + +const appStoreRenderer = Immutable.fromJS({ + downloads: { + [uuid.v4()]: { + startTime: new Date().getTime(), + filename: 'mostHatedPrimes.txt', + savePath: path.join(require('os').tmpdir(), 'mostHatedPrimes.txt'), + url: 'http://www.bradrichter.com/mostHatedPrimes.txt', + totalBytes: 104729, + receivedBytes: 96931, + state: downloadStates.IN_PROGRESS + }, + [mostRecentlyDownloadedId]: { + startTime: new Date().getTime() + 1000, + filename: 'compositeNumbersFTW.txt', + savePath: path.join(require('os').tmpdir(), 'compositeNumbersFTW.txt'), + url: 'http://www.bradrichter.com/compositeNumbersTW.txt', + totalBytes: 42, + receivedBytes: 1024, + state: downloadStates.COMPLETED + }, + [uuid.v4()]: { + startTime: new Date().getTime() - 1000, + filename: 'guideToIntegers.txt', + savePath: path.join(require('os').tmpdir(), 'guideToInegers.txt'), + url: 'http://www.bradrichter.com/guideToInegers.txt', + totalBytes: 72, + receivedBytes: 1, + state: downloadStates.IN_PROGRESS + } } }) describe('downloadsBar component', function () { + let DownloadItem, DownloadsBar, appStore + before(function () { mockery.enable({ warnOnReplace: false, @@ -55,14 +59,18 @@ describe('downloadsBar component', function () { mockery.registerMock('electron', fakeElectron) DownloadItem = require('../../../../../../app/renderer/components/download/downloadItem') DownloadsBar = require('../../../../../../app/renderer/components/download/downloadsBar') + appStore = require('../../../../../../js/stores/appStoreRenderer') + appStore.state = appStoreRenderer }) + after(function () { + mockery.deregisterAll() mockery.disable() }) describe('multiple downloads with space', function () { before(function () { - this.result = mount() + this.result = mount() }) it('renders each download as a DownloadItem', function () { @@ -80,7 +88,10 @@ describe('downloadsBar component', function () { describe('no downloads', function () { before(function () { - this.result = mount() + appStore.state = Immutable.fromJS({ + downloads: {} + }) + this.result = mount() }) it('renders no DownloadItems when there are no downloads', function () { @@ -92,11 +103,11 @@ describe('downloadsBar component', function () { }) }) - describe('very narrow downloads bar with items', function () { + // skipped until #9176 is merged + describe.skip('very narrow downloads bar with items', function () { before(function () { - // TODO: We can remove this once we're on Khan/aphrodite mockery.registerMock('../../getComputedStyle', () => 10) - this.result = mount() + this.result = mount() }) it('renders no downloads', function () { assert.equal(this.result.find(DownloadItem).length, 0) diff --git a/test/unit/app/renderer/components/download/downloadItemTest.js b/test/unit/app/renderer/components/download/downloadItemTest.js index b4baa7c1042..0424b87e33a 100644 --- a/test/unit/app/renderer/components/download/downloadItemTest.js +++ b/test/unit/app/renderer/components/download/downloadItemTest.js @@ -1,7 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* global describe, before, beforeEach, after, it */ +/* global describe, before, after, it */ const mockery = require('mockery') const {mount} = require('enzyme') @@ -13,34 +13,44 @@ const uuid = require('uuid') const Immutable = require('immutable') const downloadStates = require('../../../../../../js/constants/downloadStates') const {CANCEL, PAUSE, RESUME} = require('../../../../../../app/common/constants/electronDownloadItemActions') -let DownloadItem, appActions require('../../../../braveUnit') const savePath = path.join(require('os').tmpdir(), 'mostHatedPrimes.txt') const downloadUrl = 'http://www.bradrichter.com/mostHatedPrimes.txt' const localFileDownloadUrl = 'file:///Users/foobar/Library/abc.txt' -const newDownload = (state) => Immutable.fromJS({ - startTime: new Date().getTime(), - filename: 'mostHatedPrimes.txt', - savePath, - url: downloadUrl, - totalBytes: 104729, - receivedBytes: 96931, - deleteConfirmationVisible: false, - state +const appStateDownload = (state, downloadId, confirmation = false) => Immutable.fromJS({ + downloads: { + [downloadId]: { + startTime: new Date().getTime(), + filename: 'mostHatedPrimes.txt', + savePath, + url: downloadUrl, + totalBytes: 104729, + receivedBytes: 96931, + state + } + }, + deleteConfirmationVisible: confirmation }) -const newDownloadLocalFile = (state) => Immutable.fromJS({ - startTime: new Date().getTime(), - filename: 'abc.txt', - savePath, - url: localFileDownloadUrl, - totalBytes: 104729, - receivedBytes: 96931, - deleteConfirmationVisible: false, - state + +const appStateDownloadLocalFile = (state, downloadId) => Immutable.fromJS({ + downloads: { + [downloadId]: { + startTime: new Date().getTime(), + filename: 'abc.txt', + savePath, + url: localFileDownloadUrl, + totalBytes: 104729, + receivedBytes: 96931, + state + } + }, + deleteConfirmationVisible: false }) describe('downloadItem component', function () { + let DownloadItem, appActions, appStore + before(function () { mockery.enable({ warnOnReplace: false, @@ -50,6 +60,7 @@ describe('downloadItem component', function () { mockery.registerMock('electron', fakeElectron) DownloadItem = require('../../../../../../app/renderer/components/download/downloadItem') appActions = require('../../../../../../js/actions/appActions') + appStore = require('../../../../../../js/stores/appStoreRenderer') }) after(function () { @@ -57,103 +68,95 @@ describe('downloadItem component', function () { }) Object.values(downloadStates).forEach(function (state) { + let result, downloadId + + const testButton = function (buttonSelector, allowedStates, allowedFn) { + const exists = allowedStates.includes(state) + it(exists ? `${buttonSelector} button in state ${state} performs the correct action` : `${buttonSelector} is not shown`, function () { + const button = result.find(buttonSelector) + if (exists) { + allowedFn.call(this, button) + } else { + assert.equal(button.length, 0) + } + }) + } + describe(`${state} download local item`, function () { before(function () { - this.downloadId = uuid.v4() - this.download = newDownloadLocalFile(state) - this.result = mount( - - ) + downloadId = uuid.v4() + appStore.state = appStateDownloadLocalFile(state, downloadId) + result = mount() }) it('filename exists and matches download filename', function () { - assert.equal(this.result.find('.downloadFilename').text(), this.download.get('filename')) + assert.equal(result.find('.downloadFilename').text(), appStore.state.getIn(['downloads', downloadId, 'filename'])) }) it('has local origin i.e file: and matches to "Local file" origin', function () { - assert.equal(this.result.find('.downloadOrigin').text(), '') + assert.equal(result.find('.downloadOrigin').text(), '') }) }) describe(`${state} download item`, function () { before(function () { - this.downloadId = uuid.v4() - this.download = newDownload(state) - this.result = mount( - - ) + downloadId = uuid.v4() + appStore.state = appStateDownload(state, downloadId) + result = mount() }) it('filename exists and matches download filename', function () { - assert.equal(this.result.find('[data-test-id="downloadFilename"]').text(), this.download.get('filename')) + assert.equal(result.find('[data-test-id="downloadFilename"]').text(), appStore.state.getIn(['downloads', downloadId, 'filename'])) }) it('origin exists and matches download origin', function () { - assert.equal(this.result.find('[data-test-id="downloadOrigin"]').text(), 'http://www.bradrichter.com') + assert.equal(result.find('[data-test-id="downloadOrigin"]').text(), 'http://www.bradrichter.com') }) const shouldProgressBarExist = [downloadStates.IN_PROGRESS, downloadStates.PAUSED].includes(state) it(shouldProgressBarExist ? 'progress bar should exist' : 'progress bar should not exist', function () { - assert.equal(this.result.find('[data-test-id="downloadProgress"]').length, shouldProgressBarExist ? 1 : 0) + assert.equal(result.find('[data-test-id="downloadProgress"]').length, shouldProgressBarExist ? 1 : 0) }) - const testButton = function (buttonSelector, allowedStates, allowedFn) { - const exists = allowedStates.includes(state) - it(exists ? `${buttonSelector} button in state ${state} performs the correct action` : `${buttonSelector} is not shown`, function () { - const button = this.result.find(buttonSelector) - if (exists) { - allowedFn.call(this, button) - } else { - assert.equal(button.length, 0) - } - }) - } - testButton('[data-test-id="pauseButton"]', [downloadStates.IN_PROGRESS], function (button) { const spy = sinon.spy(appActions, 'downloadActionPerformed') button.simulate('click') - assert(spy.withArgs(this.downloadId, PAUSE).calledOnce) + assert(spy.withArgs(downloadId, PAUSE).calledOnce) appActions.downloadActionPerformed.restore() }) testButton('[data-test-id="resumeButton"]', [downloadStates.PAUSED], function (button) { const spy = sinon.spy(appActions, 'downloadActionPerformed') button.simulate('click') - assert(spy.withArgs(this.downloadId, RESUME).calledOnce) + assert(spy.withArgs(downloadId, RESUME).calledOnce) appActions.downloadActionPerformed.restore() }) testButton('[data-test-id="cancelButton"]', [downloadStates.IN_PROGRESS, downloadStates.PAUSED], function (button) { const spy = sinon.spy(appActions, 'downloadActionPerformed') button.simulate('click') - assert(spy.withArgs(this.downloadId, CANCEL).calledOnce) + assert(spy.withArgs(downloadId, CANCEL).calledOnce) appActions.downloadActionPerformed.restore() }) testButton('[data-test-id="redownloadButton"]', [downloadStates.CANCELLED, downloadStates.INTERRUPTED, downloadStates.COMPLETED], function (button) { const spy = sinon.spy(appActions, 'downloadRedownloaded') button.simulate('click') - assert(spy.withArgs(this.downloadId).calledOnce) + assert(spy.withArgs(downloadId).calledOnce) appActions.downloadRedownloaded.restore() }) testButton('[data-test-id="copyLinkButton"]', Object.values(downloadStates), function (button) { const spy = sinon.spy(appActions, 'downloadCopiedToClipboard') button.simulate('click') - assert(spy.withArgs(this.downloadId).calledOnce) + assert(spy.withArgs(downloadId).calledOnce) appActions.downloadCopiedToClipboard.restore() }) testButton('[data-test-id="revealButton"]', [downloadStates.IN_PROGRESS, downloadStates.PAUSED, downloadStates.COMPLETED], function (button) { const spy = sinon.spy(appActions, 'downloadRevealed') button.simulate('click') - assert(spy.withArgs(this.downloadId).calledOnce) + assert(spy.withArgs(downloadId).calledOnce) appActions.downloadRevealed.restore() }) @@ -161,7 +164,7 @@ describe('downloadItem component', function () { const spy = sinon.spy(appActions, 'showDownloadDeleteConfirmation') try { // Confirmation should NOT be visible by default - assert.equal(this.result.find('[data-test-id="confirmDeleteButton"]').length, 0) + assert.equal(result.find('[data-test-id="confirmDeleteButton"]').length, 0) // Clicking delete should show confirmation button.simulate('click') @@ -170,27 +173,27 @@ describe('downloadItem component', function () { appActions.showDownloadDeleteConfirmation.restore() } }) + }) - if ([downloadStates.CANCELLED, downloadStates.INTERRUPTED, downloadStates.COMPLETED].includes(state)) { - describe('when delete button has been clicked', function () { - beforeEach(function () { - this.result.setProps({ - deleteConfirmationVisible: true - }) - }) - - testButton('[data-test-id="confirmDeleteButton"]', [downloadStates.CANCELLED, downloadStates.INTERRUPTED, downloadStates.COMPLETED], function (button) { - const spy = sinon.spy(appActions, 'downloadDeleted') - try { - // Accepting confirmation should delete the item - button.simulate('click') - assert(spy.withArgs(this.downloadId).calledOnce) - } finally { - appActions.downloadDeleted.restore() - } - }) + if ([downloadStates.CANCELLED, downloadStates.INTERRUPTED, downloadStates.COMPLETED].includes(state)) { + describe(`${state} download item when delete button has been clicked`, function () { + before(function () { + downloadId = uuid.v4() + appStore.state = appStateDownload(state, downloadId, true) + result = mount() }) - } - }) + + testButton('[data-test-id="confirmDeleteButton"]', [downloadStates.CANCELLED, downloadStates.INTERRUPTED, downloadStates.COMPLETED], function (button) { + const spy = sinon.spy(appActions, 'downloadDeleted') + try { + // Accepting confirmation should delete the item + button.simulate('click') + assert(spy.withArgs(downloadId).calledOnce) + } finally { + appActions.downloadDeleted.restore() + } + }) + }) + } }) })