Skip to content

Commit

Permalink
Tests for model versions table
Browse files Browse the repository at this point in the history
  • Loading branch information
manaswinidas committed May 8, 2024
1 parent 424378e commit fe803cc
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 46 deletions.
14 changes: 10 additions & 4 deletions frontend/src/__mocks__/mockModelVersion.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { ModelVersion, ModelVersionState } from '~/concepts/modelRegistry/types';
import { ModelRegistryBase, ModelVersion, ModelVersionState } from '~/concepts/modelRegistry/types';

type MockModelVersionType = {
author?: string;
id?: string;
registeredModelId?: string;
name?: string;
customProperties?: ModelRegistryBase['customProperties'];
};

export const mockModelVersion = ({
author = 'Test author',
registeredModelId = '1',
name = 'new model version',
customProperties = {},
id = '',
}: MockModelVersionType): ModelVersion => ({
author,
createTimeSinceEpoch: '1712234877179',
customProperties: {},
id: '26',
customProperties,
id,
lastUpdateTimeSinceEpoch: '1712234877179',
name: 'fraud detection model version 1',
name,
state: ModelVersionState.ARCHIVED,
registeredModelId,
});
10 changes: 6 additions & 4 deletions frontend/src/__mocks__/mockModelVersionList.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/* eslint-disable camelcase */
import { ModelVersionList } from '~/concepts/modelRegistry/types';
import { mockModelVersion } from './mockModelVersion';

export const mockModelVersionList = (): ModelVersionList => ({
items: [mockModelVersion({ author: 'Author 1', registeredModelId: '1' })],
export const mockModelVersionList = ({
items = [],
}: Partial<ModelVersionList>): ModelVersionList => ({
items,
nextPageToken: '',
pageSize: 0,
size: 1,
size: items.length,
});
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
/* eslint-disable camelcase */
import { mockK8sResourceList, mockRouteK8sResourceModelRegistry } from '~/__mocks__';
import { mockComponents } from '~/__mocks__/mockComponents';
import { mockDashboardConfig } from '~/__mocks__/mockDashboardConfig';
import { MODEL_REGISTRY_API_VERSION } from '~/concepts/modelRegistry/const';
import { mockModelRegistry } from '~/__mocks__/mockModelRegistry';
import { mockModelVersionList } from '~/__mocks__/mockModelVersionList';
import { mockRegisteredModelList } from '~/__mocks__/mockRegisteredModelsList';
import { labelModal, modelRegistry } from '~/__tests__/cypress/cypress/pages/modelRegistry';
import { be } from '~/__tests__/cypress/cypress/utils/should';
import { ModelRegistryModel, RouteModel } from '~/__tests__/cypress/cypress/utils/models';
import { mockModelVersionList } from '~/__mocks__/mockModelVersionList';
import { mockModelVersion } from '~/__mocks__/mockModelVersion';
import { ModelVersion } from '~/concepts/modelRegistry/types';

type HandlersProps = {
disableModelRegistryFeature?: boolean;
size?: number;
registeredModelsSize?: number;
modelVersions?: ModelVersion[];
};

const initIntercepts = ({ disableModelRegistryFeature = false, size = 4 }: HandlersProps) => {
const initIntercepts = ({
disableModelRegistryFeature = false,
registeredModelsSize = 4,
modelVersions = [
mockModelVersion({ author: 'Author 1' }),
mockModelVersion({ name: 'model version' }),
],
}: HandlersProps) => {
cy.interceptOdh(
'GET /api/config',
mockDashboardConfig({
Expand All @@ -37,14 +48,15 @@ const initIntercepts = ({ disableModelRegistryFeature = false, size = 4 }: Handl
namespace: 'odh-model-registries',
}),
);

cy.interceptOdh(
`GET /api/service/modelregistry/modelregistry-sample/api/model_registry/${MODEL_REGISTRY_API_VERSION}/registered_models`,
mockRegisteredModelList({ size }),
mockRegisteredModelList({ size: registeredModelsSize }),
);

cy.interceptOdh(
`GET /api/service/modelregistry/modelregistry-sample/api/model_registry/${MODEL_REGISTRY_API_VERSION}/registered_models/1/versions`,
mockModelVersionList(),
mockModelVersionList({ items: modelVersions }),
);
};

Expand All @@ -71,7 +83,7 @@ describe('Model Registry', () => {
it('No registered models in the selected Model Registry', () => {
initIntercepts({
disableModelRegistryFeature: false,
size: 0,
registeredModelsSize: 0,
});

modelRegistry.visit();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/* eslint-disable camelcase */
import { mockK8sResourceList } from '~/__mocks__';
import { mockDashboardConfig } from '~/__mocks__/mockDashboardConfig';
import { MODEL_REGISTRY_API_VERSION } from '~/concepts/modelRegistry/const';
import { mockModelRegistry } from '~/__mocks__/mockModelRegistry';
import { mockModelVersionList } from '~/__mocks__/mockModelVersionList';
import { mockRegisteredModelList } from '~/__mocks__/mockRegisteredModelsList';
import { labelModal, modelRegistry } from '~/__tests__/cypress/cypress/pages/modelRegistry';
import { be } from '~/__tests__/cypress/cypress/utils/should';
import { ModelRegistryModel } from '~/__tests__/cypress/cypress/utils/models';
import { verifyRelativeURL } from '~/__tests__/cypress/cypress/utils/url';
import { mockRegisteredModel } from '~/__mocks__/mockRegisteredModel';
import { ModelVersion } from '~/concepts/modelRegistry/types';
import { mockModelVersion } from '~/__mocks__/mockModelVersion';

type HandlersProps = {
disableModelRegistryFeature?: boolean;
registeredModelsSize?: number;
modelVersions?: ModelVersion[];
};

const initIntercepts = ({
disableModelRegistryFeature = false,
registeredModelsSize = 4,
modelVersions = [
mockModelVersion({
author: 'Author 1',
id: '1',
customProperties: {
Financial: {
metadataType: 'MetadataStringValue',
string_value: 'non-empty',
},
'Financial data': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Fraud detection': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Test label': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Machine learning': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Next data to be overflow': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Test label x': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Test label y': {
metadataType: 'MetadataStringValue',
string_value: '',
},
'Test label z': {
metadataType: 'MetadataStringValue',
string_value: '',
},
},
}),
mockModelVersion({ id: '2', name: 'model version' }),
],
}: HandlersProps) => {
cy.interceptOdh(
'GET /api/config',
mockDashboardConfig({
disableModelRegistry: disableModelRegistryFeature,
}),
);

cy.interceptK8sList(
ModelRegistryModel,
mockK8sResourceList([mockModelRegistry({}), mockModelRegistry({ name: 'test-registry' })]),
);

cy.interceptK8s(ModelRegistryModel, mockModelRegistry({}));

cy.interceptOdh(
`GET /api/service/modelregistry/modelregistry-sample/api/model_registry/${MODEL_REGISTRY_API_VERSION}/registered_models`,
mockRegisteredModelList({ size: registeredModelsSize }),
);

cy.interceptOdh(
`GET /api/service/modelregistry/modelregistry-sample/api/model_registry/${MODEL_REGISTRY_API_VERSION}/registered_models/1/versions`,
mockModelVersionList({ items: modelVersions }),
);

cy.interceptOdh(
`GET /api/service/modelregistry/modelregistry-sample/api/model_registry/${MODEL_REGISTRY_API_VERSION}/registered_models/1`,
mockRegisteredModel({}),
);
};
describe('Model Versions', () => {
it('No model versions in the selected registered model', () => {
initIntercepts({
disableModelRegistryFeature: false,
modelVersions: [],
});

modelRegistry.visit();
const registeredModelRow = modelRegistry.getRow('Fraud detection model');
registeredModelRow.findName().contains('Fraud detection model').click();
verifyRelativeURL(`/modelRegistry/modelregistry-sample/registeredModels/1/versions`);
modelRegistry.shouldmodelVersionsEmpty();
});

it('Model versions table', () => {
initIntercepts({
disableModelRegistryFeature: false,
});

modelRegistry.visit();
const registeredModelRow = modelRegistry.getRow('Fraud detection model');
registeredModelRow.findName().contains('Fraud detection model').click();
verifyRelativeURL(`/modelRegistry/modelregistry-sample/registeredModels/1/versions`);
modelRegistry.findModelBreadcrumbItem().contains('test');
modelRegistry
.findModelVersionsTableKebab()
.findDropdownItem('View archived versions')
.should('be.disabled');
modelRegistry
.findModelVersionsHeaderAction()
.findDropdownItem('Archive model')
.should('be.disabled');
modelRegistry.findModelVersionsTable().should('be.visible');
modelRegistry.findModelVersionsTableRows().should('have.length', 2);

// Label modal
const modelVersionRow = modelRegistry.getModelVersionRow('new model version');

modelVersionRow.findLabelModalText().contains('5 more');
modelVersionRow.findLabelModalText().click();
labelModal.shouldContainsModalLabels([
'Financial',
'Financial data',
'Fraud detection',
'Test label',
'Machine learning',
'Next data to be overflow',
'Test label x',
'Test label y',
'Test label y',
]);
labelModal.findModalSearchInput().type('Financial');
labelModal.shouldContainsModalLabels(['Financial', 'Financial data']);
labelModal.findCloseModal().click();

// sort by model version name
modelRegistry.findModelVersionsTableHeaderButton('Version name').should(be.sortAscending);
modelRegistry.findModelVersionsTableHeaderButton('Version name').click();
modelRegistry.findModelVersionsTableHeaderButton('Version name').should(be.sortDescending);

// sort by model version owner
modelRegistry.findModelVersionsTableHeaderButton('Owner').click();
modelRegistry.findModelVersionsTableHeaderButton('Owner').should(be.sortAscending);
modelRegistry.findModelVersionsTableHeaderButton('Owner').click();
modelRegistry.findModelVersionsTableHeaderButton('Owner').should(be.sortDescending);

// filtering by keyword
modelRegistry.findModelVersionsTableSearch().type('new model version');
modelRegistry.findModelVersionsTableRows().should('have.length', 1);
modelRegistry.findModelVersionsTableRows().contains('new model version');
modelRegistry.findModelVersionsTableSearch().focused().clear();

// filtering by owner
modelRegistry.findModelVersionsTableFilter().findDropdownItem('Owner').click();
modelRegistry.findModelVersionsTableSearch().type('Test author');
modelRegistry.findModelVersionsTableRows().should('have.length', 1);
modelRegistry.findModelVersionsTableRows().contains('Test author');
});
});
52 changes: 49 additions & 3 deletions frontend/src/__tests__/cypress/cypress/pages/modelRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class LabelModal extends Modal {
}
}

class RegisteredModelTableRow extends TableRow {
class ModelRegistryTableRow extends TableRow {
findName() {
return this.find().findByTestId('model-name');
}
Expand Down Expand Up @@ -66,6 +66,7 @@ class ModelRegistry {

private wait() {
cy.findByTestId('app-page-title').should('exist');
cy.findByTestId('app-page-title').contains('Registered models');
cy.testA11y();
}

Expand All @@ -79,7 +80,11 @@ class ModelRegistry {
}

shouldregisteredModelsEmpty() {
cy.findByTestId('empty-model-registry').should('exist');
cy.findByTestId('empty-registered-models').should('exist');
}

shouldmodelVersionsEmpty() {
cy.findByTestId('empty-model-versions').should('exist');
}

shouldModelRegistrySelectorExist() {
Expand All @@ -104,23 +109,64 @@ class ModelRegistry {
return cy.findByTestId('registered-model-table');
}

findModelVersionsTable() {
return cy.findByTestId('model-versions-table');
}

findTableRows() {
return this.findTable().find('tbody tr');
}

findModelVersionsTableRows() {
return this.findModelVersionsTable().find('tbody tr');
}

getRow(name: string) {
return new RegisteredModelTableRow(() =>
return new ModelRegistryTableRow(() =>
this.findTable().find(`[data-label="Model name"]`).contains(name).parents('tr'),
);
}

getModelVersionRow(name: string) {
return new ModelRegistryTableRow(() =>
this.findModelVersionsTable()
.find(`[data-label="Version name"]`)
.contains(name)
.parents('tr'),
);
}

findRegisteredModelTableHeaderButton(name: string) {
return this.findTable().find('thead').findByRole('button', { name });
}

findModelVersionsTableHeaderButton(name: string) {
return this.findModelVersionsTable().find('thead').findByRole('button', { name });
}

findTableSearch() {
return cy.findByTestId('registered-model-table-search');
}

findModelVersionsTableSearch() {
return cy.findByTestId('model-versions-table-search');
}

findModelBreadcrumbItem() {
return cy.findByTestId('breadcrumb-model');
}

findModelVersionsTableKebab() {
return cy.findByTestId('model-versions-table-kebab-action');
}

findModelVersionsHeaderAction() {
return cy.findByTestId('model-version-action-toggle');
}

findModelVersionsTableFilter() {
return cy.findByTestId('model-versions-table-filter');
}
}

export const modelRegistry = new ModelRegistry();
Expand Down
Loading

0 comments on commit fe803cc

Please sign in to comment.