Skip to content

Commit

Permalink
Added accelerator column and field
Browse files Browse the repository at this point in the history
added tests

tooltip to popover
  • Loading branch information
Gkrumbach07 committed Nov 7, 2023
1 parent 0b7492e commit 92133b7
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 49 deletions.
16 changes: 16 additions & 0 deletions backend/src/routes/api/images/imageUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ const mapImageStreamToBYONImage = (is: ImageStream): BYONImage => ({
imported_time: is.metadata.creationTimestamp,
url: is.metadata.annotations['opendatahub.io/notebook-image-url'],
provider: is.metadata.annotations['opendatahub.io/notebook-image-creator'],
recommendedAccelerators: jsonParseRecommendedAccelerators(is.metadata.annotations['opendatahub.io/recommended-accelerators']),

Check failure on line 245 in backend/src/routes/api/images/imageUtils.ts

View workflow job for this annotation

GitHub Actions / Tests (18.x)

Replace `is.metadata.annotations['opendatahub.io/recommended-accelerators']` with `⏎····is.metadata.annotations['opendatahub.io/recommended-accelerators'],⏎··`
});

export const postImage = async (
Expand Down Expand Up @@ -273,6 +274,8 @@ export const postImage = async (
};
}

const validRecommendedAccelerators = body.recommendedAccelerators

Check warning on line 277 in backend/src/routes/api/images/imageUtils.ts

View workflow job for this annotation

GitHub Actions / Tests (18.x)

'validRecommendedAccelerators' is assigned a value but never used

Check failure on line 277 in backend/src/routes/api/images/imageUtils.ts

View workflow job for this annotation

GitHub Actions / Tests (18.x)

Insert `;`

const payload: ImageStream = {
kind: 'ImageStream',
apiVersion: 'image.openshift.io/v1',
Expand All @@ -282,6 +285,7 @@ export const postImage = async (
'opendatahub.io/notebook-image-name': body.display_name,
'opendatahub.io/notebook-image-url': fullURL,
'opendatahub.io/notebook-image-creator': body.provider,
'opendatahub.io/recommended-accelerators': JSON.stringify(body.recommendedAccelerators ?? []),

Check failure on line 288 in backend/src/routes/api/images/imageUtils.ts

View workflow job for this annotation

GitHub Actions / Tests (18.x)

Replace `body.recommendedAccelerators·??·[]` with `⏎··········body.recommendedAccelerators·??·[],⏎········`
},
name: `custom-${translateDisplayNameForK8s(body.display_name)}`,
namespace: namespace,
Expand Down Expand Up @@ -419,6 +423,10 @@ export const updateImage = async (
imageStream.metadata.annotations['opendatahub.io/notebook-image-desc'] = body.description;
}

if(body.recommendedAccelerators !== undefined) {

Check failure on line 426 in backend/src/routes/api/images/imageUtils.ts

View workflow job for this annotation

GitHub Actions / Tests (18.x)

Insert `·`
imageStream.metadata.annotations['opendatahub.io/recommended-accelerators'] = JSON.stringify(body.recommendedAccelerators);

Check failure on line 427 in backend/src/routes/api/images/imageUtils.ts

View workflow job for this annotation

GitHub Actions / Tests (18.x)

Replace `body.recommendedAccelerators` with `⏎········body.recommendedAccelerators,⏎······`
}

await customObjectsApi
.patchNamespacedCustomObject(
'image.openshift.io',
Expand Down Expand Up @@ -452,3 +460,11 @@ const jsonParsePackage = (unparsedPackage: string): BYONImagePackage[] => {
return [];
}
};

const jsonParseRecommendedAccelerators = (unparsedRecommendations: string): string[] => {
try {
return JSON.parse(unparsedRecommendations) || [];
} catch {
return [];
}
};
1 change: 1 addition & 0 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ export type BYONImage = {
visible: boolean;
software: BYONImagePackage[];
packages: BYONImagePackage[];
recommendedAccelerators: string[];
};

export type ImageTag = {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/__mocks__/mockByon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const mockByon = (opts?: RecursivePartial<BYONImage[]>): BYONImage[] =>
name: 'byon-123',
display_name: 'Testing Custom Image',
description: 'A custom notebook image',
recommendedAccelerators: [],
visible: true,
packages: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ test('Table filtering, sorting, searching', async ({ page }) => {
await page.getByRole('button', { name: 'Provider' }).click();
expect(page.getByText('image-0'));

// by accelerator
await page.getByRole('button', { name: 'Recommended accelerators' }).click();
expect(page.getByText('test-accelerator')).toHaveCount(0);
await page.getByRole('button', { name: 'Recommended accelerators' }).click();
expect(page.getByText('test-accelerator'));

// by enabled
await page.getByRole('button', { name: 'Enable', exact: true }).click();
expect(page.getByText('image-14'));
Expand Down Expand Up @@ -114,6 +120,30 @@ test('Import form fields', async ({ page }) => {
await page.getByLabel('Name *').fill('image');
await expect(page.getByRole('button', { name: 'Import' })).toBeEnabled();

// test accelerator select field
// select accelerator from api call
await page.getByPlaceholder('Example, nvidia.com/gpu').click();
await page.getByRole('option', { name: 'nvidia.com/gpu' }).click();

// create new and select
await page.getByPlaceholder('Example, nvidia.com/gpu').click();
await page.getByPlaceholder('Example, nvidia.com/gpu').fill('test.com/gpu');
await page.getByRole('option', { name: 'Create "test.com/gpu"' }).click();
await page.getByRole('button', { name: 'Options menu' }).click();
expect(page.getByText('test.com/gpu'));

// remove custom
await page.getByRole('button', { name: 'Remove test.com/gpu' }).click();
await page.getByRole('button', { name: 'Options menu' }).click();
await expect(page.getByText('test.com/gpu')).toHaveCount(0);

// reselect custom
await page
.getByRole('dialog', { name: 'Import notebook image' })
.getByRole('button', { name: 'Options menu' })
.click();
await page.getByRole('option', { name: 'test.com/gpu' }).click();

// test form is disabled after entering software add form
await page.getByTestId('add-software-button').click();
await expect(page.getByRole('button', { name: 'Import' })).toBeDisabled();
Expand Down Expand Up @@ -204,7 +234,7 @@ test('Edit form fields match', async ({ page }) => {
expect(await page.getByLabel('Image Location *').inputValue()).toBe('test-image:latest');
expect(await page.getByLabel('Name *').inputValue()).toBe('Testing Custom Image');
expect(await page.getByLabel('Description').inputValue()).toBe('A custom notebook image');

expect(page.getByText('nvidia.com/gpu'));
// test software and packages have correct values
expect(page.getByRole('gridcell', { name: 'test-software' }));
expect(page.getByRole('gridcell', { name: '2.0' }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,46 @@ import { rest } from 'msw';
import { userEvent, within } from '@storybook/testing-library';
import BYONImages from '~/pages/BYONImages/BYONImages';
import { mockByon } from '~/__mocks__/mockByon';
import { mockAcceleratorProfile } from '~/__mocks__/mockAcceleratorProfile';
import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList';
import { mockProjectK8sResource } from '~/__mocks__/mockProjectK8sResource';
import { mockStatus } from '~/__mocks__/mockStatus';
import useDetectUser from '~/utilities/useDetectUser';

export default {
component: BYONImages,
} as Meta<typeof BYONImages>;

const Template: StoryFn<typeof BYONImages> = (args) => <BYONImages {...args} />;

export const Default: StoryObj = {
render: Template,
parameters: {
msw: {
handlers: [
rest.get('/api/images/byon', (req, res, ctx) =>
res(ctx.json(mockByon([{ url: 'test-image:latest' }]))),
handlers: {
status: [
rest.get('/api/k8s/apis/project.openshift.io/v1/projects', (req, res, ctx) =>
res(ctx.json(mockK8sResourceList([mockProjectK8sResource({})]))),
),
rest.get('/api/status', (req, res, ctx) => res(ctx.json(mockStatus()))),
],
accelerators: rest.get(
'/api/k8s/apis/dashboard.opendatahub.io/v1/namespaces/opendatahub/acceleratorprofiles',
(req, res, ctx) => res(ctx.json(mockK8sResourceList([mockAcceleratorProfile()]))),
),
],
images: rest.get('/api/images/byon', (req, res, ctx) =>
res(
ctx.json(
mockByon([{ url: 'test-image:latest', recommendedAccelerators: ['nvidia.com/gpu'] }]),
),
),
),
},
},
},
} as Meta<typeof BYONImages>;

const Template: StoryFn<typeof BYONImages> = (args) => {
useDetectUser();
return <BYONImages {...args} />;
};

export const Default: StoryObj = {
render: Template,
play: async ({ canvasElement }) => {
// load page and wait until settled
const canvas = within(canvasElement);
Expand All @@ -34,7 +56,7 @@ export const Empty: StoryObj = {
render: Template,
parameters: {
msw: {
handlers: [rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json([])))],
handlers: { images: rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json([]))) },
},
},
play: async ({ canvasElement }) => {
Expand All @@ -48,7 +70,7 @@ export const LoadingError: StoryObj = {
render: Template,
parameters: {
msw: {
handlers: [rest.get('/api/images/byon', (req, res, ctx) => res(ctx.status(404)))],
handlers: { images: rest.get('/api/images/byon', (req, res, ctx) => res(ctx.status(404))) },
},
},
play: async ({ canvasElement }) => {
Expand All @@ -62,8 +84,8 @@ export const LargeList: StoryObj = {
render: Template,
parameters: {
msw: {
handlers: [
rest.get('/api/images/byon', (req, res, ctx) =>
handlers: {
images: rest.get('/api/images/byon', (req, res, ctx) =>
res(
ctx.json(
Array.from(
Expand All @@ -77,13 +99,14 @@ export const LargeList: StoryObj = {
description: `description-${i}`,
provider: `provider-${i}`,
visible: i % 3 === 0,
recommendedAccelerators: i % 3 ? ['nvidia.com/gpu'] : [],
},
])[0],
),
),
),
),
],
},
},
},
play: async ({ canvasElement }) => {
Expand All @@ -97,39 +120,41 @@ export const ImageError: StoryObj = {
render: Template,
parameters: {
msw: {
handlers: [
rest.post('/api/images', (req, res, ctx) =>
res(
ctx.json({
success: false,
error: 'Testing create error message',
}),
handlers: {
images: [
rest.post('/api/images', (req, res, ctx) =>
res(
ctx.json({
success: false,
error: 'Testing create error message',
}),
),
),
),
rest.put('/api/images/byon-1', (req, res, ctx) =>
res(
ctx.json({
success: false,
error: 'Testing edit error message',
}),
rest.put('/api/images/byon-1', (req, res, ctx) =>
res(
ctx.json({
success: false,
error: 'Testing edit error message',
}),
),
),
),
rest.delete('/api/images/byon-1', (req, res, ctx) =>
res(ctx.status(404, 'Testing delete error message')),
),
rest.get('/api/images/byon', (req, res, ctx) =>
res(
ctx.json(
mockByon([
{
name: 'byon-1',
error: 'Testing error message',
},
]),
rest.delete('/api/images/byon-1', (req, res, ctx) =>
res(ctx.status(404, 'Testing delete error message')),
),
rest.get('/api/images/byon', (req, res, ctx) =>
res(
ctx.json(
mockByon([
{
name: 'byon-1',
error: 'Testing error message',
},
]),
),
),
),
),
],
],
},
},
},
play: async ({ canvasElement }) => {
Expand All @@ -148,7 +173,9 @@ export const EditModal: StoryObj = {
element: '.pf-c-backdrop',
},
msw: {
handlers: [rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json(mockByon())))],
handlers: {
images: rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json(mockByon()))),
},
},
},
play: async ({ canvasElement }) => {
Expand All @@ -169,7 +196,9 @@ export const DeleteModal: StoryObj = {
element: '.pf-c-backdrop',
},
msw: {
handlers: [rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json(mockByon())))],
handlers: {
images: rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json(mockByon()))),
},
},
},
play: async ({ canvasElement }) => {
Expand All @@ -190,7 +219,9 @@ export const ImportModal: StoryObj = {
element: '.pf-c-backdrop',
},
msw: {
handlers: [rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json(mockByon())))],
handlers: {
images: rest.get('/api/images/byon', (req, res, ctx) => res(ctx.json(mockByon()))),
},
},
},
play: async ({ canvasElement }) => {
Expand Down
Loading

0 comments on commit 92133b7

Please sign in to comment.