From 95d61a267213bb3b6c21a36c813c6d2068d603b8 Mon Sep 17 00:00:00 2001 From: Cezar Augusto Date: Mon, 24 Jul 2017 20:09:46 -0300 Subject: [PATCH] make tab previews based on mouse idle time - Auditors: @bridiver - Fix #8860 - Fix #3271 --- app/common/constants/settingsEnums.js | 7 ++ .../locales/en-US/preferences.properties | 4 + .../components/preferences/tabsTab.js | 38 ++++++++- app/renderer/components/styles/tab.js | 4 +- .../components/tabs/content/tabTitle.js | 4 +- app/renderer/components/tabs/tab.js | 29 +++++-- app/renderer/lib/tabUtil.js | 14 ++++ app/renderer/reducers/frameReducer.js | 4 +- docs/state.md | 2 + docs/windowActions.md | 15 +--- js/actions/windowActions.js | 28 +++---- js/constants/appConfig.js | 1 + js/constants/settings.js | 1 + js/constants/windowConstants.js | 2 +- js/state/frameStateUtil.js | 52 ++++++------ js/stores/windowStore.js | 20 ++++- test/lib/selectors.js | 3 +- test/tab-components/tabTest.js | 21 +++-- .../components/preferences/tabsTabTest.js | 81 +++++++++++++++++-- test/unit/app/renderer/lib/tabUtilTest.js | 29 +++++++ 20 files changed, 278 insertions(+), 81 deletions(-) create mode 100644 test/unit/app/renderer/lib/tabUtilTest.js diff --git a/app/common/constants/settingsEnums.js b/app/common/constants/settingsEnums.js index 0b6dcc61961..86b70e8decb 100644 --- a/app/common/constants/settingsEnums.js +++ b/app/common/constants/settingsEnums.js @@ -21,6 +21,12 @@ const bookmarksToolbarMode = { FAVICONS_ONLY: 'faviconsOnly' } +const tabPreviewTiming = { + LONG: 2000, + NORMAL: 1000, + SHORT: 500 +} + const tabCloseAction = { LAST_ACTIVE: 'lastActive', NEXT: 'next', @@ -41,6 +47,7 @@ module.exports = { startsWithOption, newTabMode, bookmarksToolbarMode, + tabPreviewTiming, tabCloseAction, fullscreenOption, autoplayOption diff --git a/app/extensions/brave/locales/en-US/preferences.properties b/app/extensions/brave/locales/en-US/preferences.properties index ecfd1478332..134b7824594 100644 --- a/app/extensions/brave/locales/en-US/preferences.properties +++ b/app/extensions/brave/locales/en-US/preferences.properties @@ -381,3 +381,7 @@ urlBarOptions=URL Bar Options disableTitleMode=Always show the URL bar wideURLbar=Use wide URL bar autoplay=Autoplay Media +tabPreviewTiming=Time to wait before previewing a tab +long=Long +normal=Normal +short=Short diff --git a/app/renderer/components/preferences/tabsTab.js b/app/renderer/components/preferences/tabsTab.js index b8663d469ff..b4959a32f7f 100644 --- a/app/renderer/components/preferences/tabsTab.js +++ b/app/renderer/components/preferences/tabsTab.js @@ -10,7 +10,7 @@ const {SettingsList, SettingItem, SettingCheckbox} = require('../common/settings const {SettingDropdown} = require('../common/dropdown') -const {tabCloseAction} = require('../../../common/constants/settingsEnums') +const {tabCloseAction, tabPreviewTiming} = require('../../../common/constants/settingsEnums') const {changeSetting} = require('../../lib/settingsUtil') const getSetting = require('../../../../js/settings').getSetting const settings = require('../../../../js/constants/settings') @@ -36,6 +36,22 @@ class TabsTab extends ImmutableComponent { } ] } + get tabPreviewTimingOptions () { + return [ + { + id: 'long', + action: tabPreviewTiming.LONG + }, + { + id: 'normal', + action: tabPreviewTiming.NORMAL + }, + { + id: 'short', + action: tabPreviewTiming.SHORT + } + ] + } render () { return (
@@ -107,6 +123,26 @@ class TabsTab extends ImmutableComponent { settings={this.props.settings} onChangeSetting={this.props.onChangeSetting} /> + { + getSetting(settings.SHOW_TAB_PREVIEWS, this.props.settings) + ? + + {this.tabPreviewTimingOptions.map(option => + + + : null + } { @@ -291,6 +309,7 @@ class Tab extends React.Component { : null }
{ this.tabNode = node }} className={css( styles.tab, diff --git a/app/renderer/lib/tabUtil.js b/app/renderer/lib/tabUtil.js index ada265e82a0..dede6ffe2c7 100644 --- a/app/renderer/lib/tabUtil.js +++ b/app/renderer/lib/tabUtil.js @@ -36,3 +36,17 @@ module.exports.hasBreakpoint = (breakpoint, arr) => { arr = Array.isArray(arr) ? arr : [arr] return arr.includes(breakpoint) } + +/** + * Check whether or not the related target is a tab + * by checking the parentNode dataset + * @param {Object} event - The mouse event + * @returns {Boolean} Whether or not the related target is a tab + */ +module.exports.hasTabAsRelatedTarget = (event) => { + const relatedTarget = event.relatedTarget + const hasDataset = relatedTarget.parentNode && relatedTarget.parentNode.dataset + const tabAsRelatedTarget = hasDataset.tab || hasDataset.tabArea + + return hasDataset && tabAsRelatedTarget +} diff --git a/app/renderer/reducers/frameReducer.js b/app/renderer/reducers/frameReducer.js index cfe38fcc3d6..e4e7f5181c5 100644 --- a/app/renderer/reducers/frameReducer.js +++ b/app/renderer/reducers/frameReducer.js @@ -38,6 +38,7 @@ const closeFrame = (state, action) => { const frameProps = frameStateUtil.getFrameByKey(state, action.frameKey) const hoverState = frameStateUtil.getTabHoverState(state, action.frameKey) + const previewMode = state.getIn(['ui', 'tabs', 'previewMode']) state = state.merge(frameStateUtil.removeFrame( state, @@ -58,7 +59,8 @@ const closeFrame = (state, action) => { // This allow us to have closeTab button visible for sequential frames closing, // until onMouseLeave event happens. if (hoverState) { - state = frameStateUtil.setTabHoverState(state, nextFrame.get('key'), hoverState) + state = frameStateUtil + .setTabHoverState(state, nextFrame.get('key'), hoverState, previewMode) } } else if (hoverState && frameStateUtil.getPreviewFrameKey(state) === action.frameKey) { state = frameStateUtil.setPreviewFrameKey(state, null) diff --git a/docs/state.md b/docs/state.md index cf2a9e3bd44..dcb68d7d785 100644 --- a/docs/state.md +++ b/docs/state.md @@ -667,6 +667,8 @@ WindowStore hoverTabIndex: number, // index of the current hovered tab tabPageIndex: number, // index of the current tab page previewTabPageIndex: number // index of the tab being previewed + previewTabPageIndex: number, // index of the tab being previewed + previewMode: boolean // whether or not tab preview should be fired based on mouse idle time }, }, widevinePanelDetail: { diff --git a/docs/windowActions.md b/docs/windowActions.md index 453dd20ed7c..5056234b2fa 100644 --- a/docs/windowActions.md +++ b/docs/windowActions.md @@ -205,18 +205,6 @@ Dispatches a message to the store when the frame is active and the window is foc -### setPreviewFrame(frameKey) - -Dispatches a message to the store to set a preview frame. -This should only be called internally by `WINDOW_SET_TAB_HOVER_STATE` -when we need to delay updating the preview frame value - -**Parameters** - -**frameKey**: `Object`, the frame key for the webview in question. - - - ### setTabPageIndex(index) Dispatches a message to the store to set the tab page index. @@ -239,7 +227,7 @@ Dispatches a message to the store to set the tab breakpoint. -### setTabHoverState(frameKey, hoverState) +### setTabHoverState(frameKey, hoverState, previewMode) Dispatches a message to the store to set the current tab hover state. @@ -249,6 +237,7 @@ Dispatches a message to the store to set the current tab hover state. **hoverState**: `boolean`, whether or not mouse is over tab +**previewMode**: `boolean`, whether or not the next tab should be previewed based on mouse idle time ### setTabPageHoverState(tabPageIndex, hoverState) diff --git a/js/actions/windowActions.js b/js/actions/windowActions.js index 9f8c5f73149..d0138baf661 100644 --- a/js/actions/windowActions.js +++ b/js/actions/windowActions.js @@ -242,20 +242,6 @@ const windowActions = { }) }, - /** - * Dispatches a message to the store to set a preview frame. - * This should only be called internally by `WINDOW_SET_TAB_HOVER_STATE` - * when we need to delay updating the preview frame value - * - * @param {Object} frameKey - the frame key for the webview in question. - */ - setPreviewFrame: function (frameKey) { - dispatch({ - actionType: windowConstants.WINDOW_SET_PREVIEW_FRAME, - frameKey - }) - }, - /** * Dispatches a message to the store to set the tab page index. * @@ -287,12 +273,15 @@ const windowActions = { * * @param {Object} frameKey - the frame key for the webview in question. * @param {boolean} hoverState - whether or not mouse is over tab + * @param {boolean} previewMode - whether or not the next tab should be previewed + * based on mouse idle time */ - setTabHoverState: function (frameKey, hoverState) { + setTabHoverState: function (frameKey, hoverState, previewMode) { dispatch({ actionType: windowConstants.WINDOW_SET_TAB_HOVER_STATE, frameKey, - hoverState + hoverState, + previewMode }) }, @@ -1019,6 +1008,13 @@ const windowActions = { }) }, + onTabMouseMove: function (data) { + dispatch({ + actionType: windowConstants.WINDOW_TAB_MOUSE_MOVE, + data + }) + }, + onTabMouseLeave: function (data) { dispatch({ actionType: windowConstants.WINDOW_TAB_MOUSE_LEAVE, diff --git a/js/constants/appConfig.js b/js/constants/appConfig.js index 14cfab7fc04..cb7493631ed 100644 --- a/js/constants/appConfig.js +++ b/js/constants/appConfig.js @@ -142,6 +142,7 @@ module.exports = { 'tabs.tabs-per-page': 20, 'tabs.close-action': 'parent', 'tabs.show-tab-previews': true, + 'tabs.preview-timing': 2000, 'tabs.show-dashboard-images': true, 'privacy.history-suggestions': true, 'privacy.bookmark-suggestions': true, diff --git a/js/constants/settings.js b/js/constants/settings.js index bc53fce1093..fdf7180c5f1 100644 --- a/js/constants/settings.js +++ b/js/constants/settings.js @@ -28,6 +28,7 @@ const settings = { PAINT_TABS: 'tabs.paint-tabs', TABS_PER_PAGE: 'tabs.tabs-per-page', SHOW_TAB_PREVIEWS: 'tabs.show-tab-previews', + TAB_PREVIEW_TIMING: 'tabs.preview-timing', SHOW_DASHBOARD_IMAGES: 'tabs.show-dashboard-images', // Privacy Tab HISTORY_SUGGESTIONS: 'privacy.history-suggestions', diff --git a/js/constants/windowConstants.js b/js/constants/windowConstants.js index 002f927062f..3e89cde1033 100644 --- a/js/constants/windowConstants.js +++ b/js/constants/windowConstants.js @@ -10,7 +10,6 @@ const windowConstants = { WINDOW_CLOSE_FRAME: _, WINDOW_CLOSE_FRAMES: _, WINDOW_SET_FOCUSED_FRAME: _, - WINDOW_SET_PREVIEW_FRAME: _, WINDOW_SET_PREVIEW_TAB_PAGE_INDEX: _, WINDOW_SET_TAB_PAGE_INDEX: _, WINDOW_SET_TAB_BREAKPOINT: _, @@ -82,6 +81,7 @@ const windowConstants = { WINDOW_AUTOFILL_SELECTION_CLICKED: _, WINDOW_AUTOFILL_POPUP_HIDDEN: _, WINDOW_TAB_CLOSED_WITH_MOUSE: _, + WINDOW_TAB_MOUSE_MOVE: _, WINDOW_TAB_MOUSE_LEAVE: _, WINDOW_FRAME_MOUSE_ENTER: _, WINDOW_FRAME_MOUSE_LEAVE: _, diff --git a/js/state/frameStateUtil.js b/js/state/frameStateUtil.js index b71f871694e..723baab46e4 100644 --- a/js/state/frameStateUtil.js +++ b/js/state/frameStateUtil.js @@ -590,38 +590,42 @@ const setPreviewTabPageIndex = (state, index, immediate = false) => { return state.setIn(['ui', 'tabs', 'previewTabPageIndex'], newTabPageIndex) } -const setPreviewFrameKey = (state, frameKey, immediate = false) => { +/** + * Defines whether or not a tab should be allowed to preview its content + * based on mouse idle time defined by mouse move in tab.js + * @see windowConstants.WINDOW_TAB_MOUSE_MOVE for information + * on how the data is handled in the store. + * @param state {Object} - Application state + * @param previewMode {Boolean} - Whether or not minimium idle time + * has match the criteria + */ +const setPreviewMode = (state, previewMode) => { + return state.setIn(['ui', 'tabs', 'previewMode'], previewMode) +} + +/** + * Gets the previewMode application state + * @param state {Object} - Application state + * @return Immutable top level application state for previewMode + */ +const getPreviewMode = (state) => { + return state.getIn(['ui', 'tabs', 'previewMode']) +} + +const setPreviewFrameKey = (state, frameKey) => { clearTimeout(tabHoverTimeout) const frame = getFrameByKey(state, frameKey) const isActive = isFrameKeyActive(state, frameKey) const previewTabs = getSetting(settings.SHOW_TAB_PREVIEWS) const hoverState = getTabHoverState(state, frameKey) + const previewMode = getPreviewMode(state) let newPreviewFrameKey = frameKey - if (!previewTabs || frame == null || !hoverState || isActive) { + if (!previewTabs || !previewMode || frame == null || !hoverState || isActive) { newPreviewFrameKey = null } - if (!immediate) { - // if there is an existing preview frame key then we're already in preview mode - // we use actions here because that is the only way to delay updating the state - const previewMode = getPreviewFrameKey(state) != null - if (previewMode && newPreviewFrameKey == null) { - // add a small delay when we are clearing the preview frame key so we don't lose - // previewMode if the user mouses over another tab - see below - tabHoverTimeout = setTimeout(windowActions.setPreviewFrame.bind(null, null), 200) - return state - } - - if (!previewMode) { - // If user isn't in previewMode so we add a bit of delay to avoid tab from flashing out - // as reported here: https://github.com/brave/browser-laptop/issues/1434 - // using an action here because that is the only way we can do a delayed state update - tabHoverTimeout = setTimeout(windowActions.setPreviewFrame.bind(null, newPreviewFrameKey), 200) - return state - } - } - + // TODO: remove this method to a tabPageIndex-related one const index = frame ? getFrameTabPageIndex(state, frame.get('tabId')) : -1 if (index !== -1) { if (index !== state.getIn(['ui', 'tabs', 'tabPageIndex'])) { @@ -692,11 +696,11 @@ const setHoverTabIndex = (state, frameKey, hoverState) => { * @param hoverState {Boolean} - True if the current tab is being hovered. * @return Immutable top level application state for hoverTabIndex */ - -const setTabHoverState = (state, frameKey, hoverState) => { +const setTabHoverState = (state, frameKey, hoverState, enablePreviewMode) => { const frameIndex = getFrameIndex(state, frameKey) if (frameIndex !== -1) { state = setHoverTabIndex(state, frameKey, hoverState) + state = setPreviewMode(state, enablePreviewMode) state = setPreviewFrameKey(state, frameKey) } return state diff --git a/js/stores/windowStore.js b/js/stores/windowStore.js index 4e09138b53f..e0f74f9838e 100644 --- a/js/stores/windowStore.js +++ b/js/stores/windowStore.js @@ -38,6 +38,7 @@ let windowState = Immutable.fromJS({ } }) let lastEmittedState +let mouseTimeout const CHANGE_EVENT = 'change' @@ -371,9 +372,6 @@ const doAction = (action) => { case windowConstants.WINDOW_CLEAR_CLOSED_FRAMES: windowState = windowState.set('closedFrames', new Immutable.List()) break - case windowConstants.WINDOW_SET_PREVIEW_FRAME: - windowState = frameStateUtil.setPreviewFrameKey(windowState, action.frameKey, true) - break case windowConstants.WINDOW_SET_PREVIEW_TAB_PAGE_INDEX: windowState = frameStateUtil.setPreviewTabPageIndex(windowState, action.previewTabPageIndex, true) break @@ -396,9 +394,23 @@ const doAction = (action) => { } break } + case windowConstants.WINDOW_TAB_MOUSE_MOVE: + { + // previewMode is only triggered if mouse is idle over a tab + // for a given amount of time based on timing defined in prefs->tabs + // we use actions here because that is the only way to delay updating the state + clearTimeout(mouseTimeout) + mouseTimeout = setTimeout( + () => windowActions.setTabHoverState(action.data, true, true), + getSetting(settings.TAB_PREVIEW_TIMING) + ) + break + } case windowConstants.WINDOW_SET_TAB_HOVER_STATE: { - windowState = frameStateUtil.setTabHoverState(windowState, action.frameKey, action.hoverState) + clearTimeout(mouseTimeout) + windowState = frameStateUtil + .setTabHoverState(windowState, action.frameKey, action.hoverState, action.previewMode) break } case windowConstants.WINDOW_SET_TAB_PAGE_HOVER_STATE: diff --git a/test/lib/selectors.js b/test/lib/selectors.js index 0b429493afa..16b58b8ac3b 100644 --- a/test/lib/selectors.js +++ b/test/lib/selectors.js @@ -133,5 +133,6 @@ module.exports = { // about:preferences#tabs tabsPerTabPageActiveOption: '[data-test-id="tabsPerTabPageOption"][data-test-active="true"]', - tabCloseActionActiveOption: '[data-test-id="tabCloseActionActiveOption"][data-test-active="true"]' + tabCloseActionActiveOption: '[data-test-id="tabCloseActionActiveOption"][data-test-active="true"]', + tabPreviewTimingActiveOption: '[data-test-id="tabPreviewTimingOption"][data-test-active="true"]' } diff --git a/test/tab-components/tabTest.js b/test/tab-components/tabTest.js index 4664f13aad6..3a35e8fff75 100644 --- a/test/tab-components/tabTest.js +++ b/test/tab-components/tabTest.js @@ -3,6 +3,7 @@ const Brave = require('../lib/brave') const messages = require('../../js/constants/messages') const settings = require('../../js/constants/settings') +const {tabPreviewTiming} = require('../../app/common/constants/settingsEnums') const {urlInput, backButton, forwardButton, activeTab, activeTabTitle, activeTabFavicon, newFrameButton, notificationBar, contextMenu, pinnedTabsTabs, tabsTabs} = require('../lib/selectors') const newTabUrl = 'chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-newtab.html' @@ -373,6 +374,8 @@ describe('tab tests', function () { const page1 = Brave.server.url('page1.html') const page2 = Brave.server.url('page2.html') yield setup(this.app.client) + yield this.app.client + .changeSetting(settings.TAB_PREVIEW_TIMING, tabPreviewTiming.SHORT) yield this.app.client .newTab({ url: page1 }) .waitForUrl(page1) @@ -383,11 +386,11 @@ describe('tab tests', function () { .windowByUrl(Brave.browserWindowUrl) .waitForExist('[data-test-id="tab"][data-frame-key="3"]') }) - it('shows a tab preview', function * () { + it('shows a tab preview when TAB_PREVIEW_TIMING is set as SHORT', function * () { yield this.app.client .moveToObject('[data-test-id="tab"][data-frame-key="2"]') .moveToObject('[data-test-id="tab"][data-frame-key="2"]', 3, 3) - .waitForExist('.frameWrapper.isPreview webview[data-frame-key="2"]') + .waitForElementCount('.frameWrapper.isPreview webview[data-frame-key="2"]', 1) .moveToObject(urlInput) }) it('does not show preview in the active tab', function * () { @@ -424,6 +427,8 @@ describe('tab tests', function () { const page5 = Brave.server.url('page1.html') const page6 = Brave.server.url('page2.html') yield setup(this.app.client) + // Set to minimum preview timing to avoid timeout + yield this.app.client.changeSetting(settings.TAB_PREVIEW_TIMING, tabPreviewTiming.SHORT) yield this.app.client .newTab({ url: page1 }) .waitForUrl(page1) @@ -454,30 +459,36 @@ describe('tab tests', function () { it('show active tab content if next tab does not exist', function * () { yield this.app.client .moveToObject('[data-test-id="tab"][data-frame-key="2"]') + .moveToObject('[data-test-id="tab"][data-frame-key="2"]', 3, 3) .click('[data-test-id="tab"][data-frame-key="2"]') .moveToObject('[data-test-id="tab"][data-frame-key="7"]') + .moveToObject('[data-test-id="tab"][data-frame-key="7"]', 3, 3) .middleClick('[data-test-id="tab"][data-frame-key="7"]') // no preview should be shown - .waitForVisible('.frameWrapper.isPreview webview', 500, true) + .waitForElementCount('.frameWrapper.isPreview webview', 0) }) it('preview the next tab if preview option is on', function * () { yield this.app.client .moveToObject('[data-test-id="tab"][data-frame-key="2"]') + .moveToObject('[data-test-id="tab"][data-frame-key="2"]', 3, 3) .click('[data-test-id="tab"][data-frame-key="2"]') .moveToObject('[data-test-id="tab"][data-frame-key="4"]') + .moveToObject('[data-test-id="tab"][data-frame-key="4"]', 3, 3) .middleClick('[data-test-id="tab"][data-frame-key="4"]') .waitForExist('.frameWrapper.isPreview webview[data-frame-key="5"]') - .waitForVisible('.frameWrapper.isPreview webview[data-frame-key="5"]') + .waitForElementCount('.frameWrapper.isPreview webview[data-frame-key="5"]', 1) }) it('do not preview the next tab if preview option is off', function * () { yield this.app.client.changeSetting(settings.SHOW_TAB_PREVIEWS, false) yield this.app.client + .moveToObject('[data-test-id="tab"][data-frame-key="2"]', 3, 3) .moveToObject('[data-test-id="tab"][data-frame-key="2"]') .click('[data-test-id="tab"][data-frame-key="2"]') + .moveToObject('[data-test-id="tab"][data-frame-key="5"]', 3, 3) .moveToObject('[data-test-id="tab"][data-frame-key="5"]') .middleClick('[data-test-id="tab"][data-frame-key="5"]') // no preview should be shown - .waitForVisible('.frameWrapper.isPreview webview', 500, true) + .waitForElementCount('.frameWrapper.isPreview webview', 0) }) }) diff --git a/test/unit/app/renderer/components/preferences/tabsTabTest.js b/test/unit/app/renderer/components/preferences/tabsTabTest.js index 1ada4c3ffac..89cdd1795e1 100644 --- a/test/unit/app/renderer/components/preferences/tabsTabTest.js +++ b/test/unit/app/renderer/components/preferences/tabsTabTest.js @@ -5,8 +5,12 @@ const mockery = require('mockery') const {mount, shallow} = require('enzyme') -const {tabCloseAction} = require('../../../../../../app/common/constants/settingsEnums') -const {tabsPerTabPageActiveOption, tabCloseActionActiveOption} = require('../../../../../lib/selectors') +const {tabCloseAction, tabPreviewTiming} = require('../../../../../../app/common/constants/settingsEnums') +const { + tabsPerTabPageActiveOption, + tabCloseActionActiveOption, + tabPreviewTimingActiveOption +} = require('../../../../../lib/selectors') const assert = require('assert') const fakeElectron = require('../../../../lib/fakeElectron') require('../../../../braveUnit') @@ -164,26 +168,87 @@ describe('TabsTab component', function () { }) }) - describe('basic functionality', function () { - it('can switch to new tabs immediately', function () { + describe('tab preview functionality', function () { + it('can show tab previews on hover', function () { settingDefaultValue = true const wrapper = shallow() assert.notEqual( wrapper - .find('[dataTestId="switchToNewTabs"]') + .find('[dataTestId="showTabPreviews"]') .map(option => option.props().value) .includes(settingDefaultValue), true ) }) - it('can show tab previews on hover', function () { + it('show all 3 tab preview timing options if tab preview is on', function () { + settingDefaultValue = true + const wrapper = shallow() + assert.equal(wrapper.find(tabPreviewTimingActiveOption).length, 3) + }) + it('does not show tab preview timing options if tab preview is off', function () { + settingDefaultValue = false + const wrapper = shallow() + assert.equal(wrapper.find(tabPreviewTimingActiveOption).length, 0) + }) + it('can switch tab previews time to activate previews to LONG', function () { + settingDefaultValue = tabPreviewTiming.LONG + const wrapper = shallow() + + assert.equal( + wrapper + .find(tabPreviewTimingActiveOption) + .map(option => option.props().value) + .includes(settingDefaultValue), + true + ) + }) + it('can switch tab previews time to activate previews to NORMAL', function () { + settingDefaultValue = tabPreviewTiming.NORMAL + const wrapper = shallow() + + assert.equal( + wrapper + .find(tabPreviewTimingActiveOption) + .map(option => option.props().value) + .includes(settingDefaultValue), + true + ) + }) + it('can switch tab previews time to activate previews to SHORT', function () { + settingDefaultValue = tabPreviewTiming.SHORT + const wrapper = shallow() + + assert.equal( + wrapper + .find(tabPreviewTimingActiveOption) + .map(option => option.props().value) + .includes(settingDefaultValue), + true + ) + }) + it('can not switch to other values', function () { + settingDefaultValue = tabPreviewTiming.ONLY_ONCE_IN_A_LIFETIME + const wrapper = shallow() + + assert.notEqual( + wrapper + .find(tabPreviewTimingActiveOption) + .map(option => option.props().value) + .includes(settingDefaultValue), + true + ) + }) + }) + + describe('basic functionality', function () { + it('can switch to new tabs immediately', function () { settingDefaultValue = true const wrapper = shallow() assert.notEqual( wrapper - .find('[dataTestId="paintTabs"]') + .find('[dataTestId="switchToNewTabs"]') .map(option => option.props().value) .includes(settingDefaultValue), true @@ -195,7 +260,7 @@ describe('TabsTab component', function () { assert.notEqual( wrapper - .find('[dataTestId="showTabPreviews"]') + .find('[dataTestId="paintTabs"]') .map(option => option.props().value) .includes(settingDefaultValue), true diff --git a/test/unit/app/renderer/lib/tabUtilTest.js b/test/unit/app/renderer/lib/tabUtilTest.js new file mode 100644 index 00000000000..ab04895255b --- /dev/null +++ b/test/unit/app/renderer/lib/tabUtilTest.js @@ -0,0 +1,29 @@ +/* global describe, it */ +const tabUtil = require('../../../../../app/renderer/lib/tabUtil') +const assert = require('assert') + +require('../../../braveUnit') + +describe('tabUtil', function () { + describe('hasTabAsRelatedTarget', function () { + const fakeEvent = (fakeDataset) => ({ + relatedTarget: { + parentNode: { + dataset: { [fakeDataset]: true } + } + } + }) + it('returns true if dataset is tab', function () { + const fakeDataset = fakeEvent('tab') + assert.equal(tabUtil.hasTabAsRelatedTarget(fakeDataset), true) + }) + it('returns true if dataset is tabArea', function () { + const fakeDataset = fakeEvent('tabArea') + assert.equal(tabUtil.hasTabAsRelatedTarget(fakeDataset), true) + }) + it('returns false if dataset is neither tab nor tabArea', function () { + const fakeDataset = fakeEvent('badCoffee') + assert.notEqual(tabUtil.hasTabAsRelatedTarget(fakeDataset), true) + }) + }) +})