Skip to content

Commit

Permalink
Auto generate default env var from name (opendatahub-io#3105)
Browse files Browse the repository at this point in the history
  • Loading branch information
emilys314 committed Aug 27, 2024
1 parent 4bdaf71 commit 4ceae5d
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 2 deletions.
22 changes: 22 additions & 0 deletions frontend/src/concepts/connectionTypes/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { mockConnectionTypeConfigMapObj } from '~/__mocks__/mockConnectionType';
import { DropdownField, HiddenField, TextField, UriField } from '~/concepts/connectionTypes/types';
import {
defaultValueToString,
fieldNameToEnvVar,
fieldTypeToString,
toConnectionTypeConfigMap,
toConnectionTypeConfigMapObj,
Expand Down Expand Up @@ -225,3 +226,24 @@ describe('fieldTypeToString', () => {
).toBe('URI');
});
});

describe('fieldNameToEnvVar', () => {
it('should replace spaces with underscores', () => {
expect(fieldNameToEnvVar('ABC DEF')).toBe('ABC_DEF');
expect(fieldNameToEnvVar(' ')).toBe('___');
expect(fieldNameToEnvVar(' HI ')).toBe('_HI_');
});
it('should repalce lowercase with uppercase', () => {
expect(fieldNameToEnvVar('one')).toBe('ONE');
expect(fieldNameToEnvVar('tWo')).toBe('TWO');
expect(fieldNameToEnvVar('THREE_')).toBe('THREE_');
});
it('should remove invalid characters', () => {
expect(fieldNameToEnvVar('a!@#$%^&*()-=_+[]\\{}|;\':"`,./<>?1')).toBe('A-_.1');
expect(fieldNameToEnvVar('=== tWo')).toBe('_TWO');
});
it('should remove numbers at the start', () => {
expect(fieldNameToEnvVar('1one')).toBe('ONE');
expect(fieldNameToEnvVar('++123 TWO 456')).toBe('_TWO_456');
});
});
8 changes: 8 additions & 0 deletions frontend/src/concepts/connectionTypes/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ export const fieldTypeToString = <T extends ConnectionTypeDataField>(field: T):

return withCapitalized;
};

export const fieldNameToEnvVar = (name: string): string => {
const spacesAsUnderscores = name.replace(/ /g, '_');
const removeInvalid = spacesAsUnderscores.replace(/[^\w\-.]/g, '');
const removeNumbersAtStart = removeInvalid.replace(/^[0-9]+/g, '');
const allUppercase = removeNumbersAtStart.toUpperCase();
return allUppercase;
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
connectionTypeDataFields,
ConnectionTypeFieldType,
} from '~/concepts/connectionTypes/types';
import { fieldNameToEnvVar } from '~/concepts/connectionTypes/utils';
import { isEnumMember } from '~/utilities/utils';
import DashboardPopupIconButton from '~/concepts/dashboard/DashboardPopupIconButton';
import DataFieldPropertiesForm from '~/pages/connectionTypes/manage/DataFieldPropertiesForm';
Expand Down Expand Up @@ -75,6 +76,7 @@ export const ConnectionTypeDataFieldModal: React.FC<Props> = ({
const [properties, setProperties] = React.useState<unknown>(field?.properties || {});
const [isPropertiesValid, setPropertiesValid] = React.useState(true);

const [autoGenerateEnvVar, setAutoGenerateEnvVar] = React.useState<boolean>(!envVar);
const envVarValidation =
!envVar || ENV_VAR_NAME_REGEX.test(envVar) ? ValidatedOptions.default : ValidatedOptions.error;
const isValid =
Expand Down Expand Up @@ -128,7 +130,12 @@ export const ConnectionTypeDataFieldModal: React.FC<Props> = ({
<TextInput
id="name"
value={name}
onChange={(_ev, value) => setName(value)}
onChange={(_ev, value) => {
setName(value);
if (autoGenerateEnvVar) {
setEnvVar(fieldNameToEnvVar(value));
}
}}
data-testid="field-name-input"
/>
</FormGroup>
Expand Down Expand Up @@ -175,7 +182,12 @@ export const ConnectionTypeDataFieldModal: React.FC<Props> = ({
<TextInput
id="envVar"
value={envVar}
onChange={(_ev, value) => setEnvVar(value)}
onChange={(_ev, value) => {
if (autoGenerateEnvVar) {
setAutoGenerateEnvVar(false);
}
setEnvVar(value);
}}
data-testid="field-env-var-input"
validated={envVarValidation}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,67 @@ describe('ConnectionTypeDataFieldModal', () => {
type: 'short-text',
});
});

it('should auto generate env var if not entered', async () => {
const onCancel = jest.fn();
const onSubmit = jest.fn();

render(<ConnectionTypeDataFieldModal onClose={onCancel} onSubmit={onSubmit} />);
const fieldNameInput = screen.getByTestId('field-name-input');
const fieldDescriptionInput = screen.getByTestId('field-description-input');
const fieldEnvVarInput = screen.getByTestId('field-env-var-input');
const typeSelectGroup = screen.getByTestId('field-type-select');
const typeSelectToggle = within(typeSelectGroup).getByRole('button');

// Autogenerated value test
act(() => {
fireEvent.change(fieldNameInput, { target: { value: 'another field' } });
fireEvent.change(fieldDescriptionInput, { target: { value: 'test description' } });
typeSelectToggle.click();
});

const shortTextSelect = within(screen.getByTestId('field-short-text-select')).getByRole(
'option',
);

act(() => {
shortTextSelect.click();
});

await waitFor(() => expect(typeSelectToggle).toHaveAttribute('aria-expanded', 'false'));

screen.getByTestId('modal-submit-button').click();

expect(onSubmit).toHaveBeenCalledWith({
description: 'test description',
envVar: 'ANOTHER_FIELD',
name: 'another field',
properties: {
defaultReadOnly: undefined,
defaultValue: undefined,
},
required: undefined,
type: 'short-text',
});

// Override the autogenerated value and test it
act(() => {
fireEvent.change(fieldEnvVarInput, { target: { value: 'MANUAL_ENV_VAR_ENTRY' } });
fireEvent.change(fieldNameInput, { target: { value: 'another field 2' } });
});

screen.getByTestId('modal-submit-button').click();

expect(onSubmit).toHaveBeenCalledWith({
description: 'test description',
envVar: 'MANUAL_ENV_VAR_ENTRY',
name: 'another field 2',
properties: {
defaultReadOnly: undefined,
defaultValue: undefined,
},
required: undefined,
type: 'short-text',
});
});
});

0 comments on commit 4ceae5d

Please sign in to comment.