diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx index bc76020d1964..540fa65bf6c1 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx @@ -331,6 +331,7 @@ export const ScatterplotMatrix: FC = ({ fullWidth > = ({ fullWidth > { await esArchiver.loadIfNeeded('ml/bm_classification'); await ml.testResources.createIndexPatternIfNeeded('ft_bank_marketing', '@timestamp'); @@ -44,18 +43,18 @@ export default function ({ getService }: FtrProviderContext) { expected: { rocCurveColorState: [ // tick/grid/axis - { key: '#DDDDDD', value: 50 }, + { color: '#DDDDDD', percentage: 50 }, // line - { key: '#98A2B3', value: 30 }, + { color: '#98A2B3', percentage: 30 }, ], scatterplotMatrixColorStats: [ // marker colors - { key: '#7FC6B3', value: 1 }, - { key: '#88ADD0', value: 0.03 }, + { color: '#7FC6B3', percentage: 1 }, + { color: '#88ADD0', percentage: 0.03 }, // tick/grid/axis - { key: '#DDDDDD', value: 8 }, - { key: '#D3DAE6', value: 8 }, - { key: '#F5F7FA', value: 20 }, + { color: '#DDDDDD', percentage: 8 }, + { color: '#D3DAE6', percentage: 8 }, + { color: '#F5F7FA', percentage: 15 }, ], row: { type: 'classification', @@ -78,6 +77,10 @@ export default function ({ getService }: FtrProviderContext) { await ml.navigation.navigateToDataFrameAnalytics(); await ml.testExecution.logTestStep('loads the source selection modal'); + + // Disable anti-aliasing to stabilize canvas image rendering assertions + await ml.commonUI.disableAntiAliasing(); + await ml.dataFrameAnalytics.startAnalyticsCreation(); await ml.testExecution.logTestStep( @@ -106,6 +109,16 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('displays the include fields selection'); await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); + await ml.testExecution.logTestStep( + 'sets the sample size to 10000 for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsCreation.setScatterplotMatrixSampleSizeSelectValue('10000'); + + await ml.testExecution.logTestStep( + 'sets the randomize query switch to true for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsCreation.setScatterplotMatrixRandomizeQueryCheckState(true); + await ml.testExecution.logTestStep('displays the scatterplot matrix'); await ml.dataFrameAnalyticsCreation.assertScatterplotMatrix( testData.expected.scatterplotMatrixColorStats @@ -237,6 +250,12 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('displays the results view for created job'); await ml.dataFrameAnalyticsTable.openResultsView(testData.jobId); await ml.dataFrameAnalyticsResults.assertClassificationEvaluatePanelElementsExists(); + await ml.dataFrameAnalyticsResults.assertClassificationTablePanelExists(); + await ml.dataFrameAnalyticsResults.assertResultsTableExists(); + await ml.dataFrameAnalyticsResults.assertResultsTableTrainingFiltersExist(); + await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); + + await ml.testExecution.logTestStep('displays the ROC curve chart'); await ml.commonUI.assertColorsInCanvasElement( 'mlDFAnalyticsClassificationExplorationRocCurveChart', testData.expected.rocCurveColorState, @@ -247,13 +266,23 @@ export default function ({ getService }: FtrProviderContext) { // since the returned colors vary quite a bit on each run. 20 ); - await ml.dataFrameAnalyticsResults.assertClassificationTablePanelExists(); - await ml.dataFrameAnalyticsResults.assertResultsTableExists(); - await ml.dataFrameAnalyticsResults.assertResultsTableTrainingFiltersExist(); - await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); + + await ml.testExecution.logTestStep( + 'sets the sample size to 10000 for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsResults.setScatterplotMatrixSampleSizeSelectValue('10000'); + + await ml.testExecution.logTestStep( + 'sets the randomize query switch to true for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsResults.setScatterplotMatrixRandomizeQueryCheckState(true); + + await ml.testExecution.logTestStep('displays the scatterplot matrix'); await ml.dataFrameAnalyticsResults.assertScatterplotMatrix( testData.expected.scatterplotMatrixColorStats ); + + await ml.commonUI.resetAntiAliasing(); }); it('displays the analytics job in the map view', async () => { diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts index d8b52130d307..d72ee4fa0fd2 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts @@ -52,19 +52,19 @@ export default function ({ getService }: FtrProviderContext) { ], scatterplotMatrixColorsWizard: [ // markers - { key: '#52B398', value: 25 }, + { color: '#52B398', percentage: 15 }, // grey boilerplate - { key: '#6A717D', value: 30 }, + { color: '#6A717D', percentage: 33 }, ], scatterplotMatrixColorStatsResults: [ // red markers - { key: '#D98071', value: 1 }, + { color: '#D98071', percentage: 1 }, // tick/grid/axis, grey markers - { key: '#6A717D', value: 30 }, - { key: '#D3DAE6', value: 8 }, - { key: '#98A1B3', value: 25 }, + { color: '#6A717D', percentage: 33 }, + { color: '#D3DAE6', percentage: 8 }, + { color: '#98A1B3', percentage: 12 }, // anti-aliasing - { key: '#F5F7FA', value: 27 }, + { color: '#F5F7FA', percentage: 30 }, ], row: { type: 'outlier_detection', @@ -126,6 +126,16 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('displays the include fields selection'); await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); + await ml.testExecution.logTestStep( + 'sets the sample size to 10000 for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsCreation.setScatterplotMatrixSampleSizeSelectValue('10000'); + + await ml.testExecution.logTestStep( + 'sets the randomize query switch to true for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsCreation.setScatterplotMatrixRandomizeQueryCheckState(true); + await ml.testExecution.logTestStep('displays the scatterplot matrix'); await ml.dataFrameAnalyticsCreation.assertScatterplotMatrix( testData.expected.scatterplotMatrixColorsWizard @@ -255,9 +265,23 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsResults.assertResultsTableExists(); await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); await ml.dataFrameAnalyticsResults.assertFeatureInfluenceCellNotEmpty(); + + await ml.testExecution.logTestStep( + 'sets the sample size to 10000 for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsResults.setScatterplotMatrixSampleSizeSelectValue('10000'); + + await ml.testExecution.logTestStep( + 'sets the randomize query switch to true for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsResults.setScatterplotMatrixRandomizeQueryCheckState(true); + + await ml.testExecution.logTestStep('displays the scatterplot matrix'); await ml.dataFrameAnalyticsResults.assertScatterplotMatrix( testData.expected.scatterplotMatrixColorStatsResults ); + + await ml.commonUI.resetAntiAliasing(); }); it('displays the analytics job in the map view', async () => { diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts index 43dd5ad78a07..8e28a9933cda 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts @@ -42,12 +42,12 @@ export default function ({ getService }: FtrProviderContext) { expected: { scatterplotMatrixColorStats: [ // some marker colors of the continuous color scale - { key: '#61AFA3', value: 2 }, - { key: '#D1E5E0', value: 2 }, + { color: '#61AFA3', percentage: 2 }, + { color: '#D1E5E0', percentage: 2 }, // tick/grid/axis - { key: '#6A717D', value: 10 }, - { key: '#F5F7FA', value: 12 }, - { key: '#D3DAE6', value: 3 }, + { color: '#6A717D', percentage: 10 }, + { color: '#F5F7FA', percentage: 10 }, + { color: '#D3DAE6', percentage: 3 }, ], row: { type: 'regression', @@ -71,6 +71,10 @@ export default function ({ getService }: FtrProviderContext) { await ml.navigation.navigateToDataFrameAnalytics(); await ml.testExecution.logTestStep('loads the source selection modal'); + + // Disable anti-aliasing to stabilize canvas image rendering assertions + await ml.commonUI.disableAntiAliasing(); + await ml.dataFrameAnalytics.startAnalyticsCreation(); await ml.testExecution.logTestStep( @@ -99,6 +103,16 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('displays the include fields selection'); await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); + await ml.testExecution.logTestStep( + 'sets the sample size to 10000 for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsCreation.setScatterplotMatrixSampleSizeSelectValue('10000'); + + await ml.testExecution.logTestStep( + 'sets the randomize query switch to true for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsCreation.setScatterplotMatrixRandomizeQueryCheckState(true); + await ml.testExecution.logTestStep('displays the scatterplot matrix'); await ml.dataFrameAnalyticsCreation.assertScatterplotMatrix( testData.expected.scatterplotMatrixColorStats @@ -229,9 +243,23 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsResults.assertResultsTableExists(); await ml.dataFrameAnalyticsResults.assertResultsTableTrainingFiltersExist(); await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); + + await ml.testExecution.logTestStep( + 'sets the sample size to 10000 for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsResults.setScatterplotMatrixSampleSizeSelectValue('10000'); + + await ml.testExecution.logTestStep( + 'sets the randomize query switch to true for the scatterplot matrix' + ); + await ml.dataFrameAnalyticsResults.setScatterplotMatrixRandomizeQueryCheckState(true); + + await ml.testExecution.logTestStep('displays the scatterplot matrix'); await ml.dataFrameAnalyticsResults.assertScatterplotMatrix( testData.expected.scatterplotMatrixColorStats ); + + await ml.commonUI.resetAntiAliasing(); }); it('displays the analytics job in the map view', async () => { diff --git a/x-pack/test/functional/apps/transform/creation_index_pattern.ts b/x-pack/test/functional/apps/transform/creation_index_pattern.ts index fbd98e506738..a720aec6bb47 100644 --- a/x-pack/test/functional/apps/transform/creation_index_pattern.ts +++ b/x-pack/test/functional/apps/transform/creation_index_pattern.ts @@ -161,8 +161,8 @@ export default function ({ getService }: FtrProviderContext) { id: 'currency', legend: '1 category', colorStats: [ - { key: '#000000', value: 10 }, - { key: '#54B399', value: 90 }, + { color: '#000000', percentage: 10 }, + { color: '#54B399', percentage: 90 }, ], }, { @@ -177,8 +177,8 @@ export default function ({ getService }: FtrProviderContext) { id: 'customer_gender', legend: '2 categories', colorStats: [ - { key: '#000000', value: 15 }, - { key: '#54B399', value: 85 }, + { color: '#000000', percentage: 15 }, + { color: '#54B399', percentage: 85 }, ], }, { @@ -186,8 +186,8 @@ export default function ({ getService }: FtrProviderContext) { id: 'customer_id', legend: 'top 20 of 46 categories', colorStats: [ - { key: '#54B399', value: 35 }, - { key: '#000000', value: 60 }, + { color: '#54B399', percentage: 35 }, + { color: '#000000', percentage: 60 }, ], }, { chartAvailable: false, id: 'customer_last_name', legend: 'Chart not supported.' }, @@ -196,8 +196,8 @@ export default function ({ getService }: FtrProviderContext) { id: 'customer_phone', legend: '1 category', colorStats: [ - { key: '#000000', value: 10 }, - { key: '#54B399', value: 90 }, + { color: '#000000', percentage: 10 }, + { color: '#54B399', percentage: 90 }, ], }, { @@ -205,8 +205,8 @@ export default function ({ getService }: FtrProviderContext) { id: 'day_of_week', legend: '7 categories', colorStats: [ - { key: '#000000', value: 20 }, - { key: '#54B399', value: 75 }, + { color: '#000000', percentage: 20 }, + { color: '#54B399', percentage: 75 }, ], }, ], diff --git a/x-pack/test/functional/apps/transform/creation_runtime_mappings.ts b/x-pack/test/functional/apps/transform/creation_runtime_mappings.ts index cc3491932dea..1ecbdd41c219 100644 --- a/x-pack/test/functional/apps/transform/creation_runtime_mappings.ts +++ b/x-pack/test/functional/apps/transform/creation_runtime_mappings.ts @@ -8,6 +8,9 @@ import { TRANSFORM_STATE } from '../../../../plugins/transform/common/constants'; import { FtrProviderContext } from '../../ftr_provider_context'; + +import type { HistogramCharts } from '../../services/transform/wizard'; + import { GroupByEntry, isLatestTransformTestData, @@ -44,22 +47,22 @@ export default function ({ getService }: FtrProviderContext) { }); // Only testing that histogram charts are available for runtime fields here - const histogramCharts = [ + const histogramCharts: HistogramCharts = [ { chartAvailable: true, id: 'rt_airline_lower', legend: '19 categories', colorStats: [ - { key: '#000000', value: 48 }, - { key: '#54B399', value: 41 }, + { color: '#000000', percentage: 48 }, + { color: '#54B399', percentage: 41 }, ], }, { chartAvailable: true, id: 'rt_responsetime_x_2', colorStats: [ - { key: '#54B399', value: 5 }, - { key: '#000000', value: 95 }, + { color: '#54B399', percentage: 5 }, + { color: '#000000', percentage: 95 }, ], }, ]; diff --git a/x-pack/test/functional/services/canvas_element.ts b/x-pack/test/functional/services/canvas_element.ts index b6d1239b3416..6167c8fab45f 100644 --- a/x-pack/test/functional/services/canvas_element.ts +++ b/x-pack/test/functional/services/canvas_element.ts @@ -8,12 +8,13 @@ import { rgb, nest } from 'd3'; interface ColorStat { - key: string; - value: number; + color: string; + percentage: number; + pixels?: number; withinTolerance?: boolean; } -type ColorStats = ColorStat[]; +export type CanvasElementColorStats = ColorStat[]; import { FtrProviderContext } from '../ftr_provider_context'; @@ -75,12 +76,12 @@ export async function CanvasElementProvider({ getService }: FtrProviderContext) */ public async getColorStats( selector: string, - expectedColorStats?: ColorStats, + expectedColorStats?: CanvasElementColorStats, exclude?: string[], percentageThreshold = 5, channelTolerance = 10, valueTolerance = 10 - ): Promise { + ): Promise { const imageData = await this.getImageData(selector); // transform the array of RGBA numbers to an array of hex values const colors: string[] = []; @@ -109,21 +110,24 @@ export async function CanvasElementProvider({ getService }: FtrProviderContext) .filter((s) => getPixelPercentage(s.values.length) >= percentageThreshold) .sort((a, b) => a.key.localeCompare(b.key)) .map((s, i) => { - const value = getPixelPercentage(s.values.length); + const percentage = getPixelPercentage(s.values.length); + const pixels = s.values.length; return { - key: s.key, - value, + color: s.key, + percentage, + pixels, ...(expectedColorStats !== undefined ? { withinTolerance: this.isValueWithinTolerance( - value, - expectedColorStats[i]?.value, + percentage, + pixels, + expectedColorStats[i]?.percentage, valueTolerance ) && this.isColorWithinTolerance( s.key, - expectedColorStats[i]?.key, + expectedColorStats[i]?.color, channelTolerance ), } @@ -138,12 +142,12 @@ export async function CanvasElementProvider({ getService }: FtrProviderContext) */ public async getColorStatsWithColorTolerance( selector: string, - expectedColorStats: ColorStats, + expectedColorStats: CanvasElementColorStats, exclude?: string[], percentageThreshold = 0, channelTolerance = 10, valueTolerance = 10 - ) { + ): Promise { const actualColorStats = await this.getColorStats( selector, undefined, @@ -154,16 +158,26 @@ export async function CanvasElementProvider({ getService }: FtrProviderContext) ); return expectedColorStats.map((expectedColor) => { - const colorPercentageWithinTolerance = actualColorStats - .filter((d) => this.isColorWithinTolerance(d.key, expectedColor.key, channelTolerance)) - .reduce((sum, x) => sum + x.value, 0); + const colorsWithinTolerance = actualColorStats.filter((d) => + this.isColorWithinTolerance(d.color, expectedColor.color, channelTolerance) + ); + const colorPercentageWithinTolerance = colorsWithinTolerance.reduce( + (sum, x) => sum + x.percentage, + 0 + ); + const pixelsWithinTolerance = colorsWithinTolerance.reduce( + (sum, x) => sum + (x.pixels || 0), + 0 + ); return { - key: expectedColor.key, - value: colorPercentageWithinTolerance, + color: expectedColor.color, + percentage: colorPercentageWithinTolerance, + pixels: pixelsWithinTolerance, withinTolerance: this.isValueWithinTolerance( colorPercentageWithinTolerance, - expectedColor.value, + pixelsWithinTolerance, + expectedColor.percentage, valueTolerance ), }; @@ -202,15 +216,24 @@ export async function CanvasElementProvider({ getService }: FtrProviderContext) /** * Returns if a given value is within the tolerated range of an expected value * - * @param actualValue - * @param expectedValue + * @param actualPercentage + * @param actualPixels + * @param expectedPercentage * @param toleranceRange * @returns if actualValue is within the tolerance of expectedValue */ - public isValueWithinTolerance(actualValue: number, expectedValue: number, toleranceRange = 10) { - const lower = expectedValue - toleranceRange / 2; - const upper = expectedValue + toleranceRange / 2; - return actualValue > 0 && lower <= actualValue && upper >= actualValue; + public isValueWithinTolerance( + actualPercentage: number, + actualPixels: number, + expectedPercentage: number, + toleranceRange = 10 + ) { + const lower = expectedPercentage - toleranceRange / 2; + const upper = expectedPercentage + toleranceRange / 2; + return ( + // actualPercentage could be rounded to 0 so we check against actualPixels if they are above 0. + actualPixels > 0 && lower <= actualPercentage && upper >= actualPercentage + ); } })(); } diff --git a/x-pack/test/functional/services/ml/common_ui.ts b/x-pack/test/functional/services/ml/common_ui.ts index e7aa7ad5d3c8..b7ed95ef76ec 100644 --- a/x-pack/test/functional/services/ml/common_ui.ts +++ b/x-pack/test/functional/services/ml/common_ui.ts @@ -10,18 +10,13 @@ import { ProvidedType } from '@kbn/test/types/ftr'; import { FtrProviderContext } from '../../ftr_provider_context'; +import type { CanvasElementColorStats } from '../canvas_element'; + interface SetValueOptions { clearWithKeyboard?: boolean; typeCharByChar?: boolean; } -// key: color hex code, e.g. #FF3344 -// value: the expected percentage of the color to be present in the canvas element -export type CanvasElementColorStats = Array<{ - key: string; - value: number; -}>; - export type MlCommonUI = ProvidedType; export function MachineLearningCommonUIProvider({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts index d2c1291e69af..23bdc17919a7 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts @@ -9,7 +9,8 @@ import expect from '@kbn/expect'; import { DataFrameAnalyticsConfig } from '../../../../plugins/ml/public/application/data_frame_analytics/common'; import { FtrProviderContext } from '../../ftr_provider_context'; -import type { CanvasElementColorStats, MlCommonUI } from './common_ui'; +import type { CanvasElementColorStats } from '../canvas_element'; +import type { MlCommonUI } from './common_ui'; import { MlApi } from './api'; import { isRegressionAnalysis, @@ -273,6 +274,45 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( ); }, + async setScatterplotMatrixSampleSizeSelectValue(selectValue: string) { + await testSubjects.selectValue('mlScatterplotMatrixSampleSizeSelect', selectValue); + + const actualSelectState = await testSubjects.getAttribute( + 'mlScatterplotMatrixSampleSizeSelect', + 'value' + ); + + expect(actualSelectState).to.eql( + selectValue, + `Sample size should be '${selectValue}' (got '${actualSelectState}')` + ); + }, + + async getScatterplotMatrixRandomizeQuerySwitchCheckState(): Promise { + const state = await testSubjects.getAttribute( + 'mlScatterplotMatrixRandomizeQuerySwitch', + 'aria-checked' + ); + return state === 'true'; + }, + + async assertScatterplotMatrixRandomizeQueryCheckState(expectedCheckState: boolean) { + const actualCheckState = await this.getScatterplotMatrixRandomizeQuerySwitchCheckState(); + expect(actualCheckState).to.eql( + expectedCheckState, + `Randomize query check state should be '${expectedCheckState}' (got '${actualCheckState}')` + ); + }, + + async setScatterplotMatrixRandomizeQueryCheckState(checkState: boolean) { + await retry.tryForTime(30000, async () => { + if ((await this.getScatterplotMatrixRandomizeQuerySwitchCheckState()) !== checkState) { + await testSubjects.click('mlScatterplotMatrixRandomizeQuerySwitch'); + } + await this.assertScatterplotMatrixRandomizeQueryCheckState(checkState); + }); + }, + async assertTrainingPercentInputExists() { await testSubjects.existOrFail('mlAnalyticsCreateJobWizardTrainingPercentSlider'); }, diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts index c3fb75799fe6..f91ce063192d 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts @@ -10,7 +10,8 @@ import { WebElementWrapper } from 'test/functional/services/lib/web_element_wrap import { FtrProviderContext } from '../../ftr_provider_context'; -import type { CanvasElementColorStats, MlCommonUI } from './common_ui'; +import type { CanvasElementColorStats } from '../canvas_element'; +import type { MlCommonUI } from './common_ui'; export function MachineLearningDataFrameAnalyticsResultsProvider( { getService }: FtrProviderContext, @@ -84,14 +85,60 @@ export function MachineLearningDataFrameAnalyticsResultsProvider( }); }, + async setScatterplotMatrixSampleSizeSelectValue(selectValue: string) { + await testSubjects.selectValue('mlScatterplotMatrixSampleSizeSelect', selectValue); + + const actualSelectState = await testSubjects.getAttribute( + 'mlScatterplotMatrixSampleSizeSelect', + 'value' + ); + + expect(actualSelectState).to.eql( + selectValue, + `Sample size should be '${selectValue}' (got '${actualSelectState}')` + ); + }, + + async getScatterplotMatrixRandomizeQuerySwitchCheckState(): Promise { + const state = await testSubjects.getAttribute( + 'mlScatterplotMatrixRandomizeQuerySwitch', + 'aria-checked' + ); + return state === 'true'; + }, + + async assertScatterplotMatrixRandomizeQueryCheckState(expectedCheckState: boolean) { + const actualCheckState = await this.getScatterplotMatrixRandomizeQuerySwitchCheckState(); + expect(actualCheckState).to.eql( + expectedCheckState, + `Randomize query check state should be '${expectedCheckState}' (got '${actualCheckState}')` + ); + }, + + async setScatterplotMatrixRandomizeQueryCheckState(checkState: boolean) { + await retry.tryForTime(30000, async () => { + if ((await this.getScatterplotMatrixRandomizeQuerySwitchCheckState()) !== checkState) { + await testSubjects.click('mlScatterplotMatrixRandomizeQuerySwitch'); + } + await this.assertScatterplotMatrixRandomizeQueryCheckState(checkState); + }); + }, + async assertScatterplotMatrix(expectedValue: CanvasElementColorStats) { await testSubjects.existOrFail('mlDFExpandableSection-splom > mlScatterplotMatrix loaded', { timeout: 5000, }); await testSubjects.scrollIntoView('mlDFExpandableSection-splom > mlScatterplotMatrix loaded'); - await mlCommonUI.assertColorsInCanvasElement('mlDFExpandableSection-splom', expectedValue, [ - '#000000', - ]); + await mlCommonUI.assertColorsInCanvasElement( + 'mlDFExpandableSection-splom', + expectedValue, + ['#000000'], + undefined, + undefined, + // increased tolerance up from 10 to 20 + // since the returned randomized colors vary quite a bit on each run. + 20 + ); }, async assertFeatureImportanceDecisionPathChartElementsExists() { diff --git a/x-pack/test/functional/services/transform/wizard.ts b/x-pack/test/functional/services/transform/wizard.ts index ee9954fec53b..f82af4f3a6d3 100644 --- a/x-pack/test/functional/services/transform/wizard.ts +++ b/x-pack/test/functional/services/transform/wizard.ts @@ -10,6 +10,15 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; +import type { CanvasElementColorStats } from '../canvas_element'; + +export type HistogramCharts = Array<{ + chartAvailable: boolean; + id: string; + legend?: string; + colorStats?: CanvasElementColorStats; +}>; + export function TransformWizardProvider({ getService, getPageObjects }: FtrProviderContext) { const aceEditor = getService('aceEditor'); const canvasElement = getService('canvasElement'); @@ -224,14 +233,7 @@ export function TransformWizardProvider({ getService, getPageObjects }: FtrProvi ); }, - async assertIndexPreviewHistogramCharts( - expectedHistogramCharts: Array<{ - chartAvailable: boolean; - id: string; - legend?: string; - colorStats?: any[]; - }> - ) { + async assertIndexPreviewHistogramCharts(expectedHistogramCharts: HistogramCharts) { // For each chart, get the content of each header cell and assert // the legend text and column id and if the chart should be present or not. await retry.tryForTime(5000, async () => { @@ -244,7 +246,7 @@ export function TransformWizardProvider({ getService, getPageObjects }: FtrProvi if (expected.colorStats !== undefined) { const sortedExpectedColorStats = [...expected.colorStats].sort((a, b) => - a.key.localeCompare(b.key) + a.color.localeCompare(b.color) ); const actualColorStats = await canvasElement.getColorStats(