Skip to content

Commit

Permalink
[ML] Functional tests for the Test Model action (#146399)
Browse files Browse the repository at this point in the history
## Summary

Part of #142456

Adds functional tests for the Test model action


### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
darnautov authored Nov 30, 2022
1 parent 8a6cc0c commit 9ad78b2
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface MlJobEditorProps {
syntaxChecking?: boolean;
theme?: string;
onChange?: EuiCodeEditorProps['onChange'];
'data-test-subj'?: string;
}
export const MLJobEditor: FC<MlJobEditorProps> = ({
value,
Expand All @@ -34,6 +35,7 @@ export const MLJobEditor: FC<MlJobEditorProps> = ({
syntaxChecking = true,
theme = 'textmate',
onChange = () => {},
'data-test-subj': dataTestSubj,
}) => {
if (mode === ML_EDITOR_MODE.XJSON) {
try {
Expand Down Expand Up @@ -61,6 +63,7 @@ export const MLJobEditor: FC<MlJobEditorProps> = ({
useSoftTabs: true,
}}
onChange={onChange}
data-test-subj={dataTestSubj}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { FC, useState, useMemo, useCallback } from 'react';
import React, { FC, useState, useMemo, useCallback, FormEventHandler } from 'react';

import useObservable from 'react-use/lib/useObservable';
import { FormattedMessage } from '@kbn/i18n-react';
Expand All @@ -18,6 +18,7 @@ import {
EuiHorizontalRule,
EuiLoadingSpinner,
EuiText,
EuiForm,
} from '@elastic/eui';

import { ErrorMessage } from '../../inference_error';
Expand All @@ -41,17 +42,21 @@ export const IndexInputForm: FC<Props> = ({ inferrer }) => {
const outputComponent = useMemo(() => inferrer.getOutputComponent(), [inferrer]);
const infoComponent = useMemo(() => inferrer.getInfoComponent(), [inferrer]);

const run = useCallback(async () => {
setErrorText(null);
try {
await inferrer.infer();
} catch (e) {
setErrorText(extractErrorMessage(e));
}
}, [inferrer]);
const run: FormEventHandler<HTMLFormElement> = useCallback(
async (event) => {
event.preventDefault();
setErrorText(null);
try {
await inferrer.infer();
} catch (e) {
setErrorText(extractErrorMessage(e));
}
},
[inferrer]
);

return (
<>
<EuiForm component={'form'} onSubmit={run}>
<>{infoComponent}</>
<InferenceInputFormIndexControls inferrer={inferrer} data={data} />

Expand All @@ -60,9 +65,10 @@ export const IndexInputForm: FC<Props> = ({ inferrer }) => {
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiButton
onClick={run}
disabled={runningState === RUNNING_STATE.RUNNING || isValid === false}
fullWidth={false}
data-test-subj={'mlTestModelTestButton'}
type={'submit'}
>
<FormattedMessage
id="xpack.ml.trainedModels.testModelsFlyout.inferenceInputForm.runButton"
Expand Down Expand Up @@ -105,6 +111,6 @@ export const IndexInputForm: FC<Props> = ({ inferrer }) => {
: null}

{runningState === RUNNING_STATE.FINISHED ? <>{outputComponent}</> : null}
</>
</EuiForm>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
* 2.0.
*/

import React, { FC, useState, useMemo, useCallback } from 'react';
import React, { FC, useState, useMemo, useCallback, FormEventHandler } from 'react';

import useObservable from 'react-use/lib/useObservable';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiSpacer, EuiButton, EuiTabs, EuiTab } from '@elastic/eui';
import { EuiSpacer, EuiButton, EuiTabs, EuiTab, EuiForm } from '@elastic/eui';

import { ErrorMessage } from '../../inference_error';
import { extractErrorMessage } from '../../../../../../../common';
Expand Down Expand Up @@ -37,25 +37,30 @@ export const TextInputForm: FC<Props> = ({ inferrer }) => {
const outputComponent = useMemo(() => inferrer.getOutputComponent(), [inferrer]);
const infoComponent = useMemo(() => inferrer.getInfoComponent(), [inferrer]);

const run = useCallback(async () => {
setErrorText(null);
try {
await inferrer.infer();
} catch (e) {
setErrorText(extractErrorMessage(e));
}
}, [inferrer]);
const run: FormEventHandler<HTMLFormElement> = useCallback(
async (event) => {
event.preventDefault();
setErrorText(null);
try {
await inferrer.infer();
} catch (e) {
setErrorText(extractErrorMessage(e));
}
},
[inferrer]
);

return (
<>
<EuiForm component={'form'} onSubmit={run}>
<>{infoComponent}</>
<>{inputComponent}</>
<EuiSpacer size="m" />
<div>
<EuiButton
onClick={run}
disabled={runningState === RUNNING_STATE.RUNNING || isValid === false}
fullWidth={false}
data-test-subj={'mlTestModelTestButton'}
type="submit"
>
<FormattedMessage
id="xpack.ml.trainedModels.testModelsFlyout.inferenceInputForm.runButton"
Expand Down Expand Up @@ -100,13 +105,15 @@ export const TextInputForm: FC<Props> = ({ inferrer }) => {
</>
) : null}

{runningState === RUNNING_STATE.FINISHED ? <>{outputComponent}</> : null}
{runningState === RUNNING_STATE.FINISHED ? (
<div data-test-subj={'mlTestModelOutput'}>{outputComponent}</div>
) : null}
</>
) : (
<RawOutput inferrer={inferrer} />
)}
</>
) : null}
</>
</EuiForm>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const RawOutput: FC<{

return (
<>
<MLJobEditor value={rawResponse ?? ''} readOnly={true} />
<MLJobEditor data-test-subj={'mlTestModelRawOutput'} value={rawResponse ?? ''} readOnly />
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ const LanguageIdent: FC<{

return (
<>
<EuiText size="s">{inputText}</EuiText>
<EuiText size="s" data-test-subj={'mlTestModelLangIdentInputText'}>
{inputText}
</EuiText>
<EuiSpacer size="s" />
<EuiTitle size="xxs">
<h4>{title}</h4>
<h4 data-test-subj={'mlTestModelLangIdentTitle'}>{title}</h4>
</EuiTitle>

<EuiSpacer />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { FC } from 'react';
import React, { type FC, Fragment } from 'react';
import useObservable from 'react-use/lib/useObservable';
import {
EuiFlexGroup,
Expand Down Expand Up @@ -72,17 +72,17 @@ export const PredictionProbabilityList: FC<{
) : null}

{response.map(({ value, predictionProbability }) => (
<>
<Fragment key={value}>
<EuiProgress value={predictionProbability * 100} max={100} size="m" />
<EuiSpacer size="s" />
<EuiFlexGroup>
<>
<EuiFlexItem>{value}</EuiFlexItem>
<EuiFlexItem grow={false}>{predictionProbability}</EuiFlexItem>
</>
<EuiFlexItem data-test-subj={`mlTestModelLangIdentInputValue`}>{value}</EuiFlexItem>
<EuiFlexItem data-test-subj={`mlTestModelLangIdentInputProbability`} grow={false}>
{predictionProbability}
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer />
</>
</Fragment>
))}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const TextInput: FC<{
onChange={(e) => {
setInputText(e.target.value);
}}
data-test-subj={`mlTestModelInputText`}
/>
</EuiFormRow>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ export const OutputLoadingContent: FC<{ text: string }> = ({ text }) => {
const actualLines = text.split(/\r\n|\r|\n/).length + 1;
const lines = actualLines > 4 && actualLines <= 10 ? actualLines : 4;

return <EuiLoadingContent lines={lines as LineRange} />;
return (
<EuiLoadingContent data-test-subj={'mlTestModelLoadingContent'} lines={lines as LineRange} />
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.trainedModelsTable.assertPipelinesTabContent(false);
});

it('displays the built-in model and no actions are enabled', async () => {
it('displays the built-in model with only Test action enabled', async () => {
await ml.testExecution.logTestStep('should display the model in the table');
await ml.trainedModelsTable.filterWithSearchString(builtInModelData.modelId, 1);

Expand Down Expand Up @@ -121,6 +121,21 @@ export default function ({ getService }: FtrProviderContext) {
builtInModelData.modelId,
false
);

await ml.testExecution.logTestStep('should have enabled the button that opens Test flyout');
await ml.trainedModelsTable.assertModelTestButtonExists(builtInModelData.modelId, true);

await ml.trainedModelsTable.testModel(
'lang_ident',
builtInModelData.modelId,
{
inputText: 'Goedemorgen! Ik ben een appel.',
},
{
title: 'This looks like Dutch,Flemish',
topLang: { code: 'nl', minProbability: 0.9 },
}
);
});

it('displays a model with an ingest pipeline and delete action is disabled', async () => {
Expand Down
25 changes: 18 additions & 7 deletions x-pack/test/functional/services/ml/common_ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,17 +402,28 @@ export function MachineLearningCommonUIProvider({
});
},

async invokeTableRowAction(rowSelector: string, actionTestSubject: string) {
async invokeTableRowAction(
rowSelector: string,
actionTestSubject: string,
fromContextMenu: boolean = true
) {
await retry.tryForTime(30 * 1000, async () => {
await this.ensureAllMenuPopoversClosed();
await testSubjects.click(`${rowSelector} > euiCollapsedItemActionsButton`);
await find.existsByCssSelector('euiContextMenuPanel');
if (fromContextMenu) {
await this.ensureAllMenuPopoversClosed();

await testSubjects.click(`${rowSelector} > euiCollapsedItemActionsButton`);
await find.existsByCssSelector('euiContextMenuPanel');

const isEnabled = await testSubjects.isEnabled(actionTestSubject);
const isEnabled = await testSubjects.isEnabled(actionTestSubject);

expect(isEnabled).to.eql(true, `Expected action "${actionTestSubject}" to be enabled.`);
expect(isEnabled).to.eql(true, `Expected action "${actionTestSubject}" to be enabled.`);

await testSubjects.click(actionTestSubject);
await testSubjects.click(actionTestSubject);
} else {
const isEnabled = await testSubjects.isEnabled(`${rowSelector} > ${actionTestSubject}`);
expect(isEnabled).to.eql(true, `Expected action "${actionTestSubject}" to be enabled.`);
await testSubjects.click(`${rowSelector} > ${actionTestSubject}`);
}
});
},
};
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/functional/services/ml/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export function MachineLearningProvider(context: FtrProviderContext) {
const alerting = MachineLearningAlertingProvider(context, api, commonUI);
const swimLane = SwimLaneProvider(context);
const trainedModels = TrainedModelsProvider(context, commonUI);
const trainedModelsTable = TrainedModelsTableProvider(context, commonUI);
const trainedModelsTable = TrainedModelsTableProvider(context, commonUI, trainedModels);
const mlNodesPanel = MlNodesPanelProvider(context);
const notifications = NotificationsProvider(context, commonUI, tableService);

Expand Down
Loading

0 comments on commit 9ad78b2

Please sign in to comment.