diff --git a/.changeset/green-trees-wait.md b/.changeset/green-trees-wait.md new file mode 100644 index 0000000000..388298ef59 --- /dev/null +++ b/.changeset/green-trees-wait.md @@ -0,0 +1,22 @@ +--- +'@backstage/create-app': patch +--- + +imports `useSearch` hook from new `@backstage/plugin-search-react` package. + +To upgrade existing Apps: + +1. Change the import to the following: + +`packages/app/src/components/search/SearchPage.tsx` + +```diff +import { +... +SearchType, +- useSearch, +} from '@backstage/plugin-search'; ++import { useSearch } from '@backstage/plugin-search-react'; +``` + +2. Add `@backstage/plugin-search-react` as a dependency to the app. diff --git a/.changeset/strong-lions-film.md b/.changeset/strong-lions-film.md new file mode 100644 index 0000000000..5efd765e83 --- /dev/null +++ b/.changeset/strong-lions-film.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-search': minor +--- + +The following exports has now been fully deleted from this package and can be import from `@backstage/plugin-search-react` instead. + +`SearchApi` interface. +`searchApiRef` +`SearchContextProvider` +`useSearch` + +`SearchContext` has now been fully deleted from this package and is no longer exported publicly. Use `SearchContextProvider` when access to the context is needed. diff --git a/packages/app/src/components/search/SearchModal.tsx b/packages/app/src/components/search/SearchModal.tsx index 2e18a289c9..f75017a4dd 100644 --- a/packages/app/src/components/search/SearchModal.tsx +++ b/packages/app/src/components/search/SearchModal.tsx @@ -41,8 +41,8 @@ import { SearchResult, SearchResultPager, SearchType, - useSearch, } from '@backstage/plugin-search'; +import { useSearch } from '@backstage/plugin-search-react'; import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs'; const useStyles = makeStyles(theme => ({ diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index 65da72d91c..fd9c80686c 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -36,8 +36,8 @@ import { SearchResult, SearchResultPager, SearchType, - useSearch, } from '@backstage/plugin-search'; +import { useSearch } from '@backstage/plugin-search-react'; import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs'; import { Grid, List, makeStyles, Paper, Theme } from '@material-ui/core'; import React, { useContext } from 'react'; diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 06b39867fa..6f2aef14eb 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -85,6 +85,7 @@ "@backstage/plugin-scaffolder": "", "@backstage/plugin-scaffolder-backend": "", "@backstage/plugin-search": "", + "@backstage/plugin-search-react": "", "@backstage/plugin-search-backend": "", "@backstage/plugin-search-backend-module-pg": "", "@backstage/plugin-search-backend-node": "", diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 963c04afdf..b6c93a38b3 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -69,6 +69,7 @@ import { version as pluginRollbarBackend } from '../../../../plugins/rollbar-bac import { version as pluginScaffolder } from '../../../../plugins/scaffolder/package.json'; import { version as pluginScaffolderBackend } from '../../../../plugins/scaffolder-backend/package.json'; import { version as pluginSearch } from '../../../../plugins/search/package.json'; +import { version as pluginSearchReact } from '../../../../plugins/search-react/package.json'; import { version as pluginSearchBackend } from '../../../../plugins/search-backend/package.json'; import { version as pluginSearchBackendModulePg } from '../../../../plugins/search-backend-module-pg/package.json'; import { version as pluginSearchBackendNode } from '../../../../plugins/search-backend-node/package.json'; @@ -113,6 +114,7 @@ export const packageVersions = { '@backstage/plugin-scaffolder': pluginScaffolder, '@backstage/plugin-scaffolder-backend': pluginScaffolderBackend, '@backstage/plugin-search': pluginSearch, + '@backstage/plugin-search-react': pluginSearchReact, '@backstage/plugin-search-backend': pluginSearchBackend, '@backstage/plugin-search-backend-module-pg': pluginSearchBackendModulePg, '@backstage/plugin-search-backend-node': pluginSearchBackendNode, diff --git a/packages/create-app/templates/default-app/packages/app/package.json.hbs b/packages/create-app/templates/default-app/packages/app/package.json.hbs index 2ad394c68e..87a8060594 100644 --- a/packages/create-app/templates/default-app/packages/app/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/app/package.json.hbs @@ -25,6 +25,7 @@ "@backstage/plugin-permission-react": "^{{version '@backstage/plugin-permission-react'}}", "@backstage/plugin-scaffolder": "^{{version '@backstage/plugin-scaffolder'}}", "@backstage/plugin-search": "^{{version '@backstage/plugin-search'}}", + "@backstage/plugin-search-react": "^{{version '@backstage/plugin-search-react'}}", "@backstage/plugin-tech-radar": "^{{version '@backstage/plugin-tech-radar'}}", "@backstage/plugin-techdocs": "^{{version '@backstage/plugin-techdocs'}}", "@backstage/plugin-user-settings": "^{{version '@backstage/plugin-user-settings'}}", diff --git a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx index cd4603ecd3..0595e4ece8 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx @@ -14,8 +14,8 @@ import { SearchResult, SearchType, DefaultResultListItem, - useSearch, } from '@backstage/plugin-search'; +import { useSearch } from '@backstage/plugin-search-react'; import { CatalogIcon, Content, diff --git a/plugins/search/api-report.md b/plugins/search/api-report.md index 2f9a8fbb77..31d357f10c 100644 --- a/plugins/search/api-report.md +++ b/plugins/search/api-report.md @@ -5,20 +5,14 @@ ```ts /// -import { ApiRef } from '@backstage/core-plugin-api'; -import { AsyncState } from 'react-use/lib/useAsync'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { InputBaseProps } from '@material-ui/core'; -import { JsonObject } from '@backstage/types'; -import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SearchDocument } from '@backstage/plugin-search-common'; -import { SearchQuery } from '@backstage/plugin-search-common'; import { SearchResult as SearchResult_2 } from '@backstage/plugin-search-common'; -import { SearchResultSet } from '@backstage/plugin-search-common'; // Warning: (ae-missing-release-tag) "DefaultResultListItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -81,19 +75,6 @@ export type HomePageSearchBarProps = Partial< // @public (undocumented) export const Router: () => JSX.Element; -// Warning: (ae-missing-release-tag) "SearchApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated (undocumented) -export interface SearchApi { - // (undocumented) - query(query: SearchQuery): Promise; -} - -// Warning: (ae-missing-release-tag) "searchApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated (undocumented) -export const searchApiRef: ApiRef; - // @public (undocumented) export type SearchAutocompleteFilterProps = SearchFilterComponentProps & { filterSelectedOptions?: boolean; @@ -138,24 +119,6 @@ export const SearchBarNext: ({ // @public export type SearchBarProps = Partial; -// Warning: (ae-missing-release-tag) "SearchContextProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated (undocumented) -export const SearchContextProvider: ({ - initialState, - children, -}: React_2.PropsWithChildren<{ - initialState?: SearchContextState | undefined; -}>) => JSX.Element; - -// @public -export type SearchContextState = { - term: string; - types: string[]; - filters: JsonObject; - pageCursor?: string; -}; - // Warning: (ae-missing-release-tag) "SearchFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -330,13 +293,6 @@ export type SidebarSearchProps = { icon?: IconComponent; }; -// Warning: (tsdoc-at-sign-in-word) The "@" character looks like part of a TSDoc tag; use a backslash to escape it -// Warning: (ae-forgotten-export) The symbol "SearchContextValue" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "useSearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated (undocumented) -export const useSearch: () => SearchContextValue; - // @public export function useSearchModal(initialState?: boolean): { state: { diff --git a/plugins/search/src/apis.ts b/plugins/search/src/apis.ts index 096b11bb5e..208ad98b0a 100644 --- a/plugins/search/src/apis.ts +++ b/plugins/search/src/apis.ts @@ -14,30 +14,13 @@ * limitations under the License. */ -import { - createApiRef, - DiscoveryApi, - IdentityApi, -} from '@backstage/core-plugin-api'; +import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; import { ResponseError } from '@backstage/errors'; +import { SearchApi } from '@backstage/plugin-search-react'; import { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common'; import qs from 'qs'; -/** - * @deprecated import from `@backstage/plugin-search-react` instead - */ -export const searchApiRef = createApiRef({ - id: 'plugin.search.queryservice', -}); - -/** - * @deprecated import from `@backstage/plugin-search-react` instead - */ -export interface SearchApi { - query(query: SearchQuery): Promise; -} - export class SearchClient implements SearchApi { private readonly discoveryApi: DiscoveryApi; private readonly identityApi: IdentityApi; diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx index 1a6c5fbf7b..4c20ddec39 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx @@ -15,7 +15,7 @@ */ import { rootRouteRef, HomePageSearchBar } from '../../plugin'; -import { searchApiRef } from '../../apis'; +import { searchApiRef } from '@backstage/plugin-search-react'; import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils'; import { Grid, makeStyles } from '@material-ui/core'; import React, { ComponentType } from 'react'; diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx index bccf38ab1d..bc4b409d57 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx @@ -16,7 +16,6 @@ import React, { useCallback, useState } from 'react'; import { makeStyles } from '@material-ui/core/styles'; - import { SearchBarBase, SearchBarBaseProps } from '../SearchBar'; import { useNavigateToQuery } from '../util'; diff --git a/plugins/search/src/components/SearchBar/SearchBar.test.tsx b/plugins/search/src/components/SearchBar/SearchBar.test.tsx index 73afb44f12..c48c3d3ed2 100644 --- a/plugins/search/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search/src/components/SearchBar/SearchBar.test.tsx @@ -17,13 +17,15 @@ import React from 'react'; import { screen, render, waitFor, act } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { SearchContextProvider } from '../SearchContext'; - -import { SearchBar } from './SearchBar'; import { configApiRef, analyticsApiRef } from '@backstage/core-plugin-api'; import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; -import { searchApiRef } from '../../apis'; import { MockAnalyticsApi, TestApiRegistry } from '@backstage/test-utils'; +import { + SearchContextProvider, + searchApiRef, +} from '@backstage/plugin-search-react'; + +import { SearchBar } from './SearchBar'; jest.mock('@backstage/core-plugin-api', () => ({ ...jest.requireActual('@backstage/core-plugin-api'), diff --git a/plugins/search/src/components/SearchBar/SearchBar.tsx b/plugins/search/src/components/SearchBar/SearchBar.tsx index a203d27c93..70038ecc82 100644 --- a/plugins/search/src/components/SearchBar/SearchBar.tsx +++ b/plugins/search/src/components/SearchBar/SearchBar.tsx @@ -20,7 +20,6 @@ import React, { useState, useEffect, useCallback, - useContext, } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; @@ -34,10 +33,9 @@ import SearchIcon from '@material-ui/icons/Search'; import ClearButton from '@material-ui/icons/Clear'; import { - SearchContext, SearchContextProvider, useSearch, -} from '../SearchContext'; +} from '@backstage/plugin-search-react'; import { TrackSearch } from '../SearchTracker'; /** @@ -53,11 +51,6 @@ export type SearchBarBaseProps = Omit & { onChange: (value: string) => void; }; -const useSearchContextCheck = () => { - const context = useContext(SearchContext); - return context !== undefined; -}; - /** * All search boxes exported by the search plugin are based on the , * and this one is based on the component from Material UI. @@ -79,7 +72,7 @@ export const SearchBarBase = ({ }: SearchBarBaseProps) => { const configApi = useApi(configApiRef); const [value, setValue] = useState(defaultValue as string); - const hasSearchContext = useSearchContextCheck(); + const hasSearchContext = useSearch(); useEffect(() => { setValue(prevValue => diff --git a/plugins/search/src/components/SearchContext/SearchContext.tsx b/plugins/search/src/components/SearchContext/SearchContext.tsx deleted file mode 100644 index c87295ab99..0000000000 --- a/plugins/search/src/components/SearchContext/SearchContext.tsx +++ /dev/null @@ -1,144 +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 { JsonObject } from '@backstage/types'; -import { useApi, AnalyticsContext } from '@backstage/core-plugin-api'; -import { SearchResultSet } from '@backstage/plugin-search-common'; -import React, { - createContext, - PropsWithChildren, - useCallback, - useContext, - useEffect, - useState, -} from 'react'; -import useAsync, { AsyncState } from 'react-use/lib/useAsync'; -import usePrevious from 'react-use/lib/usePrevious'; -import { searchApiRef } from '../../apis'; - -type SearchContextValue = { - result: AsyncState; - setTerm: React.Dispatch>; - setTypes: React.Dispatch>; - setFilters: React.Dispatch>; - setPageCursor: React.Dispatch>; - fetchNextPage?: React.DispatchWithoutAction; - fetchPreviousPage?: React.DispatchWithoutAction; -} & SearchContextState; - -/** - * The initial state of `SearchContextProvider`. - * - * @public - */ -export type SearchContextState = { - term: string; - types: string[]; - filters: JsonObject; - pageCursor?: string; -}; - -/** - * @deprecated import from `@backstage/plugin-search-react` instead - */ -export const SearchContext = createContext( - undefined, -); - -const searchInitialState: SearchContextState = { - term: '', - pageCursor: undefined, - filters: {}, - types: [], -}; - -/** - * @deprecated import from `@backstage/plugin-search-react` instead - */ -export const SearchContextProvider = ({ - initialState = searchInitialState, - children, -}: PropsWithChildren<{ initialState?: SearchContextState }>) => { - const searchApi = useApi(searchApiRef); - const [pageCursor, setPageCursor] = useState( - initialState.pageCursor, - ); - const [filters, setFilters] = useState(initialState.filters); - const [term, setTerm] = useState(initialState.term); - const [types, setTypes] = useState(initialState.types); - - const prevTerm = usePrevious(term); - - const result = useAsync( - () => - searchApi.query({ - term, - filters, - pageCursor, - types, - }), - [term, filters, types, pageCursor], - ); - - const hasNextPage = - !result.loading && !result.error && result.value?.nextPageCursor; - const hasPreviousPage = - !result.loading && !result.error && result.value?.previousPageCursor; - const fetchNextPage = useCallback(() => { - setPageCursor(result.value?.nextPageCursor); - }, [result.value?.nextPageCursor]); - const fetchPreviousPage = useCallback(() => { - setPageCursor(result.value?.previousPageCursor); - }, [result.value?.previousPageCursor]); - - useEffect(() => { - // Any time a term is reset, we want to start from page 0. - if (term && prevTerm && term !== prevTerm) { - setPageCursor(undefined); - } - }, [term, prevTerm, initialState.pageCursor]); - - const value: SearchContextValue = { - result, - filters, - setFilters, - term, - setTerm, - types, - setTypes, - pageCursor, - setPageCursor, - fetchNextPage: hasNextPage ? fetchNextPage : undefined, - fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined, - }; - - return ( - - - - ); -}; - -/** - * @deprecated import from "@backstage/plugin-search-react" instead - */ -export const useSearch = () => { - const context = useContext(SearchContext); - if (context === undefined) { - throw new Error('useSearch must be used within a SearchContextProvider'); - } - return context; -}; diff --git a/plugins/search/src/components/SearchContext/index.tsx b/plugins/search/src/components/SearchContext/index.tsx deleted file mode 100644 index 8651e661c1..0000000000 --- a/plugins/search/src/components/SearchContext/index.tsx +++ /dev/null @@ -1,23 +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 { - SearchContextProvider, - SearchContext, - useSearch, -} from './SearchContext'; - -export type { SearchContextState } from './SearchContext'; diff --git a/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx b/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx index ae0eeb30be..15ad348bd4 100644 --- a/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx +++ b/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx @@ -18,8 +18,11 @@ import { TestApiProvider } from '@backstage/test-utils'; import { screen, render, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { searchApiRef } from '../../apis'; -import { SearchContextProvider, useSearch } from '../SearchContext'; +import { + SearchContextProvider, + useSearch, + searchApiRef, +} from '@backstage/plugin-search-react'; import { SearchFilter } from './SearchFilter'; const SearchContextFilterSpy = ({ name }: { name: string }) => { diff --git a/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.tsx b/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.tsx index 9a27f63565..03f4f28943 100644 --- a/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.tsx +++ b/plugins/search/src/components/SearchFilter/SearchFilter.Autocomplete.tsx @@ -21,7 +21,7 @@ import { AutocompleteGetTagProps, AutocompleteRenderInputParams, } from '@material-ui/lab'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { useAsyncFilterValues, useDefaultFilterValue } from './hooks'; import { SearchFilterComponentProps } from './SearchFilter'; diff --git a/plugins/search/src/components/SearchFilter/SearchFilter.test.tsx b/plugins/search/src/components/SearchFilter/SearchFilter.test.tsx index ba7abe7023..2d652df483 100644 --- a/plugins/search/src/components/SearchFilter/SearchFilter.test.tsx +++ b/plugins/search/src/components/SearchFilter/SearchFilter.test.tsx @@ -19,7 +19,7 @@ import { screen, render, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { SearchFilter } from './SearchFilter'; -import { SearchContextProvider } from '../SearchContext'; +import { SearchContextProvider } from '@backstage/plugin-search-react'; import { useApi } from '@backstage/core-plugin-api'; jest.mock('@backstage/core-plugin-api', () => ({ diff --git a/plugins/search/src/components/SearchFilter/SearchFilter.tsx b/plugins/search/src/components/SearchFilter/SearchFilter.tsx index 1308333100..bfbab8531c 100644 --- a/plugins/search/src/components/SearchFilter/SearchFilter.tsx +++ b/plugins/search/src/components/SearchFilter/SearchFilter.tsx @@ -30,7 +30,7 @@ import { AutocompleteFilter, SearchAutocompleteFilterProps, } from './SearchFilter.Autocomplete'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { useAsyncFilterValues, useDefaultFilterValue } from './hooks'; const useStyles = makeStyles({ diff --git a/plugins/search/src/components/SearchFilter/hooks.test.tsx b/plugins/search/src/components/SearchFilter/hooks.test.tsx index d8fbe698ce..14346a29eb 100644 --- a/plugins/search/src/components/SearchFilter/hooks.test.tsx +++ b/plugins/search/src/components/SearchFilter/hooks.test.tsx @@ -17,9 +17,12 @@ import React from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { TestApiRegistry } from '@backstage/test-utils'; import { renderHook } from '@testing-library/react-hooks'; -import { SearchContextProvider, useSearch } from '../SearchContext'; +import { + SearchContextProvider, + useSearch, + searchApiRef, +} from '@backstage/plugin-search-react'; import { useDefaultFilterValue, useAsyncFilterValues } from './hooks'; -import { searchApiRef } from '../../apis'; jest.useFakeTimers(); diff --git a/plugins/search/src/components/SearchFilter/hooks.ts b/plugins/search/src/components/SearchFilter/hooks.ts index 217e65d1c0..da30466522 100644 --- a/plugins/search/src/components/SearchFilter/hooks.ts +++ b/plugins/search/src/components/SearchFilter/hooks.ts @@ -17,7 +17,7 @@ import { useEffect, useRef } from 'react'; import useAsyncFn from 'react-use/lib/useAsyncFn'; import useDebounce from 'react-use/lib/useDebounce'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; /** * Utility hook for either asynchronously loading filter values from a given diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index c50d8af1eb..842f5fb401 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -21,7 +21,7 @@ import userEvent from '@testing-library/user-event'; import { configApiRef } from '@backstage/core-plugin-api'; import { ApiProvider, ConfigReader } from '@backstage/core-app-api'; import { rootRouteRef } from '../../plugin'; -import { searchApiRef } from '../../apis'; +import { searchApiRef } from '@backstage/plugin-search-react'; import { SearchModal } from './SearchModal'; diff --git a/plugins/search/src/components/SearchModal/SearchModal.tsx b/plugins/search/src/components/SearchModal/SearchModal.tsx index 67b99e0926..55fd0cb977 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.tsx @@ -31,7 +31,10 @@ import { makeStyles } from '@material-ui/core/styles'; import { SearchBar } from '../SearchBar'; import { DefaultResultListItem } from '../DefaultResultListItem'; import { SearchResult } from '../SearchResult'; -import { SearchContextProvider, useSearch } from '../SearchContext'; +import { + SearchContextProvider, + useSearch, +} from '@backstage/plugin-search-react'; import { SearchResultPager } from '../SearchResultPager'; import { useRouteRef } from '@backstage/core-plugin-api'; import { Link, useContent } from '@backstage/core-components'; diff --git a/plugins/search/src/components/SearchPage/SearchPage.test.tsx b/plugins/search/src/components/SearchPage/SearchPage.test.tsx index 9486196584..59e6e99aaf 100644 --- a/plugins/search/src/components/SearchPage/SearchPage.test.tsx +++ b/plugins/search/src/components/SearchPage/SearchPage.test.tsx @@ -17,7 +17,7 @@ import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { useLocation, useOutlet } from 'react-router'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { SearchPage } from './SearchPage'; jest.mock('react-router', () => ({ @@ -33,8 +33,8 @@ const setTypesMock = jest.fn(); const setFiltersMock = jest.fn(); const setPageCursorMock = jest.fn(); -jest.mock('../SearchContext', () => ({ - ...jest.requireActual('../SearchContext'), +jest.mock('@backstage/plugin-search-react', () => ({ + ...jest.requireActual('@backstage/plugin-search-react'), SearchContextProvider: jest .fn() .mockImplementation(({ children }) => children), @@ -51,7 +51,7 @@ jest.mock('../SearchContext', () => ({ })); jest.mock('../LegacySearchPage', () => ({ - ...jest.requireActual('../SearchContext'), + ...jest.requireActual('@backstage/plugin-search-react'), LegacySearchPage: jest.fn().mockReturnValue('LegacySearchPageMock'), })); diff --git a/plugins/search/src/components/SearchPage/SearchPage.tsx b/plugins/search/src/components/SearchPage/SearchPage.tsx index e4e1e49d57..29a22a6f5c 100644 --- a/plugins/search/src/components/SearchPage/SearchPage.tsx +++ b/plugins/search/src/components/SearchPage/SearchPage.tsx @@ -18,7 +18,10 @@ import React, { useEffect } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; import qs from 'qs'; import { useLocation, useOutlet } from 'react-router'; -import { SearchContextProvider, useSearch } from '../SearchContext'; +import { + SearchContextProvider, + useSearch, +} from '@backstage/plugin-search-react'; import { JsonObject } from '@backstage/types'; import { LegacySearchPage } from '../LegacySearchPage'; diff --git a/plugins/search/src/components/SearchResult/SearchResult.test.tsx b/plugins/search/src/components/SearchResult/SearchResult.test.tsx index 43a9cdb022..d93eacaef0 100644 --- a/plugins/search/src/components/SearchResult/SearchResult.test.tsx +++ b/plugins/search/src/components/SearchResult/SearchResult.test.tsx @@ -17,11 +17,11 @@ import { renderInTestApp } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { SearchResult } from './SearchResult'; -jest.mock('../SearchContext', () => ({ - ...jest.requireActual('../SearchContext'), +jest.mock('@backstage/plugin-search-react', () => ({ + ...jest.requireActual('@backstage/plugin-search-react'), useSearch: jest.fn().mockReturnValue({ result: {}, }), diff --git a/plugins/search/src/components/SearchResult/SearchResult.tsx b/plugins/search/src/components/SearchResult/SearchResult.tsx index d6ca9fd968..a62dddb924 100644 --- a/plugins/search/src/components/SearchResult/SearchResult.tsx +++ b/plugins/search/src/components/SearchResult/SearchResult.tsx @@ -21,7 +21,7 @@ import { } from '@backstage/core-components'; import { SearchResult } from '@backstage/plugin-search-common'; import React from 'react'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; type Props = { children: (results: { results: SearchResult[] }) => JSX.Element; diff --git a/plugins/search/src/components/SearchResultPager/SearchResultPager.test.tsx b/plugins/search/src/components/SearchResultPager/SearchResultPager.test.tsx index f24a73d63e..b1cad8d748 100644 --- a/plugins/search/src/components/SearchResultPager/SearchResultPager.test.tsx +++ b/plugins/search/src/components/SearchResultPager/SearchResultPager.test.tsx @@ -18,11 +18,11 @@ import { renderInTestApp } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { SearchResultPager } from './SearchResultPager'; -jest.mock('../SearchContext', () => ({ - ...jest.requireActual('../SearchContext'), +jest.mock('@backstage/plugin-search-react', () => ({ + ...jest.requireActual('@backstage/plugin-search-react'), useSearch: jest.fn().mockReturnValue({ result: {}, }), diff --git a/plugins/search/src/components/SearchResultPager/SearchResultPager.tsx b/plugins/search/src/components/SearchResultPager/SearchResultPager.tsx index 12f07530ef..6f4c8628a6 100644 --- a/plugins/search/src/components/SearchResultPager/SearchResultPager.tsx +++ b/plugins/search/src/components/SearchResultPager/SearchResultPager.tsx @@ -18,7 +18,7 @@ import { Button, makeStyles } from '@material-ui/core'; import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos'; import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos'; import React from 'react'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; const useStyles = makeStyles(theme => ({ root: { diff --git a/plugins/search/src/components/SearchTracker/SearchTracker.tsx b/plugins/search/src/components/SearchTracker/SearchTracker.tsx index b9da9b5560..35cfa1ec38 100644 --- a/plugins/search/src/components/SearchTracker/SearchTracker.tsx +++ b/plugins/search/src/components/SearchTracker/SearchTracker.tsx @@ -16,7 +16,7 @@ import React, { useEffect } from 'react'; import { useAnalytics } from '@backstage/core-plugin-api'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; /** * Capture search event on term change. diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx index a62d061663..da1cae46b9 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx @@ -15,29 +15,30 @@ */ import React from 'react'; -import { ApiProvider } from '@backstage/core-app-api'; -import { TestApiRegistry } from '@backstage/test-utils'; +import { TestApiProvider } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import user from '@testing-library/user-event'; - -import { searchApiRef } from '../../apis'; -import { SearchContext, SearchContextProvider } from '../SearchContext'; +import { + searchApiRef, + SearchContextProvider, +} from '@backstage/plugin-search-react'; import { SearchType } from './SearchType'; +const setTypesMock = jest.fn(); +const setPageCursorMock = jest.fn(); + +jest.mock('@backstage/plugin-search-react', () => ({ + ...jest.requireActual('@backstage/plugin-search-react'), + useSearch: jest.fn().mockReturnValue({ + types: [], + setTypes: (types: any) => setTypesMock(types), + pageCursor: '', + setPageCursor: (pageCursor: any) => setPageCursorMock(pageCursor), + }), +})); + describe('SearchType.Accordion', () => { const query = jest.fn(); - const mockApis = TestApiRegistry.from([searchApiRef, { query }]); - - const contextSpy = { - result: { loading: false, value: { results: [] } }, - term: '', - types: [], - filters: {}, - setTerm: jest.fn(), - setTypes: jest.fn(), - setFilters: jest.fn(), - setPageCursor: jest.fn(), - }; const expectedLabel = 'Expected Label'; const expectedType = { @@ -50,17 +51,19 @@ describe('SearchType.Accordion', () => { query.mockResolvedValue({ results: [] }); }); - afterEach(() => { - jest.resetAllMocks(); - }); + const Wrapper = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); + }; it('should render as expected', async () => { const { getByText } = render( - - - - - , + + + , ); // The given label should be rendered. @@ -80,49 +83,49 @@ describe('SearchType.Accordion', () => { it('should set entire types array when a type is selected', async () => { const { getByText } = render( - + - , + , ); await user.click(getByText(expectedType.name)); - expect(contextSpy.setTypes).toHaveBeenCalledWith([expectedType.value]); + expect(setTypesMock).toHaveBeenCalledWith([expectedType.value]); }); it('should reset types array when all is selected', async () => { const { getByText } = render( - + - , + , ); await user.click(getByText('All')); - expect(contextSpy.setTypes).toHaveBeenCalledWith([]); + expect(setTypesMock).toHaveBeenCalledWith([]); }); it('should reset page cursor when a new type is selected', async () => { const { getByText } = render( - + - , + , ); await user.click(getByText(expectedType.name)); - expect(contextSpy.setPageCursor).toHaveBeenCalledWith(undefined); + expect(setPageCursorMock).toHaveBeenCalledWith(undefined); }); it('should collapse when a new type is selected', async () => { const { getByText, queryByText } = render( - + - , + , ); await user.click(getByText(expectedType.name)); diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx index 57e6609bab..49f5cf74ca 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx @@ -15,7 +15,7 @@ */ import React, { cloneElement, Fragment, useEffect, useState } from 'react'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { Accordion, AccordionSummary, diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx index 2886b63ae7..16df3a8f65 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx @@ -15,50 +15,49 @@ */ import React from 'react'; -import { ApiProvider } from '@backstage/core-app-api'; -import { TestApiRegistry } from '@backstage/test-utils'; +import { TestApiProvider } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import user from '@testing-library/user-event'; - -import { searchApiRef } from '../../apis'; -import { SearchContext, SearchContextProvider } from '../SearchContext'; +import { + SearchContextProvider, + searchApiRef, +} from '@backstage/plugin-search-react'; import { SearchType } from './SearchType'; -describe('SearchType.Tabs', () => { - const query = jest.fn(); - const mockApis = TestApiRegistry.from([searchApiRef, { query }]); +const setTypesMock = jest.fn(); +const setPageCursorMock = jest.fn(); - const contextSpy = { - result: { loading: false, value: { results: [] } }, - term: '', +jest.mock('@backstage/plugin-search-react', () => ({ + ...jest.requireActual('@backstage/plugin-search-react'), + useSearch: jest.fn().mockReturnValue({ types: [], - filters: {}, - setTerm: jest.fn(), - setTypes: jest.fn(), - setFilters: jest.fn(), - setPageCursor: jest.fn(), - }; + setTypes: (types: any) => setTypesMock(types), + pageCursor: '', + setPageCursor: (pageCursor: any) => setPageCursorMock(pageCursor), + }), +})); + +describe('SearchType.Tabs', () => { + const query = jest.fn().mockResolvedValue({}); const expectedType = { value: 'expected-type', name: 'Expected Type', }; - beforeEach(() => { - query.mockResolvedValue({ results: [] }); - }); - - afterEach(() => { - jest.resetAllMocks(); - }); + const Wrapper = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); + }; it('should render as expected', async () => { const { getByText } = render( - - - - - , + + + , ); // The default "all" type should be rendered. @@ -72,40 +71,40 @@ describe('SearchType.Tabs', () => { it('should set entire types array when a type is selected', async () => { const { getByText } = render( - + - , + , ); await user.click(getByText(expectedType.name)); - expect(contextSpy.setTypes).toHaveBeenCalledWith([expectedType.value]); + expect(setTypesMock).toHaveBeenCalledWith([expectedType.value]); }); it('should reset types array when all is selected', async () => { const { getByText } = render( - + - , + , ); await user.click(getByText('All')); - expect(contextSpy.setTypes).toHaveBeenCalledWith([]); + expect(setTypesMock).toHaveBeenCalledWith([]); }); it('should reset page cursor when a new type is selected', async () => { const { getByText } = render( - + - , + , ); await user.click(getByText(expectedType.name)); - expect(contextSpy.setPageCursor).toHaveBeenCalledWith(undefined); + expect(setPageCursorMock).toHaveBeenCalledWith(undefined); }); }); diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx index 09797ae8f5..fc0380e23a 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx @@ -15,7 +15,7 @@ */ import React, { useEffect } from 'react'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; import { BackstageTheme } from '@backstage/theme'; import { makeStyles, Tab, Tabs } from '@material-ui/core'; diff --git a/plugins/search/src/components/SearchType/SearchType.test.tsx b/plugins/search/src/components/SearchType/SearchType.test.tsx index 94f6cf716c..a80782921f 100644 --- a/plugins/search/src/components/SearchType/SearchType.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.test.tsx @@ -18,7 +18,7 @@ import { useApi } from '@backstage/core-plugin-api'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { SearchContextProvider } from '../SearchContext'; +import { SearchContextProvider } from '@backstage/plugin-search-react'; import { SearchType } from './SearchType'; jest.mock('@backstage/core-plugin-api', () => ({ diff --git a/plugins/search/src/components/SearchType/SearchType.tsx b/plugins/search/src/components/SearchType/SearchType.tsx index ba20e1db5d..79c3dda2b9 100644 --- a/plugins/search/src/components/SearchType/SearchType.tsx +++ b/plugins/search/src/components/SearchType/SearchType.tsx @@ -30,7 +30,7 @@ import { SearchTypeAccordionProps, } from './SearchType.Accordion'; import { SearchTypeTabs, SearchTypeTabsProps } from './SearchType.Tabs'; -import { useSearch } from '../SearchContext'; +import { useSearch } from '@backstage/plugin-search-react'; const useStyles = makeStyles(theme => ({ label: { diff --git a/plugins/search/src/index.ts b/plugins/search/src/index.ts index bfffb9e84c..dccb2ce835 100644 --- a/plugins/search/src/index.ts +++ b/plugins/search/src/index.ts @@ -20,9 +20,6 @@ * @packageDocumentation */ -export { searchApiRef } from './apis'; -export type { SearchApi } from './apis'; - export { Filters, FiltersButton } from './components/Filters'; export type { FiltersState } from './components/Filters'; export type { HomePageSearchBarProps } from './components/HomePageComponent'; @@ -31,8 +28,6 @@ export type { SearchBarBaseProps, SearchBarProps, } from './components/SearchBar'; -export { SearchContextProvider, useSearch } from './components/SearchContext'; -export type { SearchContextState } from './components/SearchContext'; export { SearchFilter, SearchFilterNext } from './components/SearchFilter'; export type { SearchAutocompleteFilterProps, diff --git a/plugins/search/src/plugin.ts b/plugins/search/src/plugin.ts index 9dda2a84bb..96e7bc1eed 100644 --- a/plugins/search/src/plugin.ts +++ b/plugins/search/src/plugin.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { SearchClient, searchApiRef } from './apis'; +import { SearchClient } from './apis'; +import { searchApiRef } from '@backstage/plugin-search-react'; import { createApiFactory, createPlugin,