From 690657799e782254940c86ba34a81e988a55db79 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 22 Jun 2021 13:41:33 +0200 Subject: [PATCH 01/10] Add initial support for customizing the catalog import page Signed-off-by: Oliver Sand --- .changeset/few-penguins-watch.md | 35 ++++++ .../DefaultImportComponentPage.test.tsx | 84 +++++++++++++ .../DefaultImportComponentPage.tsx | 58 +++++++++ .../DefaultImportComponentPage/index.ts | 17 +++ .../src/components/ImportComponentPage.tsx | 115 ------------------ .../ImportComponentPage.test.tsx | 4 +- .../ImportComponentPage.tsx | 31 +++++ .../components/ImportComponentPage/index.ts | 17 +++ .../ImportInfoCard/ImportInfoCard.test.tsx | 51 ++++++++ .../ImportInfoCard/ImportInfoCard.tsx | 79 ++++++++++++ .../src/components/ImportInfoCard/index.ts | 17 +++ .../ImportOptionsContext.tsx | 24 ++++ .../components/ImportOptionsContext/index.ts | 17 +++ .../ImportStepper/ImportStepper.tsx | 8 +- .../src/components/ImportStepper/defaults.tsx | 23 +--- .../catalog-import/src/components/Router.tsx | 5 +- .../catalog-import/src/components/index.ts | 5 +- .../catalog-import/src/components/types.ts | 30 +++++ plugins/catalog-import/src/plugin.ts | 5 +- 19 files changed, 483 insertions(+), 142 deletions(-) create mode 100644 .changeset/few-penguins-watch.md create mode 100644 plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx create mode 100644 plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx create mode 100644 plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts delete mode 100644 plugins/catalog-import/src/components/ImportComponentPage.tsx rename plugins/catalog-import/src/components/{ => ImportComponentPage}/ImportComponentPage.test.tsx (94%) create mode 100644 plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx create mode 100644 plugins/catalog-import/src/components/ImportComponentPage/index.ts create mode 100644 plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx create mode 100644 plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx create mode 100644 plugins/catalog-import/src/components/ImportInfoCard/index.ts create mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx create mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/index.ts create mode 100644 plugins/catalog-import/src/components/types.ts diff --git a/.changeset/few-penguins-watch.md b/.changeset/few-penguins-watch.md new file mode 100644 index 0000000000..1b410f0174 --- /dev/null +++ b/.changeset/few-penguins-watch.md @@ -0,0 +1,35 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Add initial support for customizing the catalog import page. + +It is now possible to pass a custom layout to the import page, as it's already +supported by the search page. If no custom layout is passed, the default layout +is used. + +```typescript +}> + +
+ + + + Start tracking your component in Backstage by adding it to the + software catalog. + + + + + + Hello World + + + + + + + + + +``` diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx new file mode 100644 index 0000000000..5e49872319 --- /dev/null +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx @@ -0,0 +1,84 @@ +/* + * Copyright 2021 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 { CatalogClient } from '@backstage/catalog-client'; +import { + ApiProvider, + ApiRegistry, + configApiRef, + ConfigReader, +} from '@backstage/core'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { act, render } from '@testing-library/react'; +import React from 'react'; +import { catalogImportApiRef, CatalogImportClient } from '../../api'; +import { DefaultImportComponentPage } from './DefaultImportComponentPage'; + +describe('', () => { + const identityApi = { + getUserId: () => { + return 'user'; + }, + getProfile: () => { + return {}; + }, + getIdToken: () => { + return Promise.resolve('token'); + }, + signOut: () => { + return Promise.resolve(); + }, + }; + + let apis: ApiRegistry; + + beforeEach(() => { + apis = ApiRegistry.with( + configApiRef, + new ConfigReader({ integrations: {} }), + ) + .with(catalogApiRef, new CatalogClient({ discoveryApi: {} as any })) + .with( + catalogImportApiRef, + new CatalogImportClient({ + discoveryApi: {} as any, + githubAuthApi: { + getAccessToken: async () => 'token', + }, + identityApi, + scmIntegrationsApi: {} as any, + catalogApi: {} as any, + }), + ); + }); + + it('renders without exploding', async () => { + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect( + getByText('Start tracking your component in Backstage'), + ).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx new file mode 100644 index 0000000000..b9aad55274 --- /dev/null +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx @@ -0,0 +1,58 @@ +/* + * Copyright 2021 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 { + configApiRef, + Content, + ContentHeader, + Header, + Page, + SupportButton, + useApi, +} from '@backstage/core'; +import { Grid } from '@material-ui/core'; +import React from 'react'; +import { ImportInfoCard } from '../ImportInfoCard'; +import { ImportStepper } from '../ImportStepper'; + +export const DefaultImportComponentPage = () => { + const configApi = useApi(configApiRef); + const appTitle = configApi.getOptional('app.title') || 'Backstage'; + + return ( + +
+ + + + Start tracking your component in {appTitle} by adding it to the + software catalog. + + + + + + + + + + + + + + + ); +}; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts b/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts new file mode 100644 index 0000000000..f3450413a6 --- /dev/null +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 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. + */ + +export { DefaultImportComponentPage } from './DefaultImportComponentPage'; diff --git a/plugins/catalog-import/src/components/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportComponentPage.tsx deleted file mode 100644 index bf53af134f..0000000000 --- a/plugins/catalog-import/src/components/ImportComponentPage.tsx +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2020 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 { Chip, Grid, Typography } from '@material-ui/core'; -import React from 'react'; -import { ImportStepper } from './ImportStepper'; -import { StepperProviderOpts } from './ImportStepper/defaults'; - -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { - Content, - ContentHeader, - Header, - InfoCard, - Page, - SupportButton, -} from '@backstage/core-components'; - -export const ImportComponentPage = (opts: StepperProviderOpts) => { - const configApi = useApi(configApiRef); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; - - const integrations = configApi.getConfig('integrations'); - const hasGithubIntegration = integrations.has('github'); - - return ( - -
- - - - Start tracking your component in {appTitle} by adding it to the - software catalog. - - - - - - - - Enter the URL to your source code repository to add it to{' '} - {appTitle}. - - - Link to an existing entity file - - - Example:{' '} - - https://github.com/backstage/backstage/blob/master/catalog-info.yaml - - - - The wizard analyzes the file, previews the entities, and adds - them to the {appTitle} catalog. - - {hasGithubIntegration && ( - <> - - Link to a repository{' '} - - - - Example: https://github.com/backstage/backstage - - - The wizard discovers all catalog-info.yaml{' '} - files in the repository, previews the entities, and adds - them to the {appTitle} catalog. - - {!opts?.pullRequest?.disable && ( - - If no entities are found, the wizard will prepare a Pull - Request that adds an example{' '} - catalog-info.yaml and prepares the {appTitle}{' '} - catalog to load all entities as soon as the Pull Request - is merged. - - )} - - )} - - - - - - - - - - ); -}; diff --git a/plugins/catalog-import/src/components/ImportComponentPage.test.tsx b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx similarity index 94% rename from plugins/catalog-import/src/components/ImportComponentPage.test.tsx rename to plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx index 2e572c8936..4177a6ae64 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx @@ -19,7 +19,7 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; -import { catalogImportApiRef, CatalogImportClient } from '../api'; +import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { ImportComponentPage } from './ImportComponentPage'; import { @@ -78,7 +78,7 @@ describe('', () => { ); expect( - await getByText('Start tracking your component in Backstage'), + getByText('Start tracking your component in Backstage'), ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx new file mode 100644 index 0000000000..3a89705493 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx @@ -0,0 +1,31 @@ +/* + * Copyright 2020 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 React from 'react'; +import { useOutlet } from 'react-router'; +import { DefaultImportComponentPage } from '../DefaultImportComponentPage'; +import { ImportOptionsContext } from '../ImportOptionsContext'; +import { ImportOptions } from '../types'; + +export const ImportComponentPage = (opts: ImportOptions) => { + const outlet = useOutlet(); + + return ( + + {outlet || } + + ); +}; diff --git a/plugins/catalog-import/src/components/ImportComponentPage/index.ts b/plugins/catalog-import/src/components/ImportComponentPage/index.ts new file mode 100644 index 0000000000..263ba51a23 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportComponentPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 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. + */ + +export { ImportComponentPage } from './ImportComponentPage'; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx new file mode 100644 index 0000000000..899ad18cc3 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -0,0 +1,51 @@ +/* + * Copyright 2021 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 { + ApiProvider, + ApiRegistry, + configApiRef, + ConfigReader, +} from '@backstage/core'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { act, render } from '@testing-library/react'; +import React from 'react'; +import { ImportInfoCard } from './ImportInfoCard'; + +describe('', () => { + let apis: ApiRegistry; + + beforeEach(() => { + apis = ApiRegistry.with( + configApiRef, + new ConfigReader({ integrations: {} }), + ); + }); + + it('renders without exploding', async () => { + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect(getByText('Register an existing component')).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx new file mode 100644 index 0000000000..8fbbe6cc82 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2021 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 { ConfigApi, configApiRef, InfoCard, useApi } from '@backstage/core'; +import { Typography } from '@material-ui/core'; +import React from 'react'; +import { useImportOptions } from '../ImportOptionsContext'; + +export const ImportInfoCard = () => { + const configApi = useApi(configApiRef); + const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const opts = useImportOptions(); + + const integrations = configApi.getConfig('integrations'); + const hasGithubIntegration = integrations.has('github'); + + return ( + + + Enter the URL to your source code repository to add it to {appTitle}. + + Link to an existing entity file + + Example:{' '} + + https://github.com/backstage/backstage/blob/master/catalog-info.yaml + + + + The wizard analyzes the file, previews the entities, and adds them to + the {appTitle} catalog. + + {hasGithubIntegration && ( + <> + + Link to a repository{' '} + + + + Example: https://github.com/backstage/backstage + + + The wizard discovers all catalog-info.yaml files in the + repository, previews the entities, and adds them to the {appTitle}{' '} + catalog. + + {!opts?.pullRequest?.disable && ( + + If no entities are found, the wizard will prepare a Pull Request + that adds an example catalog-info.yaml and prepares + the {appTitle} catalog to load all entities as soon as the Pull + Request is merged. + + )} + + )} + + ); +}; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/index.ts b/plugins/catalog-import/src/components/ImportInfoCard/index.ts new file mode 100644 index 0000000000..c82e88f7e8 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportInfoCard/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 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. + */ + +export { ImportInfoCard } from './ImportInfoCard'; diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx b/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx new file mode 100644 index 0000000000..f22963429b --- /dev/null +++ b/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx @@ -0,0 +1,24 @@ +/* + * Copyright 2021 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 { createContext, useContext } from 'react'; +import { ImportOptions } from '../types'; + +export const ImportOptionsContext = createContext({}); + +export const useImportOptions = (): ImportOptions => { + return useContext(ImportOptionsContext); +}; diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/index.ts b/plugins/catalog-import/src/components/ImportOptionsContext/index.ts new file mode 100644 index 0000000000..42d41718e4 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportOptionsContext/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 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. + */ + +export { ImportOptionsContext, useImportOptions } from './ImportOptionsContext'; diff --git a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx index 48ee23e444..a669377b21 100644 --- a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx @@ -17,13 +17,14 @@ import { Step, StepContent, Stepper } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React, { useMemo } from 'react'; +import { useImportOptions } from '../ImportOptionsContext'; +import { ImportOptions } from '../types'; import { ImportFlows, ImportState, useImportState } from '../useImportState'; import { defaultGenerateStepper, defaultStepper, StepConfiguration, StepperProvider, - StepperProviderOpts, } from './defaults'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; @@ -42,18 +43,19 @@ type Props = { defaults: StepperProvider, ) => StepperProvider; variant?: InfoCardVariants; - opts?: StepperProviderOpts; + /// @deprecated Pass import options via ImportOptionsContext instead. + opts?: ImportOptions; }; export const ImportStepper = ({ initialUrl, generateStepper = defaultGenerateStepper, variant, - opts, }: Props) => { const configApi = useApi(configApiRef); const classes = useStyles(); const state = useImportState({ initialUrl }); + const opts = useImportOptions(); const states = useMemo( () => generateStepper(state.activeFlow, defaultStepper), diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index 79d859ce32..9afd983da5 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -35,22 +35,9 @@ import { } from '../StepPrepareCreatePullRequest'; import { StepPrepareSelectLocations } from '../StepPrepareSelectLocations'; import { StepReviewLocation } from '../StepReviewLocation'; +import { ImportOptions, StepperApis } from '../types'; import { ImportFlows, ImportState } from '../useImportState'; -export type StepperProviderOpts = { - pullRequest?: { - disable?: boolean; - preparePullRequest?: (apis: StepperApis) => { - title?: string; - body?: string; - }; - }; -}; - -type StepperApis = { - configApi: ConfigApi; -}; - export type StepConfiguration = { stepLabel: React.ReactElement; content: React.ReactElement; @@ -59,19 +46,19 @@ export type StepConfiguration = { export type StepperProvider = { analyze: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; prepare: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; review: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; finish: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; }; diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx index c8f1ae65a3..05ae51ca01 100644 --- a/plugins/catalog-import/src/components/Router.tsx +++ b/plugins/catalog-import/src/components/Router.tsx @@ -17,9 +17,10 @@ import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { ImportComponentPage } from './ImportComponentPage'; -import { StepperProviderOpts } from './ImportStepper/defaults'; +import { ImportOptions } from './types'; -export const Router = (opts: StepperProviderOpts) => ( +/// @deprecated, use ImportComponentPage instead. +export const Router = (opts: ImportOptions) => ( } /> diff --git a/plugins/catalog-import/src/components/index.ts b/plugins/catalog-import/src/components/index.ts index 9b53200317..81056274f0 100644 --- a/plugins/catalog-import/src/components/index.ts +++ b/plugins/catalog-import/src/components/index.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export * from './ImportStepper'; +export * from './DefaultImportComponentPage'; export * from './EntityListComponent'; +export * from './ImportInfoCard'; +export * from './ImportOptionsContext'; +export * from './ImportStepper'; export * from './StepInitAnalyzeUrl'; export * from './StepPrepareCreatePullRequest'; diff --git a/plugins/catalog-import/src/components/types.ts b/plugins/catalog-import/src/components/types.ts new file mode 100644 index 0000000000..7cfc8043c7 --- /dev/null +++ b/plugins/catalog-import/src/components/types.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2021 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 { ConfigApi } from '@backstage/core-plugin-api'; + +export type ImportOptions = { + pullRequest?: { + disable?: boolean; + preparePullRequest?: ( + apis: StepperApis, + ) => { title?: string; body?: string }; + }; +}; + +export type StepperApis = { + configApi: ConfigApi; +}; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 3ab999ac07..075d8a2084 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -67,7 +67,10 @@ export const catalogImportPlugin = createPlugin({ export const CatalogImportPage = catalogImportPlugin.provide( createRoutableExtension({ - component: () => import('./components/Router').then(m => m.Router), + component: () => + import('./components/ImportComponentPage').then( + m => m.ImportComponentPage, + ), mountPoint: rootRouteRef, }), ); From e0f228c46f29971c1e78f99b76eb937c2a35209c Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 12 Aug 2021 11:52:37 +0200 Subject: [PATCH 02/10] Migrate my changes to the new core-* apis Signed-off-by: Oliver Sand --- .../DefaultImportComponentPage.test.tsx | 4 ++-- .../DefaultImportComponentPage.tsx | 5 ++--- .../src/components/ImportInfoCard/ImportInfoCard.test.tsx | 4 ++-- .../src/components/ImportInfoCard/ImportInfoCard.tsx | 5 +++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx index 5e49872319..e807559cbf 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx @@ -18,9 +18,9 @@ import { CatalogClient } from '@backstage/catalog-client'; import { ApiProvider, ApiRegistry, - configApiRef, ConfigReader, -} from '@backstage/core'; +} from '@backstage/core-app-api'; +import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx index b9aad55274..d9e9e09335 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx @@ -15,14 +15,13 @@ */ import { - configApiRef, Content, ContentHeader, Header, Page, SupportButton, - useApi, -} from '@backstage/core'; +} from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Grid } from '@material-ui/core'; import React from 'react'; import { ImportInfoCard } from '../ImportInfoCard'; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index 899ad18cc3..c2302403d3 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -17,9 +17,9 @@ import { ApiProvider, ApiRegistry, - configApiRef, ConfigReader, -} from '@backstage/core'; +} from '@backstage/core-app-api'; +import { configApiRef } from '@backstage/core-plugin-api'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index 8fbbe6cc82..282070ad28 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -14,8 +14,9 @@ * limitations under the License. */ -import { ConfigApi, configApiRef, InfoCard, useApi } from '@backstage/core'; -import { Typography } from '@material-ui/core'; +import { InfoCard } from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { Chip, Typography } from '@material-ui/core'; import React from 'react'; import { useImportOptions } from '../ImportOptionsContext'; From befaae417c8f418eef50b496efde6f4a71eb375d Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 12 Aug 2021 12:04:42 +0200 Subject: [PATCH 03/10] Update api-report.md Signed-off-by: Oliver Sand --- plugins/catalog-import/api-report.md | 32 +++++++++++++++---- .../src/components/ImportStepper/defaults.tsx | 1 - 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index 6752f95748..9462894f61 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -9,6 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigApi } from '@backstage/core-plugin-api'; +import { Context } from 'react'; import { Controller } from 'react-hook-form'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; @@ -114,11 +115,11 @@ export class CatalogImportClient implements CatalogImportApi { }>; } -// Warning: (ae-forgotten-export) The symbol "StepperProviderOpts" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ImportOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CatalogImportPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const CatalogImportPage: (opts: StepperProviderOpts) => JSX.Element; +export const CatalogImportPage: (opts: ImportOptions) => JSX.Element; // Warning: (ae-missing-release-tag) "catalogImportPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -144,6 +145,11 @@ export function defaultGenerateStepper( defaults: StepperProvider, ): StepperProvider; +// Warning: (ae-missing-release-tag) "DefaultImportComponentPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const DefaultImportComponentPage: () => JSX.Element; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "EntityListComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -155,7 +161,17 @@ export const EntityListComponent: ({ onItemClick, firstListItem, withLinks, -}: Props_2) => JSX.Element; +}: Props) => JSX.Element; + +// Warning: (ae-missing-release-tag) "ImportInfoCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ImportInfoCard: () => JSX.Element; + +// Warning: (ae-missing-release-tag) "ImportOptionsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ImportOptionsContext: Context; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ImportStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -165,8 +181,7 @@ export const ImportStepper: ({ initialUrl, generateStepper, variant, - opts, -}: Props) => JSX.Element; +}: Props_2) => JSX.Element; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen @@ -206,7 +221,7 @@ export const PreviewPullRequestComponent: ({ // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: (opts: StepperProviderOpts) => JSX.Element; +export const Router: (opts: ImportOptions) => JSX.Element; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen @@ -234,6 +249,11 @@ export const StepPrepareCreatePullRequest: ({ defaultBody, }: Props_8) => JSX.Element; +// Warning: (ae-missing-release-tag) "useImportOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const useImportOptions: () => ImportOptions; + // Warnings were encountered during analysis: // // src/api/CatalogImportApi.d.ts:14:5 - (ae-forgotten-export) The symbol "PartialEntity" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index 9afd983da5..d4099c1177 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { ConfigApi } from '@backstage/core-plugin-api'; import { Box, Checkbox, From 1bbb8cee46f69ae25f184bfe889bf6c3919f98f1 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 18 Aug 2021 09:37:06 +0200 Subject: [PATCH 04/10] Rename ImportComponentPage to ImportPage as it can import all kinds of entities Signed-off-by: Oliver Sand --- plugins/catalog-import/api-report.md | 4 ++-- plugins/catalog-import/dev/index.tsx | 4 ++-- .../DefaultImportPage.test.tsx} | 17 ++++++++--------- .../DefaultImportPage.tsx} | 2 +- .../index.ts | 2 +- .../ImportPage.test.tsx} | 6 +++--- .../ImportPage.tsx} | 6 +++--- .../index.ts | 2 +- .../catalog-import/src/components/Router.tsx | 6 +++--- plugins/catalog-import/src/components/index.ts | 2 +- plugins/catalog-import/src/plugin.ts | 5 +---- 11 files changed, 26 insertions(+), 30 deletions(-) rename plugins/catalog-import/src/components/{ImportComponentPage/ImportComponentPage.test.tsx => DefaultImportPage/DefaultImportPage.test.tsx} (94%) rename plugins/catalog-import/src/components/{DefaultImportComponentPage/DefaultImportComponentPage.tsx => DefaultImportPage/DefaultImportPage.tsx} (97%) rename plugins/catalog-import/src/components/{ImportComponentPage => DefaultImportPage}/index.ts (90%) rename plugins/catalog-import/src/components/{DefaultImportComponentPage/DefaultImportComponentPage.test.tsx => ImportPage/ImportPage.test.tsx} (92%) rename plugins/catalog-import/src/components/{ImportComponentPage/ImportComponentPage.tsx => ImportPage/ImportPage.tsx} (83%) rename plugins/catalog-import/src/components/{DefaultImportComponentPage => ImportPage}/index.ts (88%) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index 9462894f61..a89654a56e 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -145,10 +145,10 @@ export function defaultGenerateStepper( defaults: StepperProvider, ): StepperProvider; -// Warning: (ae-missing-release-tag) "DefaultImportComponentPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "DefaultImportPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const DefaultImportComponentPage: () => JSX.Element; +export const DefaultImportPage: () => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "EntityListComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/catalog-import/dev/index.tsx b/plugins/catalog-import/dev/index.tsx index 48d9320ca9..a0cf034782 100644 --- a/plugins/catalog-import/dev/index.tsx +++ b/plugins/catalog-import/dev/index.tsx @@ -29,7 +29,7 @@ import { EntityListComponent, ImportStepper, } from '../src'; -import { ImportComponentPage } from '../src/components/ImportComponentPage'; +import { ImportPage } from '../src/components/ImportPage'; import { Content, Header, InfoCard, Page } from '@backstage/core-components'; const getEntityNames = (url: string): EntityName[] => [ @@ -252,7 +252,7 @@ createDevApp() }) .addPage({ title: 'Catalog Import', - element: , + element: , }) .addPage({ title: 'Catalog Import 2', diff --git a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx similarity index 94% rename from plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx rename to plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 4177a6ae64..3a66c11dde 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -15,21 +15,20 @@ */ import { CatalogClient } from '@backstage/catalog-client'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; -import React from 'react'; -import { catalogImportApiRef, CatalogImportClient } from '../../api'; -import { ImportComponentPage } from './ImportComponentPage'; - import { ApiProvider, ApiRegistry, ConfigReader, } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { act, render } from '@testing-library/react'; +import React from 'react'; +import { catalogImportApiRef, CatalogImportClient } from '../../api'; +import { DefaultImportPage } from './DefaultImportPage'; -describe('', () => { +describe('', () => { const identityApi = { getUserId: () => { return 'user'; @@ -72,7 +71,7 @@ describe('', () => { const { getByText } = render( wrapInTestApp( - + , ), ); diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx similarity index 97% rename from plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx rename to plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index d9e9e09335..8693895ec0 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -27,7 +27,7 @@ import React from 'react'; import { ImportInfoCard } from '../ImportInfoCard'; import { ImportStepper } from '../ImportStepper'; -export const DefaultImportComponentPage = () => { +export const DefaultImportPage = () => { const configApi = useApi(configApiRef); const appTitle = configApi.getOptional('app.title') || 'Backstage'; diff --git a/plugins/catalog-import/src/components/ImportComponentPage/index.ts b/plugins/catalog-import/src/components/DefaultImportPage/index.ts similarity index 90% rename from plugins/catalog-import/src/components/ImportComponentPage/index.ts rename to plugins/catalog-import/src/components/DefaultImportPage/index.ts index 263ba51a23..5a4d4907e3 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage/index.ts +++ b/plugins/catalog-import/src/components/DefaultImportPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { ImportComponentPage } from './ImportComponentPage'; +export { DefaultImportPage } from './DefaultImportPage'; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx similarity index 92% rename from plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx rename to plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index e807559cbf..8a481d74c9 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -26,9 +26,9 @@ import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; -import { DefaultImportComponentPage } from './DefaultImportComponentPage'; +import { ImportPage } from './ImportPage'; -describe('', () => { +describe('', () => { const identityApi = { getUserId: () => { return 'user'; @@ -71,7 +71,7 @@ describe('', () => { const { getByText } = render( wrapInTestApp( - + , ), ); diff --git a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx similarity index 83% rename from plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx rename to plugins/catalog-import/src/components/ImportPage/ImportPage.tsx index 3a89705493..507ea0c5df 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx @@ -16,16 +16,16 @@ import React from 'react'; import { useOutlet } from 'react-router'; -import { DefaultImportComponentPage } from '../DefaultImportComponentPage'; +import { DefaultImportPage } from '../DefaultImportPage'; import { ImportOptionsContext } from '../ImportOptionsContext'; import { ImportOptions } from '../types'; -export const ImportComponentPage = (opts: ImportOptions) => { +export const ImportPage = (opts: ImportOptions) => { const outlet = useOutlet(); return ( - {outlet || } + {outlet || } ); }; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts b/plugins/catalog-import/src/components/ImportPage/index.ts similarity index 88% rename from plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts rename to plugins/catalog-import/src/components/ImportPage/index.ts index f3450413a6..891c5302db 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts +++ b/plugins/catalog-import/src/components/ImportPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { DefaultImportComponentPage } from './DefaultImportComponentPage'; +export { ImportPage } from './ImportPage'; diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx index 05ae51ca01..3fc9896800 100644 --- a/plugins/catalog-import/src/components/Router.tsx +++ b/plugins/catalog-import/src/components/Router.tsx @@ -16,12 +16,12 @@ import React from 'react'; import { Route, Routes } from 'react-router-dom'; -import { ImportComponentPage } from './ImportComponentPage'; +import { ImportPage } from './ImportPage'; import { ImportOptions } from './types'; -/// @deprecated, use ImportComponentPage instead. +/// @deprecated, use ImportPage instead. export const Router = (opts: ImportOptions) => ( - } /> + } /> ); diff --git a/plugins/catalog-import/src/components/index.ts b/plugins/catalog-import/src/components/index.ts index 81056274f0..d34ecf3bcc 100644 --- a/plugins/catalog-import/src/components/index.ts +++ b/plugins/catalog-import/src/components/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export * from './DefaultImportComponentPage'; +export * from './DefaultImportPage'; export * from './EntityListComponent'; export * from './ImportInfoCard'; export * from './ImportOptionsContext'; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 075d8a2084..2aa4d78f2d 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -67,10 +67,7 @@ export const catalogImportPlugin = createPlugin({ export const CatalogImportPage = catalogImportPlugin.provide( createRoutableExtension({ - component: () => - import('./components/ImportComponentPage').then( - m => m.ImportComponentPage, - ), + component: () => import('./components/ImportPage').then(m => m.ImportPage), mountPoint: rootRouteRef, }), ); From 66a9e17035cbd1fae4f01fae0986e4720824c046 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 18 Aug 2021 14:06:47 +0200 Subject: [PATCH 05/10] Implement customization with an API instead of context Signed-off-by: Oliver Sand --- .changeset/few-penguins-watch.md | 12 ++++- plugins/catalog-import/api-report.md | 30 +++++------ .../src/api/CatalogImportApi.ts | 4 ++ .../src/api/CatalogImportClient.test.ts | 1 + .../src/api/CatalogImportClient.ts | 22 ++++++++ .../DefaultImportPage.test.tsx | 1 + .../ImportInfoCard/ImportInfoCard.test.tsx | 54 ++++++++++++++++++- .../ImportInfoCard/ImportInfoCard.tsx | 9 ++-- .../ImportOptionsContext.tsx | 24 --------- .../components/ImportOptionsContext/index.ts | 17 ------ .../components/ImportPage/ImportPage.test.tsx | 25 +++++++++ .../src/components/ImportPage/ImportPage.tsx | 10 +--- .../ImportStepper/ImportStepper.tsx | 21 +++----- .../src/components/ImportStepper/defaults.tsx | 41 ++++---------- .../catalog-import/src/components/Router.tsx | 27 ---------- .../catalog-import/src/components/index.ts | 1 - .../catalog-import/src/components/types.ts | 13 +---- plugins/catalog-import/src/index.ts | 1 - plugins/catalog-import/src/plugin.ts | 10 ++-- 19 files changed, 160 insertions(+), 163 deletions(-) delete mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx delete mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/index.ts delete mode 100644 plugins/catalog-import/src/components/Router.tsx diff --git a/.changeset/few-penguins-watch.md b/.changeset/few-penguins-watch.md index 1b410f0174..3d7d9fb457 100644 --- a/.changeset/few-penguins-watch.md +++ b/.changeset/few-penguins-watch.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-import': patch +'@backstage/plugin-catalog-import': minor --- Add initial support for customizing the catalog import page. @@ -33,3 +33,13 @@ is used. ``` + +Previously it was possible to disable and customize the automatic pull request +feature by passing options to `` (`pullRequest.disable` and +`pullRequest.preparePullRequest`). This functionality is moved to the +`CatalogImportApi` which now provides an optional `preparePullRequest()` +function. The function can either be overridden to generate a different content +for the pull request, or removed to disable this feature. + +The export of the long term deprecated legacy `` is removed, migrate to +`` instead. diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index a89654a56e..894a7fab61 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -9,7 +9,6 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigApi } from '@backstage/core-plugin-api'; -import { Context } from 'react'; import { Controller } from 'react-hook-form'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; @@ -69,6 +68,11 @@ export interface CatalogImportApi { // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) + preparePullRequest?(): { + title: string; + body: string; + }; + // (undocumented) submitPullRequest(options: { repositoryUrl: string; fileContent: string; @@ -95,10 +99,16 @@ export class CatalogImportClient implements CatalogImportApi { identityApi: IdentityApi; scmIntegrationsApi: ScmIntegrationRegistry; catalogApi: CatalogApi; + configApi: ConfigApi; }); // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) + preparePullRequest(): { + title: string; + body: string; + }; + // (undocumented) submitPullRequest({ repositoryUrl, fileContent, @@ -115,11 +125,10 @@ export class CatalogImportClient implements CatalogImportApi { }>; } -// Warning: (ae-forgotten-export) The symbol "ImportOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CatalogImportPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const CatalogImportPage: (opts: ImportOptions) => JSX.Element; +export const CatalogImportPage: () => JSX.Element; // Warning: (ae-missing-release-tag) "catalogImportPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -168,11 +177,6 @@ export const EntityListComponent: ({ // @public (undocumented) export const ImportInfoCard: () => JSX.Element; -// Warning: (ae-missing-release-tag) "ImportOptionsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ImportOptionsContext: Context; - // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ImportStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -218,11 +222,6 @@ export const PreviewPullRequestComponent: ({ classes, }: Props_7) => JSX.Element; -// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const Router: (opts: ImportOptions) => JSX.Element; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen @@ -249,11 +248,6 @@ export const StepPrepareCreatePullRequest: ({ defaultBody, }: Props_8) => JSX.Element; -// Warning: (ae-missing-release-tag) "useImportOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const useImportOptions: () => ImportOptions; - // Warnings were encountered during analysis: // // src/api/CatalogImportApi.d.ts:14:5 - (ae-forgotten-export) The symbol "PartialEntity" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog-import/src/api/CatalogImportApi.ts b/plugins/catalog-import/src/api/CatalogImportApi.ts index 04e98f3d7c..fae4e3d3b3 100644 --- a/plugins/catalog-import/src/api/CatalogImportApi.ts +++ b/plugins/catalog-import/src/api/CatalogImportApi.ts @@ -42,6 +42,10 @@ export type AnalyzeResult = export interface CatalogImportApi { analyzeUrl(url: string): Promise; + preparePullRequest?(): { + title: string; + body: string; + }; submitPullRequest(options: { repositoryUrl: string; fileContent: string; diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 2936f956e4..99928727fb 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -115,6 +115,7 @@ describe('CatalogImportClient', () => { scmIntegrationsApi, identityApi, catalogApi, + configApi: new ConfigReader({}), }); }); diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 2497af99d8..12aabf2b7f 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -17,6 +17,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { EntityName } from '@backstage/catalog-model'; import { + ConfigApi, DiscoveryApi, IdentityApi, OAuthApi, @@ -37,6 +38,7 @@ export class CatalogImportClient implements CatalogImportApi { private readonly githubAuthApi: OAuthApi; private readonly scmIntegrationsApi: ScmIntegrationRegistry; private readonly catalogApi: CatalogApi; + private readonly configApi: ConfigApi; constructor(options: { discoveryApi: DiscoveryApi; @@ -44,12 +46,14 @@ export class CatalogImportClient implements CatalogImportApi { identityApi: IdentityApi; scmIntegrationsApi: ScmIntegrationRegistry; catalogApi: CatalogApi; + configApi: ConfigApi; }) { this.discoveryApi = options.discoveryApi; this.githubAuthApi = options.githubAuthApi; this.identityApi = options.identityApi; this.scmIntegrationsApi = options.scmIntegrationsApi; this.catalogApi = options.catalogApi; + this.configApi = options.configApi; } async analyzeUrl(url: string): Promise { @@ -114,6 +118,24 @@ export class CatalogImportClient implements CatalogImportApi { }; } + preparePullRequest(): { + title: string; + body: string; + } { + const appTitle = + this.configApi.getOptionalString('app.title') ?? 'Backstage'; + const appBaseUrl = this.configApi.getString('app.baseUrl'); + + return { + title: 'Add catalog-info.yaml config file', + body: `This pull request adds a **Backstage entity metadata file** \ +to this repository so that the component can be added to the \ +[${appTitle} software catalog](${appBaseUrl}).\n\nAfter this pull request is merged, \ +the component will become available.\n\nFor more information, read an \ +[overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview).`, + }; + } + async submitPullRequest({ repositoryUrl, fileContent, diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 3a66c11dde..5551a060b6 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -62,6 +62,7 @@ describe('', () => { identityApi, scmIntegrationsApi: {} as any, catalogApi: {} as any, + configApi: {} as any, }), ); }); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index c2302403d3..f03d6b28e8 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -23,19 +23,35 @@ import { configApiRef } from '@backstage/core-plugin-api'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; +import { CatalogImportApi, catalogImportApiRef } from '../../api'; import { ImportInfoCard } from './ImportInfoCard'; describe('', () => { let apis: ApiRegistry; + let catalogImportApi: jest.Mocked; beforeEach(() => { + catalogImportApi = { + analyzeUrl: jest.fn(), + submitPullRequest: jest.fn(), + }; + apis = ApiRegistry.with( configApiRef, - new ConfigReader({ integrations: {} }), - ); + new ConfigReader({ + integrations: { + github: [{ token: 'my-token' }], + }, + }), + ).with(catalogImportApiRef, catalogImportApi); }); it('renders without exploding', async () => { + apis = ApiRegistry.with( + configApiRef, + new ConfigReader({ integrations: {} }), + ).with(catalogImportApiRef, catalogImportApi); + await act(async () => { const { getByText } = render( wrapInTestApp( @@ -48,4 +64,38 @@ describe('', () => { expect(getByText('Register an existing component')).toBeInTheDocument(); }); }); + + it('renders section on GitHub discovery if supported', async () => { + catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect(getByText(/The wizard discovers all/)).toBeInTheDocument(); + }); + }); + + it('renders section on pull requests if supported', async () => { + catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect( + getByText(/the wizard will prepare a Pull Request/), + ).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index 282070ad28..2fab223f20 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -18,12 +18,12 @@ import { InfoCard } from '@backstage/core-components'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Chip, Typography } from '@material-ui/core'; import React from 'react'; -import { useImportOptions } from '../ImportOptionsContext'; +import { catalogImportApiRef } from '../../api'; export const ImportInfoCard = () => { const configApi = useApi(configApiRef); const appTitle = configApi.getOptional('app.title') || 'Backstage'; - const opts = useImportOptions(); + const catalogImportApi = useApi(catalogImportApiRef); const integrations = configApi.getConfig('integrations'); const hasGithubIntegration = integrations.has('github'); @@ -33,8 +33,7 @@ export const ImportInfoCard = () => { title="Register an existing component" deepLink={{ title: 'Learn more about the Software Catalog', - link: - 'https://backstage.io/docs/features/software-catalog/software-catalog-overview', + link: 'https://backstage.io/docs/features/software-catalog/software-catalog-overview', }} > @@ -65,7 +64,7 @@ export const ImportInfoCard = () => { repository, previews the entities, and adds them to the {appTitle}{' '} catalog. - {!opts?.pullRequest?.disable && ( + {catalogImportApi.preparePullRequest && ( If no entities are found, the wizard will prepare a Pull Request that adds an example catalog-info.yaml and prepares diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx b/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx deleted file mode 100644 index f22963429b..0000000000 --- a/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 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 { createContext, useContext } from 'react'; -import { ImportOptions } from '../types'; - -export const ImportOptionsContext = createContext({}); - -export const useImportOptions = (): ImportOptions => { - return useContext(ImportOptionsContext); -}; diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/index.ts b/plugins/catalog-import/src/components/ImportOptionsContext/index.ts deleted file mode 100644 index 42d41718e4..0000000000 --- a/plugins/catalog-import/src/components/ImportOptionsContext/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2021 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. - */ - -export { ImportOptionsContext, useImportOptions } from './ImportOptionsContext'; diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index 8a481d74c9..1e2182005e 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -25,9 +25,15 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; +import { useOutlet } from 'react-router'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { ImportPage } from './ImportPage'; +jest.mock('react-router', () => ({ + ...jest.requireActual('react-router'), + useOutlet: jest.fn(), +})); + describe('', () => { const identityApi = { getUserId: () => { @@ -62,10 +68,13 @@ describe('', () => { identityApi, scmIntegrationsApi: {} as any, catalogApi: {} as any, + configApi: new ConfigReader({}), }), ); }); + afterEach(() => jest.resetAllMocks()); + it('renders without exploding', async () => { await act(async () => { const { getByText } = render( @@ -81,4 +90,20 @@ describe('', () => { ).toBeInTheDocument(); }); }); + + it('renders with custom children', async () => { + (useOutlet as jest.Mock).mockReturnValue(
Hello World
); + + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect(getByText('Hello World')).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx index 507ea0c5df..467bd710f0 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx @@ -17,15 +17,9 @@ import React from 'react'; import { useOutlet } from 'react-router'; import { DefaultImportPage } from '../DefaultImportPage'; -import { ImportOptionsContext } from '../ImportOptionsContext'; -import { ImportOptions } from '../types'; -export const ImportPage = (opts: ImportOptions) => { +export const ImportPage = () => { const outlet = useOutlet(); - return ( - - {outlet || } - - ); + return outlet || ; }; diff --git a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx index a669377b21..4112775c2d 100644 --- a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx @@ -14,11 +14,12 @@ * limitations under the License. */ +import { InfoCard, InfoCardVariants } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; import { Step, StepContent, Stepper } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React, { useMemo } from 'react'; -import { useImportOptions } from '../ImportOptionsContext'; -import { ImportOptions } from '../types'; +import { catalogImportApiRef } from '../../api'; import { ImportFlows, ImportState, useImportState } from '../useImportState'; import { defaultGenerateStepper, @@ -27,9 +28,6 @@ import { StepperProvider, } from './defaults'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { InfoCard, InfoCardVariants } from '@backstage/core-components'; - const useStyles = makeStyles(() => ({ stepperRoot: { padding: 0, @@ -43,8 +41,6 @@ type Props = { defaults: StepperProvider, ) => StepperProvider; variant?: InfoCardVariants; - /// @deprecated Pass import options via ImportOptionsContext instead. - opts?: ImportOptions; }; export const ImportStepper = ({ @@ -52,10 +48,9 @@ export const ImportStepper = ({ generateStepper = defaultGenerateStepper, variant, }: Props) => { - const configApi = useApi(configApiRef); + const catalogImportApi = useApi(catalogImportApiRef); const classes = useStyles(); const state = useImportState({ initialUrl }); - const opts = useImportOptions(); const states = useMemo( () => generateStepper(state.activeFlow, defaultStepper), @@ -81,25 +76,25 @@ export const ImportStepper = ({ {render( states.analyze( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} {render( states.prepare( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} {render( states.review( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} {render( states.finish( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index d4099c1177..72f946af6c 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -34,7 +34,7 @@ import { } from '../StepPrepareCreatePullRequest'; import { StepPrepareSelectLocations } from '../StepPrepareSelectLocations'; import { StepReviewLocation } from '../StepReviewLocation'; -import { ImportOptions, StepperApis } from '../types'; +import { StepperApis } from '../types'; import { ImportFlows, ImportState } from '../useImportState'; export type StepConfiguration = { @@ -45,41 +45,22 @@ export type StepConfiguration = { export type StepperProvider = { analyze: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; prepare: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; review: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; finish: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; }; -function defaultPreparePullRequest( - apis: StepperApis, - { title, body }: { title?: string; body?: string } = {}, -) { - const appTitle = apis.configApi.getOptionalString('app.title') ?? 'Backstage'; - const appBaseUrl = apis.configApi.getString('app.baseUrl'); - - return { - title: title ?? 'Add catalog-info.yaml config file', - body: - body ?? - `This pull request adds a **Backstage entity metadata file** \ -to this repository so that the component can be added to the \ -[${appTitle} software catalog](${appBaseUrl}).\n\nAfter this pull request is merged, \ -the component will become available.\n\nFor more information, read an \ -[overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview).`, - }; -} - /** * The default stepper generation function. * @@ -155,12 +136,8 @@ export function defaultGenerateStepper( return defaults.prepare(state, opts); } - const preparePullRequest = - opts?.opts?.pullRequest?.preparePullRequest; - const { title, body } = defaultPreparePullRequest( - opts.apis, - preparePullRequest ? preparePullRequest(opts.apis) : {}, - ); + const { title, body } = + opts.apis.catalogImportApi.preparePullRequest!(); return { stepLabel: Create Pull Request, @@ -285,14 +262,14 @@ export function defaultGenerateStepper( } export const defaultStepper: StepperProvider = { - analyze: (state, { opts }) => ({ + analyze: (state, { apis }) => ({ stepLabel: Select URL, content: ( ), }), diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx deleted file mode 100644 index 3fc9896800..0000000000 --- a/plugins/catalog-import/src/components/Router.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 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 React from 'react'; -import { Route, Routes } from 'react-router-dom'; -import { ImportPage } from './ImportPage'; -import { ImportOptions } from './types'; - -/// @deprecated, use ImportPage instead. -export const Router = (opts: ImportOptions) => ( - - } /> - -); diff --git a/plugins/catalog-import/src/components/index.ts b/plugins/catalog-import/src/components/index.ts index d34ecf3bcc..886c679d2d 100644 --- a/plugins/catalog-import/src/components/index.ts +++ b/plugins/catalog-import/src/components/index.ts @@ -17,7 +17,6 @@ export * from './DefaultImportPage'; export * from './EntityListComponent'; export * from './ImportInfoCard'; -export * from './ImportOptionsContext'; export * from './ImportStepper'; export * from './StepInitAnalyzeUrl'; export * from './StepPrepareCreatePullRequest'; diff --git a/plugins/catalog-import/src/components/types.ts b/plugins/catalog-import/src/components/types.ts index 7cfc8043c7..baa279ff21 100644 --- a/plugins/catalog-import/src/components/types.ts +++ b/plugins/catalog-import/src/components/types.ts @@ -14,17 +14,8 @@ * limitations under the License. */ -import { ConfigApi } from '@backstage/core-plugin-api'; - -export type ImportOptions = { - pullRequest?: { - disable?: boolean; - preparePullRequest?: ( - apis: StepperApis, - ) => { title?: string; body?: string }; - }; -}; +import { CatalogImportApi } from '../api'; export type StepperApis = { - configApi: ConfigApi; + catalogImportApi: CatalogImportApi; }; diff --git a/plugins/catalog-import/src/index.ts b/plugins/catalog-import/src/index.ts index adee41bdbd..149c3e55c6 100644 --- a/plugins/catalog-import/src/index.ts +++ b/plugins/catalog-import/src/index.ts @@ -25,6 +25,5 @@ export { catalogImportPlugin as plugin, CatalogImportPage, } from './plugin'; -export { Router } from './components/Router'; export * from './components'; export * from './api'; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 2aa4d78f2d..d7d6370de3 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -14,10 +14,8 @@ * limitations under the License. */ -import { scmIntegrationsApiRef } from '@backstage/integration-react'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { catalogImportApiRef, CatalogImportClient } from './api'; import { + configApiRef, createApiFactory, createPlugin, createRoutableExtension, @@ -26,6 +24,9 @@ import { githubAuthApiRef, identityApiRef, } from '@backstage/core-plugin-api'; +import { scmIntegrationsApiRef } from '@backstage/integration-react'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { catalogImportApiRef, CatalogImportClient } from './api'; export const rootRouteRef = createRouteRef({ path: '', @@ -43,6 +44,7 @@ export const catalogImportPlugin = createPlugin({ identityApi: identityApiRef, scmIntegrationsApi: scmIntegrationsApiRef, catalogApi: catalogApiRef, + configApi: configApiRef, }, factory: ({ discoveryApi, @@ -50,6 +52,7 @@ export const catalogImportPlugin = createPlugin({ identityApi, scmIntegrationsApi, catalogApi, + configApi, }) => new CatalogImportClient({ discoveryApi, @@ -57,6 +60,7 @@ export const catalogImportPlugin = createPlugin({ scmIntegrationsApi, identityApi, catalogApi, + configApi, }), }), ], From 18571288a8f1b254c374766164dd2dec15ef1ff5 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 16 Sep 2021 16:05:11 +0200 Subject: [PATCH 06/10] Make preparePullRequest async Signed-off-by: Oliver Sand --- .../src/api/CatalogImportApi.ts | 6 +- .../src/api/CatalogImportClient.test.ts | 15 +- .../src/api/CatalogImportClient.ts | 4 +- .../ImportInfoCard/ImportInfoCard.test.tsx | 4 +- .../src/components/ImportStepper/defaults.tsx | 5 - .../StepPrepareCreatePullRequest.test.tsx | 53 +++--- .../StepPrepareCreatePullRequest.tsx | 169 ++++++++++-------- 7 files changed, 139 insertions(+), 117 deletions(-) diff --git a/plugins/catalog-import/src/api/CatalogImportApi.ts b/plugins/catalog-import/src/api/CatalogImportApi.ts index fae4e3d3b3..a4645dc7ef 100644 --- a/plugins/catalog-import/src/api/CatalogImportApi.ts +++ b/plugins/catalog-import/src/api/CatalogImportApi.ts @@ -15,8 +15,8 @@ */ import { EntityName } from '@backstage/catalog-model'; -import { PartialEntity } from '../types'; import { createApiRef } from '@backstage/core-plugin-api'; +import { PartialEntity } from '../types'; export const catalogImportApiRef = createApiRef({ id: 'plugin.catalog-import.service', @@ -42,10 +42,10 @@ export type AnalyzeResult = export interface CatalogImportApi { analyzeUrl(url: string): Promise; - preparePullRequest?(): { + preparePullRequest?(): Promise<{ title: string; body: string; - }; + }>; submitPullRequest(options: { repositoryUrl: string; fileContent: string; diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 99928727fb..0782b44147 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -115,7 +115,11 @@ describe('CatalogImportClient', () => { scmIntegrationsApi, identityApi, catalogApi, - configApi: new ConfigReader({}), + configApi: new ConfigReader({ + app: { + baseUrl: 'https://demo.backstage.io/', + }, + }), }); }); @@ -444,4 +448,13 @@ describe('CatalogImportClient', () => { }); }); }); + + describe('preparePullRequest', () => { + test('should prepare pull request details', async () => { + await expect(catalogImportClient.preparePullRequest()).resolves.toEqual({ + title: 'Add catalog-info.yaml config file', + body: expect.any(String), + }); + }); + }); }); diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 12aabf2b7f..242f8440d1 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -118,10 +118,10 @@ export class CatalogImportClient implements CatalogImportApi { }; } - preparePullRequest(): { + async preparePullRequest(): Promise<{ title: string; body: string; - } { + }> { const appTitle = this.configApi.getOptionalString('app.title') ?? 'Backstage'; const appBaseUrl = this.configApi.getString('app.baseUrl'); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index f03d6b28e8..b33e3c4d36 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -66,7 +66,7 @@ describe('', () => { }); it('renders section on GitHub discovery if supported', async () => { - catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); await act(async () => { const { getByText } = render( @@ -82,7 +82,7 @@ describe('', () => { }); it('renders section on pull requests if supported', async () => { - catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); await act(async () => { const { getByText } = render( diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index 72f946af6c..357ed64e14 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -136,9 +136,6 @@ export function defaultGenerateStepper( return defaults.prepare(state, opts); } - const { title, body } = - opts.apis.catalogImportApi.preparePullRequest!(); - return { stepLabel: Create Pull Request, content: ( @@ -146,8 +143,6 @@ export function defaultGenerateStepper( analyzeResult={state.analyzeResult} onPrepare={state.onPrepare} onGoBack={state.onGoBack} - defaultTitle={title} - defaultBody={body} renderFormFields={({ values, setValue, diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 08b8177291..e697b54b19 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -14,23 +14,25 @@ * limitations under the License. */ +import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TextField } from '@material-ui/core'; import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; +import { errorApiRef } from '../../../../../packages/core-plugin-api/src'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; import { asInputRef } from '../helpers'; import { generateEntities, StepPrepareCreatePullRequest, } from './StepPrepareCreatePullRequest'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogImportApi: jest.Mocked = { analyzeUrl: jest.fn(), submitPullRequest: jest.fn(), + preparePullRequest: jest.fn(), }; const catalogApi: jest.Mocked = { @@ -44,12 +46,16 @@ describe('', () => { removeEntityByUid: jest.fn(), }; + const errorApi: jest.Mocked = { + error$: jest.fn(), + post: jest.fn(), + }; + const Wrapper = ({ children }: { children?: React.ReactNode }) => ( {children} @@ -77,16 +83,19 @@ describe('', () => { beforeEach(() => { jest.resetAllMocks(); + + (catalogImportApi.preparePullRequest! as jest.Mock).mockResolvedValue({ + title: 'My title', + body: 'My **body**', + }); }); it('renders without exploding', async () => { catalogApi.getEntities.mockReturnValue(Promise.resolve({ items: [] })); await act(async () => { - const { getByText } = render( + const { findByText } = render( { @@ -105,8 +114,8 @@ describe('', () => { }, ); - const title = getByText('My title'); - const description = getByText('body', { selector: 'strong' }); + const title = await findByText('My title'); + const description = await findByText('body', { selector: 'strong' }); expect(title).toBeInTheDocument(); expect(title).toBeVisible(); expect(description).toBeInTheDocument(); @@ -124,10 +133,8 @@ describe('', () => { ); await act(async () => { - await render( + render( { @@ -154,11 +161,9 @@ describe('', () => { }, ); - await userEvent.type(await screen.getByLabelText('name'), '-changed'); - await userEvent.type(await screen.getByLabelText('owner'), '-changed'); - await userEvent.click( - await screen.getByRole('button', { name: /Create PR/i }), - ); + userEvent.type(await screen.findByLabelText('name'), '-changed'); + userEvent.type(await screen.findByLabelText('owner'), '-changed'); + userEvent.click(screen.getByRole('button', { name: /Create PR/i })); }); expect(catalogImportApi.submitPullRequest).toBeCalledTimes(1); @@ -212,10 +217,8 @@ spec: ); await act(async () => { - await render( + render( { @@ -234,8 +237,8 @@ spec: }, ); - await userEvent.click( - await screen.getByRole('button', { name: /Create PR/i }), + userEvent.click( + await screen.findByRole('button', { name: /Create PR/i }), ); }); @@ -261,10 +264,8 @@ spec: ); await act(async () => { - await render( + render( void; onGoBack?: () => void; - defaultTitle: string; - defaultBody: string; - renderFormFields: ( props: Pick< UseFormReturn, @@ -99,16 +96,30 @@ export const StepPrepareCreatePullRequest = ({ onPrepare, onGoBack, renderFormFields, - defaultTitle, - defaultBody, }: Props) => { const classes = useStyles(); const catalogApi = useApi(catalogApiRef); - const catalogInfoApi = useApi(catalogImportApiRef); + const catalogImportApi = useApi(catalogImportApiRef); + const errorApi = useApi(errorApiRef); const [submitted, setSubmitted] = useState(false); const [error, setError] = useState(); + const { + loading: prDefaultsLoading, + value: prDefaults, + error: prDefaultsError, + } = useAsync( + () => catalogImportApi.preparePullRequest!(), + [catalogImportApi.preparePullRequest], + ); + + useEffect(() => { + if (prDefaultsError) { + errorApi.post(prDefaultsError); + } + }, [prDefaultsError, errorApi]); + const { loading: groupsLoading, value: groups } = useAsync(async () => { const groupEntities = await catalogApi.getEntities({ filter: { kind: 'group' }, @@ -124,7 +135,7 @@ export const StepPrepareCreatePullRequest = ({ setSubmitted(true); try { - const pr = await catalogInfoApi.submitPullRequest({ + const pr = await catalogImportApi.submitPullRequest({ repositoryUrl: analyzeResult.url, title: data.title, body: data.body, @@ -171,7 +182,7 @@ export const StepPrepareCreatePullRequest = ({ analyzeResult.generatedEntities, analyzeResult.integrationType, analyzeResult.url, - catalogInfoApi, + catalogImportApi, onPrepare, ], ); @@ -184,79 +195,81 @@ export const StepPrepareCreatePullRequest = ({ a Pull Request that creates one.
- - onSubmit={handleResult} - defaultValues={{ - title: defaultTitle, - body: defaultBody, - owner: - (analyzeResult.generatedEntities[0]?.spec?.owner as string) || '', - componentName: - analyzeResult.generatedEntities[0]?.metadata?.name || '', - useCodeowners: false, - }} - render={({ values, formState, register, setValue }) => ( - <> - {renderFormFields({ - values, - formState, - register, - setValue, - groups: groups ?? [], - groupsLoading, - })} + {!prDefaultsLoading && ( + + onSubmit={handleResult} + defaultValues={{ + title: prDefaults?.title ?? '', + body: prDefaults?.body ?? '', + owner: + (analyzeResult.generatedEntities[0]?.spec?.owner as string) || '', + componentName: + analyzeResult.generatedEntities[0]?.metadata?.name || '', + useCodeowners: false, + }} + render={({ values, formState, register, setValue }) => ( + <> + {renderFormFields({ + values, + formState, + register, + setValue, + groups: groups ?? [], + groupsLoading, + })} - - Preview Pull Request - + + Preview Pull Request + - + - - Preview Entities - + + Preview Entities + - - - {error && {error}} - - - {onGoBack && ( - - )} - - Create PR - - - - )} - /> + repositoryUrl={analyzeResult.url} + classes={{ + card: classes.previewCard, + cardContent: classes.previewCardContent, + }} + /> + + {error && {error}} + + + {onGoBack && ( + + )} + + Create PR + + + + )} + /> + )} ); }; From bd44d3adce5922ba9d4d1b339ff19887882e1512 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 16 Sep 2021 16:19:14 +0200 Subject: [PATCH 07/10] Update api report Signed-off-by: Oliver Sand --- plugins/catalog-import/api-report.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index 894a7fab61..753244b28f 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -68,10 +68,10 @@ export interface CatalogImportApi { // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) - preparePullRequest?(): { + preparePullRequest?(): Promise<{ title: string; body: string; - }; + }>; // (undocumented) submitPullRequest(options: { repositoryUrl: string; @@ -104,10 +104,10 @@ export class CatalogImportClient implements CatalogImportApi { // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) - preparePullRequest(): { + preparePullRequest(): Promise<{ title: string; body: string; - }; + }>; // (undocumented) submitPullRequest({ repositoryUrl, @@ -244,8 +244,6 @@ export const StepPrepareCreatePullRequest: ({ onPrepare, onGoBack, renderFormFields, - defaultTitle, - defaultBody, }: Props_8) => JSX.Element; // Warnings were encountered during analysis: From a5e881809ab275f53a47f8e844bcef1e6a1a6cba Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 17 Sep 2021 08:27:43 +0200 Subject: [PATCH 08/10] Fix import Signed-off-by: Oliver Sand --- .../StepPrepareCreatePullRequest.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index e697b54b19..2212daf0c0 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -15,12 +15,12 @@ */ import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TextField } from '@material-ui/core'; import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { errorApiRef } from '../../../../../packages/core-plugin-api/src'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; import { asInputRef } from '../helpers'; import { From 86c716c60b35e8fc44799c2dda896a45347ec0ed Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 17 Sep 2021 08:27:57 +0200 Subject: [PATCH 09/10] Use `renderInTestApp` Signed-off-by: Oliver Sand --- .../DefaultImportPage.test.tsx | 23 +++----- .../ImportInfoCard/ImportInfoCard.test.tsx | 55 +++++++------------ .../components/ImportPage/ImportPage.test.tsx | 39 +++++-------- .../StepInitAnalyzeUrl.test.tsx | 9 ++- 4 files changed, 49 insertions(+), 77 deletions(-) diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 5551a060b6..57376c33f2 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -22,8 +22,7 @@ import { } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { DefaultImportPage } from './DefaultImportPage'; @@ -68,18 +67,14 @@ describe('', () => { }); it('renders without exploding', async () => { - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect( - getByText('Start tracking your component in Backstage'), - ).toBeInTheDocument(); - }); + expect( + getByText('Start tracking your component in Backstage'), + ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index b33e3c4d36..4e0c3694cd 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -20,8 +20,7 @@ import { ConfigReader, } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { CatalogImportApi, catalogImportApiRef } from '../../api'; import { ImportInfoCard } from './ImportInfoCard'; @@ -52,50 +51,38 @@ describe('', () => { new ConfigReader({ integrations: {} }), ).with(catalogImportApiRef, catalogImportApi); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect(getByText('Register an existing component')).toBeInTheDocument(); - }); + expect(getByText('Register an existing component')).toBeInTheDocument(); }); it('renders section on GitHub discovery if supported', async () => { catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect(getByText(/The wizard discovers all/)).toBeInTheDocument(); - }); + expect(getByText(/The wizard discovers all/)).toBeInTheDocument(); }); it('renders section on pull requests if supported', async () => { catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect( - getByText(/the wizard will prepare a Pull Request/), - ).toBeInTheDocument(); - }); + expect( + getByText(/the wizard will prepare a Pull Request/), + ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index 1e2182005e..fe3c3673f8 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -22,8 +22,7 @@ import { } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { useOutlet } from 'react-router'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; @@ -76,34 +75,26 @@ describe('', () => { afterEach(() => jest.resetAllMocks()); it('renders without exploding', async () => { - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect( - getByText('Start tracking your component in Backstage'), - ).toBeInTheDocument(); - }); + expect( + getByText('Start tracking your component in Backstage'), + ).toBeInTheDocument(); }); it('renders with custom children', async () => { (useOutlet as jest.Mock).mockReturnValue(
Hello World
); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect(getByText('Hello World')).toBeInTheDocument(); - }); + expect(getByText('Hello World')).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index 9cc9532a3d..ec058dee62 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -14,15 +14,14 @@ * limitations under the License. */ +import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { errorApiRef } from '@backstage/core-plugin-api'; import { act, render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { AnalyzeResult, catalogImportApiRef } from '../../api/'; import { StepInitAnalyzeUrl } from './StepInitAnalyzeUrl'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { errorApiRef } from '@backstage/core-plugin-api'; - describe('', () => { const catalogImportApi: jest.Mocked = { analyzeUrl: jest.fn(), @@ -313,7 +312,7 @@ describe('', () => { ); await act(async () => { - await userEvent.type( + userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); @@ -357,7 +356,7 @@ describe('', () => { ); await act(async () => { - await userEvent.type( + userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); From a8f8446859eb127342dee96e3b827f9d56a37049 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 17 Sep 2021 10:14:10 +0200 Subject: [PATCH 10/10] Fix build Signed-off-by: Oliver Sand --- .../components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index ec058dee62..4a72a653ea 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -312,7 +312,7 @@ describe('', () => { ); await act(async () => { - userEvent.type( + await userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); @@ -356,7 +356,7 @@ describe('', () => { ); await act(async () => { - userEvent.type( + await userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', );