diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 3c7052b78b..00bc98b251 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -16,6 +16,9 @@ "publishConfig": { "access": "public" }, + "keywords": [ + "backstage" + ], "homepage": "https://backstage.io", "repository": { "type": "git", diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index c959e22b9e..cc59c46a6c 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -30,6 +30,7 @@ "exports": { ".": "./src/index.ts", "./alpha": "./src/alpha/index.ts", + "./testUtils": "./src/testUtils.ts", "./package.json": "./package.json" }, "main": "src/index.ts", @@ -39,6 +40,9 @@ "alpha": [ "src/alpha/index.ts" ], + "testUtils": [ + "src/testUtils.ts" + ], "package.json": [ "package.json" ] diff --git a/plugins/catalog-react/report-testUtils.api.md b/plugins/catalog-react/report-testUtils.api.md new file mode 100644 index 0000000000..5b00512236 --- /dev/null +++ b/plugins/catalog-react/report-testUtils.api.md @@ -0,0 +1,19 @@ +## API Report File for "@backstage/plugin-catalog-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { DefaultEntityFilters } from '@backstage/plugin-catalog-react'; +import { EntityListContextProps } from '@backstage/plugin-catalog-react'; +import { PropsWithChildren } from 'react'; +import { default as React_2 } from 'react'; + +// @public +export function MockEntityListContextProvider< + T extends DefaultEntityFilters = DefaultEntityFilters, +>( + props: PropsWithChildren<{ + value?: Partial>; + }>, +): React_2.JSX.Element; +``` diff --git a/plugins/catalog-react/report.api.md b/plugins/catalog-react/report.api.md index 0fbb27e70e..515a3526be 100644 --- a/plugins/catalog-react/report.api.md +++ b/plugins/catalog-react/report.api.md @@ -695,7 +695,7 @@ export function MissingAnnotationEmptyState(props: { // @public (undocumented) export type MissingAnnotationEmptyStateClassKey = 'code'; -// @public (undocumented) +// @public @deprecated (undocumented) export function MockEntityListContextProvider< T extends DefaultEntityFilters = DefaultEntityFilters, >( @@ -887,6 +887,7 @@ export function useStarredEntity( // src/components/UserListPicker/UserListPicker.d.ts:5:1 - (ae-undocumented) Missing documentation for "CatalogReactUserListPickerClassKey". // src/components/UserListPicker/UserListPicker.d.ts:15:1 - (ae-undocumented) Missing documentation for "UserListPickerProps". // src/components/UserListPicker/UserListPicker.d.ts:20:22 - (ae-undocumented) Missing documentation for "UserListPicker". +// src/deprecated.d.ts:7:1 - (ae-undocumented) Missing documentation for "MockEntityListContextProvider". // src/filters.d.ts:8:5 - (ae-undocumented) Missing documentation for "value". // src/filters.d.ts:10:5 - (ae-undocumented) Missing documentation for "getCatalogFilters". // src/filters.d.ts:11:5 - (ae-undocumented) Missing documentation for "toQueryValue". @@ -948,7 +949,6 @@ export function useStarredEntity( // src/hooks/useStarredEntity.d.ts:3:1 - (ae-undocumented) Missing documentation for "useStarredEntity". // src/overridableComponents.d.ts:6:1 - (ae-undocumented) Missing documentation for "CatalogReactComponentsNameToClassKey". // src/overridableComponents.d.ts:19:1 - (ae-undocumented) Missing documentation for "BackstageOverrides". -// src/testUtils/providers.d.ts:4:1 - (ae-undocumented) Missing documentation for "MockEntityListContextProvider". // src/types.d.ts:3:1 - (ae-undocumented) Missing documentation for "EntityFilter". // src/types.d.ts:25:1 - (ae-undocumented) Missing documentation for "UserListFilterKind". // src/types.d.ts:27:1 - (ae-undocumented) Missing documentation for "EntityListPagination". diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx index 26dee40ec3..3e6ed3c2ed 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx @@ -16,7 +16,7 @@ import { fireEvent, render, waitFor, screen } from '@testing-library/react'; import React from 'react'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityAutocompletePicker } from './EntityAutocompletePicker'; import { TestApiProvider } from '@backstage/test-utils'; import { catalogApiRef } from '../../api'; diff --git a/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx b/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx index 612c515d28..4633862f2c 100644 --- a/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.test.tsx @@ -24,7 +24,7 @@ import { capitalize } from 'lodash'; import { default as React } from 'react'; import { catalogApiRef } from '../../api'; import { EntityKindFilter } from '../../filters'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityKindPicker } from './EntityKindPicker'; const entities: Entity[] = [ diff --git a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx index fd779be1a2..701e1047c9 100644 --- a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx @@ -16,7 +16,7 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityLifecycleFilter } from '../../filters'; import { EntityLifecyclePicker } from './EntityLifecyclePicker'; import { TestApiProvider, renderInTestApp } from '@backstage/test-utils'; diff --git a/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx b/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx index 0fd336da42..5253dfae28 100644 --- a/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx @@ -16,7 +16,7 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityNamespaceFilter } from '../../filters'; import { EntityNamespacePicker } from './EntityNamespacePicker'; import { TestApiProvider, renderInTestApp } from '@backstage/test-utils'; diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx index 8942dadca3..f8f2497b0f 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx @@ -17,7 +17,7 @@ import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityOwnerFilter } from '../../filters'; import { EntityOwnerPicker } from './EntityOwnerPicker'; import { ApiProvider } from '@backstage/core-app-api'; diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx index 329df71fae..16fb3130f3 100644 --- a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.test.tsx @@ -17,7 +17,7 @@ import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { EntityErrorFilter, EntityOrphanFilter } from '../../filters'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityProcessingStatusPicker } from './EntityProcessingStatusPicker'; import { renderInTestApp } from '@backstage/test-utils'; diff --git a/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.test.tsx b/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.test.tsx index cbfeffa009..63047c163b 100644 --- a/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.test.tsx +++ b/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { fireEvent, waitFor, screen } from '@testing-library/react'; import { EntitySearchBar } from './EntitySearchBar'; import { EntityTextFilter } from '../../filters'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { renderInTestApp } from '@backstage/test-utils'; describe('EntitySearchBar', () => { diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx index 62f6991034..9b7fa2d2a3 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx @@ -16,7 +16,7 @@ import { fireEvent, waitFor, screen, act } from '@testing-library/react'; import React from 'react'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityTagFilter } from '../../filters'; import { EntityTagPicker } from './EntityTagPicker'; import { TestApiProvider, renderInTestApp } from '@backstage/test-utils'; diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx index e558a36869..f7954f2604 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { fireEvent, waitFor, screen, within } from '@testing-library/react'; import { Entity } from '@backstage/catalog-model'; import { EntityTypePicker } from './EntityTypePicker'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { catalogApiRef } from '../../api'; import { EntityKindFilter, EntityTypeFilter } from '../../filters'; import { alertApiRef } from '@backstage/core-plugin-api'; diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index 0b101e8174..5efb7339cf 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { fireEvent, waitFor, screen } from '@testing-library/react'; import { UserEntity } from '@backstage/catalog-model'; import { UserListPicker, UserListPickerProps } from './UserListPicker'; -import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { MockEntityListContextProvider } from '@backstage/plugin-catalog-react/testUtils'; import { EntityKindFilter, EntityNamespaceFilter, diff --git a/plugins/catalog-react/src/deprecated.tsx b/plugins/catalog-react/src/deprecated.tsx new file mode 100644 index 0000000000..8e088502e8 --- /dev/null +++ b/plugins/catalog-react/src/deprecated.tsx @@ -0,0 +1,93 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { + PropsWithChildren, + useCallback, + useMemo, + useState, +} from 'react'; +import { + DefaultEntityFilters, + EntityListContext, + EntityListContextProps, +} from './hooks/useEntityListProvider'; + +/** + * @public + * @deprecated Moved to `@backstage/plugin-catalog-react/testUtils` + */ +export function MockEntityListContextProvider< + T extends DefaultEntityFilters = DefaultEntityFilters, +>( + props: PropsWithChildren<{ + value?: Partial>; + }>, +) { + const { children, value } = props; + + // Provides a default implementation that stores filter state, for testing components that + // reflect filter state. + const [filters, setFilters] = useState(value?.filters ?? ({} as T)); + + const updateFilters = useCallback( + (update: Partial | ((prevFilters: T) => Partial)) => { + setFilters(prevFilters => { + const newFilters = + typeof update === 'function' ? update(prevFilters) : update; + return { ...prevFilters, ...newFilters }; + }); + }, + [], + ); + + // Memoize the default values since pickers have useEffect triggers on these; naively defaulting + // below with `?? ` breaks referential equality on subsequent updates. + const defaultValues = useMemo( + () => ({ + entities: [], + backendEntities: [], + queryParameters: {}, + }), + [], + ); + + const resolvedValue: EntityListContextProps = useMemo( + () => ({ + entities: value?.entities ?? defaultValues.entities, + backendEntities: value?.backendEntities ?? defaultValues.backendEntities, + updateFilters: value?.updateFilters ?? updateFilters, + filters, + loading: value?.loading ?? false, + queryParameters: value?.queryParameters ?? defaultValues.queryParameters, + error: value?.error, + totalItems: + value?.totalItems ?? (value?.entities ?? defaultValues.entities).length, + limit: value?.limit ?? 20, + offset: value?.offset, + setLimit: value?.setLimit ?? (() => {}), + setOffset: value?.setOffset, + paginationMode: value?.paginationMode ?? 'none', + }), + [value, defaultValues, filters, updateFilters], + ); + + return ( + + {children} + + ); +} diff --git a/plugins/catalog-react/src/index.ts b/plugins/catalog-react/src/index.ts index b511116f84..2ea1eb6f53 100644 --- a/plugins/catalog-react/src/index.ts +++ b/plugins/catalog-react/src/index.ts @@ -28,8 +28,8 @@ export * from './components'; export * from './hooks'; export * from './filters'; export { entityRouteParams, entityRouteRef } from './routes'; -export * from './testUtils'; export * from './types'; export * from './overridableComponents'; export { getEntityRelations, getEntitySourceLocation } from './utils'; export type { EntitySourceLocation } from './utils'; +export * from './deprecated'; diff --git a/plugins/catalog-react/src/testUtils/index.ts b/plugins/catalog-react/src/testUtils.ts similarity index 72% rename from plugins/catalog-react/src/testUtils/index.ts rename to plugins/catalog-react/src/testUtils.ts index 2bfec07c81..4688e73feb 100644 --- a/plugins/catalog-react/src/testUtils/index.ts +++ b/plugins/catalog-react/src/testUtils.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * Copyright 2024 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,4 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { MockEntityListContextProvider } from './providers'; + +/** + * Frontend test helpers for the Catalog plugin. + * + * @packageDocumentation + */ + +export { MockEntityListContextProvider } from './testUtils/MockEntityListContextProvider'; diff --git a/plugins/catalog-react/src/testUtils/providers.tsx b/plugins/catalog-react/src/testUtils/MockEntityListContextProvider.tsx similarity index 95% rename from plugins/catalog-react/src/testUtils/providers.tsx rename to plugins/catalog-react/src/testUtils/MockEntityListContextProvider.tsx index 9bb46dc6e5..fc01b5847b 100644 --- a/plugins/catalog-react/src/testUtils/providers.tsx +++ b/plugins/catalog-react/src/testUtils/MockEntityListContextProvider.tsx @@ -24,9 +24,13 @@ import { DefaultEntityFilters, EntityListContext, EntityListContextProps, -} from '../hooks/useEntityListProvider'; +} from '@backstage/plugin-catalog-react'; -/** @public */ +/** + * Simplifies testing of code that uses the entity list hooks. + * + * @public + */ export function MockEntityListContextProvider< T extends DefaultEntityFilters = DefaultEntityFilters, >(