Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert templates to use websocket #2855

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList';
import { mockServingRuntimeTemplateK8sResource } from '~/__mocks__/mockServingRuntimeTemplateK8sResource';
import { servingRuntimes } from '~/__tests__/cypress/cypress/pages/servingRuntimes';
import { ServingRuntimeAPIProtocol, ServingRuntimePlatform } from '~/types';
import { deleteModal } from '~/__tests__/cypress/cypress/pages/components/DeleteModal';
import { mockServingRuntimeK8sResource } from '~/__mocks__/mockServingRuntimeK8sResource';
import { asProductAdminUser, asProjectAdminUser } from '~/__tests__/cypress/cypress/utils/users';
import { pageNotfound } from '~/__tests__/cypress/cypress/pages/pageNotFound';
import {
customServingRuntimesInitialMock,
customServingRuntimesIntercept,
} from '~/__tests__/cypress/cypress/tests/mocked/customServingRuntimes/customServingRuntimesUtils';
import { customServingRuntimesIntercept } from '~/__tests__/cypress/cypress/tests/mocked/customServingRuntimes/customServingRuntimesUtils';
import { TemplateModel } from '~/__tests__/cypress/cypress/utils/models';

const addfilePath = '../../__mocks__/mock-custom-serving-runtime-add.yaml';
const editfilePath = '../../__mocks__/mock-custom-serving-runtime-edit.yaml';
Expand Down Expand Up @@ -81,7 +78,6 @@ describe('Custom serving runtimes', () => {

servingRuntimes.findSubmitButton().should('be.enabled');
servingRuntimes.findSubmitButton().click();

cy.wait('@createSingleModelServingRuntime').then((interception) => {
expect(interception.request.url).to.include('?dryRun=All');
expect(interception.request.body).to.containSubset({
Expand Down Expand Up @@ -112,6 +108,19 @@ describe('Custom serving runtimes', () => {
],
});
});

cy.wsK8s(
'ADDED',
TemplateModel,
mockServingRuntimeTemplateK8sResource({
name: 'template-new',
displayName: 'New OVMS Server',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.REST,
}),
);

servingRuntimes.getRowById('template-new').shouldBeSingleModel(true);
});

it('should add a new multi model serving runtime', () => {
Expand Down Expand Up @@ -172,6 +181,18 @@ describe('Custom serving runtimes', () => {
],
});
});

cy.wsK8s(
'ADDED',
TemplateModel,
mockServingRuntimeTemplateK8sResource({
name: 'template-new',
displayName: 'New OVMS Server',
platforms: [ServingRuntimePlatform.MULTI],
}),
);

servingRuntimes.getRowById('template-new').shouldBeMultiModel(true);
});

it('should duplicate a serving runtime', () => {
Expand All @@ -185,19 +206,6 @@ describe('Custom serving runtimes', () => {
'duplicateTemplate',
);

const ServingRuntimeTemplateMock = mockServingRuntimeTemplateK8sResource({
name: 'serving-runtime-template-1',
displayName: 'Multi platform',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.GRPC,
});

cy.interceptOdh(
'GET /api/templates/:namespace',
{ path: { namespace: 'opendatahub' } },
mockK8sResourceList([...customServingRuntimesInitialMock, ServingRuntimeTemplateMock]),
).as('refreshServingRuntime');

servingRuntimes.getRowById('template-1').find().findKebabAction('Duplicate').click();
servingRuntimes.findAppTitle().should('have.text', 'Duplicate serving runtime');
cy.url().should('include', '/addServingRuntime');
Expand Down Expand Up @@ -236,10 +244,20 @@ describe('Custom serving runtimes', () => {
],
});
});
cy.wait('@refreshServingRuntime');

cy.wsK8s(
'ADDED',
TemplateModel,
mockServingRuntimeTemplateK8sResource({
name: 'template-1-copy',
displayName: 'Copy of Multi platform',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.GRPC,
}),
);

servingRuntimes
.getRowById('serving-runtime-template-1')
.getRowById('template-1-copy')
.shouldHaveAPIProtocol(ServingRuntimeAPIProtocol.GRPC);
});

Expand Down Expand Up @@ -310,5 +328,16 @@ describe('Custom serving runtimes', () => {
deleteModal.findSubmitButton().should('be.enabled').click();

cy.wait('@deleteServingRuntime');
cy.wsK8s(
'DELETED',
TemplateModel,
mockServingRuntimeTemplateK8sResource({
name: 'template-1',
displayName: 'Multi platform',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.REST,
}),
);
servingRuntimes.getRowById('template-1').find().should('not.exist');
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList';
import { mockServingRuntimeTemplateK8sResource } from '~/__mocks__/mockServingRuntimeTemplateK8sResource';
import { ServingRuntimeAPIProtocol, ServingRuntimePlatform } from '~/types';
import { ProjectModel } from '~/__tests__/cypress/cypress/utils/models';
import { ProjectModel, TemplateModel } from '~/__tests__/cypress/cypress/utils/models';
import { mockProjectK8sResource } from '~/__mocks__';

export const customServingRuntimesInitialMock = [
Expand All @@ -28,10 +28,11 @@ export const customServingRuntimesInitialMock = [
];

export const customServingRuntimesIntercept = (): void => {
cy.interceptK8sList(TemplateModel, mockK8sResourceList(customServingRuntimesInitialMock));
cy.interceptK8sList(ProjectModel, mockK8sResourceList([mockProjectK8sResource({})]));
cy.interceptOdh(
'GET /api/templates/:namespace',
{ path: { namespace: 'opendatahub' } },
mockK8sResourceList(customServingRuntimesInitialMock),
);
cy.interceptK8sList(ProjectModel, mockK8sResourceList([mockProjectK8sResource({})]));
};
52 changes: 37 additions & 15 deletions frontend/src/api/k8s/__tests__/groups.spec.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import { useK8sWatchResource } from '@openshift/dynamic-plugin-sdk-utils';
import { groupVersionKind, useAccessReview, useGroups } from '~/api';
import { testHook } from '~/__tests__/unit/testUtils/hooks';
import { GroupModel } from '~/api/models';
import { mockGroup } from '~/__mocks__/mockGroup';
import useK8sWatchResourceList from '~/utilities/useK8sWatchResourceList';
import { GroupKind } from '~/k8sTypes';

jest.mock('@openshift/dynamic-plugin-sdk-utils', () => ({
useK8sWatchResource: jest.fn(),
jest.mock('~/utilities/useK8sWatchResourceList', () => ({
__esModule: true,
default: jest.fn(),
}));

jest.mock('~/api/useAccessReview', () => ({
useAccessReview: jest.fn(),
}));

const useAccessReviewMock = jest.mocked(useAccessReview);
const useK8sWatchResourceMock = useK8sWatchResource as jest.Mock;
const useK8sWatchResourceListMock = jest.mocked(useK8sWatchResourceList<GroupKind[]>);

describe('useGroups', () => {
it('should wrap useK8sWatchResource to watch groups', async () => {
const mockReturnValue: ReturnType<typeof useK8sWatchResourceMock> = [[], false, undefined];
const mockReturnValue: ReturnType<typeof useK8sWatchResourceListMock> = [[], false, undefined];
useAccessReviewMock.mockReturnValue([true, true]);
useK8sWatchResourceMock.mockReturnValue(mockReturnValue);
useK8sWatchResourceListMock.mockReturnValue(mockReturnValue);
const { result } = testHook(useGroups)();

expect(useK8sWatchResourceMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceMock).toHaveBeenCalledWith(
expect(useK8sWatchResourceListMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceListMock).toHaveBeenCalledWith(
{
isList: true,
groupVersionKind: groupVersionKind(GroupModel),
Expand All @@ -34,16 +36,16 @@ describe('useGroups', () => {
});

it('should render list of groups', () => {
const mockReturnValue: ReturnType<typeof useK8sWatchResourceMock> = [
const mockReturnValue: ReturnType<typeof useK8sWatchResourceListMock> = [
[mockGroup({})],
true,
undefined,
];
useAccessReviewMock.mockReturnValue([true, true]);
useK8sWatchResourceMock.mockReturnValue(mockReturnValue);
useK8sWatchResourceListMock.mockReturnValue(mockReturnValue);
const { result } = testHook(useGroups)();
expect(useK8sWatchResourceMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceMock).toHaveBeenCalledWith(
expect(useK8sWatchResourceListMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceListMock).toHaveBeenCalledWith(
{
isList: true,
groupVersionKind: groupVersionKind(GroupModel),
Expand All @@ -55,10 +57,30 @@ describe('useGroups', () => {

it('should handle 403 error', () => {
useAccessReviewMock.mockReturnValue([false, true]);
useK8sWatchResourceMock.mockReturnValue([undefined, true, undefined]);
useK8sWatchResourceListMock.mockReturnValue([[], true, undefined]);
const { result } = testHook(useGroups)();
expect(useK8sWatchResourceMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceMock).toHaveBeenCalledWith(null, GroupModel);
expect(useK8sWatchResourceListMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceListMock).toHaveBeenCalledWith(null, GroupModel);
expect(result.current).toStrictEqual([[], true, undefined]);
});

it('should handle errors and rethrow', () => {
const mockReturnValue: ReturnType<typeof useK8sWatchResourceListMock> = [
[],
true,
new Error('Unknown error occured'),
];
useAccessReviewMock.mockReturnValue([true, true]);
useK8sWatchResourceListMock.mockReturnValue(mockReturnValue);
const { result } = testHook(useGroups)();
expect(useK8sWatchResourceListMock).toHaveBeenCalledTimes(1);
expect(useK8sWatchResourceListMock).toHaveBeenCalledWith(
{
isList: true,
groupVersionKind: groupVersionKind(GroupModel),
},
GroupModel,
);
expect(result.current).toStrictEqual(mockReturnValue);
});
});
16 changes: 10 additions & 6 deletions frontend/src/api/k8s/__tests__/projects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
k8sCreateResource,
k8sUpdateResource,
k8sDeleteResource,
useK8sWatchResource,
} from '@openshift/dynamic-plugin-sdk-utils';
import axios from 'axios';
import { mockProjectK8sResource } from '~/__mocks__/mockProjectK8sResource';
Expand All @@ -23,13 +22,18 @@ import { ODH_PRODUCT_NAME } from '~/utilities/const';
import { NamespaceApplicationCase } from '~/pages/projects/types';
import { ProjectKind } from '~/k8sTypes';
import { groupVersionKind } from '~/api/k8sUtils';
import useK8sWatchResourceList from '~/utilities/useK8sWatchResourceList';

jest.mock('@openshift/dynamic-plugin-sdk-utils', () => ({
k8sListResource: jest.fn(),
k8sCreateResource: jest.fn(),
k8sUpdateResource: jest.fn(),
k8sDeleteResource: jest.fn(),
useK8sWatchResource: jest.fn(),
}));

jest.mock('~/utilities/useK8sWatchResourceList', () => ({
__esModule: true,
default: jest.fn(),
}));

jest.mock('~/api/k8s/servingRuntimes.ts', () => ({
Expand All @@ -43,14 +47,14 @@ const k8sListResourceMock = jest.mocked(k8sListResource<ProjectKind>);
const k8sCreateResourceMock = jest.mocked(k8sCreateResource<ProjectKind>);
const k8sUpdateResourceMock = jest.mocked(k8sUpdateResource<ProjectKind>);
const k8sDeleteResourceMock = jest.mocked(k8sDeleteResource<ProjectKind>);
const useK8sWatchResourceMock = jest.mocked(useK8sWatchResource<ProjectKind[]>);
const useK8sWatchResourceListMock = jest.mocked(useK8sWatchResourceList<ProjectKind[]>);

describe('useProjects', () => {
it('should wrap useK8sWatchResource to watch projects', async () => {
const mockReturnValue: ReturnType<typeof useK8sWatchResourceMock> = [[], false, false];
useK8sWatchResourceMock.mockReturnValue(mockReturnValue);
const mockReturnValue: ReturnType<typeof useK8sWatchResourceListMock> = [[], false, undefined];
useK8sWatchResourceListMock.mockReturnValue(mockReturnValue);
expect(useProjects()).toBe(mockReturnValue);
expect(useK8sWatchResourceMock).toHaveBeenCalledWith(
expect(useK8sWatchResourceListMock).toHaveBeenCalledWith(
{
isList: true,
groupVersionKind: groupVersionKind(ProjectModel),
Expand Down
Loading
Loading