mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* test start model deployment
* start and stop tests
* wait for refresh
* wait for refresh
* update assertLastToastHeader with retry
(cherry picked from commit b08914c0db
)
Co-authored-by: Dima Arnautov <dmitrii.arnautov@elastic.co>
This commit is contained in:
parent
6c6a872ebd
commit
d8f57738ff
5 changed files with 134 additions and 11 deletions
|
@ -345,6 +345,7 @@ export const ModelsList: FC<Props> = ({
|
|||
description: i18n.translate('xpack.ml.inference.modelsList.startModelDeploymentActionLabel', {
|
||||
defaultMessage: 'Start deployment',
|
||||
}),
|
||||
'data-test-subj': 'mlModelsTableRowStartDeploymentAction',
|
||||
icon: 'play',
|
||||
type: 'icon',
|
||||
isPrimary: true,
|
||||
|
@ -399,6 +400,7 @@ export const ModelsList: FC<Props> = ({
|
|||
description: i18n.translate('xpack.ml.inference.modelsList.stopModelDeploymentActionLabel', {
|
||||
defaultMessage: 'Stop deployment',
|
||||
}),
|
||||
'data-test-subj': 'mlModelsTableRowStopDeploymentAction',
|
||||
icon: 'stop',
|
||||
type: 'icon',
|
||||
isPrimary: true,
|
||||
|
@ -497,6 +499,7 @@ export const ModelsList: FC<Props> = ({
|
|||
description: i18n.translate('xpack.ml.inference.modelsList.testModelActionLabel', {
|
||||
defaultMessage: 'Test model',
|
||||
}),
|
||||
'data-test-subj': 'mlModelsTableRowTestAction',
|
||||
icon: 'inputOutput',
|
||||
type: 'icon',
|
||||
isPrimary: true,
|
||||
|
|
|
@ -111,6 +111,7 @@ export const StartDeploymentSetup: FC<StartDeploymentSetup> = ({ config, onConfi
|
|||
onChange={(event) => {
|
||||
onConfigChange({ ...config, numOfAllocations: Number(event.target.value) });
|
||||
}}
|
||||
data-test-subj={'mlModelsStartDeploymentModalNumOfAllocations'}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
|
@ -156,6 +157,7 @@ export const StartDeploymentSetup: FC<StartDeploymentSetup> = ({ config, onConfi
|
|||
onConfigChange({ ...config, threadsPerAllocations: value });
|
||||
}}
|
||||
options={threadsPerAllocationsOptions}
|
||||
data-test-subj={'mlModelsStartDeploymentModalThreadsPerAllocation'}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
|
@ -195,7 +197,12 @@ export const StartDeploymentModal: FC<StartDeploymentModalProps> = ({
|
|||
const errors = numOfAllocationsValidator(config.numOfAllocations);
|
||||
|
||||
return (
|
||||
<EuiModal onClose={onClose} initialFocus="[name=numOfAllocations]" maxWidth={false}>
|
||||
<EuiModal
|
||||
onClose={onClose}
|
||||
initialFocus="[name=numOfAllocations]"
|
||||
maxWidth={false}
|
||||
data-test-subj="mlModelsStartDeploymentModal"
|
||||
>
|
||||
<EuiModalHeader>
|
||||
<EuiModalHeaderTitle>
|
||||
<EuiFlexGroup justifyContent={'spaceBetween'}>
|
||||
|
@ -288,6 +295,7 @@ export const StartDeploymentModal: FC<StartDeploymentModalProps> = ({
|
|||
onClick={onConfigChange.bind(null, config)}
|
||||
fill
|
||||
disabled={!!errors}
|
||||
data-test-subj={'mlModelsStartDeploymentModalStartButton'}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.trainedModels.modelsList.startDeployment.startButton"
|
||||
|
|
|
@ -91,16 +91,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
await ml.trainedModelsTable.assertPipelinesTabContent(false);
|
||||
});
|
||||
|
||||
for (const model of trainedModels) {
|
||||
it(`renders expanded row content correctly for imported tiny model ${model.id} without pipelines`, async () => {
|
||||
await ml.trainedModelsTable.ensureRowIsExpanded(model.id);
|
||||
await ml.trainedModelsTable.assertDetailsTabContent();
|
||||
await ml.trainedModelsTable.assertInferenceConfigTabContent();
|
||||
await ml.trainedModelsTable.assertStatsTabContent();
|
||||
await ml.trainedModelsTable.assertPipelinesTabContent(false);
|
||||
});
|
||||
}
|
||||
|
||||
it('displays the built-in model and no actions are enabled', async () => {
|
||||
await ml.testExecution.logTestStep('should display the model in the table');
|
||||
await ml.trainedModelsTable.filterWithSearchString(builtInModelData.modelId, 1);
|
||||
|
@ -186,6 +176,29 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
false
|
||||
);
|
||||
});
|
||||
|
||||
describe('with imported models', function () {
|
||||
for (const model of trainedModels) {
|
||||
it(`renders expanded row content correctly for imported tiny model ${model.id} without pipelines`, async () => {
|
||||
await ml.trainedModelsTable.ensureRowIsExpanded(model.id);
|
||||
await ml.trainedModelsTable.assertDetailsTabContent();
|
||||
await ml.trainedModelsTable.assertInferenceConfigTabContent();
|
||||
await ml.trainedModelsTable.assertStatsTabContent();
|
||||
await ml.trainedModelsTable.assertPipelinesTabContent(false);
|
||||
});
|
||||
|
||||
it(`starts deployment of the imported model ${model.id}`, async () => {
|
||||
await ml.trainedModelsTable.startDeploymentWithParams(model.id, {
|
||||
numOfAllocations: 1,
|
||||
threadsPerAllocation: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it(`stops deployment of the imported model ${model.id}`, async () => {
|
||||
await ml.trainedModelsTable.stopDeployment(model.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('for ML user with read-only access', () => {
|
||||
|
|
|
@ -32,6 +32,7 @@ export function MachineLearningCommonUIProvider({
|
|||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const browser = getService('browser');
|
||||
const toasts = getService('toasts');
|
||||
|
||||
return {
|
||||
async setValueWithChecks(
|
||||
|
@ -356,5 +357,36 @@ export function MachineLearningCommonUIProvider({
|
|||
);
|
||||
});
|
||||
},
|
||||
|
||||
async selectButtonGroupValue(inputTestSubj: string, value: string) {
|
||||
await retry.tryForTime(5000, async () => {
|
||||
// The input element can not be clicked directly.
|
||||
// Instead, we need to click the corresponding label
|
||||
|
||||
const fieldSetElement = await testSubjects.find(inputTestSubj);
|
||||
|
||||
const labelElement = await fieldSetElement.findByCssSelector(`label[title="${value}"]`);
|
||||
await labelElement.click();
|
||||
|
||||
const labelClasses = await labelElement.getAttribute('class');
|
||||
expect(labelClasses).to.contain(
|
||||
'euiButtonGroupButton-isSelected',
|
||||
`Label for '${inputTestSubj}' should be selected`
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
async assertLastToastHeader(expectedHeader: string, timeout: number = 5000) {
|
||||
await retry.tryForTime(timeout, async () => {
|
||||
const resultToast = await toasts.getToastElement(1);
|
||||
const titleElement = await testSubjects.findDescendant('euiToastHeader', resultToast);
|
||||
const title: string = await titleElement.getVisibleText();
|
||||
expect(title).to.eql(
|
||||
expectedHeader,
|
||||
`Expected the toast header to equal "${expectedHeader}" (got "${title}")`
|
||||
);
|
||||
});
|
||||
await toasts.dismissAllToasts();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -197,6 +197,14 @@ export function TrainedModelsTableProvider(
|
|||
await testSubjects.existOrFail('mlModelsDeleteModal', { timeout: 60 * 1000 });
|
||||
}
|
||||
|
||||
public async assertStartDeploymentModalExists(expectExist = true) {
|
||||
if (expectExist) {
|
||||
await testSubjects.existOrFail('mlModelsStartDeploymentModal', { timeout: 60 * 1000 });
|
||||
} else {
|
||||
await testSubjects.missingOrFail('mlModelsStartDeploymentModal', { timeout: 60 * 1000 });
|
||||
}
|
||||
}
|
||||
|
||||
public async assertDeleteModalNotExists() {
|
||||
await testSubjects.missingOrFail('mlModelsDeleteModal', { timeout: 60 * 1000 });
|
||||
}
|
||||
|
@ -214,6 +222,65 @@ export function TrainedModelsTableProvider(
|
|||
await this.assertDeleteModalExists();
|
||||
}
|
||||
|
||||
async assertNumOfAllocations(expectedValue: number) {
|
||||
const actualValue = await testSubjects.getAttribute(
|
||||
'mlModelsStartDeploymentModalNumOfAllocations',
|
||||
'value'
|
||||
);
|
||||
expect(actualValue).to.eql(
|
||||
expectedValue,
|
||||
`Expected number of allocations to equal ${expectedValue}, got ${actualValue}`
|
||||
);
|
||||
}
|
||||
|
||||
public async setNumOfAllocations(value: number) {
|
||||
await testSubjects.setValue('mlModelsStartDeploymentModalNumOfAllocations', value.toString());
|
||||
await this.assertNumOfAllocations(value);
|
||||
}
|
||||
|
||||
public async setThreadsPerAllocation(value: number) {
|
||||
await mlCommonUI.selectButtonGroupValue(
|
||||
'mlModelsStartDeploymentModalThreadsPerAllocation',
|
||||
value.toString()
|
||||
);
|
||||
}
|
||||
|
||||
public async startDeploymentWithParams(
|
||||
modelId: string,
|
||||
params: { numOfAllocations: number; threadsPerAllocation: number }
|
||||
) {
|
||||
await this.openStartDeploymentModal(modelId);
|
||||
|
||||
await this.setNumOfAllocations(params.numOfAllocations);
|
||||
await this.setThreadsPerAllocation(params.threadsPerAllocation);
|
||||
|
||||
await testSubjects.click('mlModelsStartDeploymentModalStartButton');
|
||||
await this.assertStartDeploymentModalExists(false);
|
||||
|
||||
await mlCommonUI.waitForRefreshButtonEnabled();
|
||||
|
||||
await mlCommonUI.assertLastToastHeader(
|
||||
`Deployment for "${modelId}" has been started successfully.`
|
||||
);
|
||||
}
|
||||
|
||||
public async stopDeployment(modelId: string) {
|
||||
await this.clickStopDeploymentAction(modelId);
|
||||
await mlCommonUI.waitForRefreshButtonEnabled();
|
||||
await mlCommonUI.assertLastToastHeader(
|
||||
`Deployment for "${modelId}" has been stopped successfully.`
|
||||
);
|
||||
}
|
||||
|
||||
public async openStartDeploymentModal(modelId: string) {
|
||||
await testSubjects.click(this.rowSelector(modelId, 'mlModelsTableRowStartDeploymentAction'));
|
||||
await this.assertStartDeploymentModalExists(true);
|
||||
}
|
||||
|
||||
public async clickStopDeploymentAction(modelId: string) {
|
||||
await testSubjects.click(this.rowSelector(modelId, 'mlModelsTableRowStopDeploymentAction'));
|
||||
}
|
||||
|
||||
public async ensureRowIsExpanded(modelId: string) {
|
||||
await this.filterWithSearchString(modelId);
|
||||
await retry.tryForTime(10 * 1000, async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue