[ML] Data Frame Analytics: Fix color assertion with risk of percentage being rounded to 0. (#95797)
- Fix color assertion with risk of percentage being rounded to 0. - Better naming of attributes of expected values. - Adds assertions to use the sample size dropdown and randomize query switch.
This commit is contained in:
parent
d10935cf07
commit
d9a475258b
|
@ -331,6 +331,7 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
|
|||
fullWidth
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="mlScatterplotMatrixSampleSizeSelect"
|
||||
compressed
|
||||
options={sampleSizeOptions}
|
||||
value={fetchSize}
|
||||
|
@ -355,6 +356,7 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
|
|||
fullWidth
|
||||
>
|
||||
<EuiSwitch
|
||||
data-test-subj="mlScatterplotMatrixRandomizeQuerySwitch"
|
||||
name="mlScatterplotMatrixRandomizeQuery"
|
||||
label={randomizeQuery ? TOGGLE_ON : TOGGLE_OFF}
|
||||
checked={randomizeQuery}
|
||||
|
|
|
@ -12,8 +12,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const ml = getService('ml');
|
||||
const editedDescription = 'Edited description';
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/91450
|
||||
describe.skip('classification creation', function () {
|
||||
describe('classification creation', function () {
|
||||
before(async () => {
|
||||
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 () => {
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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 },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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 },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -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<ColorStats> {
|
||||
): Promise<CanvasElementColorStats> {
|
||||
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<CanvasElementColorStats> {
|
||||
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
|
||||
);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
|
|
@ -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<typeof MachineLearningCommonUIProvider>;
|
||||
|
||||
export function MachineLearningCommonUIProvider({ getService }: FtrProviderContext) {
|
||||
|
|
|
@ -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<boolean> {
|
||||
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');
|
||||
},
|
||||
|
|
|
@ -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<boolean> {
|
||||
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() {
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue