diff --git a/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 1b331043a530d..5ff9f9ed810ed 100644 --- a/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { camelCase } from 'lodash'; +import { camelCase, pick } from 'lodash'; import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/react'; @@ -46,6 +46,7 @@ import { DatasourceMap, VisualizationMap, UserMessagesGetter, + DatasourceLayers, } from '../../types'; import { getSuggestions, switchToSuggestion } from './suggestion_helpers'; import { getDatasourceExpressionsByLayers } from './expression_helpers'; @@ -130,7 +131,7 @@ const PreviewRenderer = ({ const euiThemeContext = useEuiTheme(); const { euiTheme } = euiThemeContext; const onErrorMessage = ( -
+
{ + if (updatedLayerApis[layerId]) { + updatedLayerApis[layerId] = datasource.getPublicAPI({ + layerId, + state: datasourceState, + indexPatterns: frame.dataViews.indexPatterns, + }); + } + suggestionFrameApi.datasourceLayers[layerId] = updatedLayerApis[layerId]; + }); + } const datasourceExpressionsByLayers = getDatasourceExpressionsByLayers( datasources, datasourceStates, diff --git a/x-pack/platform/plugins/shared/lens/public/visualizations/xy/visualization.tsx b/x-pack/platform/plugins/shared/lens/public/visualizations/xy/visualization.tsx index 0a596ca1ea224..9df8ce382497b 100644 --- a/x-pack/platform/plugins/shared/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/platform/plugins/shared/lens/public/visualizations/xy/visualization.tsx @@ -1345,6 +1345,7 @@ export const stackingTypes = [ defaultMessage: 'Stacked', }), subtypes: ['bar_stacked', 'area_stacked', 'bar_horizontal_stacked'], + dataTestSubj: 'lnsStackingOptionsButtonStacked', }, { type: 'unstacked', @@ -1352,6 +1353,7 @@ export const stackingTypes = [ defaultMessage: 'Unstacked', }), subtypes: ['bar', 'area', 'bar_horizontal'], + dataTestSubj: 'lnsStackingOptionsButtonUnstacked', }, { type: 'percentage', @@ -1363,6 +1365,7 @@ export const stackingTypes = [ 'area_percentage_stacked', 'bar_horizontal_percentage_stacked', ], + dataTestSubj: 'lnsStackingOptionsButtonPercentage', }, ]; @@ -1380,10 +1383,11 @@ const SubtypeSwitch = ({ return null; } const subTypeIndex = stackingType.subtypes.indexOf(layer.seriesType); - const options = stackingTypes.map(({ label, subtypes }) => ({ + const options = stackingTypes.map(({ label, subtypes, dataTestSubj }) => ({ label, value: subtypes[subTypeIndex], checked: subtypes[subTypeIndex] === layer.seriesType ? ('on' as const) : undefined, + 'data-test-subj': dataTestSubj, })); return ( @@ -1400,6 +1404,7 @@ const SubtypeSwitch = ({ fullWidth size="s" label={stackingType.label} + data-test-subj="lnsStackingOptionsButton" /> } isOpen={flyoutOpen} diff --git a/x-pack/test/functional/apps/lens/group1/smokescreen.ts b/x-pack/test/functional/apps/lens/group1/smokescreen.ts index dbe48cdd395da..ff9274d7b1c40 100644 --- a/x-pack/test/functional/apps/lens/group1/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/group1/smokescreen.ts @@ -829,5 +829,39 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await lens.waitForVisualization('xyVisChart'); expect(await lens.getWorkspaceErrorCount()).to.eql(0); }); + + it('should keep suggestions up to date with the current configuration', async () => { + await visualize.navigateToNewVisualization(); + await visualize.clickVisType('lens'); + await lens.configureDimension({ + dimension: 'lnsXY_xDimensionPanel > lns-empty-dimension', + operation: 'date_histogram', + field: '@timestamp', + }); + await lens.configureDimension({ + dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension', + operation: 'average', + field: 'bytes', + }); + // duplicate the layer + await lens.duplicateLayer(); + + // now make the first layer bar percentage to lead it in an broken rendering state + await lens.switchToVisualizationSubtype('Percentage'); + + // now check that both the main visualization and the current visualization suggestion are in error state + expect(await lens.getWorkspaceErrorCount()).to.eql(1); + await testSubjects.existOrFail( + 'lnsSuggestion-currentVisualization > lnsSuggestionPanel__error' + ); + + // revert the subtype to stacked and everything should be fine again + await lens.switchToVisualizationSubtype('Stacked'); + + expect(await lens.getWorkspaceErrorCount()).to.eql(0); + await testSubjects.missingOrFail( + 'lnsSuggestion-currentVisualization > lnsSuggestionPanel__error' + ); + }); }); } diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 635a9c4ba6c3a..40ba82f7fa84d 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -925,6 +925,19 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }); }, + async switchToVisualizationSubtype(subType: string, layerIndex: number = 0) { + if (!(await testSubjects.exists(`lns-layerPanel-${layerIndex} > lnsStackingOptionsButton`))) { + throw new Error('No subtype available for the current visualization'); + } + await testSubjects.click(`lns-layerPanel-${layerIndex} > lnsStackingOptionsButton`); + await testSubjects.click(`lnsStackingOptionsButton${subType}`); + }, + + async getChartTypeFromChartSwitcher() { + const chartSwitcher = await testSubjects.find('lnsChartSwitchPopover'); + return await chartSwitcher.getVisibleText(); + }, + async openChartSwitchPopover(layerIndex = 0) { if (await testSubjects.exists('lnsChartSwitchList', { timeout: 50 })) { return; @@ -1104,6 +1117,15 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont } }, + async duplicateLayer(index: number = 0) { + await retry.try(async () => { + if (await testSubjects.exists(`lnsLayerSplitButton--${index}`)) { + await testSubjects.click(`lnsLayerSplitButton--${index}`); + } + await testSubjects.click(`lnsLayerClone--${index}`); + }); + }, + /** * Changes the index pattern in the data panel */