From 4b835ff5371bd91d6fee6b1ca2d29cad31fe5d0e Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Tue, 14 Jan 2020 16:56:38 +0100 Subject: [PATCH] Functional tests: refactor dashboard_page (#54588) * [test/functional] cleanup & tsfy dashboard_page * fix & improvement Co-authored-by: Elastic Machine --- .../apps/dashboard/dashboard_clone.js | 15 +- .../apps/dashboard/dashboard_filter_bar.js | 6 +- .../apps/dashboard/dashboard_filtering.js | 6 +- .../apps/dashboard/dashboard_listing.js | 54 +-- .../apps/dashboard/dashboard_save.js | 17 +- .../apps/dashboard/dashboard_snapshots.js | 6 +- .../apps/dashboard/dashboard_state.js | 7 +- .../apps/dashboard/dashboard_time_picker.js | 4 +- .../apps/dashboard/panel_controls.js | 12 +- test/functional/apps/dashboard/view_edit.js | 4 +- .../{dashboard_page.js => dashboard_page.ts} | 337 ++++++------------ test/functional/page_objects/index.ts | 1 - test/functional/page_objects/time_picker.js | 16 + .../functional/page_objects/visualize_page.ts | 10 +- .../services/dashboard/visualizations.js | 11 +- test/functional/services/listing_table.ts | 116 +++++- .../dashboard_mode/dashboard_view_mode.js | 4 +- .../functional/apps/lens/lens_reporting.ts | 3 +- .../apps/spaces/spaces_selection.ts | 5 +- 19 files changed, 312 insertions(+), 322 deletions(-) rename test/functional/page_objects/{dashboard_page.js => dashboard_page.ts} (60%) diff --git a/test/functional/apps/dashboard/dashboard_clone.js b/test/functional/apps/dashboard/dashboard_clone.js index 2a955a2dc90b1e..f5485c1db206e7 100644 --- a/test/functional/apps/dashboard/dashboard_clone.js +++ b/test/functional/apps/dashboard/dashboard_clone.js @@ -21,6 +21,7 @@ import expect from '@kbn/expect'; export default function({ getService, getPageObjects }) { const retry = getService('retry'); + const listingTable = getService('listingTable'); const PageObjects = getPageObjects(['dashboard', 'header', 'common']); describe('dashboard clone', function describeIndexTests() { @@ -40,10 +41,12 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.clickClone(); await PageObjects.dashboard.confirmClone(); - - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + await PageObjects.dashboard.gotoDashboardLandingPage(); + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', clonedDashboardName ); + expect(countOfDashboards).to.equal(1); }); @@ -70,8 +73,10 @@ export default function({ getService, getPageObjects }) { it("and doesn't save", async () => { await PageObjects.dashboard.cancelClone(); + await PageObjects.dashboard.gotoDashboardLandingPage(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName ); expect(countOfDashboards).to.equal(1); @@ -85,8 +90,10 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.expectDuplicateTitleWarningDisplayed({ displayed: true }); await PageObjects.dashboard.confirmClone(); await PageObjects.dashboard.waitForRenderComplete(); + await PageObjects.dashboard.gotoDashboardLandingPage(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName + ' Copy' ); expect(countOfDashboards).to.equal(2); diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js index 5dcb18374c51f7..6d2a30fa85325d 100644 --- a/test/functional/apps/dashboard/dashboard_filter_bar.js +++ b/test/functional/apps/dashboard/dashboard_filter_bar.js @@ -27,7 +27,7 @@ export default function({ getService, getPageObjects }) { const pieChart = getService('pieChart'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize']); + const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'timePicker']); describe('dashboard filter bar', () => { before(async () => { @@ -91,7 +91,7 @@ export default function({ getService, getPageObjects }) { await filterBar.ensureFieldEditorModalIsClosed(); await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.timePicker.setDefaultDataRange(); }); it('are not selected by default', async function() { @@ -136,7 +136,7 @@ export default function({ getService, getPageObjects }) { await filterBar.ensureFieldEditorModalIsClosed(); await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.timePicker.setDefaultDataRange(); }); it('are added when a cell magnifying glass is clicked', async function() { diff --git a/test/functional/apps/dashboard/dashboard_filtering.js b/test/functional/apps/dashboard/dashboard_filtering.js index bd31bb010f2609..1cb9f1490d4427 100644 --- a/test/functional/apps/dashboard/dashboard_filtering.js +++ b/test/functional/apps/dashboard/dashboard_filtering.js @@ -34,7 +34,7 @@ export default function({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const dashboardPanelActions = getService('dashboardPanelActions'); - const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize']); + const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'timePicker']); describe('dashboard filtering', function() { this.tags('smoke'); @@ -52,7 +52,7 @@ export default function({ getService, getPageObjects }) { describe('adding a filter that excludes all data', () => { before(async () => { await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.timePicker.setDefaultDataRange(); await dashboardAddPanel.addEveryVisualization('"Filter Bytes Test"'); await dashboardAddPanel.addEverySavedSearch('"Filter Bytes Test"'); @@ -234,7 +234,7 @@ export default function({ getService, getPageObjects }) { it('visualization saved with a query filters data', async () => { await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.timePicker.setDefaultDataRange(); await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie'); await PageObjects.header.waitUntilLoadingHasFinished(); diff --git a/test/functional/apps/dashboard/dashboard_listing.js b/test/functional/apps/dashboard/dashboard_listing.js index 179f10223afb2e..e3e835109da2cd 100644 --- a/test/functional/apps/dashboard/dashboard_listing.js +++ b/test/functional/apps/dashboard/dashboard_listing.js @@ -22,6 +22,7 @@ import expect from '@kbn/expect'; export default function({ getService, getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'header', 'common']); const browser = getService('browser'); + const listingTable = getService('listingTable'); describe('dashboard listing page', function describeIndexTests() { const dashboardName = 'Dashboard Listing Test'; @@ -41,7 +42,8 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.saveDashboard(dashboardName); await PageObjects.dashboard.gotoDashboardLandingPage(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName ); expect(countOfDashboards).to.equal(1); @@ -53,7 +55,8 @@ export default function({ getService, getPageObjects }) { }); it('is not shown when there are no dashboards shown during a search', async function() { - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', 'gobeldeguck' ); expect(countOfDashboards).to.equal(0); @@ -65,9 +68,9 @@ export default function({ getService, getPageObjects }) { describe('delete', function() { it('default confirm action is cancel', async function() { - await PageObjects.dashboard.searchForDashboardWithName(dashboardName); - await PageObjects.dashboard.checkDashboardListingSelectAllCheckbox(); - await PageObjects.dashboard.clickDeleteSelectedDashboards(); + await listingTable.searchForItemWithName(dashboardName); + await listingTable.checkListingSelectAllCheckbox(); + await listingTable.clickDeleteSelected(); await PageObjects.common.expectConfirmModalOpenState(true); @@ -75,19 +78,21 @@ export default function({ getService, getPageObjects }) { await PageObjects.common.expectConfirmModalOpenState(false); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName ); expect(countOfDashboards).to.equal(1); }); it('succeeds on confirmation press', async function() { - await PageObjects.dashboard.checkDashboardListingSelectAllCheckbox(); - await PageObjects.dashboard.clickDeleteSelectedDashboards(); + await listingTable.checkListingSelectAllCheckbox(); + await listingTable.clickDeleteSelected(); await PageObjects.common.clickConfirmOnModal(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName ); expect(countOfDashboards).to.equal(0); @@ -96,44 +101,45 @@ export default function({ getService, getPageObjects }) { describe('search', function() { before(async () => { - await PageObjects.dashboard.clearSearchValue(); + await listingTable.clearSearchFilter(); await PageObjects.dashboard.clickNewDashboard(); await PageObjects.dashboard.saveDashboard('Two Words'); + await PageObjects.dashboard.gotoDashboardLandingPage(); }); it('matches on the first word', async function() { - await PageObjects.dashboard.searchForDashboardWithName('Two'); - const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + await listingTable.searchForItemWithName('Two'); + const countOfDashboards = await listingTable.getItemsCount('dashboard'); expect(countOfDashboards).to.equal(1); }); it('matches the second word', async function() { - await PageObjects.dashboard.searchForDashboardWithName('Words'); - const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + await listingTable.searchForItemWithName('Words'); + const countOfDashboards = await listingTable.getItemsCount('dashboard'); expect(countOfDashboards).to.equal(1); }); it('matches the second word prefix', async function() { - await PageObjects.dashboard.searchForDashboardWithName('Wor'); - const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + await listingTable.searchForItemWithName('Wor'); + const countOfDashboards = await listingTable.getItemsCount('dashboard'); expect(countOfDashboards).to.equal(1); }); it('does not match mid word', async function() { - await PageObjects.dashboard.searchForDashboardWithName('ords'); - const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + await listingTable.searchForItemWithName('ords'); + const countOfDashboards = await listingTable.getItemsCount('dashboard'); expect(countOfDashboards).to.equal(0); }); it('is case insensitive', async function() { - await PageObjects.dashboard.searchForDashboardWithName('two words'); - const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + await listingTable.searchForItemWithName('two words'); + const countOfDashboards = await listingTable.getItemsCount('dashboard'); expect(countOfDashboards).to.equal(1); }); it('is using AND operator', async function() { - await PageObjects.dashboard.searchForDashboardWithName('three words'); - const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable(); + await listingTable.searchForItemWithName('three words'); + const countOfDashboards = await listingTable.getItemsCount('dashboard'); expect(countOfDashboards).to.equal(0); }); }); @@ -176,7 +182,7 @@ export default function({ getService, getPageObjects }) { }); it('preloads search filter bar when there is no match', async function() { - const searchFilter = await PageObjects.dashboard.getSearchFilterValue(); + const searchFilter = await listingTable.getSearchFilterValue(); expect(searchFilter).to.equal('"nodashboardsnamedme"'); }); @@ -196,7 +202,7 @@ export default function({ getService, getPageObjects }) { }); it('preloads search filter bar when there is more than one match', async function() { - const searchFilter = await PageObjects.dashboard.getSearchFilterValue(); + const searchFilter = await listingTable.getSearchFilterValue(); expect(searchFilter).to.equal('"two words"'); }); diff --git a/test/functional/apps/dashboard/dashboard_save.js b/test/functional/apps/dashboard/dashboard_save.js index 23bb784c79cd0b..2ea1389b89ad43 100644 --- a/test/functional/apps/dashboard/dashboard_save.js +++ b/test/functional/apps/dashboard/dashboard_save.js @@ -19,8 +19,9 @@ import expect from '@kbn/expect'; -export default function({ getPageObjects }) { +export default function({ getPageObjects, getService }) { const PageObjects = getPageObjects(['dashboard', 'header']); + const listingTable = getService('listingTable'); describe('dashboard save', function describeIndexTests() { this.tags('smoke'); @@ -47,8 +48,10 @@ export default function({ getPageObjects }) { it('does not save on reject confirmation', async function() { await PageObjects.dashboard.cancelSave(); + await PageObjects.dashboard.gotoDashboardLandingPage(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName ); expect(countOfDashboards).to.equal(1); @@ -68,15 +71,17 @@ export default function({ getPageObjects }) { // wait till it finishes reloading or it might reload the url after simulating the // dashboard landing page click. await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.gotoDashboardLandingPage(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardName ); expect(countOfDashboards).to.equal(2); }); it('Does not warn when you save an existing dashboard with the title it already has, and that title is a duplicate', async function() { - await PageObjects.dashboard.selectDashboard(dashboardName); + await listingTable.clickItemLink('dashboard', dashboardName); await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); await PageObjects.dashboard.switchToEditMode(); await PageObjects.dashboard.saveDashboard(dashboardName); @@ -121,8 +126,10 @@ export default function({ getPageObjects }) { // wait till it finishes reloading or it might reload the url after simulating the // dashboard landing page click. await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.gotoDashboardLandingPage(); - const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName( + const countOfDashboards = await listingTable.searchAndGetItemsCount( + 'dashboard', dashboardNameEnterKey ); expect(countOfDashboards).to.equal(1); diff --git a/test/functional/apps/dashboard/dashboard_snapshots.js b/test/functional/apps/dashboard/dashboard_snapshots.js index 9900881e4690d9..3a09b46a713cc1 100644 --- a/test/functional/apps/dashboard/dashboard_snapshots.js +++ b/test/functional/apps/dashboard/dashboard_snapshots.js @@ -20,7 +20,7 @@ import expect from '@kbn/expect'; export default function({ getService, getPageObjects, updateBaselines }) { - const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common']); + const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common', 'timePicker']); const screenshot = getService('screenshots'); const browser = getService('browser'); const esArchiver = getService('esArchiver'); @@ -48,7 +48,7 @@ export default function({ getService, getPageObjects, updateBaselines }) { it('compare TSVB snapshot', async () => { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInLogstashDataRange(); + await PageObjects.timePicker.setLogstashDataRange(); await dashboardAddPanel.addVisualization('Rendering Test: tsvb-ts'); await PageObjects.common.closeToast(); @@ -71,7 +71,7 @@ export default function({ getService, getPageObjects, updateBaselines }) { it('compare area chart snapshot', async () => { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInLogstashDataRange(); + await PageObjects.timePicker.setLogstashDataRange(); await dashboardAddPanel.addVisualization('Rendering Test: area with not filter'); await PageObjects.common.closeToast(); diff --git a/test/functional/apps/dashboard/dashboard_state.js b/test/functional/apps/dashboard/dashboard_state.js index 3b9e404e9b94d1..b9172990c501dc 100644 --- a/test/functional/apps/dashboard/dashboard_state.js +++ b/test/functional/apps/dashboard/dashboard_state.js @@ -34,6 +34,7 @@ export default function({ getService, getPageObjects }) { 'discover', 'tileMap', 'visChart', + 'timePicker', ]); const testSubjects = getService('testSubjects'); const browser = getService('browser'); @@ -58,7 +59,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await dashboardAddPanel.addVisualization(AREA_CHART_VIS_NAME); await PageObjects.dashboard.saveDashboard('Overridden colors'); @@ -83,7 +84,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.header.clickDiscover(); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await PageObjects.discover.clickFieldListItemAdd('bytes'); await PageObjects.discover.saveSearch('my search'); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -147,7 +148,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await dashboardAddPanel.addVisualization('Visualization TileMap'); await PageObjects.dashboard.saveDashboard('No local edits'); diff --git a/test/functional/apps/dashboard/dashboard_time_picker.js b/test/functional/apps/dashboard/dashboard_time_picker.js index 0b73bc224ab742..b99de9fee6db19 100644 --- a/test/functional/apps/dashboard/dashboard_time_picker.js +++ b/test/functional/apps/dashboard/dashboard_time_picker.js @@ -44,7 +44,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); await pieChart.expectPieSliceCount(0); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await pieChart.expectPieSliceCount(10); }); @@ -95,7 +95,7 @@ export default function({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); - // Same date range as `setTimepickerInHistoricalDataRange` + // Same date range as `timePicker.setHistoricalDataRange()` await PageObjects.timePicker.setAbsoluteRange( '2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000' diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js index 683f3683e65e51..f30f58913bd970 100644 --- a/test/functional/apps/dashboard/panel_controls.js +++ b/test/functional/apps/dashboard/panel_controls.js @@ -33,7 +33,13 @@ export default function({ getService, getPageObjects }) { const dashboardReplacePanel = getService('dashboardReplacePanel'); const dashboardVisualizations = getService('dashboardVisualizations'); const renderable = getService('renderable'); - const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'discover']); + const PageObjects = getPageObjects([ + 'dashboard', + 'header', + 'visualize', + 'discover', + 'timePicker', + ]); const dashboardName = 'Dashboard Panel Controls Test'; describe('dashboard panel controls', function viewEditModeTests() { @@ -52,7 +58,7 @@ export default function({ getService, getPageObjects }) { let intialDimensions; before(async () => { await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); await dashboardAddPanel.addVisualization(LINE_CHART_VIS_NAME); intialDimensions = await PageObjects.dashboard.getPanelDimensions(); @@ -110,7 +116,7 @@ export default function({ getService, getPageObjects }) { describe('panel edit controls', function() { before(async () => { await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); }); diff --git a/test/functional/apps/dashboard/view_edit.js b/test/functional/apps/dashboard/view_edit.js index 212044d898251a..a0b972f3ab63c2 100644 --- a/test/functional/apps/dashboard/view_edit.js +++ b/test/functional/apps/dashboard/view_edit.js @@ -68,7 +68,7 @@ export default function({ getService, getPageObjects }) { }); it('when time changed is stored with dashboard', async function() { - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.timePicker.setDefaultDataRange(); const originalTime = await PageObjects.timePicker.getTimeConfig(); @@ -196,7 +196,7 @@ export default function({ getService, getPageObjects }) { describe('and preserves edits on cancel', function() { it('when time changed is stored with dashboard', async function() { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.timePicker.setDefaultDataRange(); await PageObjects.dashboard.saveDashboard(dashboardName, true); await PageObjects.dashboard.switchToEditMode(); await PageObjects.timePicker.setAbsoluteRange( diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.ts similarity index 60% rename from test/functional/page_objects/dashboard_page.js rename to test/functional/page_objects/dashboard_page.ts index b0f1a3304a9b8e..af0a0160a81d80 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.ts @@ -17,89 +17,85 @@ * under the License. */ -import _ from 'lodash'; import { DashboardConstants } from '../../../src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_constants'; export const PIE_CHART_VIS_NAME = 'Visualization PieChart'; export const AREA_CHART_VIS_NAME = 'Visualization漢字 AreaChart'; export const LINE_CHART_VIS_NAME = 'Visualization漢字 LineChart'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function DashboardPageProvider({ getService, getPageObjects }) { +export function DashboardPageProvider({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const find = getService('find'); const retry = getService('retry'); - const config = getService('config'); const browser = getService('browser'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const testSubjects = getService('testSubjects'); const dashboardAddPanel = getService('dashboardAddPanel'); const renderable = getService('renderable'); - const PageObjects = getPageObjects(['common', 'header', 'settings', 'visualize', 'timePicker']); - - const defaultFindTimeout = config.get('timeouts.find'); + const listingTable = getService('listingTable'); + const PageObjects = getPageObjects(['common', 'header', 'visualize']); + + interface SaveDashboardOptions { + waitDialogIsClosed: boolean; + needsConfirm?: boolean; + storeTimeWithDashboard?: boolean; + saveAsNew?: boolean; + } class DashboardPage { async initTests({ kibanaIndex = 'dashboard/legacy', defaultIndex = 'logstash-*' } = {}) { log.debug('load kibana index with visualizations and log data'); await esArchiver.load(kibanaIndex); - await kibanaServer.uiSettings.replace({ - defaultIndex: defaultIndex, - }); + await kibanaServer.uiSettings.replace({ defaultIndex }); await PageObjects.common.navigateToApp('dashboard'); } - async preserveCrossAppState() { + public async preserveCrossAppState() { const url = await browser.getCurrentUrl(); await browser.get(url, false); await PageObjects.header.waitUntilLoadingHasFinished(); } - async selectDefaultIndex(indexName) { - await PageObjects.settings.navigateTo(); - await PageObjects.settings.clickKibanaIndexPatterns(); - await find.clickByPartialLinkText(indexName); - await PageObjects.settings.clickDefaultIndexButton(); - } - - async clickFullScreenMode() { + public async clickFullScreenMode() { log.debug(`clickFullScreenMode`); await testSubjects.click('dashboardFullScreenMode'); await testSubjects.exists('exitFullScreenModeLogo'); await this.waitForRenderComplete(); } - async fullScreenModeMenuItemExists() { + public async fullScreenModeMenuItemExists() { return await testSubjects.exists('dashboardFullScreenMode'); } - async exitFullScreenTextButtonExists() { + public async exitFullScreenTextButtonExists() { return await testSubjects.exists('exitFullScreenModeText'); } - async getExitFullScreenTextButton() { + public async getExitFullScreenTextButton() { return await testSubjects.find('exitFullScreenModeText'); } - async exitFullScreenLogoButtonExists() { + public async exitFullScreenLogoButtonExists() { return await testSubjects.exists('exitFullScreenModeLogo'); } - async getExitFullScreenLogoButton() { + public async getExitFullScreenLogoButton() { return await testSubjects.find('exitFullScreenModeLogo'); } - async clickExitFullScreenLogoButton() { + public async clickExitFullScreenLogoButton() { await testSubjects.click('exitFullScreenModeLogo'); await this.waitForRenderComplete(); } - async clickExitFullScreenTextButton() { + public async clickExitFullScreenTextButton() { await testSubjects.click('exitFullScreenModeText'); await this.waitForRenderComplete(); } - async getDashboardIdFromCurrentUrl() { + public async getDashboardIdFromCurrentUrl() { const currentUrl = await browser.getCurrentUrl(); const urlSubstring = 'kibana#/dashboard/'; const startOfIdIndex = currentUrl.indexOf(urlSubstring) + urlSubstring.length; @@ -115,25 +111,25 @@ export function DashboardPageProvider({ getService, getPageObjects }) { * Returns true if already on the dashboard landing page (that page doesn't have a link to itself). * @returns {Promise} */ - async onDashboardLandingPage() { + public async onDashboardLandingPage() { log.debug(`onDashboardLandingPage`); return await testSubjects.exists('dashboardLandingPage', { timeout: 5000, }); } - async expectExistsDashboardLandingPage() { + public async expectExistsDashboardLandingPage() { log.debug(`expectExistsDashboardLandingPage`); await testSubjects.existOrFail('dashboardLandingPage'); } - async clickDashboardBreadcrumbLink() { + public async clickDashboardBreadcrumbLink() { log.debug('clickDashboardBreadcrumbLink'); await find.clickByCssSelector(`a[href="#${DashboardConstants.LANDING_PAGE_PATH}"]`); await this.expectExistsDashboardLandingPage(); } - async gotoDashboardLandingPage() { + public async gotoDashboardLandingPage() { log.debug('gotoDashboardLandingPage'); const onPage = await this.onDashboardLandingPage(); if (!onPage) { @@ -141,26 +137,26 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } } - async clickClone() { + public async clickClone() { log.debug('Clicking clone'); await testSubjects.click('dashboardClone'); } - async getCloneTitle() { + public async getCloneTitle() { return await testSubjects.getAttribute('clonedDashboardTitle', 'value'); } - async confirmClone() { + public async confirmClone() { log.debug('Confirming clone'); await testSubjects.click('cloneConfirmButton'); } - async cancelClone() { + public async cancelClone() { log.debug('Canceling clone'); await testSubjects.click('cloneCancelButton'); } - async setClonedDashboardTitle(title) { + public async setClonedDashboardTitle(title: string) { await testSubjects.setValue('clonedDashboardTitle', title); } @@ -168,7 +164,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { * Asserts that the duplicate title warning is either displayed or not displayed. * @param { displayed: boolean } */ - async expectDuplicateTitleWarningDisplayed({ displayed }) { + public async expectDuplicateTitleWarningDisplayed({ displayed = true }) { if (displayed) { await testSubjects.existOrFail('titleDupicateWarnMsg'); } else { @@ -180,18 +176,16 @@ export function DashboardPageProvider({ getService, getPageObjects }) { * Asserts that the toolbar pagination (count and arrows) is either displayed or not displayed. * @param { displayed: boolean } */ - async expectToolbarPaginationDisplayed({ displayed }) { + public async expectToolbarPaginationDisplayed({ displayed = true }) { const subjects = ['btnPrevPage', 'btnNextPage', 'toolBarPagerText']; if (displayed) { - return await Promise.all(subjects.map(async subj => await testSubjects.existOrFail(subj))); + await Promise.all(subjects.map(async subj => await testSubjects.existOrFail(subj))); } else { - return await Promise.all( - subjects.map(async subj => await testSubjects.missingOrFail(subj)) - ); + await Promise.all(subjects.map(async subj => await testSubjects.missingOrFail(subj))); } } - async switchToEditMode() { + public async switchToEditMode() { log.debug('Switching to edit mode'); await testSubjects.click('dashboardEditMode'); // wait until the count of dashboard panels equals the count of toggle menu icons @@ -204,66 +198,34 @@ export function DashboardPageProvider({ getService, getPageObjects }) { }); } - async getIsInViewMode() { + public async getIsInViewMode() { log.debug('getIsInViewMode'); return await testSubjects.exists('dashboardEditMode'); } - async clickCancelOutOfEditMode() { + public async clickCancelOutOfEditMode() { log.debug('clickCancelOutOfEditMode'); - return await testSubjects.click('dashboardViewOnlyMode'); + await testSubjects.click('dashboardViewOnlyMode'); } - async clickNewDashboard() { - // One or the other will eventually show up on the landing page, depending on whether there are - // dashboards. - await retry.try(async () => { - const createNewItemButtonExists = await testSubjects.exists('newItemButton'); - if (createNewItemButtonExists) { - return await testSubjects.click('newItemButton'); - } - const createNewItemPromptExists = await this.getCreateDashboardPromptExists(); - if (createNewItemPromptExists) { - return await this.clickCreateDashboardPrompt(); - } - - throw new Error( - 'Page is still loading... waiting for create new prompt or button to appear' - ); - }); + public async clickNewDashboard() { + await listingTable.clickNewButton('createDashboardPromptButton'); } - async clickCreateDashboardPrompt() { + public async clickCreateDashboardPrompt() { await testSubjects.click('createDashboardPromptButton'); } - async getCreateDashboardPromptExists() { + public async getCreateDashboardPromptExists() { return await testSubjects.exists('createDashboardPromptButton'); } - async checkDashboardListingRow(id) { - await testSubjects.click(`checkboxSelectRow-${id}`); - } - - async checkDashboardListingSelectAllCheckbox() { - const element = await testSubjects.find('checkboxSelectAll'); - const isSelected = await element.isSelected(); - if (!isSelected) { - log.debug(`checking checkbox "checkboxSelectAll"`); - await testSubjects.click('checkboxSelectAll'); - } - } - - async clickDeleteSelectedDashboards() { - await testSubjects.click('deleteSelectedItems'); - } - - async isOptionsOpen() { + public async isOptionsOpen() { log.debug('isOptionsOpen'); return await testSubjects.exists('dashboardOptionsMenu'); } - async openOptions() { + public async openOptions() { log.debug('openOptions'); const isOpen = await this.isOptionsOpen(); if (!isOpen) { @@ -272,36 +234,36 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } // avoids any 'Object with id x not found' errors when switching tests. - async clearSavedObjectsFromAppLinks() { + public async clearSavedObjectsFromAppLinks() { await PageObjects.header.clickVisualize(); await PageObjects.visualize.gotoLandingPage(); await PageObjects.header.clickDashboard(); await this.gotoDashboardLandingPage(); } - async isMarginsOn() { + public async isMarginsOn() { log.debug('isMarginsOn'); await this.openOptions(); return await testSubjects.getAttribute('dashboardMarginsCheckbox', 'checked'); } - async useMargins(on = true) { + public async useMargins(on = true) { await this.openOptions(); const isMarginsOn = await this.isMarginsOn(); - if (isMarginsOn !== on) { + if (isMarginsOn !== 'on') { return await testSubjects.click('dashboardMarginsCheckbox'); } } - async gotoDashboardEditMode(dashboardName) { + public async gotoDashboardEditMode(dashboardName: string) { await this.loadSavedDashboard(dashboardName); await this.switchToEditMode(); } - async renameDashboard(dashName) { - log.debug(`Naming dashboard ` + dashName); + public async renameDashboard(dashboardName: string) { + log.debug(`Naming dashboard ` + dashboardName); await testSubjects.click('dashboardRenameButton'); - await testSubjects.setValue('savedObjectTitle', dashName); + await testSubjects.setValue('savedObjectTitle', dashboardName); } /** @@ -309,11 +271,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) { * verify that the save was successful, close the toast and return the * toast message * - * @param dashName {String} + * @param dashboardName {String} * @param saveOptions {{storeTimeWithDashboard: boolean, saveAsNew: boolean, needsConfirm: false, waitDialogIsClosed: boolean }} */ - async saveDashboard(dashName, saveOptions = { waitDialogIsClosed: true }) { - await this.enterDashboardTitleAndClickSave(dashName, saveOptions); + public async saveDashboard( + dashboardName: string, + saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true } + ) { + await this.enterDashboardTitleAndClickSave(dashboardName, saveOptions); if (saveOptions.needsConfirm) { await this.clickSave(); @@ -328,37 +293,24 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return message; } - async deleteDashboard(dashboardName, dashboardId) { - await this.gotoDashboardLandingPage(); - await this.searchForDashboardWithName(dashboardName); - await this.checkDashboardListingRow(dashboardId); - await this.clickDeleteSelectedDashboards(); - await PageObjects.common.clickConfirmOnModal(); - } - - async cancelSave() { + public async cancelSave() { log.debug('Canceling save'); await testSubjects.click('saveCancelButton'); } - async clickSave() { + public async clickSave() { log.debug('DashboardPage.clickSave'); await testSubjects.click('confirmSaveSavedObjectButton'); } - async pressEnterKey() { - log.debug('DashboardPage.pressEnterKey'); - await PageObjects.common.pressEnterKey(); - } - /** * * @param dashboardTitle {String} * @param saveOptions {{storeTimeWithDashboard: boolean, saveAsNew: boolean, waitDialogIsClosed: boolean}} */ - async enterDashboardTitleAndClickSave( - dashboardTitle, - saveOptions = { waitDialogIsClosed: true } + public async enterDashboardTitleAndClickSave( + dashboardTitle: string, + saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true } ) { await testSubjects.click('dashboardSaveMenuItem'); const modalDialog = await testSubjects.find('savedObjectSaveModal'); @@ -380,128 +332,66 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } } - async ensureDuplicateTitleCallout() { + public async ensureDuplicateTitleCallout() { await testSubjects.existOrFail('titleDupicateWarnMsg'); } /** * @param dashboardTitle {String} */ - async enterDashboardTitleAndPressEnter(dashboardTitle) { + public async enterDashboardTitleAndPressEnter(dashboardTitle: string) { await testSubjects.click('dashboardSaveMenuItem'); const modalDialog = await testSubjects.find('savedObjectSaveModal'); log.debug('entering new title'); await testSubjects.setValue('savedObjectTitle', dashboardTitle); - await this.pressEnterKey(); + await PageObjects.common.pressEnterKey(); await testSubjects.waitForDeleted(modalDialog); } - async selectDashboard(dashName) { - await testSubjects.click(`dashboardListingTitleLink-${dashName.split(' ').join('-')}`); - } - - async clearSearchValue() { - log.debug(`clearSearchValue`); - - await this.gotoDashboardLandingPage(); - - await retry.try(async () => { - const searchFilter = await this.getSearchFilter(); - await searchFilter.clearValue(); - await PageObjects.common.pressEnterKey(); - }); - } - - async getSearchFilterValue() { - const searchFilter = await this.getSearchFilter(); - return await searchFilter.getAttribute('value'); - } - - async getSearchFilter() { - const searchFilter = await find.allByCssSelector('.euiFieldSearch'); - return searchFilter[0]; - } - - async searchForDashboardWithName(dashName) { - log.debug(`searchForDashboardWithName: ${dashName}`); - - await this.gotoDashboardLandingPage(); - - await retry.try(async () => { - const searchFilter = await this.getSearchFilter(); - await searchFilter.clearValue(); - await searchFilter.click(); - // Note: this replacement of - to space is to preserve original logic but I'm not sure why or if it's needed. - await searchFilter.type(dashName.replace('-', ' ')); - await PageObjects.common.pressEnterKey(); - await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 5000); - }); - - await PageObjects.header.waitUntilLoadingHasFinished(); - } - - async getCountOfDashboardsInListingTable() { - const dashboardTitles = await find.allByCssSelector( - '[data-test-subj^="dashboardListingTitleLink"]' - ); - return dashboardTitles.length; - } - - async getDashboardCountWithName(dashName) { - log.debug(`getDashboardCountWithName: ${dashName}`); - - await this.searchForDashboardWithName(dashName); - const links = await testSubjects.findAll( - `dashboardListingTitleLink-${dashName.replace(/ /g, '-')}` - ); - return links.length; - } - // use the search filter box to narrow the results down to a single // entry, or at least to a single page of results - async loadSavedDashboard(dashName) { - log.debug(`Load Saved Dashboard ${dashName}`); + public async loadSavedDashboard(dashboardName: string) { + log.debug(`Load Saved Dashboard ${dashboardName}`); await this.gotoDashboardLandingPage(); - await this.searchForDashboardWithName(dashName); + await listingTable.searchForItemWithName(dashboardName); await retry.try(async () => { - await this.selectDashboard(dashName); + await listingTable.clickItemLink('dashboard', dashboardName); await PageObjects.header.waitUntilLoadingHasFinished(); // check Dashboard landing page is not present await testSubjects.missingOrFail('dashboardLandingPage', { timeout: 10000 }); }); } - async getPanelTitles() { + public async getPanelTitles() { log.debug('in getPanelTitles'); const titleObjects = await testSubjects.findAll('dashboardPanelTitle'); return await Promise.all(titleObjects.map(async title => await title.getVisibleText())); } - async getPanelDimensions() { + public async getPanelDimensions() { const panels = await find.allByCssSelector('.react-grid-item'); // These are gridster-defined elements and classes - async function getPanelDimensions(panel) { - const size = await panel.getSize(); - return { - width: size.width, - height: size.height, - }; - } - - const getDimensionsPromises = _.map(panels, getPanelDimensions); - return await Promise.all(getDimensionsPromises); + return await Promise.all( + panels.map(async panel => { + const size = await panel.getSize(); + return { + width: size.width, + height: size.height, + }; + }) + ); } - async getPanelCount() { + public async getPanelCount() { log.debug('getPanelCount'); const panels = await testSubjects.findAll('embeddablePanel'); return panels.length; } - getTestVisualizations() { + public getTestVisualizations() { return [ { name: PIE_CHART_VIS_NAME, description: 'PieChart' }, { name: 'Visualization☺ VerticalBarChart', description: 'VerticalBarChart' }, @@ -513,69 +403,45 @@ export function DashboardPageProvider({ getService, getPageObjects }) { ]; } - getTestVisualizationNames() { + public getTestVisualizationNames() { return this.getTestVisualizations().map(visualization => visualization.name); } - getTestVisualizationDescriptions() { + public getTestVisualizationDescriptions() { return this.getTestVisualizations().map(visualization => visualization.description); } - async getDashboardPanels() { + public async getDashboardPanels() { return await testSubjects.findAll('embeddablePanel'); } - async addVisualizations(visualizations) { + public async addVisualizations(visualizations: string[]) { await dashboardAddPanel.addVisualizations(visualizations); } - async setTimepickerInHistoricalDataRange() { - await PageObjects.timePicker.setDefaultAbsoluteRange(); - } - - async setTimepickerInDataRange() { - const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; - const toTime = 'Apr 13, 2018 @ 00:00:00.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); - } - - async setTimepickerInLogstashDataRange() { - const fromTime = 'Apr 9, 2018 @ 00:00:00.000'; - const toTime = 'Apr 13, 2018 @ 00:00:00.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); - } - - async setSaveAsNewCheckBox(checked) { + public async setSaveAsNewCheckBox(checked: boolean) { log.debug('saveAsNewCheckbox: ' + checked); - const saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox'); + let saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox'); const isAlreadyChecked = (await saveAsNewCheckbox.getAttribute('aria-checked')) === 'true'; if (isAlreadyChecked !== checked) { log.debug('Flipping save as new checkbox'); - const saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox'); + saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox'); await retry.try(() => saveAsNewCheckbox.click()); } } - async setStoreTimeWithDashboard(checked) { + public async setStoreTimeWithDashboard(checked: boolean) { log.debug('Storing time with dashboard: ' + checked); - const storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard'); + let storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard'); const isAlreadyChecked = (await storeTimeCheckbox.getAttribute('aria-checked')) === 'true'; if (isAlreadyChecked !== checked) { log.debug('Flipping store time checkbox'); - const storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard'); + storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard'); await retry.try(() => storeTimeCheckbox.click()); } } - async getFilterDescriptions(timeout = defaultFindTimeout) { - const filters = await find.allByCssSelector( - '.filter-bar > .filter > .filter-description', - timeout - ); - return _.map(filters, async filter => await filter.getVisibleText()); - } - - async getSharedItemsCount() { + public async getSharedItemsCount() { log.debug('in getSharedItemsCount'); const attributeName = 'data-shared-items-count'; const element = await find.byCssSelector(`[${attributeName}]`); @@ -586,13 +452,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) { throw new Error('no element'); } - async waitForRenderComplete() { + public async waitForRenderComplete() { log.debug('waitForRenderComplete'); const count = await this.getSharedItemsCount(); + // eslint-disable-next-line radix await renderable.waitForRender(parseInt(count)); } - async getSharedContainerData() { + public async getSharedContainerData() { log.debug('getSharedContainerData'); const sharedContainer = await find.byCssSelector('[data-shared-items-container]'); return { @@ -602,7 +469,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { }; } - async getPanelSharedItemData() { + public async getPanelSharedItemData() { log.debug('in getPanelSharedItemData'); const sharedItems = await find.allByCssSelector('[data-shared-item]'); return await Promise.all( @@ -615,17 +482,17 @@ export function DashboardPageProvider({ getService, getPageObjects }) { ); } - async checkHideTitle() { + public async checkHideTitle() { log.debug('ensure that you can click on hide title checkbox'); await this.openOptions(); return await testSubjects.click('dashboardPanelTitlesCheckbox'); } - async expectMissingSaveOption() { + public async expectMissingSaveOption() { await testSubjects.missingOrFail('dashboardSaveMenuItem'); } - async getNotLoadedVisualizations(vizList) { + public async getNotLoadedVisualizations(vizList: string[]) { const checkList = []; for (const name of vizList) { const isPresent = await testSubjects.exists( diff --git a/test/functional/page_objects/index.ts b/test/functional/page_objects/index.ts index 5526243ea2bbde..4ba8ddb0359132 100644 --- a/test/functional/page_objects/index.ts +++ b/test/functional/page_objects/index.ts @@ -22,7 +22,6 @@ import { CommonPageProvider } from './common_page'; import { ConsolePageProvider } from './console_page'; // @ts-ignore not TS yet import { ContextPageProvider } from './context_page'; -// @ts-ignore not TS yet import { DashboardPageProvider } from './dashboard_page'; // @ts-ignore not TS yet import { DiscoverPageProvider } from './discover_page'; diff --git a/test/functional/page_objects/time_picker.js b/test/functional/page_objects/time_picker.js index 8717517f448648..7c676784294784 100644 --- a/test/functional/page_objects/time_picker.js +++ b/test/functional/page_objects/time_picker.js @@ -264,6 +264,22 @@ export function TimePickerPageProvider({ getService, getPageObjects }) { await this.closeQuickSelectTimeMenu(); } + + async setHistoricalDataRange() { + await this.setDefaultAbsoluteRange(); + } + + async setDefaultDataRange() { + const fromTime = 'Jan 1, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; + await this.setAbsoluteRange(fromTime, toTime); + } + + async setLogstashDataRange() { + const fromTime = 'Apr 9, 2018 @ 00:00:00.000'; + const toTime = 'Apr 13, 2018 @ 00:00:00.000'; + await this.setAbsoluteRange(fromTime, toTime); + } } return new TimePickerPage(); diff --git a/test/functional/page_objects/visualize_page.ts b/test/functional/page_objects/visualize_page.ts index 4ba64ea771effe..0071b8d993f706 100644 --- a/test/functional/page_objects/visualize_page.ts +++ b/test/functional/page_objects/visualize_page.ts @@ -44,15 +44,7 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide } public async clickNewVisualization() { - // newItemButton button is only visible when there are items in the listing table is displayed. - let exists = await testSubjects.exists('newItemButton'); - if (exists) { - return await testSubjects.click('newItemButton'); - } - - exists = await testSubjects.exists('createVisualizationPromptButton'); - // no viz exist, click createVisualizationPromptButton to create new dashboard - return await this.createVisualizationPromptButton(); + await listingTable.clickNewButton('createVisualizationPromptButton'); } public async createVisualizationPromptButton() { diff --git a/test/functional/services/dashboard/visualizations.js b/test/functional/services/dashboard/visualizations.js index 5e722ccce89701..f7a6fb7d2f694f 100644 --- a/test/functional/services/dashboard/visualizations.js +++ b/test/functional/services/dashboard/visualizations.js @@ -24,7 +24,14 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { const queryBar = getService('queryBar'); const testSubjects = getService('testSubjects'); const dashboardAddPanel = getService('dashboardAddPanel'); - const PageObjects = getPageObjects(['dashboard', 'visualize', 'visEditor', 'header', 'discover']); + const PageObjects = getPageObjects([ + 'dashboard', + 'visualize', + 'visEditor', + 'header', + 'discover', + 'timePicker', + ]); return new (class DashboardVisualizations { async createAndAddTSVBVisualization(name) { @@ -43,7 +50,7 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { log.debug(`createSavedSearch(${name})`); await PageObjects.header.clickDiscover(); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); if (query) { await queryBar.setQuery(query); diff --git a/test/functional/services/listing_table.ts b/test/functional/services/listing_table.ts index ec886cf694f2e4..c7667ae7b4049e 100644 --- a/test/functional/services/listing_table.ts +++ b/test/functional/services/listing_table.ts @@ -25,20 +25,35 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider const log = getService('log'); const retry = getService('retry'); const { common, header } = getPageObjects(['common', 'header']); + const prefixMap = { visualize: 'vis', dashboard: 'dashboard' }; + /** + * This class provides functions for dashboard and visualize landing pages + */ class ListingTable { - public async getSearchFilter() { + private async getSearchFilter() { const searchFilter = await find.allByCssSelector('.euiFieldSearch'); return searchFilter[0]; } - public async clearFilter() { + /** + * Returns search input value on landing page + */ + public async getSearchFilterValue() { + const searchFilter = await this.getSearchFilter(); + return await searchFilter.getAttribute('value'); + } + + /** + * Clears search input on landing page + */ + public async clearSearchFilter() { const searchFilter = await this.getSearchFilter(); await searchFilter.clearValue(); await searchFilter.click(); } - public async getAllVisualizationNamesOnCurrentPage(): Promise { + private async getAllItemsNamesOnCurrentPage(): Promise { const visualizationNames = []; const links = await find.allByCssSelector('.kuiLink'); for (let i = 0; i < links.length; i++) { @@ -48,14 +63,39 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider return visualizationNames; } + /** + * Navigates through all pages on Landing page and returns array of items names + */ + public async getAllItemsNames(): Promise { + log.debug('ListingTable.getAllItemsNames'); + let morePages = true; + let visualizationNames: string[] = []; + while (morePages) { + visualizationNames = visualizationNames.concat(await this.getAllItemsNamesOnCurrentPage()); + morePages = !((await testSubjects.getAttribute('pagerNextButton', 'disabled')) === 'true'); + if (morePages) { + await testSubjects.click('pagerNextButton'); + await header.waitUntilLoadingHasFinished(); + } + } + return visualizationNames; + } + + /** + * Returns items count on landing page + * @param appName 'visualize' | 'dashboard' + */ public async getItemsCount(appName: 'visualize' | 'dashboard'): Promise { - const prefixMap = { visualize: 'vis', dashboard: 'dashboard' }; const elements = await find.allByCssSelector( `[data-test-subj^="${prefixMap[appName]}ListingTitleLink"]` ); return elements.length; } + /** + * Types name into search field on Landing page and waits till search completed + * @param name item name + */ public async searchForItemWithName(name: string) { log.debug(`searchForItemWithName: ${name}`); @@ -71,10 +111,51 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider await header.waitUntilLoadingHasFinished(); } + /** + * Searches for item on Landing page and retruns items count that match `ListingTitleLink-${name}` pattern + * @param appName 'visualize' | 'dashboard' + * @param name item name + */ + public async searchAndGetItemsCount(appName: 'visualize' | 'dashboard', name: string) { + await this.searchForItemWithName(name); + const links = await testSubjects.findAll( + `${prefixMap[appName]}ListingTitleLink-${name.replace(/ /g, '-')}` + ); + return links.length; + } + public async clickDeleteSelected() { await testSubjects.click('deleteSelectedItems'); } + public async clickItemCheckbox(id: string) { + await testSubjects.click(`checkboxSelectRow-${id}`); + } + + /** + * Searches for item by name, selects checbox and deletes it + * @param name item name + * @param id row id + */ + public async deleteItem(name: string, id: string) { + await this.searchForItemWithName(name); + await this.clickItemCheckbox(id); + await this.clickDeleteSelected(); + await common.clickConfirmOnModal(); + } + + /** + * Clicks item on Landing page by link name if it is present + * @param appName 'dashboard' | 'visualize' + * @param name item name + */ + public async clickItemLink(appName: 'dashboard' | 'visualize', name: string) { + await testSubjects.click(`${appName}ListingTitleLink-${name.split(' ').join('-')}`); + } + + /** + * Checks 'SelectAll' checkbox on + */ public async checkListingSelectAllCheckbox() { const element = await testSubjects.find('checkboxSelectAll'); const isSelected = await element.isSelected(); @@ -84,21 +165,20 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider } } - public async getAllVisualizationNames(): Promise { - log.debug('ListingTable.getAllVisualizationNames'); - let morePages = true; - let visualizationNames: string[] = []; - while (morePages) { - visualizationNames = visualizationNames.concat( - await this.getAllVisualizationNamesOnCurrentPage() - ); - morePages = !((await testSubjects.getAttribute('pagerNextButton', 'disabled')) === 'true'); - if (morePages) { - await testSubjects.click('pagerNextButton'); - await header.waitUntilLoadingHasFinished(); + /** + * Clicks NewItem button on Landing page + * @param promptBtnTestSubj testSubj locator for Prompt button + */ + public async clickNewButton(promptBtnTestSubj: string): Promise { + await retry.try(async () => { + // newItemButton button is only visible when there are items in the listing table is displayed. + if (await testSubjects.exists('newItemButton')) { + await testSubjects.click('newItemButton'); + } else { + // no items exist, click createPromptButton to create new dashboard/visualization + await testSubjects.click(promptBtnTestSubj); } - } - return visualizationNames; + }); } } diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index 510a8b035f053e..bab798dacc453b 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -43,7 +43,7 @@ export default function({ getService, getPageObjects }) { await browser.setWindowSize(1600, 1000); await PageObjects.common.navigateToApp('discover'); - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await PageObjects.discover.saveSearch(savedSearchName); await PageObjects.common.navigateToApp('dashboard'); @@ -142,7 +142,7 @@ export default function({ getService, getPageObjects }) { }); it('can filter on a visualization', async () => { - await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await PageObjects.timePicker.setHistoricalDataRange(); await pieChart.filterOnPieSlice(); const filterCount = await filterBar.getFilterCount(); expect(filterCount).to.equal(1); diff --git a/x-pack/test/functional/apps/lens/lens_reporting.ts b/x-pack/test/functional/apps/lens/lens_reporting.ts index 8c742537431c86..3d70390a2de41a 100644 --- a/x-pack/test/functional/apps/lens/lens_reporting.ts +++ b/x-pack/test/functional/apps/lens/lens_reporting.ts @@ -12,6 +12,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'reporting']); const find = getService('find'); const esArchiver = getService('esArchiver'); + const listingTable = getService('listingTable'); describe('lens reporting', () => { before(async () => { @@ -24,7 +25,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { it('should not cause PDF reports to fail', async () => { await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.selectDashboard('Lens reportz'); + await listingTable.clickItemLink('dashboard', 'Lens reportz'); await PageObjects.reporting.openPdfReportingPanel(); await PageObjects.reporting.clickGenerateReportButton(); diff --git a/x-pack/test/functional/apps/spaces/spaces_selection.ts b/x-pack/test/functional/apps/spaces/spaces_selection.ts index 3d1ef40262b1dd..5af9bc135ae27c 100644 --- a/x-pack/test/functional/apps/spaces/spaces_selection.ts +++ b/x-pack/test/functional/apps/spaces/spaces_selection.ts @@ -10,6 +10,7 @@ export default function spaceSelectorFunctonalTests({ getPageObjects, }: FtrProviderContext) { const esArchiver = getService('esArchiver'); + const listingTable = getService('listingTable'); const PageObjects = getPageObjects([ 'common', 'dashboard', @@ -55,8 +56,8 @@ export default function spaceSelectorFunctonalTests({ const sampleDataHash = '/home/tutorial_directory/sampleData'; const expectDashboardRenders = async (dashName: string) => { - await PageObjects.dashboard.searchForDashboardWithName(dashName); - await PageObjects.dashboard.selectDashboard(dashName); + await listingTable.searchForItemWithName(dashName); + await listingTable.clickItemLink('dashboard', dashName); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.dashboard.waitForRenderComplete(); // throws if all items are not rendered };