diff --git a/frontend/src/__mocks__/index.ts b/frontend/src/__mocks__/index.ts index 37611da8a9..b73f92d395 100644 --- a/frontend/src/__mocks__/index.ts +++ b/frontend/src/__mocks__/index.ts @@ -13,3 +13,5 @@ export * from './mockDscStatus'; export * from './mockNotebookK8sResource'; export * from './mockPipelineKF'; export * from './mockSecretK8sResource'; +export * from './mockGoogleRpcStatusKF'; +export * from './mockK8sStatus'; diff --git a/frontend/src/__tests__/cypress/cypress.config.ts b/frontend/src/__tests__/cypress/cypress.config.ts index cb1bcf733e..4c4c1f5f00 100644 --- a/frontend/src/__tests__/cypress/cypress.config.ts +++ b/frontend/src/__tests__/cypress/cypress.config.ts @@ -52,7 +52,7 @@ export default defineConfig({ ODH_PRODUCT_NAME: env.ODH_PRODUCT_NAME, resolution: 'high', }, - defaultCommandTimeout: 10000, + defaultCommandTimeout: 15000, e2e: { baseUrl: BASE_URL, specPattern: env.CY_MOCK diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts index e6fdce200f..288a95c796 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelines.cy.ts @@ -1,13 +1,16 @@ /* eslint-disable camelcase */ -import { mockDataSciencePipelineApplicationK8sResource } from '~/__mocks__/mockDataSciencePipelinesApplicationK8sResource'; -import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList'; -import { buildMockPipelineV2, buildMockPipelines } from '~/__mocks__/mockPipelinesProxy'; import { + mockDataSciencePipelineApplicationK8sResource, + mockK8sResourceList, + buildMockPipelineV2, + buildMockPipelines, buildMockPipelineVersionV2, buildMockPipelineVersionsV2, -} from '~/__mocks__/mockPipelineVersionsProxy'; -import { mockProjectK8sResource } from '~/__mocks__/mockProjectK8sResource'; -import { mockRouteK8sResource } from '~/__mocks__/mockRouteK8sResource'; + mockProjectK8sResource, + mockRouteK8sResource, + mockSecretK8sResource, + mockSuccessGoogleRpcStatus, +} from '~/__mocks__'; import { pipelinesGlobal, pipelinesTable, @@ -26,10 +29,8 @@ import { SecretModel, } from '~/__tests__/cypress/cypress/utils/models'; import { asProductAdminUser } from '~/__tests__/cypress/cypress/utils/mockUsers'; -import { mockSecretK8sResource } from '~/__mocks__/mockSecretK8sResource'; import type { PipelineKFv2 } from '~/concepts/pipelines/kfTypes'; import { tablePagination } from '~/__tests__/cypress/cypress/pages/components/Pagination'; -import { mockSuccessGoogleRpcStatus } from '~/__mocks__/mockGoogleRpcStatusKF'; const projectName = 'test-project-name'; const initialMockPipeline = buildMockPipelineV2({ display_name: 'Test pipeline' }); @@ -602,8 +603,10 @@ describe('Pipelines', () => { }); }); - // Verify the uploaded pipeline is in the table - pipelinesTable.getRowById(uploadedMockPipeline.pipeline_id).find().should('exist'); + cy.url().should( + 'include', + `/pipelines/${projectName}/${uploadedMockPipeline.pipeline_id}/${initialMockPipelineVersion.pipeline_version_id}/view`, + ); }); it('fails to import a too-large file', () => { @@ -638,6 +641,9 @@ describe('Pipelines', () => { }, }; const createdMockPipeline = buildMockPipelineV2(createPipelineAndVersionParams.pipeline); + const createdVersion = buildMockPipelineVersionV2( + createPipelineAndVersionParams.pipeline_version, + ); // Intercept upload/re-fetch of pipelines pipelineImportModal @@ -646,11 +652,7 @@ describe('Pipelines', () => { pipelinesTable .mockGetPipelines([initialMockPipeline, createdMockPipeline], projectName) .as('refreshPipelines'); - pipelinesTable.mockGetPipelineVersions( - [buildMockPipelineVersionV2(createPipelineAndVersionParams.pipeline_version)], - 'new-pipeline', - projectName, - ); + pipelinesTable.mockGetPipelineVersions([createdVersion], 'new-pipeline', projectName); // Wait for the pipelines table to load pipelinesTable.find(); @@ -670,8 +672,10 @@ describe('Pipelines', () => { cy.wait('@createPipelineAndVersion'); cy.wait('@refreshPipelines'); - // Verify the uploaded pipeline is in the table - pipelinesTable.getRowById(createdMockPipeline.pipeline_id).find().should('exist'); + cy.url().should( + 'include', + `/pipelines/${projectName}/${createdMockPipeline.pipeline_id}/${createdVersion.pipeline_version_id}/view`, + ); }); it('uploads a new pipeline version', () => { diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts index a4b6291f7d..0ee0a6f655 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/pipelines/pipelinesList.cy.ts @@ -5,11 +5,12 @@ import { mockProjectK8sResource, mockRouteK8sResource, mockSecretK8sResource, + mockDataSciencePipelineApplicationK8sResource, + mockK8sResourceList, + mock404Error, + buildMockPipelineV2, + buildMockPipelines, } from '~/__mocks__'; -import { mockDataSciencePipelineApplicationK8sResource } from '~/__mocks__/mockDataSciencePipelinesApplicationK8sResource'; -import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList'; -import { mock404Error } from '~/__mocks__/mockK8sStatus'; -import { buildMockPipelineV2, buildMockPipelines } from '~/__mocks__/mockPipelinesProxy'; import { pipelinesTable, configurePipelineServerModal, diff --git a/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx b/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx index 923f37529c..2d17b98fa1 100644 --- a/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx +++ b/frontend/src/concepts/pipelines/content/import/PipelineImportModal.tsx @@ -1,4 +1,6 @@ import * as React from 'react'; +import { useNavigate } from 'react-router-dom'; + import { Alert, Button, @@ -10,12 +12,14 @@ import { TextArea, TextInput, } from '@patternfly/react-core'; + import { usePipelinesAPI } from '~/concepts/pipelines/context'; import { usePipelineImportModalData } from '~/concepts/pipelines/content/import/useImportModalData'; import { PipelineKFv2 } from '~/concepts/pipelines/kfTypes'; import { getDisplayNameFromK8sResource } from '~/concepts/k8s/utils'; import { DuplicateNameHelperText } from '~/concepts/pipelines/content/DuplicateNameHelperText'; import { getNameEqualsFilter } from '~/concepts/pipelines/utils'; +import { pipelineVersionDetailsRoute } from '~/routes'; import PipelineUploadRadio from './PipelineUploadRadio'; import { PipelineUploadOption } from './utils'; @@ -25,7 +29,8 @@ type PipelineImportModalProps = { }; const PipelineImportModal: React.FC = ({ isOpen, onClose }) => { - const { project, api, apiAvailable } = usePipelinesAPI(); + const navigate = useNavigate(); + const { project, api, apiAvailable, namespace } = usePipelinesAPI(); const [importing, setImporting] = React.useState(false); const [error, setError] = React.useState(); const [{ name, description, fileContents, pipelineUrl, uploadOption }, setData, resetData] = @@ -39,12 +44,35 @@ const PipelineImportModal: React.FC = ({ isOpen, onClo hasDuplicateName || (uploadOption === PipelineUploadOption.URL_IMPORT ? !pipelineUrl : !fileContents); - const onBeforeClose = (pipeline?: PipelineKFv2) => { - onClose(pipeline); - setImporting(false); - setError(undefined); - resetData(); - }; + const onBeforeClose = React.useCallback( + (pipeline?: PipelineKFv2) => { + onClose(pipeline); + setImporting(false); + setError(undefined); + resetData(); + }, + [onClose, resetData], + ); + + const onSubmitSuccess = React.useCallback( + async (pipeline: PipelineKFv2) => { + onBeforeClose(pipeline); + + const { pipeline_versions: versions } = await api.listPipelineVersions( + {}, + pipeline.pipeline_id, + { + pageSize: 1, + }, + ); + const versionId = versions?.[0].pipeline_version_id; + + if (versionId) { + navigate(pipelineVersionDetailsRoute(namespace, pipeline.pipeline_id, versionId)); + } + }, + [api, namespace, navigate, onBeforeClose], + ); const onNameBlur = React.useCallback(async () => { if (name) { @@ -66,7 +94,7 @@ const PipelineImportModal: React.FC = ({ isOpen, onClo if (uploadOption === PipelineUploadOption.FILE_UPLOAD) { api .uploadPipeline({}, name, description, fileContents) - .then((pipeline) => onBeforeClose(pipeline)) + .then(onSubmitSuccess) .catch((e) => { setImporting(false); setError(e); @@ -91,7 +119,7 @@ const PipelineImportModal: React.FC = ({ isOpen, onClo }, }, ) - .then((pipeline) => onBeforeClose(pipeline)) + .then(onSubmitSuccess) .catch((e) => { setImporting(false); setError(e);