diff --git a/src/core_plugins/kibana/ui_setting_defaults.js b/src/core_plugins/kibana/ui_setting_defaults.js index dc00edaad0b27..acfb03db0e392 100644 --- a/src/core_plugins/kibana/ui_setting_defaults.js +++ b/src/core_plugins/kibana/ui_setting_defaults.js @@ -510,5 +510,13 @@ export function getUiSettingDefaults() { is present and sortable in the current index pattern is used.`, category: ['discover'], }, + 'accessibility:disableAnimations': { + name: 'Disable Animations', + value: false, + description: ` + Turn off all unnecessary animations in the Kibana UI. Refresh the page to apply the changes. + `, + category: ['accessibility'], + }, }; } diff --git a/src/es_archiver/es_archiver.js b/src/es_archiver/es_archiver.js index bc4f79b8f8075..e600a37d98fe4 100644 --- a/src/es_archiver/es_archiver.js +++ b/src/es_archiver/es_archiver.js @@ -95,7 +95,7 @@ export class EsArchiver { * @return Promise */ async rebuildAll() { - return rebuildAllAction({ + return await rebuildAllAction({ client: this.client, dataDir: this.dataDir, log: this.log @@ -109,6 +109,6 @@ export class EsArchiver { * @return Promise */ async loadIfNeeded(name) { - return this.load(name, { skipExisting: true }); + return await this.load(name, { skipExisting: true }); } } diff --git a/src/functional_test_runner/lib/config/schema.js b/src/functional_test_runner/lib/config/schema.js index 93450fc88732c..ec0aeaf2b5b76 100644 --- a/src/functional_test_runner/lib/config/schema.js +++ b/src/functional_test_runner/lib/config/schema.js @@ -138,7 +138,12 @@ export const schema = Joi.object().keys({ // settings for the esArchiver module esArchiver: Joi.object().keys({ - directory: Joi.string().default(defaultRelativeToConfigPath('fixtures/es_archiver')) + directory: Joi.string().default(defaultRelativeToConfigPath('fixtures/es_archiver')), + }).default(), + + // settings for the kibanaServer.uiSettings module + uiSettings: Joi.object().keys({ + defaults: Joi.object().unknown(true) }).default(), // settings for the screenshots module diff --git a/src/functional_test_runner/lib/providers/provider_collection.js b/src/functional_test_runner/lib/providers/provider_collection.js index 11a6181c25e84..5826f09502ba0 100644 --- a/src/functional_test_runner/lib/providers/provider_collection.js +++ b/src/functional_test_runner/lib/providers/provider_collection.js @@ -31,6 +31,10 @@ export class ProviderCollection { this._getInstance('Service', name) ) + hasService = name => ( + Boolean(this._findProvider('Service', name)) + ) + getPageObject = name => ( this._getInstance('PageObject', name) ) @@ -68,8 +72,12 @@ export class ProviderCollection { } } + _findProvider(type, name) { + return this._providers.find(p => p.type === type && p.name === name); + } + _getProvider(type, name) { - const providerDef = this._providers.find(p => p.type === type && p.name === name); + const providerDef = this._findProvider(type, name); if (!providerDef) { throw new Error(`Unknown ${type} "${name}"`); } @@ -87,6 +95,7 @@ export class ProviderCollection { if (!instances.has(provider)) { let instance = provider({ getService: this.getService, + hasService: this.hasService, getPageObject: this.getPageObject, getPageObjects: this.getPageObjects, }); diff --git a/src/ui/public/autoload/styles.js b/src/ui/public/autoload/styles.js index df9e05e6d71c5..c919bd33cda1e 100644 --- a/src/ui/public/autoload/styles.js +++ b/src/ui/public/autoload/styles.js @@ -36,3 +36,6 @@ theme.applyTheme('light'); // All Kibana styles inside of the /styles dir const context = require.context('../styles', false, /[\/\\](?!mixins|variables|_|\.)[^\/\\]+\.less/); context.keys().forEach(key => context(key)); + +// manually require non-less files +require('../styles/disable_animations'); diff --git a/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap b/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap index 301e34bb42050..b9d9391a05d80 100644 --- a/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap +++ b/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap @@ -6,7 +6,7 @@ exports[`kbnLoadingIndicator is hidden by default 1`] = ` data-test-subj="globalLoadingIndicator-hidden" >
`; @@ -17,7 +17,7 @@ exports[`kbnLoadingIndicator is visible when loadingCount is > 0 1`] = ` data-test-subj="globalLoadingIndicator" >
`; diff --git a/src/ui/public/chrome/directives/loading_indicator.js b/src/ui/public/chrome/directives/loading_indicator.js index f8f6c671683f5..dee04bc2d51c3 100644 --- a/src/ui/public/chrome/directives/loading_indicator.js +++ b/src/ui/public/chrome/directives/loading_indicator.js @@ -56,7 +56,7 @@ export class LoadingIndicator extends React.Component { return (
-
+
); } diff --git a/src/ui/public/styles/disable_animations/disable_animations.css b/src/ui/public/styles/disable_animations/disable_animations.css new file mode 100644 index 0000000000000..9cf9d9eb4e5f2 --- /dev/null +++ b/src/ui/public/styles/disable_animations/disable_animations.css @@ -0,0 +1,14 @@ +*:not(.essentialAnimation), +*:not(.essentialAnimation):before, +*:not(.essentialAnimation):after { + /** + * set the animation/transition duration to 0s so that animation callbacks are + * still triggered, allowing components that require them to remain functional + */ + + -webkit-animation-duration: 0s !important; + animation-duration: 0s !important; + + -webkit-transition-duration: 0s !important; + transition-duration: 0s !important; +} diff --git a/src/ui/public/styles/disable_animations/disable_animations.js b/src/ui/public/styles/disable_animations/disable_animations.js new file mode 100644 index 0000000000000..067bbd040df33 --- /dev/null +++ b/src/ui/public/styles/disable_animations/disable_animations.js @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 chrome from 'ui/chrome'; +import disableAnimationsCss from '!!raw-loader!./disable_animations.css'; + +const uiSettings = chrome.getUiSettingsClient(); + +// rather than silently ignore when the style element is missing in the tests +// like ui/theme does, we automatically create a style tag because ordering doesn't +// really matter for these styles, they should really take top priority because +// they all use `!important`, and we don't want to silently ignore the possibility +// of accidentally removing the style element from the chrome template. +const styleElement = document.createElement('style'); +styleElement.setAttribute('id', 'disableAnimationsCss'); +document.head.appendChild(styleElement); + +function updateStyleSheet() { + styleElement.textContent = uiSettings.get('accessibility:disableAnimations') + ? disableAnimationsCss + : ''; +} + +updateStyleSheet(); +uiSettings.subscribe(({ key }) => { + if (key === 'accessibility:disableAnimations') { + updateStyleSheet(); + } +}); + diff --git a/src/ui/public/styles/disable_animations/index.js b/src/ui/public/styles/disable_animations/index.js new file mode 100644 index 0000000000000..2c459667d5996 --- /dev/null +++ b/src/ui/public/styles/disable_animations/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 './disable_animations'; diff --git a/src/ui/public/tooltip/tooltip.js b/src/ui/public/tooltip/tooltip.js index d53070fd6a6ea..7ae8c54375040 100644 --- a/src/ui/public/tooltip/tooltip.js +++ b/src/ui/public/tooltip/tooltip.js @@ -18,12 +18,16 @@ */ import html from './tooltip.html'; +import chrome from 'ui/chrome'; require('ui-bootstrap') .config(function ($tooltipProvider) { + // we use the uiSettings client because the config service is not available in the config phase + const uiSettings = chrome.getUiSettingsClient(); + $tooltipProvider.options({ placement: 'bottom', - animation: true, + animation: !uiSettings.get('accessibility:disableAnimations'), popupDelay: 150, appendToBody: false }); diff --git a/test/common/services/es_archiver.js b/test/common/services/es_archiver.js index 8dd796e70bd4f..57b0f5664d022 100644 --- a/test/common/services/es_archiver.js +++ b/test/common/services/es_archiver.js @@ -18,8 +18,9 @@ */ import { EsArchiver } from '../../../src/es_archiver'; +import * as KibanaServer from './kibana_server'; -export async function EsArchiverProvider({ getService }) { +export function EsArchiverProvider({ getService, hasService }) { const config = getService('config'); const client = getService('es'); const log = getService('log'); @@ -30,9 +31,19 @@ export async function EsArchiverProvider({ getService }) { const dataDir = config.get('esArchiver.directory'); - return new EsArchiver({ + const esArchiver = new EsArchiver({ client, dataDir, log, }); + + if (hasService('kibanaServer')) { + KibanaServer.extendEsArchiver({ + esArchiver, + kibanaServer: getService('kibanaServer'), + defaults: config.get('uiSettings.defaults'), + }); + } + + return esArchiver; } diff --git a/test/common/services/kibana_server/extend_es_archiver.js b/test/common/services/kibana_server/extend_es_archiver.js new file mode 100644 index 0000000000000..1c804c630b026 --- /dev/null +++ b/test/common/services/kibana_server/extend_es_archiver.js @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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. + */ + +const ES_ARCHIVER_LOAD_METHODS = ['load', 'loadIfNeeded']; +const KIBANA_INDEX = '.kibana'; + +export function extendEsArchiver({ esArchiver, kibanaServer, defaults }) { + // only extend the esArchiver if there are default uiSettings to restore + if (!defaults) { + return; + } + + ES_ARCHIVER_LOAD_METHODS.forEach(method => { + const originalMethod = esArchiver[method]; + + esArchiver[method] = async (...args) => { + // esArchiver methods return a stats object, with information about the indexes created + const stats = await originalMethod.apply(esArchiver, args); + + // if the kibana index was created by the esArchiver then update the uiSettings + // with the defaults to make sure that they are always in place initially + if (stats[KIBANA_INDEX] && stats[KIBANA_INDEX].created) { + await kibanaServer.uiSettings.update(defaults); + } + + return stats; + }; + }); +} diff --git a/test/common/services/kibana_server/index.js b/test/common/services/kibana_server/index.js index 70b4e934e30dc..6d9035008c6b7 100644 --- a/test/common/services/kibana_server/index.js +++ b/test/common/services/kibana_server/index.js @@ -18,3 +18,4 @@ */ export { KibanaServerProvider } from './kibana_server'; +export { extendEsArchiver } from './extend_es_archiver'; diff --git a/test/common/services/kibana_server/kibana_server.js b/test/common/services/kibana_server/kibana_server.js index 5f413fe0b58d1..d5125d8eba256 100644 --- a/test/common/services/kibana_server/kibana_server.js +++ b/test/common/services/kibana_server/kibana_server.js @@ -23,7 +23,7 @@ import { KibanaServerStatus } from './status'; import { KibanaServerUiSettings } from './ui_settings'; import { KibanaServerVersion } from './version'; -export async function KibanaServerProvider({ getService }) { +export function KibanaServerProvider({ getService }) { const log = getService('log'); const config = getService('config'); @@ -32,7 +32,7 @@ export async function KibanaServerProvider({ getService }) { const url = formatUrl(config.get('servers.kibana')); this.status = new KibanaServerStatus(url); this.version = new KibanaServerVersion(this.status); - this.uiSettings = new KibanaServerUiSettings(url, log, this.version); + this.uiSettings = new KibanaServerUiSettings(url, log, config.get('uiSettings.defaults')); } }; } diff --git a/test/common/services/kibana_server/ui_settings.js b/test/common/services/kibana_server/ui_settings.js index ff318fa5eeb16..ac7987bfb3717 100644 --- a/test/common/services/kibana_server/ui_settings.js +++ b/test/common/services/kibana_server/ui_settings.js @@ -24,9 +24,9 @@ const MINUTE = 60 * 1000; const HOUR = 60 * MINUTE; export class KibanaServerUiSettings { - constructor(url, log, kibanaVersion) { + constructor(url, log, defaults) { this._log = log; - this._kibanaVersion = kibanaVersion; + this._defaults = defaults; this._wreck = Wreck.defaults({ headers: { 'kbn-xsrf': 'ftr/services/uiSettings' }, baseUrl: url, @@ -35,9 +35,9 @@ export class KibanaServerUiSettings { }); } - /* - ** Gets defaultIndex from the config doc. - */ + /** + * Gets defaultIndex from the config doc. + */ async getDefaultIndex() { const { payload } = await this._wreck.get('/api/kibana/settings'); const defaultIndex = get(payload, 'settings.defaultIndex.userValue'); @@ -75,15 +75,18 @@ export class KibanaServerUiSettings { await this._wreck.post('/api/kibana/settings', { payload: { - changes: doc + changes: { + ...this._defaults, + ...doc, + } } }); } /** - * Add fields to the config doc (like setting timezone and defaultIndex) - * @return {Promise} A promise that is resolved when elasticsearch has a response - */ + * Add fields to the config doc (like setting timezone and defaultIndex) + * @return {Promise} A promise that is resolved when elasticsearch has a response + */ async update(updates) { this._log.debug('applying update to kibana config: %j', updates); await this._wreck.post('/api/kibana/settings', { diff --git a/test/functional/apps/dashboard/_create_and_add_embeddables.js b/test/functional/apps/dashboard/_create_and_add_embeddables.js index 6a6b4a539a39c..007050c6d3b32 100644 --- a/test/functional/apps/dashboard/_create_and_add_embeddables.js +++ b/test/functional/apps/dashboard/_create_and_add_embeddables.js @@ -37,7 +37,7 @@ export default function ({ getService, getPageObjects }) { describe('add new visualization link', () => { it('adds a new visualization', async () => { const originalPanelCount = await PageObjects.dashboard.getPanelCount(); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await dashboardAddPanel.ensureAddPanelIsShowing(); await dashboardAddPanel.clickAddNewEmbeddableLink(); await PageObjects.visualize.clickAreaChart(); diff --git a/test/functional/apps/dashboard/_dashboard_grid.js b/test/functional/apps/dashboard/_dashboard_grid.js index 933d40bc390fc..2840424e7f017 100644 --- a/test/functional/apps/dashboard/_dashboard_grid.js +++ b/test/functional/apps/dashboard/_dashboard_grid.js @@ -28,7 +28,7 @@ export default function ({ getService, getPageObjects }) { before(async () => { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.loadSavedDashboard('few panels'); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); }); describe('move panel', () => { diff --git a/test/functional/apps/dashboard/_dashboard_options.js b/test/functional/apps/dashboard/_dashboard_options.js index c3e4587feb8b3..02dc1e7a4af7b 100644 --- a/test/functional/apps/dashboard/_dashboard_options.js +++ b/test/functional/apps/dashboard/_dashboard_options.js @@ -28,7 +28,7 @@ export default function ({ getService, getPageObjects }) { before(async () => { await PageObjects.dashboard.loadSavedDashboard('few panels'); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); originalTitles = await PageObjects.dashboard.getPanelTitles(); }); diff --git a/test/functional/apps/dashboard/_dashboard_save.js b/test/functional/apps/dashboard/_dashboard_save.js index 7549457fc1f6c..53dc69fd145c7 100644 --- a/test/functional/apps/dashboard/_dashboard_save.js +++ b/test/functional/apps/dashboard/_dashboard_save.js @@ -76,7 +76,7 @@ export default function ({ getService, getPageObjects }) { async function () { await PageObjects.dashboard.selectDashboard(dashboardName); await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.dashboard.saveDashboard(dashboardName); const isWarningDisplayed = await PageObjects.dashboard.isDuplicateTitleWarningDisplayed(); @@ -85,7 +85,7 @@ export default function ({ getService, getPageObjects }) { ); it('Warns you when you Save as New Dashboard, and the title is a duplicate', async function () { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.dashboard.enterDashboardTitleAndClickSave(dashboardName, { saveAsNew: true }); const isWarningDisplayed = await PageObjects.dashboard.isDuplicateTitleWarningDisplayed(); @@ -102,7 +102,7 @@ export default function ({ getService, getPageObjects }) { }); it('Warns when case is different', async function () { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.dashboard.enterDashboardTitleAndClickSave(dashboardName.toUpperCase()); // We expect isWarningDisplayed to be open, hence the retry if not found. diff --git a/test/functional/apps/dashboard/_dashboard_state.js b/test/functional/apps/dashboard/_dashboard_state.js index ea7439c1dbd82..1c9054111074e 100644 --- a/test/functional/apps/dashboard/_dashboard_state.js +++ b/test/functional/apps/dashboard/_dashboard_state.js @@ -52,7 +52,7 @@ export default function ({ getService, getPageObjects }) { await dashboardAddPanel.addVisualization(AREA_CHART_VIS_NAME); await PageObjects.dashboard.saveDashboard('Overridden colors'); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.visualize.openLegendOptionColors('Count'); await PageObjects.visualize.selectNewLegendColorChoice('#EA6460'); @@ -100,7 +100,7 @@ export default function ({ getService, getPageObjects }) { it('Saved search with column changes will not update when the saved object changes', async () => { await PageObjects.discover.removeHeaderColumn('bytes'); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.dashboard.saveDashboard('Has local edits'); await PageObjects.header.clickDiscover(); @@ -129,7 +129,7 @@ export default function ({ getService, getPageObjects }) { const tileMapData = await PageObjects.visualize.getInspectorTableData(); await PageObjects.visualize.closeInspector(); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await dashboardPanelActions.clickEdit(); await PageObjects.visualize.clickMapZoomIn(); diff --git a/test/functional/apps/dashboard/_dashboard_time.js b/test/functional/apps/dashboard/_dashboard_time.js index 285da16bfb443..5e6ff78fb2079 100644 --- a/test/functional/apps/dashboard/_dashboard_time.js +++ b/test/functional/apps/dashboard/_dashboard_time.js @@ -59,7 +59,7 @@ export default function ({ getPageObjects, getService }) { describe('dashboard with stored timed', async function () { it('is saved with quick time', async function () { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.header.setQuickTime('Today'); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); }); @@ -74,7 +74,7 @@ export default function ({ getPageObjects, getService }) { }); it('is saved with absolute time', async function () { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.header.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); }); diff --git a/test/functional/apps/dashboard/_data_shared_attributes.js b/test/functional/apps/dashboard/_data_shared_attributes.js index 0a50ed3db398a..27ac2184071f8 100644 --- a/test/functional/apps/dashboard/_data_shared_attributes.js +++ b/test/functional/apps/dashboard/_data_shared_attributes.js @@ -55,7 +55,7 @@ export default function ({ getService, getPageObjects }) { }); it('data-shared-item title should update a viz when using a custom panel title', async () => { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); const CUSTOM_VIS_TITLE = 'ima custom title for a vis!'; await dashboardPanelActions.setCustomPanelTitle(CUSTOM_VIS_TITLE); await retry.try(async () => { diff --git a/test/functional/apps/dashboard/_full_screen_mode.js b/test/functional/apps/dashboard/_full_screen_mode.js index 35af03ae05ac3..94ff8323f14de 100644 --- a/test/functional/apps/dashboard/_full_screen_mode.js +++ b/test/functional/apps/dashboard/_full_screen_mode.js @@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }) { }); it('option not available in edit mode', async () => { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); const exists = await PageObjects.dashboard.fullScreenModeMenuItemExists(); expect(exists).to.be(false); }); diff --git a/test/functional/apps/dashboard/_panel_controls.js b/test/functional/apps/dashboard/_panel_controls.js index 158efae00e0cc..20c781e0ac382 100644 --- a/test/functional/apps/dashboard/_panel_controls.js +++ b/test/functional/apps/dashboard/_panel_controls.js @@ -69,7 +69,7 @@ export default function ({ getService, getPageObjects }) { }); it('are shown in edit mode', async function () { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); const isContextMenuIconVisible = await dashboardPanelActions.isContextMenuIconVisible(); expect(isContextMenuIconVisible).to.equal(true); @@ -115,7 +115,7 @@ export default function ({ getService, getPageObjects }) { }); it('in edit mode hides remove icons ', async function () { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await dashboardPanelActions.openContextMenu(); const editLinkExists = await dashboardPanelActions.editPanelActionExists(); const removeExists = await dashboardPanelActions.removePanelActionExists(); diff --git a/test/functional/apps/dashboard/_view_edit.js b/test/functional/apps/dashboard/_view_edit.js index f99e59323aa28..7d26dbe27daeb 100644 --- a/test/functional/apps/dashboard/_view_edit.js +++ b/test/functional/apps/dashboard/_view_edit.js @@ -67,7 +67,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: true }); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.header.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); @@ -99,7 +99,7 @@ export default function ({ getService, getPageObjects }) { // This may seem like a pointless line but there was a bug that only arose when the dashboard // was loaded initially await PageObjects.dashboard.loadSavedDashboard(dashboardName); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); let hasFilter = await filterBar.hasFilter('animal', 'dog'); expect(hasFilter).to.be(true); @@ -157,7 +157,7 @@ export default function ({ getService, getPageObjects }) { const newToTime = '2015-09-19 06:31:44.000'; await PageObjects.header.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); await PageObjects.dashboard.saveDashboard(dashboardName, true); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.header.setAbsoluteRange(newToTime, newToTime); await PageObjects.dashboard.clickCancelOutOfEditMode(); @@ -180,7 +180,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); await PageObjects.dashboard.setTimepickerInDataRange(); await PageObjects.dashboard.saveDashboard(dashboardName, true); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.header.setAbsoluteRange('2013-09-19 06:31:44.000', '2013-09-19 06:31:44.000'); const newFromTime = await PageObjects.header.getFromTime(); @@ -205,7 +205,7 @@ export default function ({ getService, getPageObjects }) { it('when time changed is not stored with dashboard', async function () { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: false }); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.header.setAbsoluteRange('2014-10-19 06:31:44.000', '2014-12-19 06:31:44.000'); await PageObjects.dashboard.clickCancelOutOfEditMode(); diff --git a/test/functional/config.js b/test/functional/config.js index 147431a184fe4..c142d46ccd29b 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -122,6 +122,12 @@ export default async function ({ readConfigFile }) { ], }, + uiSettings: { + defaults: { + 'accessibility:disableAnimations': true, + }, + }, + apps: { status_page: { pathname: '/status', diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.js index e9c0ddde2ba5c..bb7611c233ae5 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.js @@ -173,9 +173,12 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return await testSubjects.exists('titleDupicateWarnMsg'); } - async clickEdit() { - log.debug('Clicking edit'); - return await testSubjects.click('dashboardEditMode'); + async switchToEditMode() { + log.debug('Switching to edit mode'); + await testSubjects.click('dashboardEditMode'); + await retry.waitFor('not in view mode', async () => ( + !await this.getIsInViewMode() + )); } async getIsInViewMode() { @@ -278,7 +281,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { async gotoDashboardEditMode(dashboardName) { await this.loadSavedDashboard(dashboardName); - await this.clickEdit(); + await this.switchToEditMode(); } async renameDashboard(dashName) { diff --git a/test/functional/services/dashboard/visualizations.js b/test/functional/services/dashboard/visualizations.js index 0d3ea8cf4d257..918aa404fe0e6 100644 --- a/test/functional/services/dashboard/visualizations.js +++ b/test/functional/services/dashboard/visualizations.js @@ -30,7 +30,7 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { log.debug(`createAndAddTSVBVisualization(${name})`); const inViewMode = await PageObjects.dashboard.getIsInViewMode(); if (inViewMode) { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); } await dashboardAddPanel.ensureAddPanelIsShowing(); await dashboardAddPanel.clickAddNewEmbeddableLink(); @@ -68,7 +68,7 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { const inViewMode = await PageObjects.dashboard.getIsInViewMode(); if (inViewMode) { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); } await dashboardAddPanel.addSavedSearch(name); } @@ -77,7 +77,7 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { log.debug(`createAndAddMarkdown(${markdown})`); const inViewMode = await PageObjects.dashboard.getIsInViewMode(); if (inViewMode) { - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); } await dashboardAddPanel.ensureAddPanelIsShowing(); await dashboardAddPanel.clickAddNewEmbeddableLink(); diff --git a/x-pack/test/reporting/functional/reporting.js b/x-pack/test/reporting/functional/reporting.js index 11e0f9716e3cf..16501ec701b03 100644 --- a/x-pack/test/reporting/functional/reporting.js +++ b/x-pack/test/reporting/functional/reporting.js @@ -86,7 +86,7 @@ export default function ({ getService, getPageObjects }) { // report than phantom. this.timeout(360000); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.reporting.setTimepickerInDataRange(); const visualizations = PageObjects.dashboard.getTestVisualizationNames(); @@ -124,7 +124,7 @@ export default function ({ getService, getPageObjects }) { // report than phantom. this.timeout(360000); - await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.switchToEditMode(); await PageObjects.dashboard.useMargins(true); await PageObjects.dashboard.saveDashboard('report test'); await PageObjects.reporting.openReportingPanel();