scaffolder: migrate nfs form fields to utility API
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -16,9 +16,8 @@
|
||||
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { createPlugin } from '@backstage/core-plugin-api';
|
||||
import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { ScaffolderFormFieldsApi, formFieldsApiRef } from '../alpha';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useCustomFieldExtensions } from './useCustomFieldExtensions';
|
||||
import {
|
||||
ScaffolderFieldExtensions,
|
||||
@@ -33,22 +32,10 @@ const plugin = createPlugin({
|
||||
});
|
||||
|
||||
describe('useCustomFieldExtensions', () => {
|
||||
const mockFormFieldsApi: jest.Mocked<ScaffolderFormFieldsApi> = {
|
||||
getFormFields: jest.fn(),
|
||||
};
|
||||
const wrapper = ({ children }: PropsWithChildren<{}>) =>
|
||||
wrapInTestApp(
|
||||
<TestApiProvider apis={[[formFieldsApiRef, mockFormFieldsApi]]}>
|
||||
{children}
|
||||
</TestApiProvider>,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
wrapInTestApp(<>{children}</>);
|
||||
|
||||
it('should return field extensions from the React tree', async () => {
|
||||
mockFormFieldsApi.getFormFields.mockResolvedValue([]);
|
||||
const CustomFieldExtension = plugin.provide(
|
||||
createScaffolderFieldExtension({
|
||||
name: 'test',
|
||||
@@ -70,60 +57,4 @@ describe('useCustomFieldExtensions', () => {
|
||||
|
||||
expect(result.current).toEqual([expect.objectContaining({ name: 'test' })]);
|
||||
});
|
||||
|
||||
it('should return field extensions from formFieldsApi', async () => {
|
||||
mockFormFieldsApi.getFormFields.mockResolvedValue([
|
||||
{
|
||||
name: 'blueprint',
|
||||
component: () => <div>Test</div>,
|
||||
},
|
||||
]);
|
||||
|
||||
const { result } = renderHook(() => useCustomFieldExtensions(<div />), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
expect(result.current).toEqual([
|
||||
expect.objectContaining({ name: 'blueprint' }),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return field extensions from both sources', async () => {
|
||||
mockFormFieldsApi.getFormFields.mockResolvedValue([
|
||||
{
|
||||
name: 'blueprint',
|
||||
component: () => <div>Test</div>,
|
||||
},
|
||||
]);
|
||||
|
||||
const CustomFieldExtension = plugin.provide(
|
||||
createScaffolderFieldExtension({
|
||||
name: 'test',
|
||||
component: () => <div>Test</div>,
|
||||
}),
|
||||
);
|
||||
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useCustomFieldExtensions(
|
||||
<ScaffolderFieldExtensions>
|
||||
<CustomFieldExtension />
|
||||
</ScaffolderFieldExtensions>,
|
||||
),
|
||||
{
|
||||
wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toHaveLength(2);
|
||||
});
|
||||
|
||||
const fieldNames = result.current.map(field => field.name);
|
||||
expect(fieldNames).toEqual(expect.arrayContaining(['test', 'blueprint']));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,9 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { useAsync, useMountEffect } from '@react-hookz/web';
|
||||
import { useApi, useElementFilter } from '@backstage/core-plugin-api';
|
||||
import { formFieldsApiRef } from '../next';
|
||||
import { useElementFilter } from '@backstage/core-plugin-api';
|
||||
import { FieldExtensionOptions } from '../extensions';
|
||||
import {
|
||||
FIELD_EXTENSION_KEY,
|
||||
@@ -32,14 +30,6 @@ export const useCustomFieldExtensions = <
|
||||
>(
|
||||
outlet: React.ReactNode,
|
||||
) => {
|
||||
// Get custom fields created with FormFieldBlueprint
|
||||
const formFieldsApi = useApi(formFieldsApiRef);
|
||||
const [{ result: blueprintFields }, { execute }] = useAsync(
|
||||
() => formFieldsApi.getFormFields(),
|
||||
[],
|
||||
);
|
||||
useMountEffect(execute);
|
||||
|
||||
// Get custom fields created with ScaffolderFieldExtensions
|
||||
const outletFields = useElementFilter(outlet, elements =>
|
||||
elements
|
||||
@@ -51,17 +41,5 @@ export const useCustomFieldExtensions = <
|
||||
}),
|
||||
);
|
||||
|
||||
// This should really be a different type moving forward, but we do this to keep type compatibility.
|
||||
// should probably also move the defaults into the API eventually too, but that will come with the move
|
||||
// to the new frontend system.
|
||||
const blueprintsToLegacy: FieldExtensionOptions[] = blueprintFields?.map(
|
||||
field => ({
|
||||
component: field.component,
|
||||
name: field.name,
|
||||
validation: field.validation,
|
||||
schema: field.schema?.schema,
|
||||
}),
|
||||
);
|
||||
|
||||
return [...blueprintsToLegacy, ...outletFields] as TComponentDataType[];
|
||||
return outletFields as TComponentDataType[];
|
||||
};
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ApiBlueprint,
|
||||
createExtensionInput,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { formFieldsApiRef } from './ref';
|
||||
import { FormField, ScaffolderFormFieldsApi } from './types';
|
||||
import { FormFieldBlueprint } from '../blueprints';
|
||||
import { OpaqueFormField } from '@internal/scaffolder';
|
||||
|
||||
class DefaultScaffolderFormFieldsApi implements ScaffolderFormFieldsApi {
|
||||
private readonly formFieldLoaders: Array<() => Promise<FormField>>;
|
||||
|
||||
constructor(formFieldLoaders: Array<() => Promise<FormField>> = []) {
|
||||
this.formFieldLoaders = formFieldLoaders;
|
||||
}
|
||||
|
||||
async getFormFields() {
|
||||
const formFields = await Promise.all(
|
||||
this.formFieldLoaders.map(loader => loader()),
|
||||
);
|
||||
|
||||
const internalFormFields = formFields.map(OpaqueFormField.toInternal);
|
||||
|
||||
return internalFormFields;
|
||||
}
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
export const formFieldsApi = ApiBlueprint.makeWithOverrides({
|
||||
name: 'form-fields',
|
||||
inputs: {
|
||||
formFields: createExtensionInput([
|
||||
FormFieldBlueprint.dataRefs.formFieldLoader,
|
||||
]),
|
||||
},
|
||||
factory(originalFactory, { inputs }) {
|
||||
const formFieldLoaders = inputs.formFields.map(e =>
|
||||
e.get(FormFieldBlueprint.dataRefs.formFieldLoader),
|
||||
);
|
||||
|
||||
return originalFactory(defineParams =>
|
||||
defineParams({
|
||||
api: formFieldsApiRef,
|
||||
deps: {},
|
||||
factory: () => new DefaultScaffolderFormFieldsApi(formFieldLoaders),
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -14,6 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { formFieldsApi } from './FormFieldsApi';
|
||||
export { formFieldsApiRef } from './ref';
|
||||
export type { ScaffolderFormFieldsApi, FormField } from './types';
|
||||
export { type FormField } from './types';
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createApiRef } from '@backstage/frontend-plugin-api';
|
||||
import { ScaffolderFormFieldsApi } from './types';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated This API is no longer necessary and will be removed
|
||||
*/
|
||||
export const formFieldsApiRef = createApiRef<ScaffolderFormFieldsApi>({
|
||||
id: 'plugin.scaffolder.form-fields',
|
||||
});
|
||||
@@ -14,16 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormFieldExtensionData } from '../blueprints';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated This API is no longer necessary and will be removed
|
||||
*/
|
||||
export interface ScaffolderFormFieldsApi {
|
||||
getFormFields(): Promise<FormFieldExtensionData[]>;
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
export interface FormField {
|
||||
readonly $$type: '@backstage/scaffolder/FormField';
|
||||
|
||||
@@ -35,10 +35,7 @@ const formFieldExtensionDataRef = createExtensionDataRef<
|
||||
* */
|
||||
export const FormFieldBlueprint = createExtensionBlueprint({
|
||||
kind: 'scaffolder-form-field',
|
||||
attachTo: [
|
||||
{ id: 'page:scaffolder', input: 'formFields' },
|
||||
{ id: 'api:scaffolder/form-fields', input: 'formFields' },
|
||||
],
|
||||
attachTo: { id: 'api:scaffolder/form-fields', input: 'formFields' },
|
||||
dataRefs: {
|
||||
formFieldLoader: formFieldExtensionDataRef,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user