From 2aad00265af0c2bbad14494a955227dcde553ae0 Mon Sep 17 00:00:00 2001 From: Thiago Dallacqua <104855841+thiagodallacqua-hpe@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:51:07 -0300 Subject: [PATCH] feat: add e2e tests for the "move" experiment row action (#10070) --- .../src/components/ExperimentMoveModal.tsx | 2 + .../components/ExperimentActionDropdown.ts | 4 + .../models/components/ExperimentMoveModal.ts | 16 ++++ .../src/e2e/tests/experimentList.spec.ts | 83 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 webui/react/src/e2e/models/components/ExperimentMoveModal.ts diff --git a/webui/react/src/components/ExperimentMoveModal.tsx b/webui/react/src/components/ExperimentMoveModal.tsx index 07e380ea5c88..f46f1b643577 100644 --- a/webui/react/src/components/ExperimentMoveModal.tsx +++ b/webui/react/src/components/ExperimentMoveModal.tsx @@ -169,6 +169,7 @@ const ExperimentMoveModalComponent: React.FC = ({ name="workspaceId" rules={[{ message: 'Workspace is required', required: true }]}> (option?.title?.toString() ?? '').toLowerCase().includes(input.toLowerCase()) } diff --git a/webui/react/src/e2e/models/components/ExperimentActionDropdown.ts b/webui/react/src/e2e/models/components/ExperimentActionDropdown.ts index f95d12a34500..4c0cb3d2bd0e 100644 --- a/webui/react/src/e2e/models/components/ExperimentActionDropdown.ts +++ b/webui/react/src/e2e/models/components/ExperimentActionDropdown.ts @@ -1,6 +1,7 @@ import { DropdownMenu } from 'e2e/models/common/hew/Dropdown'; import ExperimentEditModal from './ExperimentEditModal'; +import ExperimentMoveModal from './ExperimentMoveModal'; /** * Represents the ExperimentActionDropdown component in src/components/ExperimentActionDropdown.tsx @@ -14,4 +15,7 @@ export class ExperimentActionDropdown extends DropdownMenu { readonly editModal = new ExperimentEditModal({ root: this.root, }); + readonly moveModal = new ExperimentMoveModal({ + root: this.root, + }); } diff --git a/webui/react/src/e2e/models/components/ExperimentMoveModal.ts b/webui/react/src/e2e/models/components/ExperimentMoveModal.ts new file mode 100644 index 000000000000..cd90cd80334a --- /dev/null +++ b/webui/react/src/e2e/models/components/ExperimentMoveModal.ts @@ -0,0 +1,16 @@ +import { Modal } from 'e2e/models/common/hew/Modal'; +import { Select } from 'e2e/models/common/hew/Select'; + +/** + * Represents the ExperimentMoveModal component in src/components/ExperimentMoveModal.tsx + */ +export default class ExperimentMoveModal extends Modal { + readonly destinationWorkspace = new Select({ + parent: this, + selector: '[data-test="workspace"]', + }); + readonly destinationProject = new Select({ + parent: this, + selector: '[data-test="project"]', + }); +} diff --git a/webui/react/src/e2e/tests/experimentList.spec.ts b/webui/react/src/e2e/tests/experimentList.spec.ts index e2bcc21a50b9..ece0eaf536f3 100644 --- a/webui/react/src/e2e/tests/experimentList.spec.ts +++ b/webui/react/src/e2e/tests/experimentList.spec.ts @@ -4,6 +4,7 @@ import { ProjectDetails } from 'e2e/models/pages/ProjectDetails'; import { detExecSync, fullPath } from 'e2e/utils/detCLI'; import { safeName } from 'e2e/utils/naming'; import { repeatWithFallback } from 'e2e/utils/polling'; +import { V1Project } from 'services/api-ts-sdk'; import { ExperimentBase } from 'types'; test.describe('Experiment List', () => { @@ -559,4 +560,86 @@ test.describe('Experiment List', () => { }); }); }); + + test.describe('Row Actions', () => { + let destinationProject: V1Project; + let experimentId: number; + + // create a new project, workspace and experiment + test.beforeAll( + async ({ + backgroundApiProject, + newProject: { + response: { project }, + }, + }) => { + destinationProject = ( + await backgroundApiProject.createProject( + project.workspaceId, + backgroundApiProject.new({ projectProps: { workspaceId: project.workspaceId } }), + ) + ).project; + + const expId = Number( + detExecSync( + `experiment create ${fullPath('examples/tutorials/mnist_pytorch/adaptive.yaml')} --paused --project_id ${project.id}`, + ).split(' ')[2], + ); // returns in the format "Created experiment " + + if (Number.isNaN(expId)) throw new Error('No experiment ID was found'); + + experimentId = expId; + }, + ); + + // cleanup + test.afterAll(async ({ backgroundApiProject }) => { + if (experimentId !== undefined) { + detExecSync(`experiment kill ${experimentId}`); + detExecSync(`experiment delete ${experimentId} --y`); + } + + await backgroundApiProject.deleteProject(destinationProject.id); + }); + + test('move experiment', async ({ + newWorkspace: { + response: { workspace }, + }, + }) => { + if (experimentId === undefined) throw new Error('No experiment ID was found'); + + const newExperimentRow = + await projectDetailsPage.f_experimentList.dataGrid.getRowByColumnValue( + 'ID', + experimentId.toString(), + ); + + const experimentActionDropdown = await newExperimentRow.experimentActionDropdown.open(); + + await experimentActionDropdown.menuItem('Move').pwLocator.click(); + await experimentActionDropdown.moveModal.destinationWorkspace.selectMenuOption( + workspace.name, + ); + await experimentActionDropdown.moveModal.destinationProject.pwLocator.waitFor({ + state: 'visible', + }); + await experimentActionDropdown.moveModal.destinationProject.selectMenuOption( + destinationProject.name, + ); + await experimentActionDropdown.moveModal.footer.submit.pwLocator.click(); + await experimentActionDropdown.moveModal.pwLocator.waitFor({ state: 'hidden' }); + + await newExperimentRow.pwLocator.waitFor({ state: 'hidden' }); + + await projectDetailsPage.gotoProject(destinationProject.id); + const grid = projectDetailsPage.f_experimentList.dataGrid; + await grid.setColumnHeight(); + await grid.headRow.setColumnDefs(); + const newProjectRows = await projectDetailsPage.f_experimentList.dataGrid.filterRows(() => + Promise.resolve(true), + ); + await expect(newProjectRows.length).toBe(1); + }); + }); });