[ML] Data Frame Analytics: adds functional tests for runtime fields support (#96262)

* add basic runtime mapping functional tests to analyics

* confirm runtime mapping added correctly.
This commit is contained in:
Melissa Alvarez 2021-04-06 12:06:36 -04:00 committed by GitHub
parent 177322fd9e
commit 40cbb1fe79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 133 additions and 1 deletions

View file

@ -38,6 +38,7 @@ const COPY_TO_CLIPBOARD_RUNTIME_MAPPINGS = i18n.translate(
const { useXJsonMode } = XJson;
const xJsonMode = new XJsonMode();
export type XJsonModeType = ReturnType<typeof XJsonMode>;
interface Props {
actions: CreateAnalyticsFormProps['actions'];

View file

@ -10,6 +10,7 @@ import React, { memo, FC } from 'react';
import { EuiCodeEditor } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { isRuntimeMappings } from '../../../../../../../common/util/runtime_field_utils';
import { XJsonModeType } from './runtime_mappings';
interface Props {
convertToJson: (data: string) => string;
@ -17,7 +18,7 @@ interface Props {
setIsRuntimeMappingsEditorApplyButtonEnabled: React.Dispatch<React.SetStateAction<boolean>>;
advancedEditorRuntimeMappingsLastApplied: string | undefined;
advancedRuntimeMappingsConfig: string;
xJsonMode: any;
xJsonMode: XJsonModeType;
}
export const RuntimeMappingsEditor: FC<Props> = memo(

View file

@ -36,6 +36,12 @@ export default function ({ getService }: FtrProviderContext) {
get destinationIndex(): string {
return `user-${this.jobId}`;
},
runtimeFields: {
uppercase_y: {
type: 'keyword',
script: 'emit(params._source.y.toUpperCase())',
},
},
dependentVariable: 'y',
trainingPercent: 20,
modelMemory: '60mb',
@ -95,6 +101,22 @@ export default function ({ getService }: FtrProviderContext) {
await ml.dataFrameAnalyticsCreation.assertJobTypeSelectExists();
await ml.dataFrameAnalyticsCreation.selectJobType(testData.jobType);
await ml.testExecution.logTestStep('displays the runtime mappings editor switch');
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingSwitchExists();
await ml.testExecution.logTestStep('enables the runtime mappings editor');
await ml.dataFrameAnalyticsCreation.toggleRuntimeMappingsEditorSwitch(true);
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent(['']);
await ml.testExecution.logTestStep('sets runtime mappings');
await ml.dataFrameAnalyticsCreation.setRuntimeMappingsEditorContent(
JSON.stringify(testData.runtimeFields)
);
await ml.dataFrameAnalyticsCreation.applyRuntimeMappings();
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent([
'{"uppercase_y":{"type":"keyword","script":"emit(params._source.y.toUpperCase())"}}',
]);
await ml.testExecution.logTestStep('inputs the dependent variable');
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputExists();
await ml.dataFrameAnalyticsCreation.selectDependentVariable(testData.dependentVariable);

View file

@ -35,6 +35,12 @@ export default function ({ getService }: FtrProviderContext) {
get destinationIndex(): string {
return `user-${this.jobId}`;
},
runtimeFields: {
lowercase_central_air: {
type: 'keyword',
script: 'emit(params._source.CentralAir.toLowerCase())',
},
},
modelMemory: '5mb',
createIndexPattern: true,
expected: {
@ -106,6 +112,22 @@ export default function ({ getService }: FtrProviderContext) {
await ml.dataFrameAnalyticsCreation.assertJobTypeSelectExists();
await ml.dataFrameAnalyticsCreation.selectJobType(testData.jobType);
await ml.testExecution.logTestStep('displays the runtime mappings editor switch');
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingSwitchExists();
await ml.testExecution.logTestStep('enables the runtime mappings editor');
await ml.dataFrameAnalyticsCreation.toggleRuntimeMappingsEditorSwitch(true);
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent(['']);
await ml.testExecution.logTestStep('sets runtime mappings');
await ml.dataFrameAnalyticsCreation.setRuntimeMappingsEditorContent(
JSON.stringify(testData.runtimeFields)
);
await ml.dataFrameAnalyticsCreation.applyRuntimeMappings();
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent([
'{"lowercase_central_air":{"type":"keyword","script":"emit(params._source.CentralAir.toLowerCase())"}}',
]);
await ml.testExecution.logTestStep('does not display the dependent variable input');
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputMissing();

View file

@ -35,6 +35,12 @@ export default function ({ getService }: FtrProviderContext) {
get destinationIndex(): string {
return `user-${this.jobId}`;
},
runtimeFields: {
uppercase_stab: {
type: 'keyword',
script: 'emit(params._source.stabf.toUpperCase())',
},
},
dependentVariable: 'stab',
trainingPercent: 20,
modelMemory: '20mb',
@ -89,6 +95,22 @@ export default function ({ getService }: FtrProviderContext) {
await ml.dataFrameAnalyticsCreation.assertJobTypeSelectExists();
await ml.dataFrameAnalyticsCreation.selectJobType(testData.jobType);
await ml.testExecution.logTestStep('displays the runtime mappings editor switch');
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingSwitchExists();
await ml.testExecution.logTestStep('enables the runtime mappings editor');
await ml.dataFrameAnalyticsCreation.toggleRuntimeMappingsEditorSwitch(true);
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent(['']);
await ml.testExecution.logTestStep('sets runtime mappings');
await ml.dataFrameAnalyticsCreation.setRuntimeMappingsEditorContent(
JSON.stringify(testData.runtimeFields)
);
await ml.dataFrameAnalyticsCreation.applyRuntimeMappings();
await ml.dataFrameAnalyticsCreation.assertRuntimeMappingsEditorContent([
'{"uppercase_stab":{"type":"keyword","script":"emit(params._source.stabf.toUpperCase())"}}',
]);
await ml.testExecution.logTestStep('inputs the dependent variable');
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputExists();
await ml.dataFrameAnalyticsCreation.selectDependentVariable(testData.dependentVariable);

View file

@ -25,6 +25,7 @@ export function MachineLearningDataFrameAnalyticsCreationProvider(
const testSubjects = getService('testSubjects');
const comboBox = getService('comboBox');
const retry = getService('retry');
const aceEditor = getService('aceEditor');
return {
async assertJobTypeSelectExists() {
@ -237,6 +238,69 @@ export function MachineLearningDataFrameAnalyticsCreationProvider(
);
},
async assertRuntimeMappingSwitchExists() {
await testSubjects.existOrFail('mlDataFrameAnalyticsRuntimeMappingsEditorSwitch');
},
async assertRuntimeMappingEditorExists() {
await testSubjects.existOrFail('mlDataFrameAnalyticsAdvancedRuntimeMappingsEditor');
},
async assertRuntimeMappingsEditorSwitchCheckState(expectedCheckState: boolean) {
const actualCheckState = await this.getRuntimeMappingsEditorSwitchCheckedState();
expect(actualCheckState).to.eql(
expectedCheckState,
`Advanced runtime mappings editor switch check state should be '${expectedCheckState}' (got '${actualCheckState}')`
);
},
async getRuntimeMappingsEditorSwitchCheckedState(): Promise<boolean> {
const subj = 'mlDataFrameAnalyticsRuntimeMappingsEditorSwitch';
const isSelected = await testSubjects.getAttribute(subj, 'aria-checked');
return isSelected === 'true';
},
async toggleRuntimeMappingsEditorSwitch(toggle: boolean) {
const subj = 'mlDataFrameAnalyticsRuntimeMappingsEditorSwitch';
if ((await this.getRuntimeMappingsEditorSwitchCheckedState()) !== toggle) {
await retry.tryForTime(5 * 1000, async () => {
await testSubjects.clickWhenNotDisabled(subj);
await this.assertRuntimeMappingsEditorSwitchCheckState(toggle);
});
}
},
async setRuntimeMappingsEditorContent(input: string) {
await aceEditor.setValue('mlDataFrameAnalyticsAdvancedRuntimeMappingsEditor', input);
},
async assertRuntimeMappingsEditorContent(expectedContent: string[]) {
await this.assertRuntimeMappingEditorExists();
const runtimeMappingsEditorString = await aceEditor.getValue(
'mlDataFrameAnalyticsAdvancedRuntimeMappingsEditor'
);
// Not all lines may be visible in the editor and thus aceEditor may not return all lines.
// This means we might not get back valid JSON so we only test against the first few lines
// and see if the string matches.
const splicedAdvancedEditorValue = runtimeMappingsEditorString.split('\n').splice(0, 3);
expect(splicedAdvancedEditorValue).to.eql(
expectedContent,
`Expected the first editor lines to be '${expectedContent}' (got '${splicedAdvancedEditorValue}')`
);
},
async applyRuntimeMappings() {
const subj = 'mlDataFrameAnalyticsRuntimeMappingsApplyButton';
await testSubjects.existOrFail(subj);
await testSubjects.clickWhenNotDisabled(subj);
const isEnabled = await testSubjects.isEnabled(subj);
expect(isEnabled).to.eql(
false,
`Expected runtime mappings 'Apply changes' button to be disabled, got enabled.`
);
},
async assertDependentVariableSelection(expectedSelection: string[]) {
await this.waitForDependentVariableInputLoaded();
const actualSelection = await comboBox.getComboBoxSelectedOptions(