Skip to content

Commit

Permalink
Merge pull request #2287 from jpuzz0/RHOAIENG-265-pipeline-details-to…
Browse files Browse the repository at this point in the history
…olbar

[RHOAIENG-265] Update pipeline details page
  • Loading branch information
openshift-merge-bot[bot] authored Dec 11, 2023
2 parents fbceadc + 4484f19 commit 5b8f4c5
Show file tree
Hide file tree
Showing 37 changed files with 620 additions and 635 deletions.
686 changes: 166 additions & 520 deletions frontend/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
"npm-run-all": "^4.1.5",
"playwright": "^1.31.2",
"storybook": "^7.5.0",
"storybook-addon-react-router-v6": "^0.3.6",
"storybook-addon-react-router-v6": "^2.0.10",
"ts-jest": "^28.0.8"
},
"overrides": {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/__mocks__/mock-upload-pipeline-version.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test-yaml-content
4 changes: 4 additions & 0 deletions frontend/src/__mocks__/mockPipelineVersionTemplateResource.ts

Large diffs are not rendered by default.

27 changes: 25 additions & 2 deletions frontend/src/__mocks__/mockPipelineVersionsProxy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
/* eslint-disable camelcase */
import { PipelineVersionKF, RelationshipKF, ResourceTypeKF } from '~/concepts/pipelines/kfTypes';

/* eslint-disable camelcase */
export const mockPipelineVersionsProxy: PipelineVersionKF[] = [
export const buildMockPipelineVersion = (
pipelineVersion?: Partial<PipelineVersionKF>,
): PipelineVersionKF => ({
id: '8ce2d041-3eb9-41a0-828c-45209fdf1c20',
name: 'version-1',
created_at: '2023-12-07T16:08:01Z',
resource_references: [
{
key: { type: 'PIPELINE' as ResourceTypeKF, id: 'b2ff4cbf-f7f5-4c8a-b454-906bd9b00510' },
relationship: 'OWNER' as RelationshipKF,
},
],
description: 'test',
...pipelineVersion,
});

export const buildMockPipelineVersions = (
versions: PipelineVersionKF[] = mockPipelineVersionsList,
) => ({
versions,
total_size: versions.length,
});

export const mockPipelineVersionsList: PipelineVersionKF[] = [
{
id: 'ad1b7153-d2fd-4e5e-ae12-30c824b19b03',
name: 'flip coin_version_at_2023-12-01T01:42:09.321Z',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { test, expect } from '@playwright/test';
import { mockPipelineVersionsProxy } from '~/__mocks__/mockPipelineVersionsProxy';
import { mockPipelineVersionsList } from '~/__mocks__/mockPipelineVersionsProxy';
import { navigateToStory } from '~/__tests__/integration/utils';

test('Pipeline version selector - Test filter and view more', async ({ page }) => {
Expand All @@ -8,10 +8,10 @@ test('Pipeline version selector - Test filter and view more', async ({ page }) =
await expect(page.locator('[data-id="pipeline-selector-table-list-row"]')).toHaveCount(10);

// check the view more button and the label
await expect(page.getByText(`Showing 10/${mockPipelineVersionsProxy.length}`)).toBeVisible();
await expect(page.getByText(`Showing 10/${mockPipelineVersionsList.length}`)).toBeVisible();
await page.getByText('View more').click();
await expect(page.locator('[data-id="pipeline-selector-table-list-row"]')).toHaveCount(
mockPipelineVersionsProxy.length,
mockPipelineVersionsList.length,
);

// test the search
Expand All @@ -20,7 +20,7 @@ test('Pipeline version selector - Test filter and view more', async ({ page }) =
await expect(page.locator('[data-id="pipeline-selector-table-list-row"]')).toHaveCount(10);
await page.getByText('View more').click();
await expect(page.locator('[data-id="pipeline-selector-table-list-row"]')).toHaveCount(
mockPipelineVersionsProxy.filter((version) => version.name.startsWith(search)).length,
mockPipelineVersionsList.filter((version) => version.name.startsWith(search)).length,
);
await page.getByLabel('Filter pipelines').fill('test-no-result');
await expect(page.getByText('No results match the filter.')).toBeVisible();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import PipelineSelector from '~/concepts/pipelines/content/pipelineSelector/PipelineSelector';
import { pipelineVersionSelectorColumns } from '~/concepts/pipelines/content/pipelineSelector/columns';
import { mockPipelineVersionsProxy } from '~/__mocks__/mockPipelineVersionsProxy';
import { mockPipelineVersionsList } from '~/__mocks__/mockPipelineVersionsProxy';

export default {
component: PipelineSelector,
Expand All @@ -14,10 +14,10 @@ export const Default: StoryObj = {
<PipelineSelector
maxWidth="500px"
columns={pipelineVersionSelectorColumns}
data={mockPipelineVersionsProxy}
data={mockPipelineVersionsList}
onSelect={() => null}
placeHolder="Select a pipeline version"
searchHelperText={`Type a name to search your ${mockPipelineVersionsProxy.length} versions.`}
searchHelperText={`Type a name to search your ${mockPipelineVersionsList.length} versions.`}
isLoading={false}
/>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,16 @@ export default {
component: ModelServingGlobal,
parameters: {
reactRouter: {
routePath: '/modelServing/:namespace/*',
routeParams: { namespace: 'test-project' },
location: {
pathParams: {
namespace: 'test-project',
},
},
routing: [
{
path: '/modelServing/:namespace/*',
},
],
},
},
} as Meta<typeof ModelServingGlobal>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,16 @@ export default {
component: ModelServingPlatform,
parameters: {
reactRouter: {
routePath: '/projects/:namespace/*',
routeParams: { namespace: 'test-project' },
location: {
pathParams: {
namespace: 'test-project',
},
},
routing: [
{
path: '/projects/:namespace/*',
},
],
},
},
} as Meta<typeof ModelServingPlatform>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ test('Edit form fields match', async ({ page }) => {
navigateToStory('pages-notebookimagesettings-notebookimagesettings', 'edit-modal'),
);

await page.waitForSelector('[data-testid="notebook-image-modal"]');

// test inputs have correct values
expect(await page.getByTestId('byon-image-location-input').inputValue()).toBe(
'test-image:latest',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { test, expect } from '@playwright/test';
import { navigateToStory } from '~/__tests__/integration/utils';

test('page details are updated when a new pipeline version is selected', async ({ page }) => {
await page.goto(navigateToStory('pages-pipelines-pipelinedetails', 'default'));
await page.waitForSelector('[data-testid="pipeline-version-topology-content"]');

const toggleButtonInput = await page.getByTestId('pipeline-version-toggle-button');

// Verify default version is selected and visible by default
await expect(toggleButtonInput).toHaveText('Pipeline version: version-1');

await toggleButtonInput.click();
await page
.locator('[data-id="pipeline-selector-table-list-row"]', { hasText: 'version-2' })
.click();

// Verify new version is selected and visible after selection
await expect(toggleButtonInput).toHaveText('Pipeline version: version-2');
});

test('page details are updated after uploading a new version', async ({ page }) => {
const newVersionName = 'new-upload-version';

await page.goto(navigateToStory('pages-pipelines-pipelinedetails', 'default'));
await page.waitForSelector('[data-testid="pipeline-version-topology-content"]');

const toggleButtonInput = await page.getByTestId('pipeline-version-toggle-button');

// Verify default version is selected and visible by default
await expect(toggleButtonInput).toHaveText('Pipeline version: version-1');

await page.getByRole('button', { name: 'Actions' }).click();
await page.getByRole('menuitem', { name: 'Upload new version' }).click();

const versionNameInput = await page.getByLabel('Pipeline version name');
await versionNameInput.clear();
await versionNameInput.fill(newVersionName);

// Simulate file upload
await page.setInputFiles(
'[data-testid="pipeline-file-upload"] input[type="file"]',
'./src/__mocks__/mock-upload-pipeline-version.yaml',
);

const submitButton = await page.getByTestId('upload-version-submit-button');
await submitButton.click();
await page.waitForSelector('[data-testid="upload-version-modal"]', { state: 'hidden' });

// Verify new version is selected and visible after selection
await expect(toggleButtonInput).toHaveText(`Pipeline version: ${newVersionName}`);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React from 'react';

import { StoryObj } from '@storybook/react';
import { rest } from 'msw';

import PipelineDetails from '~/concepts/pipelines/content/pipelinesDetails/pipeline/PipelineDetails';
import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList';
import { mockProjectK8sResource } from '~/__mocks__/mockProjectK8sResource';
import { mockDataSciencePipelineApplicationK8sResource } from '~/__mocks__/mockDataSciencePipelinesApplicationK8sResource';
import { mockRouteK8sResource } from '~/__mocks__/mockRouteK8sResource';
import { mockSecretK8sResource } from '~/__mocks__/mockSecretK8sResource';
import { PipelineContextProvider } from '~/concepts/pipelines/context';
import mockPipelineVersionTemplateResource from '~/__mocks__/mockPipelineVersionTemplateResource';
import {
buildMockPipelineVersions,
buildMockPipelineVersion,
} from '~/__mocks__/mockPipelineVersionsProxy';
import { mockPipelinesProxy } from '~/__mocks__/mockPipelinesProxy';

const mockPipelineVersions = buildMockPipelineVersions([
buildMockPipelineVersion({ id: '1', name: 'version-1' }),
buildMockPipelineVersion({ id: '2', name: 'version-2' }),
buildMockPipelineVersion({ id: '3', name: 'version-3' }),
]);

export default {
component: PipelineDetails,
parameters: {
reactRouter: {
location: {
pathParams: {
namespace: 'test-project',
pipelineVersionId: mockPipelineVersions.versions[0].id,
},
},
routing: [
{
path: '/pipelines/:namespace/pipeline/view/:pipelineVersionId',
},
],
},
msw: {
handlers: [
rest.get('/api/k8s/apis/project.openshift.io/v1/projects', (req, res, ctx) =>
res(ctx.json(mockK8sResourceList([mockProjectK8sResource({})]))),
),
rest.get(
'/api/k8s/apis/datasciencepipelinesapplications.opendatahub.io/v1alpha1/namespaces/test-project/datasciencepipelinesapplications/pipelines-definition',
(_req, res, ctx) => res(ctx.json(mockDataSciencePipelineApplicationK8sResource({}))),
),
rest.get(
'/api/k8s/apis/route.openshift.io/v1/namespaces/test-project/routes/ds-pipeline-pipelines-definition',
(_req, res, ctx) =>
res(
ctx.json(mockRouteK8sResource({ notebookName: 'ds-pipeline-pipelines-definition' })),
),
),
rest.get(
'/api/k8s/api/v1/namespaces/test-project/secrets/ds-pipeline-config',
(_req, res, ctx) => res(ctx.json(mockSecretK8sResource({ name: 'ds-pipeline-config' }))),
),
rest.get(
'/api/k8s/api/v1/namespaces/test-project/secrets/aws-connection-testdb',
(_req, res, ctx) =>
res(ctx.json(mockSecretK8sResource({ name: 'aws-connection-testdb' }))),
),
rest.post('/api/proxy/apis/v1beta1/pipelines', (req, res, ctx) =>
res(
ctx.json({
...mockPipelinesProxy,
pipelines: [
...mockPipelinesProxy.pipelines,
{
...mockPipelinesProxy.pipelines[1],
id: mockPipelineVersions.versions[0].resource_references[0].key.id,
},
],
}),
),
),
rest.post('/api/proxy/apis/v1beta1/pipelines/:pipeline_id', (req, res, ctx) =>
res(
ctx.json({
...mockPipelinesProxy.pipelines[1],
id: mockPipelineVersions.versions[0].resource_references[0].key.id,
}),
),
),
rest.post('/api/proxy/apis/v1beta1/pipeline_versions', (_req, res, ctx) =>
res(ctx.json(mockPipelineVersions)),
),
rest.post('/api/proxy/apis/v1beta1/pipeline_versions/:version_id', (req, res, ctx) => {
const existingMockPipelineVersion = mockPipelineVersions.versions.find(
(version) => version.id === req.params.version_id,
);

const newMockPipelineVersion = buildMockPipelineVersion({
name: 'new-upload-version',
id: 'new-version-id',
});

return res(ctx.json(existingMockPipelineVersion || newMockPipelineVersion));
}),
rest.post(
'/api/proxy/apis/v1beta1/pipeline_versions/:version_id/templates',
(_req, res, ctx) => res(ctx.json(mockPipelineVersionTemplateResource)),
),
],
},
},
};

export const Default: StoryObj = {
render: () => (
<PipelineContextProvider namespace="test-project">
<PipelineDetails breadcrumbPath={[]} />
</PipelineContextProvider>
),
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ export default {
component: PipelineRunJobDetails,
parameters: {
reactRouter: {
routePath: '/pipelineRuns/:namespace/pipelineRunJob/view/:pipelineRunJobId/*',
routeParams: { namespace: 'test-project', pipelineRunJobId: 'test-pipeline-run-job' },
location: {
pathParams: { namespace: 'test-project', pipelineRunJobId: 'test-pipeline-run-job' },
},
routing: [
{
path: '/pipelineRuns/:namespace/pipelineRunJob/view/:pipelineRunJobId/*',
},
],
},
msw: {
handlers: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,14 @@ export default {
component: ProjectDetails,
parameters: {
reactRouter: {
routePath: '/projects/:namespace/*',
routeParams: { namespace: 'test-project' },
location: {
pathParams: { namespace: 'test-project' },
},
routing: [
{
path: '/projects/:namespace/*',
},
],
},
msw: {
handlers: handlers(false),
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/api/pipelines/callTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ListPipelineRunJobs,
ListPipelineRunsByPipeline,
ListPipelines,
ListPipelineTemplates,
ListPipelineVersionTemplates,
UploadPipeline,
UpdatePipelineRunJob,
GetPipelineRun,
Expand Down Expand Up @@ -47,7 +47,7 @@ export type ListPipelinesAPI = KubeflowAPICall<ListPipelines>;
export type ListPipelinesRunAPI = KubeflowAPICall<ListPipelineRuns>;
export type ListPipelinesRunJobAPI = KubeflowAPICall<ListPipelineRunJobs>;
export type ListPipelineRunsByPipelineAPI = KubeflowAPICall<ListPipelineRunsByPipeline>;
export type ListPipelineTemplatesAPI = KubeflowAPICall<ListPipelineTemplates>;
export type ListPipelineVersionTemplatesAPI = KubeflowAPICall<ListPipelineVersionTemplates>;
export type ListPipelineVersionsByPipelineAPI = KubeflowAPICall<ListPipelineVersionsByPipeline>;
export type StopPipelineRunAPI = KubeflowAPICall<StopPipelineRun>;
export type UpdatePipelineRunJobAPI = KubeflowAPICall<UpdatePipelineRunJob>;
Expand Down
16 changes: 11 additions & 5 deletions frontend/src/api/pipelines/custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ListPipelinesRunAPI,
ListPipelinesRunJobAPI,
ListPipelinesAPI,
ListPipelineTemplatesAPI,
ListPipelineVersionTemplatesAPI,
UploadPipelineAPI,
UpdatePipelineRunJobAPI,
GetPipelineRunAPI,
Expand Down Expand Up @@ -129,10 +129,16 @@ export const listPipelineRunsByPipeline: ListPipelineRunsByPipelineAPI =
),
);

export const listPipelineTemplates: ListPipelineTemplatesAPI = (hostPath) => (opts, pipelineId) =>
handlePipelineFailures(
proxyGET(hostPath, `/apis/v1beta1/pipelines/${pipelineId}/templates`, {}, opts),
);
export const listPipelineVersionTemplates: ListPipelineVersionTemplatesAPI =
(hostPath) => (opts, pipelineVersionId) =>
handlePipelineFailures(
proxyGET(
hostPath,
`/apis/v1beta1/pipeline_versions/${pipelineVersionId}/templates`,
{},
opts,
),
);

export const listPipelineVersionsByPipeline: ListPipelineVersionsByPipelineAPI =
(hostPath) => (opts, pipelineId, params) =>
Expand Down
Loading

0 comments on commit 5b8f4c5

Please sign in to comment.