Skip to content

Commit fa57c19

Browse files
authored
Merge branch 'main' into RHOAIENG36088-refactor-llamastack-config
2 parents d3e1925 + 9355642 commit fa57c19

98 files changed

Lines changed: 3060 additions & 1805 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

frontend/src/__mocks__/mockModelServingPodSpecOptions.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export const mockModelServingPodSpecOptions = ({
1515
},
1616
tolerations = [],
1717
nodeSelector = {},
18-
selectedAcceleratorProfile,
1918
selectedHardwareProfile,
2019
selectedModelSize = {
2120
name: 'small',
@@ -34,7 +33,6 @@ export const mockModelServingPodSpecOptions = ({
3433
resources,
3534
tolerations,
3635
nodeSelector,
37-
selectedAcceleratorProfile,
3836
selectedHardwareProfile,
3937
selectedModelSize,
4038
});

frontend/src/__mocks__/mockProjectK8sResource.ts

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -55,39 +55,59 @@ export const mockProjectK8sResource = ({
5555
},
5656
});
5757

58-
export const mockProjectsK8sList = (): K8sResourceListResult<ProjectKind> => ({
59-
apiVersion: 'project.openshift.io/v1',
60-
metadata: { continue: '', resourceVersion: '1462210' },
61-
items: [
62-
mockProjectK8sResource({
63-
k8sName: 'ds-project-1',
64-
displayName: 'DS Project 1',
65-
isDSProject: true,
66-
}),
67-
mockProjectK8sResource({
68-
k8sName: 'ds-project-2',
69-
displayName: 'DS Project 2',
70-
isDSProject: true,
71-
}),
72-
mockProjectK8sResource({
73-
k8sName: 'ds-project-3',
74-
displayName: 'DS Project 3',
75-
isDSProject: true,
76-
}),
77-
mockProjectK8sResource({
78-
k8sName: 'non-ds-project-1',
79-
displayName: 'Non-DS Project 1',
80-
isDSProject: false,
81-
}),
82-
mockProjectK8sResource({
83-
k8sName: 'non-ds-project-2',
84-
displayName: 'Non-DS Project 2',
85-
isDSProject: false,
86-
}),
87-
mockProjectK8sResource({
88-
k8sName: 'non-ds-project-3',
89-
displayName: 'Non-DS Project 3',
90-
isDSProject: false,
91-
}),
92-
],
93-
});
58+
export const mockProjectsK8sList = (
59+
numberOfExtraProjects = 0,
60+
): K8sResourceListResult<ProjectKind> => {
61+
const extraProjs = [];
62+
if (numberOfExtraProjects > 0) {
63+
let i = 0;
64+
while (i < numberOfExtraProjects) {
65+
extraProjs.push(
66+
mockProjectK8sResource({
67+
k8sName: `extra-project-${i}`,
68+
displayName: `Extra Project ${i}`,
69+
isDSProject: true,
70+
}),
71+
);
72+
i++;
73+
}
74+
}
75+
76+
return {
77+
apiVersion: 'project.openshift.io/v1',
78+
metadata: { continue: '', resourceVersion: '1462210' },
79+
items: [
80+
mockProjectK8sResource({
81+
k8sName: 'ds-project-1',
82+
displayName: 'DS Project 1',
83+
isDSProject: true,
84+
}),
85+
mockProjectK8sResource({
86+
k8sName: 'ds-project-2',
87+
displayName: 'DS Project 2',
88+
isDSProject: true,
89+
}),
90+
mockProjectK8sResource({
91+
k8sName: 'ds-project-3',
92+
displayName: 'DS Project 3',
93+
isDSProject: true,
94+
}),
95+
mockProjectK8sResource({
96+
k8sName: 'non-ds-project-1',
97+
displayName: 'Non-DS Project 1',
98+
isDSProject: false,
99+
}),
100+
mockProjectK8sResource({
101+
k8sName: 'non-ds-project-2',
102+
displayName: 'Non-DS Project 2',
103+
isDSProject: false,
104+
}),
105+
mockProjectK8sResource({
106+
k8sName: 'non-ds-project-3',
107+
displayName: 'Non-DS Project 3',
108+
isDSProject: false,
109+
}),
110+
...extraProjs,
111+
],
112+
};
113+
};

frontend/src/__mocks__/mockServingRuntimeK8sResource.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ type MockResourceConfigType = {
1919
templateDisplayName?: string;
2020
scope?: string;
2121
hardwareProfileNamespace?: string;
22-
acceleratorProfileNamespace?: string;
2322
isNonDashboardItem?: boolean;
2423
version?: string;
2524
templateName?: string;
@@ -108,7 +107,6 @@ export const mockServingRuntimeK8sResource = ({
108107
replicas = 0,
109108
displayName = 'OVMS Model Serving',
110109
acceleratorName = '',
111-
acceleratorProfileNamespace = undefined,
112110
hardwareProfileName = '',
113111
apiProtocol = ServingRuntimeAPIProtocol.REST,
114112
resources = {
@@ -154,9 +152,6 @@ export const mockServingRuntimeK8sResource = ({
154152
...(hardwareProfileNamespace && {
155153
'opendatahub.io/hardware-profile-namespace': hardwareProfileNamespace,
156154
}),
157-
...(acceleratorProfileNamespace && {
158-
'opendatahub.io/accelerator-profile-namespace': acceleratorProfileNamespace,
159-
}),
160155
},
161156
name,
162157
namespace,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
projectResourceName: "test-model-catalog"
2+
singleModelName: "catalog-model-test"

frontend/src/__tests__/cypress/cypress/pages/components/NIMDeployModal.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ class NIMDeployModal extends Modal {
152152
}
153153

154154
setModelPath(path: string) {
155-
this.findModelPathInput().clear().type(path);
155+
// Select all text and type to replace it, rather than clearing
156+
// This prevents React's useEffect from re-filling the field with the default value
157+
// when it detects an empty field
158+
this.findModelPathInput().type('{selectall}').type(path);
156159
return this;
157160
}
158161

frontend/src/__tests__/cypress/cypress/pages/home/homeProject.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,12 @@ export class HomeProject extends Contextual<HTMLElement> {
3232
findGoToProjectLink(): Cypress.Chainable<JQuery<HTMLElement>> {
3333
return this.find().findByTestId('goto-projects-link');
3434
}
35+
36+
findProjectCard(projectName: string): Cypress.Chainable<JQuery<HTMLElement>> {
37+
return this.find().findByTestId(`project-card-${projectName}`);
38+
}
39+
40+
findAILabelInCard(projectName: string): Cypress.Chainable<JQuery<HTMLElement>> {
41+
return this.findProjectCard(projectName).findByTestId('ai-project-label');
42+
}
3543
}

frontend/src/__tests__/cypress/cypress/pages/modelCatalog/modelCatalog.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ class ModelCatalog {
1111
this.wait();
1212
}
1313

14-
visitTempDetails() {
15-
cy.visitWithLogin(`/ai-hub/catalog/tempDetails`);
16-
this.wait();
17-
}
18-
1914
navigate() {
2015
appChrome.findNavItem({ name: 'Catalog', rootSection: 'AI hub' }).click();
2116
this.wait();
@@ -45,12 +40,12 @@ class ModelCatalog {
4540
return cy.findByTestId('empty-model-catalog-state');
4641
}
4742

48-
findModelCatalogModelDetailLink(modelName: string) {
49-
return cy.findByTestId(`model-catalog-detail-link`).contains(modelName);
43+
findModelCatalogModelDetailLink() {
44+
return cy.findAllByTestId(`model-catalog-card-name`).first();
5045
}
5146

5247
findModelCatalogCards() {
53-
return cy.findByTestId('model-catalog-cards');
48+
return cy.findAllByTestId('model-catalog-card');
5449
}
5550

5651
findModelCatalogCard(modelName: string) {
@@ -59,6 +54,37 @@ class ModelCatalog {
5954
.contains('[data-testid~=model-catalog-card]', modelName);
6055
}
6156

57+
findFirstModelCatalogCard() {
58+
return cy.findAllByTestId('model-catalog-card').first();
59+
}
60+
61+
findFirstModelCatalogCardLink() {
62+
return this.findFirstModelCatalogCard().findByTestId('model-catalog-detail-link');
63+
}
64+
65+
findCatalogDeployButton() {
66+
return cy.findByTestId('deploy-button');
67+
}
68+
69+
clickDeployModelButtonWithRetry() {
70+
const maxRetries = 3;
71+
let attempt = 0;
72+
const tryClick = () => {
73+
attempt++;
74+
cy.log(`Click attempt #${attempt}`);
75+
this.findCatalogDeployButton().click();
76+
77+
cy.location('pathname').then((path) => {
78+
if (!path.includes('/ai-hub/deployments/deploy') && attempt < maxRetries) {
79+
cy.log('Wizard did not open, retrying...');
80+
tryClick();
81+
}
82+
});
83+
};
84+
tryClick();
85+
return this;
86+
}
87+
6288
expandCardLabelGroup(modelName: string) {
6389
this.findModelCatalogCard(modelName)
6490
.findAllByTestId('model-catalog-label-group')

frontend/src/__tests__/cypress/cypress/pages/modelCatalog/modelDetailsPage.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
class ModelDetailsPage {
22
visit() {
3-
const sourceName = 'Red%20Hat';
4-
const repositoryName = 'rhelai1';
5-
const modelName = 'granite-8b-code-instruct';
6-
const tag = '1%252E3%252E0';
7-
cy.visitWithLogin(`/ai-hub/catalog/${sourceName}/${repositoryName}/${modelName}/${tag}`);
3+
const sourceName = 'source-2';
4+
const modelName = 'sample%20category%201-model-1';
5+
cy.visitWithLogin(`/ai-hub/catalog/${sourceName}/${modelName}/overview`);
86
this.wait();
97
}
108

@@ -18,7 +16,7 @@ class ModelDetailsPage {
1816
}
1917

2018
findDeployModelButton() {
21-
return cy.findByTestId('deploy-model-button');
19+
return cy.findByTestId('deploy-button');
2220
}
2321

2422
findTuneModelButton() {
@@ -49,6 +47,10 @@ class ModelDetailsPage {
4947
return cy.findByTestId('source-image-location');
5048
}
5149

50+
getModelSourceImageLocation() {
51+
return cy.get('@modelSourceImageLocation');
52+
}
53+
5254
findModelCardMarkdown() {
5355
return cy.findByTestId('model-card-markdown');
5456
}

frontend/src/__tests__/cypress/cypress/pages/modelServing.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,6 @@ class InferenceServiceModal extends ServingModal {
310310
cy.findByRole('option', { name }).click();
311311
}
312312

313-
findAcceleratorProfileSelect(): Cypress.Chainable<JQuery<HTMLElement>> {
314-
return cy.findByTestId('accelerator-profile-select');
315-
}
316-
317-
selectAcceleratorProfileOption(name: string): void {
318-
this.findAcceleratorProfileSelect().click();
319-
cy.contains(name).click();
320-
}
321-
322313
selectPotentiallyDisabledProfile(profileDisplayName: string, profileName?: string): void {
323314
const dropdown = this.findHardProfileSelection();
324315

@@ -968,6 +959,20 @@ class ModelServingWizard extends Wizard {
968959
return cy.findByTestId('serving-runtime-template-selection-toggle');
969960
}
970961

962+
findServingRuntimeSelectRadio() {
963+
return cy.findByLabelText('Select from a list of serving runtimes, including custom ones');
964+
}
965+
966+
findFirstServingRuntimeTemplateOption() {
967+
// Open the menu
968+
this.findServingRuntimeTemplateSearchSelector().click();
969+
// Grab the first runtime whose testid starts with "servingRuntime"
970+
return cy
971+
.findByTestId('global-scoped-serving-runtimes')
972+
.find('[data-testid^="servingRuntime"]')
973+
.first();
974+
}
975+
971976
findServingRuntimeTemplateSearchInput() {
972977
return cy.findByTestId('serving-runtime-template-selection-search').find('input');
973978
}

frontend/src/__tests__/cypress/cypress/pages/notebookServer.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ class NotebookServer {
7272
return cy.findByTestId('stop-workbench-button');
7373
}
7474

75-
findAcceleratorProfileSelect() {
76-
return cy.findByTestId('accelerator-profile-select');
77-
}
78-
7975
findHardProfileSelection(): Cypress.Chainable<JQuery<HTMLElement>> {
8076
return cy.findByTestId('hardware-profile-select');
8177
}

0 commit comments

Comments
 (0)