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

Cypress e2e Test - Admin Model Serving (Multi & Single Model) Tests #3662

Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
cacbfe5
Initial WIP version of resource creation test
antowaddle Nov 20, 2024
0fa2201
Experimental changes to poll the UI for updates
antowaddle Nov 21, 2024
af87ad1
Working version if resource is present
antowaddle Nov 21, 2024
0e9868a
increase card timeout and delete active wait
FedeAlonso Nov 21, 2024
429f086
Merge pull request #1 from FedeAlonso/fix/active_wait
antowaddle Nov 21, 2024
443e530
Added changes to find namespace from variables
antowaddle Nov 22, 2024
966917f
Final changes to read variables, cleaned up utils
antowaddle Nov 22, 2024
69db944
Merge branch 'main' into cypress-RHOAIENG-14368
antowaddle Nov 22, 2024
a9ecfa3
Small change to a comment
antowaddle Nov 22, 2024
6cd6a3e
Dummy change to trigger mocks
antowaddle Nov 22, 2024
fcc6d18
Merge branch 'opendatahub-io:main' into main
antowaddle Nov 22, 2024
c7d471a
Merge branch 'main' into cypress-RHOAIENG-14368
antowaddle Nov 22, 2024
7628316
Save changes on cypress-RHOAIENG-12649
antowaddle Nov 25, 2024
847ad11
Changed file directories and names as requested on a PR comment
antowaddle Nov 25, 2024
552a516
Merge branch 'main' into cypress-RHOAIENG-14368
antowaddle Nov 25, 2024
80cc894
Merge branch 'cypress-RHOAIENG-14368' of https://github.com/antowaddl…
antowaddle Nov 25, 2024
163ed94
Merge remote-tracking branch 'origin/main' into cypress-RHOAIENG-12649
antowaddle Nov 25, 2024
0f7eead
Saving changes to current branch
antowaddle Nov 25, 2024
48c7435
Additional directory/file name changes
antowaddle Nov 25, 2024
14a39de
Additional changes to save
antowaddle Nov 25, 2024
6a93ec2
Resolving timeout issue breaking mock tests, also resolved latest PR …
antowaddle Nov 25, 2024
31b9723
Further changes for this test
antowaddle Nov 25, 2024
f2b636d
Changes to revert the exist method appended to getCardView.
antowaddle Nov 25, 2024
a9feb1b
Fixed linting
antowaddle Nov 25, 2024
aa9430e
Linting fixes
antowaddle Nov 25, 2024
eddd7d8
Merge branch 'main' into cypress-RHOAIENG-12649Merge branch 'main' of…
antowaddle Nov 25, 2024
680a0ee
Final comments added
antowaddle Nov 25, 2024
b6bc5b3
Merge branch 'main' into cypress-RHOAIENG-12649
antowaddle Nov 26, 2024
781e952
Fixed merge conflict
antowaddle Nov 26, 2024
b05b676
Small change to page object name
antowaddle Nov 26, 2024
3681244
dummy commit
antowaddle Nov 26, 2024
fb11cc5
Removed RHOAI bug workaround
antowaddle Nov 26, 2024
e0b9cca
Removed comments
antowaddle Nov 26, 2024
06167d8
Last comment change
antowaddle Nov 26, 2024
ae51479
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 9, 2024
dac0574
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 10, 2024
2cd1f7e
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 11, 2024
645dca1
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 13, 2024
f044a29
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 16, 2024
7aa9059
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 16, 2024
ff28a5d
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 18, 2024
bca2ef3
Merge branch 'main' of https://github.com/antowaddle/odh-dashboard
antowaddle Dec 18, 2024
45dd834
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Dec 31, 2024
bd20cdd
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Jan 2, 2025
d7afb9d
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Jan 6, 2025
290d114
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Jan 7, 2025
60d6e41
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Jan 9, 2025
a87272f
Merge branch 'main' of github.com:opendatahub-io/odh-dashboard
antowaddle Jan 10, 2025
7ee804b
Committing intermediate changes
antowaddle Jan 14, 2025
30832c1
Initial changes
antowaddle Jan 15, 2025
1927e12
Initial changes
antowaddle Jan 15, 2025
d9c513f
Messy working test
antowaddle Jan 16, 2025
77a4dde
Committing working test - not linted/cleaned up
antowaddle Jan 16, 2025
c7bd528
Committing working test with exception of status check on UI
antowaddle Jan 17, 2025
0cf19f3
Merge branch 'main' into cypress-RHOAIENG-17157
antowaddle Jan 17, 2025
8d65c21
Committing fully working test on RHOAI
antowaddle Jan 17, 2025
6c958e1
Linting fixes
antowaddle Jan 17, 2025
3ac15b1
Adding in description for bug relating to manifest links
antowaddle Jan 17, 2025
6283fa7
Actioning PR comments
antowaddle Jan 17, 2025
add8bbc
Comitting initial changes
antowaddle Jan 20, 2025
12cd47a
Comitting working test for Single Model Creation
antowaddle Jan 21, 2025
73a8b84
Comitting final completed test
antowaddle Jan 21, 2025
55812f5
Small amendment to select model server on ODH
antowaddle Jan 21, 2025
abf0310
Merge branch 'main' into cypress-RHOAIENG-17169/RHOAIENG-17174
antowaddle Jan 21, 2025
b24ff29
Linting after merge conflict resolution
antowaddle Jan 21, 2025
45aa457
Merge branch 'main' into cypress-RHOAIENG-17169/RHOAIENG-17174
antowaddle Jan 21, 2025
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
@@ -0,0 +1,5 @@
# testMultiModelAdminCreation.cy.ts Test Data #
projectMultiModelAdminDisplayName: "Cypress Multi Model Admin Test Project"
projectMultiModelAdminResourceName: "cy-multi-model-admin-test"
multiModelAdminName: "cy-multi-openvino-model"
modelOpenVinoExamplePath: "openvino-example-model"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# testSingleModelAdminCreation.cy.ts Test Data #
projectSingleModelAdminDisplayName: "Cypress Single Model Admin Test Project"
projectSingleModelAdminResourceName: "cy-single-model-admin-test"
singleModelAdminName: "cy-openvino-model"
modelOpenVinoPath: "kserve-openvino-test/openvino-example-model"
48 changes: 48 additions & 0 deletions frontend/src/__tests__/cypress/cypress/pages/modelServing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class ModelServingGlobal {
return cy.findByTestId('single-serving-select-button');
}

findMultiModelButton() {
return cy.findByTestId('multi-serving-select-button');
}

private findModelsTable() {
// TODO be more precise
return cy.findByTestId('inference-service-table');
Expand Down Expand Up @@ -121,14 +125,34 @@ class InferenceServiceModal extends Modal {
return this.find().findByTestId('caikit-tgis-runtime');
}

findOpenVinoServingRuntime() {
return this.find().findByTestId('kserve-ovms');
}

findModelFrameworkSelect() {
return this.find().findByTestId('inference-service-framework-selection');
}

findOpenVinoIROpSet1() {
return this.find().findByTestId('openvino_ir - opset1');
}

findOpenVinoIROpSet13() {
return this.find().findByTestId('openvino_ir - opset13');
}

findDeploymentModeSelect() {
return this.find().findByTestId('deployment-mode-select');
}

findDeployedModelRouteCheckbox() {
return this.find().findByTestId('alt-form-checkbox-route');
}

findTokenAuthenticationCheckbox() {
return this.find().findByTestId('alt-form-checkbox-auth');
}

findExistingDataConnectionOption() {
return this.find().findByTestId('existing-data-connection-radio');
}
Expand Down Expand Up @@ -245,6 +269,10 @@ class ServingRuntimeModal extends Modal {
return this.find().findByTestId('serving-runtime-template-selection');
}

findOpenVinoModelServer() {
return this.find().findByTestId('ovms');
}

findPredefinedArgsButton() {
return this.find().findByTestId('view-predefined-args-button');
}
Expand Down Expand Up @@ -289,10 +317,22 @@ class ServingRuntimeModal extends Modal {
return this.find().findByTestId('service-account-form-name');
}

findModelServerName() {
return this.find().findByTestId('serving-runtime-name');
}

findModelServerSizeSelect() {
return this.find().findByTestId('model-server-size-selection');
}

findDeployedModelRouteCheckbox() {
return this.find().findByTestId('alt-form-checkbox-route');
}

findTokenAuthenticationCheckbox() {
return this.find().findByTestId('alt-form-checkbox-auth');
}

findModelServerReplicasMinusButton() {
return this.find()
.findByTestId('model-server-replicas')
Expand Down Expand Up @@ -442,6 +482,14 @@ class ModelServingSection {
return this.findKServeTable().find('thead').findByRole('button', { name });
}

findInternalExternalServiceButton() {
return this.find().findByTestId('internal-external-service-button');
}

findExternalServicePopoverTable() {
return cy.findByTestId('external-service-popover');
}

getKServeRow(name: string) {
return new KServeRow(() =>
this.findKServeTable().find('[data-label=Name]').contains(name).parents('tr'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import type { DataScienceProjectData } from '~/__tests__/cypress/cypress/types';
import { deleteOpenShiftProject } from '~/__tests__/cypress/cypress/utils/oc_commands/project';
import { loadDSPFixture } from '~/__tests__/cypress/cypress/utils/dataLoader';
import { HTPASSWD_CLUSTER_ADMIN_USER } from '~/__tests__/cypress/cypress/utils/e2eUsers';
import { projectListPage, projectDetails } from '~/__tests__/cypress/cypress/pages/projects';
import {
modelServingGlobal,
inferenceServiceModal,
modelServingSection,
createServingRuntimeModal,
} from '~/__tests__/cypress/cypress/pages/modelServing';
import {
checkInferenceServiceState,
provisionProjectForModelServing,
modelExternalURLOpenVinoTester,
} from '~/__tests__/cypress/cypress/utils/oc_commands/modelServing';

let testData: DataScienceProjectData;
let projectName: string;
let modelName: string;
let modelFilePath: string;
const awsBucket = 'BUCKET_1' as const;

describe('Verify Admin Multi Model Creation and Validation using the UI', () => {
before(() => {
Cypress.on('uncaught:exception', (err) => {
if (err.message.includes('Error: secrets "ds-pipeline-config" already exists')) {
return false;
}
return true;
});
// Setup: Load test data and ensure clean state
return loadDSPFixture('e2e/dataScienceProjects/testMultiModelAdminCreation.yaml').then(
(fixtureData: DataScienceProjectData) => {
testData = fixtureData;
projectName = testData.projectMultiModelAdminResourceName;
modelName = testData.multiModelAdminName;
modelFilePath = testData.modelOpenVinoExamplePath;

if (!projectName) {
throw new Error('Project name is undefined or empty in the loaded fixture');
}
cy.log(`Loaded project name: ${projectName}`);
// Create a Project for pipelines
provisionProjectForModelServing(
projectName,
awsBucket,
'resources/yaml/data_connection_model_serving.yaml',
);
},
);
});
after(() => {
// Delete provisioned Project - 5 min timeout to accomadate increased time to delete a project with a model
deleteOpenShiftProject(projectName, { timeout: 300000 });
});

it(
'Verify that an Admin can Serve, Query a Multi Model using both the UI and External links',
{ tags: ['@Smoke', '@SmokeSet3', '@ODS-2053', '@ODS-2054', '@Dashboard', '@Modelserving'] },
() => {
cy.log('Model Name:', modelName);
// Authentication and navigation
cy.step(`Log into the application with ${HTPASSWD_CLUSTER_ADMIN_USER.USERNAME}`);
cy.visitWithLogin('/', HTPASSWD_CLUSTER_ADMIN_USER);

// Project navigation
cy.step(
`Navigate to the Project list tab and search for ${testData.projectMultiModelAdminResourceName}`,
);
projectListPage.navigate();
projectListPage.filterProjectByName(testData.projectMultiModelAdminResourceName);
projectListPage.findProjectLink(testData.projectMultiModelAdminResourceName).click();

// Navigate to Model Serving tab and Deploy a Multi Model
cy.step('Navigate to Model Serving and click to Deploy a Model Server');
projectDetails.findSectionTab('model-server').click();
modelServingGlobal.findMultiModelButton().click();
modelServingSection.findAddModelServerButton().click();
createServingRuntimeModal.findModelServerName().type(testData.multiModelAdminName);
// Check if Serving Runtime is selectable, if it is then select OpenVino Model Server
createServingRuntimeModal
.findServingRuntimeTemplateDropdown()
.should('be.visible')
.then(($element) => {
if ($element.is(':visible') && !$element.prop('disabled')) {
cy.wrap($element).click();
createServingRuntimeModal.findOpenVinoModelServer().click();
} else {
cy.log('Serving Runtime Template dropdown is not clickable. Skipping this step.');
}
});

// Click the deployed model route checkbox and confirm it's checked
cy.step('Allow Model to be accessed from an External route without Authentication');
createServingRuntimeModal.findDeployedModelRouteCheckbox().click();
createServingRuntimeModal.findDeployedModelRouteCheckbox().should('be.checked');
// Uncheck the token authentication checkbox and confirm it's unchecked
createServingRuntimeModal.findTokenAuthenticationCheckbox().click();
createServingRuntimeModal.findTokenAuthenticationCheckbox().should('not.be.checked');
createServingRuntimeModal.findSubmitButton().click();

// Verify the Model Server was created successfully
cy.step('Verify the Model Server created Successfully');
const modelMeshRow = modelServingSection.getModelMeshRow(testData.multiModelAdminName);
modelMeshRow.findDeployModelButton().click();

// Launch a Multi Model and select the required entries
cy.step('Launch a Multi Model using Openvino IR');
inferenceServiceModal.findModelNameInput().type(testData.multiModelAdminName);
inferenceServiceModal.findModelFrameworkSelect().click();
inferenceServiceModal.findOpenVinoIROpSet1().click();
inferenceServiceModal.findLocationPathInput().type(modelFilePath);
inferenceServiceModal.findSubmitButton().click();

//Verify the Model was created successfully
cy.step('Verify that the Model is created Successfully on the backend and frontend');
checkInferenceServiceState(testData.multiModelAdminName);
modelServingSection.findModelServerName(testData.multiModelAdminName);
modelServingSection.findStatusTooltip().click({ force: true });
cy.contains('Loaded', { timeout: 120000 }).should('be.visible');

//Verify the Model is accessible externally
cy.step('Verify the model is accessible externally');
modelExternalURLOpenVinoTester(modelName).then(({ url, response }) => {
expect(response.status).to.equal(200);

//verify the External URL Matches the Backend
modelServingSection.findInternalExternalServiceButton().click();
modelServingSection.findExternalServicePopoverTable().should('contain', url);
});
},
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import type { DataScienceProjectData } from '~/__tests__/cypress/cypress/types';
import { deleteOpenShiftProject } from '~/__tests__/cypress/cypress/utils/oc_commands/project';
import { loadDSPFixture } from '~/__tests__/cypress/cypress/utils/dataLoader';
import { HTPASSWD_CLUSTER_ADMIN_USER } from '~/__tests__/cypress/cypress/utils/e2eUsers';
import { projectListPage, projectDetails } from '~/__tests__/cypress/cypress/pages/projects';
import {
modelServingGlobal,
inferenceServiceModal,
modelServingSection,
} from '~/__tests__/cypress/cypress/pages/modelServing';
import {
checkInferenceServiceState,
provisionProjectForModelServing,
modelExternalURLOpenVinoTester,
} from '~/__tests__/cypress/cypress/utils/oc_commands/modelServing';

let testData: DataScienceProjectData;
let projectName: string;
let modelName: string;
let modelFilePath: string;
const awsBucket = 'BUCKET_1' as const;

describe('Verify Admin Single Model Creation and Validation using the UI', () => {
before(() => {
Cypress.on('uncaught:exception', (err) => {
if (err.message.includes('Error: secrets "ds-pipeline-config" already exists')) {
return false;
}
return true;
});
// Setup: Load test data and ensure clean state
return loadDSPFixture('e2e/dataScienceProjects/testSingleModelAdminCreation.yaml').then(
(fixtureData: DataScienceProjectData) => {
testData = fixtureData;
projectName = testData.projectSingleModelAdminResourceName;
modelName = testData.singleModelAdminName;
modelFilePath = testData.modelOpenVinoPath;

if (!projectName) {
throw new Error('Project name is undefined or empty in the loaded fixture');
}
cy.log(`Loaded project name: ${projectName}`);
// Create a Project for pipelines
provisionProjectForModelServing(
projectName,
awsBucket,
'resources/yaml/data_connection_model_serving.yaml',
);
},
);
});
after(() => {
// Delete provisioned Project - 5 min timeout to accomadate increased time to delete a project with a model
deleteOpenShiftProject(projectName, { timeout: 300000 });
});

it(
'Verify that an Admin can Serve, Query a Single Model using both the UI and External links',
{ tags: ['@Smoke', '@SmokeSet3', '@ODS-2626', '@Dashboard', '@Modelserving'] },
() => {
cy.log('Model Name:', modelName);
// Authentication and navigation
cy.step(`Log into the application with ${HTPASSWD_CLUSTER_ADMIN_USER.USERNAME}`);
cy.visitWithLogin('/', HTPASSWD_CLUSTER_ADMIN_USER);

// Project navigation
cy.step(
`Navigate to the Project list tab and search for ${testData.projectSingleModelAdminResourceName}`,
);
projectListPage.navigate();
projectListPage.filterProjectByName(testData.projectSingleModelAdminResourceName);
projectListPage.findProjectLink(testData.projectSingleModelAdminResourceName).click();

// Navigate to Model Serving tab and Deploy a Single Model
cy.step('Navigate to Model Serving and click to Deploy a Single Model');
projectDetails.findSectionTab('model-server').click();
modelServingGlobal.findSingleServingModelButton().click();
modelServingGlobal.findDeployModelButton().click();

// Launch a Single Serving Model and select the required entries
cy.step('Launch a Single Serving Model using Openvino');
inferenceServiceModal.findModelNameInput().type(testData.singleModelAdminName);
inferenceServiceModal.findServingRuntimeTemplate().click();
inferenceServiceModal.findOpenVinoServingRuntime().click();
inferenceServiceModal.findModelFrameworkSelect().click();
inferenceServiceModal.findOpenVinoIROpSet13().click();

// Enable Model access through an external route
cy.step('Allow Model to be accessed from an External route without Authentication');
inferenceServiceModal.findDeployedModelRouteCheckbox().click();
inferenceServiceModal.findDeployedModelRouteCheckbox().should('be.checked');
inferenceServiceModal.findTokenAuthenticationCheckbox().click();
inferenceServiceModal.findTokenAuthenticationCheckbox().should('not.be.checked');
inferenceServiceModal.findLocationPathInput().type(modelFilePath);
inferenceServiceModal.findSubmitButton().click();

//Verify the model created
cy.step('Verify that the Model is created Successfully on the backend and frontend');
checkInferenceServiceState(testData.singleModelAdminName);
modelServingSection.findModelServerName(testData.singleModelAdminName);
// Note reload is required as status tooltip was not found due to a stale element
cy.reload();
modelServingSection.findStatusTooltip().click({ force: true });
cy.contains('Loaded', { timeout: 120000 }).should('be.visible');

//Verify the Model is accessible externally
cy.step('Verify the model is accessible externally');
modelExternalURLOpenVinoTester(modelName).then(({ url, response }) => {
expect(response.status).to.equal(200);

//verify the External URL Matches the Backend
modelServingSection.findInternalExternalServiceButton().click();
modelServingSection.findExternalServicePopoverTable().should('contain', url);
});
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('Verify Model Creation and Validation using the UI', () => {

it(
'Verify that a Non Admin can Serve and Query a Model using the UI',
{ tags: ['@Smoke', '@SmokeSet2', '@ODS-2552', '@Dashboard'] },
{ tags: ['@Smoke', '@SmokeSet3', '@ODS-2552', '@Dashboard', '@Modelserving'] },
() => {
cy.log('Model Name:', modelName);
// Authentication and navigation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ describe('Verify that users can provide contributor project permissions to non-a
cy.step('Assign contributor user Project Permissions');
permissions.findAddUserButton().click();
permissions.getUserTable().findAddInput().type(LDAP_CONTRIBUTOR_USER.USERNAME);
cy.debug();
permissions
.getUserTable()
.selectPermission(
Expand Down
Loading
Loading