diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerModel.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerModel.cy.ts index 9d39f00ee1..de158ec3b0 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerModel.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerModel.cy.ts @@ -182,6 +182,7 @@ describe('Register model page', () => { }); it('Creates expected resources on submit in object storage mode', () => { + const veryLongName = 'Test name'.repeat(15); // A string over 128 characters registerModelPage.findFormField(FormFieldSelector.MODEL_NAME).type('Test model name'); registerModelPage .findFormField(FormFieldSelector.MODEL_DESCRIPTION) @@ -201,7 +202,17 @@ describe('Register model page', () => { registerModelPage .findFormField(FormFieldSelector.LOCATION_PATH) .type('demo-models/flan-t5-small-caikit'); + registerModelPage.findSubmitButton().should('be.enabled'); + registerModelPage.findFormField(FormFieldSelector.MODEL_NAME).clear().type(veryLongName); + registerModelPage.findSubmitButton().should('be.disabled'); + registerModelPage.findFormField(FormFieldSelector.VERSION_NAME).clear().type(veryLongName); + registerModelPage.findFormField(FormFieldSelector.MODEL_NAME).clear().type('Test model name'); + registerModelPage.findSubmitButton().should('be.disabled'); + registerModelPage + .findFormField(FormFieldSelector.VERSION_NAME) + .clear() + .type('Test version name'); registerModelPage.findSubmitButton().click(); cy.wait('@createRegisteredModel').then((interception) => { @@ -224,7 +235,7 @@ describe('Register model page', () => { }); cy.wait('@createModelArtifact').then((interception) => { expect(interception.request.body).to.containSubset({ - name: 'Test model name-Test version name-artifact', + name: 'Test version name', description: 'Test version description', customProperties: {}, state: ModelArtifactState.LIVE, @@ -292,7 +303,7 @@ describe('Register model page', () => { }); cy.wait('@createModelArtifact').then((interception) => { expect(interception.request.body).to.containSubset({ - name: 'Test model name-Test version name-artifact', + name: 'Test version name', description: 'Test version description', customProperties: {}, state: ModelArtifactState.LIVE, diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerVersion.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerVersion.cy.ts index 494abadbd5..8f422c8f2b 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerVersion.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistry/registerVersion.cy.ts @@ -350,6 +350,7 @@ describe('Register model page with no preselected model', () => { }); it('Creates expected resources on submit in object storage mode', () => { + const veryLongName = 'Test name'.repeat(15); // A string over 128 characters registerVersionPage.selectRegisteredModel('Test model 1'); registerVersionPage.findFormField(FormFieldSelector.VERSION_NAME).type('Test version name'); registerVersionPage @@ -359,6 +360,14 @@ describe('Register model page with no preselected model', () => { .findFormField(FormFieldSelector.LOCATION_PATH) .type('demo-models/flan-t5-small-caikit'); + registerVersionPage.findFormField(FormFieldSelector.VERSION_NAME).clear().type(veryLongName); + registerVersionPage.findSubmitButton().should('be.disabled'); + registerVersionPage + .findFormField(FormFieldSelector.VERSION_NAME) + .clear() + .type('Test version name'); + + registerVersionPage.findSubmitButton().should('be.enabled'); registerVersionPage.findSubmitButton().click(); cy.wait('@createModelVersion').then((interception) => { @@ -373,7 +382,7 @@ describe('Register model page with no preselected model', () => { }); cy.wait('@createModelArtifact').then((interception) => { expect(interception.request.body).to.containSubset({ - name: 'Test model 1-Test version name-artifact', + name: 'Test version name', description: 'Test version description', customProperties: {}, state: ModelArtifactState.LIVE, @@ -428,7 +437,7 @@ describe('Register model page with no preselected model', () => { }); cy.wait('@createModelArtifact').then((interception) => { expect(interception.request.body).to.containSubset({ - name: 'Test model 1-Test version name-artifact', + name: 'Test version name', description: 'Test version description', customProperties: {}, state: ModelArtifactState.LIVE, @@ -513,7 +522,7 @@ describe('Register model page with preselected model', () => { }); cy.wait('@createModelArtifact').then((interception) => { expect(interception.request.body).to.containSubset({ - name: 'Test model 1-Test version name-artifact', + name: 'Test version name', description: 'Test version description', customProperties: {}, state: ModelArtifactState.LIVE, @@ -568,7 +577,7 @@ describe('Register model page with preselected model', () => { }); cy.wait('@createModelArtifact').then((interception) => { expect(interception.request.body).to.containSubset({ - name: 'Test model 1-Test version name-artifact', + name: 'Test version name', description: 'Test version description', customProperties: {}, state: ModelArtifactState.LIVE, diff --git a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx index 5bf60dc589..d4379c569c 100644 --- a/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx +++ b/frontend/src/pages/modelRegistry/screens/RegisterModel/RegisterModel.tsx @@ -4,6 +4,9 @@ import { BreadcrumbItem, Form, FormGroup, + FormHelperText, + HelperText, + HelperTextItem, PageSection, Stack, StackItem, @@ -17,7 +20,7 @@ import FormSection from '~/components/pf-overrides/FormSection'; import ApplicationsPage from '~/pages/ApplicationsPage'; import { modelRegistryUrl, registeredModelUrl } from '~/pages/modelRegistry/screens/routeUtils'; import { useRegisterModelData } from './useRegisterModelData'; -import { isRegisterModelSubmitDisabled, registerModel } from './utils'; +import { isNameValid, isRegisterModelSubmitDisabled, registerModel } from './utils'; import RegistrationCommonFormSections from './RegistrationCommonFormSections'; import { useRegistrationCommonState } from './useRegistrationCommonState'; import PrefilledModelRegistryField from './PrefilledModelRegistryField'; @@ -31,7 +34,13 @@ const RegisterModel: React.FC = () => { useRegistrationCommonState(); const [formData, setData] = useRegisterModelData(); - const isSubmitDisabled = isSubmitting || isRegisterModelSubmitDisabled(formData); + const isVersionNameValid = isNameValid(formData.versionName); + const isModelNameValid = isNameValid(formData.modelName); + const isSubmitDisabled = + isSubmitting || + isRegisterModelSubmitDisabled(formData) || + !isVersionNameValid || + !isModelNameValid; const { modelName, modelDescription } = formData; const onSubmit = () => @@ -75,7 +84,17 @@ const RegisterModel: React.FC = () => { name="model-name" value={modelName} onChange={(_e, value) => setData('modelName', value)} + validated={isModelNameValid ? 'default' : 'error'} /> + {!isModelNameValid && ( + + + + Cannot exceed 128 characters + + + + )}