feat: ui:disabled allowed in EntityPicker

Signed-off-by: Nikunj Hudka <nikunjhudka123@gmail.com>
This commit is contained in:
Nikunj Hudka
2025-02-23 22:58:14 -04:00
parent b5a82087a7
commit 6ed865136e
2 changed files with 74 additions and 3 deletions
@@ -28,6 +28,7 @@ import { EntityPickerProps } from './schema';
import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react';
import { DefaultEntityPresentationApi } from '@backstage/plugin-catalog';
import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils';
import userEvent from '@testing-library/user-event';
const makeEntity = (kind: string, namespace: string, name: string): Entity => ({
apiVersion: 'scaffolder.backstage.io/v1beta3',
@@ -261,6 +262,73 @@ describe('<EntityPicker />', () => {
});
});
describe('ui:disabled EntityPicker', () => {
beforeEach(() => {
uiSchema = {
'ui:options': {
catalogFilter: [
{
kind: ['Group'],
'metadata.name': 'test-entity',
},
{
kind: ['User'],
'metadata.name': 'test-entity',
},
],
},
};
props = {
onChange,
schema,
required: true,
uiSchema,
rawErrors,
formData,
} as unknown as FieldProps<any>;
catalogApi.getEntities.mockResolvedValue({ items: entities });
});
it('Prevents user from modifying input when ui:disabled is true', async () => {
props.uiSchema = { 'ui:disabled': true };
props.formData = 'component:default/myentity';
await renderInTestApp(
<Wrapper>
<EntityPicker {...props} />
</Wrapper>,
);
const input = screen.getByRole('textbox');
// Expect input to be disabled
expect(input).toBeDisabled();
expect(input).toHaveValue('component:default/myentity');
});
it('Allows user to edit when ui:disabled is false', async () => {
props.uiSchema = { 'ui:disabled': false };
props.formData = 'component:default/myentity';
await renderInTestApp(
<Wrapper>
<EntityPicker {...props} />
</Wrapper>,
);
const input = screen.getByRole('textbox');
expect(input).not.toBeDisabled();
fireEvent.change(input, {
target: { value: 'component:default/mynewentity' },
});
fireEvent.blur(input);
expect(input).toHaveValue('component:default/mynewentity');
expect(onChange).toHaveBeenCalledWith('component:default/mynewentity');
});
});
describe('catalogFilter should take precedence over allowedKinds', () => {
beforeEach(() => {
uiSchema = {
@@ -73,6 +73,7 @@ export const EntityPicker = (props: EntityPickerProps) => {
const defaultKind = uiSchema['ui:options']?.defaultKind;
const defaultNamespace =
uiSchema['ui:options']?.defaultNamespace || undefined;
const isDisabled = uiSchema?.['ui:disabled'] ?? false;
const catalogApi = useApi(catalogApiRef);
const entityPresentationApi = useApi(entityPresentationApiRef);
@@ -185,9 +186,10 @@ export const EntityPicker = (props: EntityPickerProps) => {
>
<Autocomplete
disabled={
required &&
!allowArbitraryValues &&
entities?.catalogEntities.length === 1
isDisabled ||
(required &&
!allowArbitraryValues &&
entities?.catalogEntities.length === 1)
}
id={idSchema?.$id}
value={selectedEntity}
@@ -212,6 +214,7 @@ export const EntityPicker = (props: EntityPickerProps) => {
FormHelperTextProps={{ margin: 'dense', style: { marginLeft: 0 } }}
variant="outlined"
required={required}
disabled={isDisabled}
InputProps={params.InputProps}
/>
)}