chore: just the error validation left I think for the next scaffolder

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2022-09-12 11:09:45 +02:00
parent 6183125008
commit b9f71b15af
16 changed files with 114 additions and 87 deletions
@@ -68,6 +68,6 @@ describe('createValidator', () => {
/* THEN */
expect(result).not.toBeNull();
expect(result.p1.addError).toHaveBeenCalledTimes(1);
expect(result.p1?.addError).toHaveBeenCalledTimes(1);
});
});
@@ -62,7 +62,7 @@ export const createValidator = (
if (fieldName && typeof validators[fieldName] === 'function') {
validators[fieldName]!(
propData as JsonValue,
propValidation,
propValidation as FormValidation,
context,
);
}
@@ -29,7 +29,7 @@ export const EntityNamePicker = (
schema: { title = 'Name', description = 'Unique name of the component' },
rawErrors,
formData,
uiSchema: { 'ui:autofocus': autoFocus },
uiSchema: { 'ui:autofocus': autoFocus } = {},
idSchema,
placeholder,
} = props;
@@ -39,7 +39,7 @@ describe('<EntityPicker />', () => {
const rawErrors: string[] = [];
const formData = undefined;
let props: FieldProps;
let props: FieldProps<string | undefined>;
const catalogApi: jest.Mocked<CatalogApi> = {
getLocationById: jest.fn(),
@@ -76,7 +76,7 @@ describe('<EntityPicker />', () => {
uiSchema,
rawErrors,
formData,
} as unknown as FieldProps<any>;
} as any;
catalogApi.getEntities.mockResolvedValue({ items: entities });
});
@@ -117,7 +117,7 @@ describe('<EntityPicker />', () => {
uiSchema,
rawErrors,
formData,
} as unknown as FieldProps<any>;
} as any;
catalogApi.getEntities.mockResolvedValue({ items: entities });
});
@@ -45,7 +45,10 @@ export interface EntityPickerUiOptions {
* @public
*/
export const EntityPicker = (
props: FieldExtensionComponentProps<string, EntityPickerUiOptions>,
props: FieldExtensionComponentProps<
string | undefined,
EntityPickerUiOptions
>,
) => {
const {
onChange,
@@ -56,9 +59,9 @@ export const EntityPicker = (
formData,
idSchema,
} = props;
const allowedKinds = uiSchema['ui:options']?.allowedKinds;
const defaultKind = uiSchema['ui:options']?.defaultKind;
const defaultNamespace = uiSchema['ui:options']?.defaultNamespace;
const allowedKinds = uiSchema?.['ui:options']?.allowedKinds;
const defaultKind = uiSchema?.['ui:options']?.defaultKind;
const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace;
const catalogApi = useApi(catalogApiRef);
@@ -99,7 +102,7 @@ export const EntityPicker = (
onChange={onSelect}
options={entityRefs || []}
autoSelect
freeSolo={uiSchema['ui:options']?.allowArbitraryValues ?? true}
freeSolo={uiSchema?.['ui:options']?.allowArbitraryValues ?? true}
renderInput={params => (
<TextField
{...params}
@@ -51,9 +51,9 @@ export const EntityTagsPicker = (
const [inputValue, setInputValue] = useState('');
const [inputError, setInputError] = useState(false);
const tagValidator = makeValidator().isValidTag;
const kinds = uiSchema['ui:options']?.kinds;
const showCounts = uiSchema['ui:options']?.showCounts;
const helperText = uiSchema['ui:options']?.helperText;
const kinds = uiSchema?.['ui:options']?.kinds;
const showCounts = uiSchema?.['ui:options']?.showCounts;
const helperText = uiSchema?.['ui:options']?.helperText;
const { loading, value: existingTags } = useAsync(async () => {
const facet = 'metadata.tags';
@@ -59,12 +59,12 @@ export const OwnedEntityPicker = (
formData,
idSchema,
} = props;
const allowedKinds = uiSchema?.['ui:options']?.allowedKinds;
const defaultKind = uiSchema?.['ui:options']?.defaultKind;
const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace;
const allowedKinds = uiSchema['ui:options']?.allowedKinds;
const defaultKind = uiSchema['ui:options']?.defaultKind;
const defaultNamespace = uiSchema['ui:options']?.defaultNamespace;
const allowArbitraryValues =
uiSchema['ui:options']?.allowArbitraryValues ?? true;
uiSchema?.['ui:options']?.allowArbitraryValues ?? true;
const { ownedEntities, loading } = useOwnedEntities(allowedKinds);
const entityRefs = ownedEntities?.items
@@ -36,7 +36,7 @@ describe('<OwnerPicker />', () => {
const rawErrors: string[] = [];
const formData = undefined;
let props: FieldProps;
let props: FieldProps<string | undefined>;
const catalogApi: jest.Mocked<CatalogApi> = {
getLocationById: jest.fn(),
@@ -36,7 +36,7 @@ export interface OwnerPickerUiOptions {
* @public
*/
export const OwnerPicker = (
props: FieldExtensionComponentProps<string, OwnerPickerUiOptions>,
props: FieldExtensionComponentProps<string | undefined, OwnerPickerUiOptions>,
) => {
const {
schema: { title = 'Owner', description = 'The owner of the component' },
@@ -44,18 +44,18 @@ export const OwnerPicker = (
...restProps
} = props;
const defaultNamespace = uiSchema['ui:options']?.defaultNamespace;
const defaultNamespace = uiSchema?.['ui:options']?.defaultNamespace;
const ownerUiSchema = {
...uiSchema,
'ui:options': {
allowedKinds: (uiSchema['ui:options']?.allowedKinds || [
allowedKinds: (uiSchema?.['ui:options']?.allowedKinds || [
'Group',
'User',
]) as string[],
defaultKind: 'Group',
allowArbitraryValues:
uiSchema['ui:options']?.allowArbitraryValues ?? true,
uiSchema?.['ui:options']?.allowArbitraryValues ?? true,
...(defaultNamespace !== undefined ? { defaultNamespace } : {}),
},
};
@@ -32,6 +32,7 @@ import {
SecretsContext,
} from '../../secrets/SecretsContext';
import { act, fireEvent } from '@testing-library/react';
import { Field } from '@rjsf/utils';
describe('RepoUrlPicker', () => {
const mockScaffolderApi: Partial<ScaffolderApi> = {
@@ -68,7 +69,7 @@ describe('RepoUrlPicker', () => {
<Form
schema={{ type: 'string' }}
uiSchema={{ 'ui:field': 'RepoUrlPicker' }}
fields={{ RepoUrlPicker: RepoUrlPicker }}
fields={{ RepoUrlPicker: RepoUrlPicker as Field<unknown> }}
onSubmit={onSubmit}
/>
</SecretsContextProvider>
@@ -107,7 +108,7 @@ describe('RepoUrlPicker', () => {
'ui:field': 'RepoUrlPicker',
'ui:options': { allowedHosts: ['dev.azure.com'] },
}}
fields={{ RepoUrlPicker: RepoUrlPicker }}
fields={{ RepoUrlPicker: RepoUrlPicker as Field<unknown> }}
/>
</SecretsContextProvider>
</TestApiProvider>,
@@ -145,7 +146,7 @@ describe('RepoUrlPicker', () => {
},
},
}}
fields={{ RepoUrlPicker: RepoUrlPicker }}
fields={{ RepoUrlPicker: RepoUrlPicker as Field<unknown> }}
/>
<SecretsComponent />
</SecretsContextProvider>
@@ -62,7 +62,10 @@ export interface RepoUrlPickerUiOptions {
* @public
*/
export const RepoUrlPicker = (
props: FieldExtensionComponentProps<string, RepoUrlPickerUiOptions>,
props: FieldExtensionComponentProps<
string | undefined,
RepoUrlPickerUiOptions
>,
) => {
const { uiSchema, onChange, rawErrors, formData } = props;
const [state, setState] = useState<RepoUrlPickerState>(
@@ -26,7 +26,7 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react';
* @public
*/
export const repoPickerValidation = (
value: string,
value: string | undefined,
validation: FieldValidation,
context: { apiHolder: ApiHolder },
) => {
+2 -1
View File
@@ -21,6 +21,7 @@ import {
FieldExtensionComponentProps,
} from './types';
import { Extension, attachComponentData } from '@backstage/core-plugin-api';
import { UIOptionsType } from '@rjsf/utils';
export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1';
export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1';
@@ -39,7 +40,7 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null;
*/
export function createScaffolderFieldExtension<
TReturnValue = unknown,
TInputProps = unknown,
TInputProps extends UIOptionsType = {},
>(
options: FieldExtensionOptions<TReturnValue, TInputProps>,
): Extension<FieldExtensionComponent<TReturnValue, TInputProps>> {
+12 -6
View File
@@ -14,7 +14,13 @@
* limitations under the License.
*/
import { ApiHolder } from '@backstage/core-plugin-api';
import { FieldValidation, FieldProps } from '@rjsf/utils';
import {
FieldValidation,
FieldProps,
UIOptionsType,
UiSchema,
} from '@rjsf/utils';
import { PropsWithChildren } from 'react';
/**
* Field validation type for Custom Field Extensions.
@@ -35,7 +41,7 @@ export type CustomFieldValidator<TFieldReturnValue> = (
*/
export type FieldExtensionOptions<
TFieldReturnValue = unknown,
TInputProps = unknown,
TInputProps extends UIOptionsType = {},
> = {
name: string;
component: (
@@ -52,9 +58,9 @@ export type FieldExtensionOptions<
*/
export interface FieldExtensionComponentProps<
TFieldReturnValue,
TUiOptions extends {} = {},
> extends FieldProps<TFieldReturnValue> {
uiSchema: FieldProps['uiSchema'] & {
'ui:options'?: TUiOptions;
TUiOptions = {},
> extends PropsWithChildren<FieldProps<TFieldReturnValue>> {
uiSchema?: UiSchema<TFieldReturnValue> & {
'ui:options'?: TUiOptions & UIOptionsType;
};
}