diff --git a/x-pack/plugins/lens/public/visualization_container.test.tsx b/x-pack/plugins/lens/public/visualization_container.test.tsx index 7fc94ee434eb3..04a21e7740009 100644 --- a/x-pack/plugins/lens/public/visualization_container.test.tsx +++ b/x-pack/plugins/lens/public/visualization_container.test.tsx @@ -28,6 +28,18 @@ describe('VisualizationContainer', () => { expect(reportingEl.prop('data-shared-item')).toBeTruthy(); }); + test('increments counter in data attribute for each render', () => { + const component = mount(Hello!); + + let reportingEl = component.find('[data-shared-item]').first(); + expect(reportingEl.prop('data-rendering-count')).toEqual(1); + + component.setProps({ children: 'Hello2!' }); + + reportingEl = component.find('[data-shared-item]').first(); + expect(reportingEl.prop('data-rendering-count')).toEqual(2); + }); + test('renders child content', () => { const component = mount( Hello! diff --git a/x-pack/plugins/lens/public/visualization_container.tsx b/x-pack/plugins/lens/public/visualization_container.tsx index 394f228e49622..89f7f3eb0d61e 100644 --- a/x-pack/plugins/lens/public/visualization_container.tsx +++ b/x-pack/plugins/lens/public/visualization_container.tsx @@ -7,7 +7,7 @@ import './visualization_container.scss'; -import React from 'react'; +import React, { useRef } from 'react'; import classNames from 'classnames'; interface Props extends React.HTMLAttributes { @@ -28,6 +28,8 @@ export function VisualizationContainer({ className, ...rest }: Props) { + const counterRef = useRef(0); + counterRef.current++; const attributes: Partial<{ 'data-title': string; 'data-description': string }> = {}; if (reportTitle) { attributes['data-title'] = reportTitle; @@ -39,6 +41,8 @@ export function VisualizationContainer({
{ await PageObjects.lens.switchToVisualization('pie'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); const data = await PageObjects.lens.getCurrentChartDebugState(); assertMatchesExpectedData(data!); }); it.skip('should render donut chart', async () => { await PageObjects.lens.switchToVisualization('donut'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); const data = await PageObjects.lens.getCurrentChartDebugState(); assertMatchesExpectedData(data!); }); it.skip('should render treemap chart', async () => { await PageObjects.lens.switchToVisualization('treemap'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); const data = await PageObjects.lens.getCurrentChartDebugState(); assertMatchesExpectedData(data!); }); it('should render datatable', async () => { await PageObjects.lens.switchToVisualization('lnsDatatable'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); const terms = await Promise.all( range(0, 6).map((index) => PageObjects.lens.getDatatableCellText(index, 0)) ); @@ -101,7 +101,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should render metric', async () => { await PageObjects.lens.switchToVisualization('lnsMetric'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); await PageObjects.lens.assertMetric('Average of bytes', '5,727.322'); }); }); diff --git a/x-pack/test/functional/apps/lens/drag_and_drop.ts b/x-pack/test/functional/apps/lens/drag_and_drop.ts index 0e4d428c26029..5e4557057212f 100644 --- a/x-pack/test/functional/apps/lens/drag_and_drop.ts +++ b/x-pack/test/functional/apps/lens/drag_and_drop.ts @@ -54,7 +54,7 @@ export default function ({ getPageObjects }: FtrProviderContext) { it('should reorder the elements for the table', async () => { await PageObjects.lens.reorderDimensions('lnsDatatable_column', 3, 1); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect(await PageObjects.lens.getDimensionTriggersTexts('lnsDatatable_column')).to.eql([ 'Top values of @message.raw', 'Top values of clientip', @@ -224,9 +224,9 @@ export default function ({ getPageObjects }: FtrProviderContext) { await PageObjects.lens.goToTimeRange(); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.lens.dragFieldToWorkspace('@timestamp'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); await PageObjects.lens.dragFieldToWorkspace('clientip'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect( await PageObjects.lens.getDimensionTriggersTexts('lnsXY_splitDimensionPanel') ).to.eql(['Top values of clientip']); @@ -239,9 +239,9 @@ export default function ({ getPageObjects }: FtrProviderContext) { it('overwrite existing time dimension if one exists already', async () => { await PageObjects.lens.dragFieldToWorkspace('utc_time'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); await PageObjects.lens.dragFieldToWorkspace('clientip'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect(await PageObjects.lens.getDimensionTriggersTexts('lnsXY_xDimensionPanel')).to.eql([ 'utc_time', ]); diff --git a/x-pack/test/functional/apps/lens/rollup.ts b/x-pack/test/functional/apps/lens/rollup.ts index cd32c7de06f6b..86b34e893e7b1 100644 --- a/x-pack/test/functional/apps/lens/rollup.ts +++ b/x-pack/test/functional/apps/lens/rollup.ts @@ -84,12 +84,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { operation: 'sum', field: 'bytes', }); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); await PageObjects.lens.assertMetric('Sum of bytes', '16,788'); await PageObjects.lens.switchFirstLayerIndexPattern('lens_rolled_up_data'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); await PageObjects.lens.assertMetric('Sum of bytes', '16,788'); }); diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts index bf79ac996f8ec..946f3a1dcba95 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/smokescreen.ts @@ -180,7 +180,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const longLabel = 'Veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryvery long label wrapping multiple lines'; await PageObjects.lens.editDimensionLabel(longLabel); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); await PageObjects.lens.closeDimensionEditor(); expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql( @@ -223,7 +223,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.lens.closeDimensionEditor(); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); const data = await PageObjects.lens.getCurrentChartDebugState(); expect(data?.axes?.y.length).to.eql(2); @@ -235,7 +235,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.lens.toggleToolbarPopover('lnsValuesButton'); await testSubjects.click('lnsXY_valueLabels_inside'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); // check for value labels let data = await PageObjects.lens.getCurrentChartDebugState(); @@ -243,7 +243,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // switch to stacked bar chart await PageObjects.lens.switchToVisualization('bar_stacked'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); // check for value labels data = await PageObjects.lens.getCurrentChartDebugState(); @@ -256,14 +256,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.setValue('lnsyLeftAxisTitle', axisTitle, { clearWithKeyboard: true, }); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); let data = await PageObjects.lens.getCurrentChartDebugState(); expect(data?.axes?.y?.[0].title).to.eql(axisTitle); // hide the gridlines await testSubjects.click('lnsshowyLeftAxisGridlines'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); data = await PageObjects.lens.getCurrentChartDebugState(); expect(data?.axes?.y?.[0].gridlines.length).to.eql(0); diff --git a/x-pack/test/functional/apps/lens/table.ts b/x-pack/test/functional/apps/lens/table.ts index 7326aa24304a3..2d96458523cb6 100644 --- a/x-pack/test/functional/apps/lens/table.ts +++ b/x-pack/test/functional/apps/lens/table.ts @@ -23,20 +23,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.lens.switchToVisualization('lnsDatatable'); // Sort by number await PageObjects.lens.changeTableSortingBy(2, 'ascending'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect(await PageObjects.lens.getDatatableCellText(0, 2)).to.eql('17,246'); // Now sort by IP await PageObjects.lens.changeTableSortingBy(0, 'ascending'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('78.83.247.30'); // Change the sorting await PageObjects.lens.changeTableSortingBy(0, 'descending'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('169.228.188.120'); // Remove the sorting await retry.try(async () => { await PageObjects.lens.changeTableSortingBy(0, 'none'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect(await PageObjects.lens.isDatatableHeaderSorted(0)).to.eql(false); }); }); @@ -45,7 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const firstCellContent = await PageObjects.lens.getDatatableCellText(0, 0); await retry.try(async () => { await PageObjects.lens.clickTableCellAction(0, 0, 'lensDatatableFilterOut'); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); expect( await find.existsByCssSelector( `[data-test-subj*="filter-value-${firstCellContent}"][data-test-subj*="filter-negated"]` diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 2ecf6f3163d7e..48bede9754c58 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -19,6 +19,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const browser = getService('browser'); const PageObjects = getPageObjects([ + 'common', 'header', 'timePicker', 'common', @@ -753,5 +754,23 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const focusedElementText = await fieldAncestor.getVisibleText(); expect(focusedElementText).to.eql(name); }, + + async waitForVisualization() { + async function getRenderingCount() { + const visualizationContainer = await testSubjects.find('lnsVisualizationContainer'); + const renderingCount = await visualizationContainer.getAttribute('data-rendering-count'); + return Number(renderingCount); + } + await PageObjects.header.waitUntilLoadingHasFinished(); + await retry.waitFor('rendering count to stabilize', async () => { + const firstCount = await getRenderingCount(); + + await PageObjects.common.sleep(1000); + + const secondCount = await getRenderingCount(); + + return firstCount === secondCount; + }); + }, }); }