Skip to content

Commit 89081d7

Browse files
Taj010ConorOM1
andauthored
Add E2E tests for model registry register-and-store OCI flow (#6743)
* add e2e test for register and store flow * address coderabbit comments * fix tests * restest * address comments * add strings * address comments * adjust path and add job check * remove feature flag path * Add URI origin flow * fix lint error * address comments for uri flow * retest * address comments and fix test flakiness * adjust the tests * adjust the test and address comments * adjust the form namespace selector * adjust test * adjust test * add contributions * fix typecheck * retest --------- Co-authored-by: Conor O'Malley <conormomalley@gmail.com> Co-authored-by: Conor O'Malley <97108400+ConorOM1@users.noreply.github.com>
1 parent 694ddc2 commit 89081d7

10 files changed

Lines changed: 503 additions & 41 deletions

File tree

packages/cypress/cypress/fixtures/e2e/modelRegistry/testModelRegistry.yaml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,28 @@ newDatabaseUsername: "mlmduser_updated"
6464
newDatabasePassword: "NewTestPassword123"
6565

6666
# Object storage paths for v2
67-
objectStoragePathV2: "models/test-model/v2.0"
67+
objectStoragePathV2: "models/test-model/v2.0"
68+
69+
# OCI Register and Store
70+
ociModelName: "test-oci-model"
71+
ociModelDescription: "E2E test model using OCI register and store"
72+
ociVersionName: "v1.0"
73+
ociVersionDescription: "First version via OCI transfer job"
74+
ociModelFormat: "onnx"
75+
ociModelFormatVersion: "1.0"
76+
ociJobName: "oci-transfer-job"
77+
ociSourceEndpoint: "http://minio.example.com:9000"
78+
ociSourceBucket: "test-models"
79+
ociSourceRegion: "us-east-1"
80+
ociSourcePath: "models/oci-test-model/v1.0"
81+
ociTransferJobStartedNotification: "Model transfer job started"
82+
ociTransferJobFailedNotification: "Model transfer job failed"
83+
ociDestinationRegistry: "quay.io"
84+
ociDestinationUri: "quay.io/test-org/test-oci-model:v1"
85+
ociDestinationUsername: "dummy-oci-user"
86+
ociDestinationPassword: "dummy-oci-pass"
87+
88+
# OCI Register and Store — URI origin variant
89+
ociUriModelName: "test-oci-uri-model"
90+
ociUriJobName: "oci-uri-transfer-job"
91+
ociUriOriginUri: "s3://test-models/models/oci-test-model/v1.0?endpoint=http%3A%2F%2Fminio.example.com%3A9000&defaultRegion=us-east-1"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: RoleBinding
3+
metadata:
4+
name: {{PROJECT_NAME}}-rb
5+
namespace: {{NAMESPACE}}
6+
labels:
7+
opendatahub.io/dashboard: "true"
8+
opendatahub.io/rb-project-subject: "true"
9+
app: {{REGISTRY_NAME}}
10+
app.kubernetes.io/component: model-registry
11+
app.kubernetes.io/part-of: model-registry
12+
app.kubernetes.io/name: {{REGISTRY_NAME}}
13+
component: model-registry
14+
subjects:
15+
- kind: Group
16+
apiGroup: rbac.authorization.k8s.io
17+
name: system:serviceaccounts:{{PROJECT_NAME}}
18+
roleRef:
19+
apiGroup: rbac.authorization.k8s.io
20+
kind: Role
21+
name: registry-user-{{REGISTRY_NAME}}

packages/cypress/cypress/pages/modelRegistry.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,25 @@ class ModelRegistry {
5858
this.waitLanding();
5959
}
6060

61-
visit() {
62-
this.visitWithRegistry('modelregistry-sample');
61+
visit(registryName = 'modelregistry-sample') {
62+
cy.visitWithLogin(`/ai-hub/registry/${registryName}`);
63+
cy.findByTestId('app-page-title', { timeout: 60000 }).should('exist');
6364
}
6465

6566
visitWithRegistry(registryName: string) {
66-
cy.visitWithLogin(`/ai-hub/models/registry/${registryName}`);
67-
this.wait();
67+
this.visit(registryName);
6868
}
6969

7070
navigate() {
71-
appChrome.findNavItem({ name: 'Models', rootSection: 'AI hub' }).click();
71+
appChrome
72+
.findNavItem({ name: 'Registry', rootSection: 'AI hub', subSection: 'Models' })
73+
.click();
7274
this.wait();
7375
}
7476

7577
private wait() {
76-
cy.findByTestId('app-tab-page-title').should('exist');
77-
cy.findByText('Select a model registry to view and manage your registered models.', {
78-
exact: false,
79-
}).should('exist');
78+
cy.findByTestId('app-page-title').should('exist');
79+
cy.findByTestId('app-page-title').contains('Registry');
8080
cy.testA11y();
8181
}
8282

@@ -134,12 +134,16 @@ class ModelRegistry {
134134
}
135135

136136
tabEnabled() {
137-
appChrome.findNavItem({ name: 'Models', rootSection: 'AI hub' }).should('exist');
137+
appChrome
138+
.findNavItem({ name: 'Registry', rootSection: 'AI hub', subSection: 'Models' })
139+
.should('exist');
138140
return this;
139141
}
140142

141143
tabDisabled() {
142-
appChrome.findNavItem({ name: 'Models', rootSection: 'AI hub' }).should('not.exist');
144+
appChrome
145+
.findNavItem({ name: 'Registry', rootSection: 'AI hub', subSection: 'Models' })
146+
.should('not.exist');
143147
return this;
144148
}
145149

packages/cypress/cypress/pages/modelRegistry/registerAndStorePage.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,16 @@ class RegisterAndStorePage {
2222
return cy.findByTestId('namespace-form-group');
2323
}
2424

25-
findProjectSelectorToggle() {
26-
return cy.findByTestId('project-selector-toggle');
25+
findProjectSelectorToggle(timeout?: number) {
26+
return cy.findByTestId('project-selector-toggle', { timeout });
27+
}
28+
29+
findProjectSelectorSearch() {
30+
return cy.findByTestId('project-selector-search');
31+
}
32+
33+
findProjectSelectorMenuList() {
34+
return cy.findByTestId('project-selector-menuList');
2735
}
2836

2937
findNoAccessAlert() {

packages/cypress/cypress/pages/modelRegistry/registerModelPage.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ export enum FormFieldSelector {
1414
LOCATION_PATH = '#location-path',
1515
LOCATION_TYPE_URI = '#location-type-uri',
1616
LOCATION_URI = '#location-uri',
17+
JOB_NAME = '#model-transfer-job-name',
18+
LOCATION_S3_ACCESS_KEY_ID = '#location-s3-access-key-id',
19+
LOCATION_S3_SECRET_ACCESS_KEY = '#location-s3-secret-access-key',
20+
DESTINATION_OCI_REGISTRY = '#destination-oci-registry',
21+
DESTINATION_OCI_URI = '#destination-oci-uri',
22+
DESTINATION_OCI_USERNAME = '#destination-oci-username',
23+
DESTINATION_OCI_PASSWORD = '#destination-oci-password',
1724
}
1825

1926
class RegisterModelPage {
@@ -67,13 +74,56 @@ class RegisterModelPage {
6774
return cy.findByTestId('autofill-modal-button');
6875
}
6976

70-
findSubmitButton() {
71-
return cy.findByTestId('create-button');
77+
findSubmitButton(timeout?: number) {
78+
return cy.findByTestId('create-button', { timeout });
7279
}
7380

7481
findModelNameError() {
7582
return cy.findByTestId('model-name-error');
7683
}
84+
85+
findRegistrationModeToggleGroup(timeout?: number) {
86+
return cy.findByTestId('registration-mode-toggle-group', { timeout });
87+
}
88+
89+
findRegisterToggle() {
90+
return cy.findByTestId('registration-mode-register');
91+
}
92+
93+
findRegisterAndStoreToggle() {
94+
return cy.findByTestId('registration-mode-register-and-store');
95+
}
96+
97+
findRegisterAndStoreToggleButton() {
98+
return this.findRegisterAndStoreToggle().find('button');
99+
}
100+
101+
findNamespaceSelector(timeout?: number) {
102+
return cy.findByTestId('form-namespace-selector', { timeout });
103+
}
104+
105+
findNamespaceSelectorTrigger() {
106+
return cy.findByTestId('form-namespace-selector-trigger');
107+
}
108+
109+
findNamespaceTextInput(timeout?: number) {
110+
return cy.findByTestId('form-namespace-text-input', { timeout });
111+
}
112+
113+
/**
114+
* Namespace options render in the SimpleSelect menu (often portaled). Query by role after opening the menu.
115+
*/
116+
findNamespaceOption(name: string) {
117+
return cy.findByRole('option', { name });
118+
}
119+
120+
findOriginLocationSection(timeout?: number) {
121+
return cy.findByTestId('model-origin-location-section', { timeout });
122+
}
123+
124+
findDestinationLocationSection(timeout?: number) {
125+
return cy.findByTestId('model-destination-location-section', { timeout });
126+
}
77127
}
78128

79129
export const registerModelPage = new RegisterModelPage();

0 commit comments

Comments
 (0)