Merge pull request #25611 from RikClaessens/use-search-icon
Update the SearchBar to make use of the useApp hook to retrieve the search icon specified in the createApp call
This commit is contained in:
+12
-11
@@ -19,7 +19,7 @@ import React, { ComponentType, PropsWithChildren } from 'react';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import LabelIcon from '@material-ui/icons/Label';
|
||||
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils';
|
||||
|
||||
import { searchApiRef, MockSearchApi } from '../../api';
|
||||
import { SearchContextProvider } from '../../context';
|
||||
@@ -31,17 +31,18 @@ export default {
|
||||
title: 'Plugins/Search/SearchAutocomplete',
|
||||
component: SearchAutocomplete,
|
||||
decorators: [
|
||||
(Story: ComponentType<PropsWithChildren<{}>>) => (
|
||||
<TestApiProvider apis={[[searchApiRef, new MockSearchApi()]]}>
|
||||
<SearchContextProvider>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={12}>
|
||||
<Story />
|
||||
(Story: ComponentType<PropsWithChildren<{}>>) =>
|
||||
wrapInTestApp(
|
||||
<TestApiProvider apis={[[searchApiRef, new MockSearchApi()]]}>
|
||||
<SearchContextProvider>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={12}>
|
||||
<Story />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</SearchContextProvider>
|
||||
</TestApiProvider>
|
||||
),
|
||||
</SearchContextProvider>
|
||||
</TestApiProvider>,
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import LabelIcon from '@material-ui/icons/Label';
|
||||
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
import { ConfigReader } from '@backstage/core-app-api';
|
||||
import { TestApiProvider, renderWithEffects } from '@backstage/test-utils';
|
||||
import { TestApiProvider, renderInTestApp } from '@backstage/test-utils';
|
||||
|
||||
import { searchApiRef } from '../../api';
|
||||
import { SearchAutocomplete } from './SearchAutocomplete';
|
||||
@@ -44,7 +44,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Renders without exploding', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -59,7 +59,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Show all options by default when focused', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -84,7 +84,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Updates context with the initial value', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -106,7 +106,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Updates context when value is cleared', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -139,7 +139,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Updates context when an option is select', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -165,7 +165,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Shows a circular progress when loading options', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -184,7 +184,7 @@ describe('SearchAutocomplete', () => {
|
||||
});
|
||||
|
||||
it('Uses the default search autocomplete option component', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
|
||||
@@ -18,7 +18,7 @@ import React, { ComponentType, PropsWithChildren } from 'react';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils';
|
||||
|
||||
import { searchApiRef, MockSearchApi } from '../../api';
|
||||
import { SearchContextProvider } from '../../context';
|
||||
@@ -28,18 +28,22 @@ import { SearchBar } from './SearchBar';
|
||||
export default {
|
||||
title: 'Plugins/Search/SearchBar',
|
||||
component: SearchBar,
|
||||
loaders: [
|
||||
async () => ({ component: (await import('./SearchBar')).SearchBar }),
|
||||
],
|
||||
decorators: [
|
||||
(Story: ComponentType<PropsWithChildren<{}>>) => (
|
||||
<TestApiProvider apis={[[searchApiRef, new MockSearchApi()]]}>
|
||||
<SearchContextProvider>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={12}>
|
||||
<Story />
|
||||
(Story: ComponentType<PropsWithChildren<{}>>) =>
|
||||
wrapInTestApp(
|
||||
<TestApiProvider apis={[[searchApiRef, new MockSearchApi()]]}>
|
||||
<SearchContextProvider>
|
||||
<Grid container direction="row">
|
||||
<Grid item xs={12}>
|
||||
<Story />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</SearchContextProvider>
|
||||
</TestApiProvider>
|
||||
),
|
||||
</SearchContextProvider>
|
||||
</TestApiProvider>,
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ConfigReader } from '@backstage/core-app-api';
|
||||
import {
|
||||
MockAnalyticsApi,
|
||||
TestApiProvider,
|
||||
renderWithEffects,
|
||||
renderInTestApp,
|
||||
} from '@backstage/test-utils';
|
||||
import { searchApiRef } from '../../api';
|
||||
import { SearchContextProvider } from '../../context';
|
||||
@@ -61,7 +61,7 @@ describe('SearchBar', () => {
|
||||
});
|
||||
|
||||
it('Renders without exploding', async () => {
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -82,7 +82,7 @@ describe('SearchBar', () => {
|
||||
it('Renders with custom label', async () => {
|
||||
const label = 'label';
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -103,7 +103,7 @@ describe('SearchBar', () => {
|
||||
it('Renders with custom placeholder', async () => {
|
||||
const placeholder = 'placeholder';
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -124,7 +124,7 @@ describe('SearchBar', () => {
|
||||
it('Renders based on initial search', async () => {
|
||||
const term = 'term';
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -145,7 +145,7 @@ describe('SearchBar', () => {
|
||||
it('Updates term state when text is entered', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -181,7 +181,7 @@ describe('SearchBar', () => {
|
||||
it('Clear button clears term state', async () => {
|
||||
const term = 'term';
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -210,7 +210,7 @@ describe('SearchBar', () => {
|
||||
it('Should not show clear button', async () => {
|
||||
const term = 'term';
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -233,7 +233,7 @@ describe('SearchBar', () => {
|
||||
|
||||
const debounceTime = 100;
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -275,7 +275,7 @@ describe('SearchBar', () => {
|
||||
it('Does not capture analytics event if not enabled in app', async () => {
|
||||
const analyticsApiMock = new MockAnalyticsApi();
|
||||
|
||||
await renderWithEffects(
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
@@ -298,4 +298,37 @@ describe('SearchBar', () => {
|
||||
|
||||
expect(analyticsApiMock.getEvents()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('Renders custom search icon', async () => {
|
||||
const CustomSearchIcon = () => (
|
||||
<svg>
|
||||
<path id="custom-search-icon" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[configApiRef, configApiMock],
|
||||
[searchApiRef, searchApiMock],
|
||||
]}
|
||||
>
|
||||
<SearchContextProvider>
|
||||
<SearchBar />
|
||||
</SearchContextProvider>
|
||||
</TestApiProvider>,
|
||||
{
|
||||
icons: {
|
||||
search: CustomSearchIcon,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const queryButton = screen.getByLabelText('Query');
|
||||
|
||||
expect(queryButton).toBeInTheDocument();
|
||||
expect(queryButton.innerHTML).toContain(
|
||||
'<svg><path id="custom-search-icon"></path></svg>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,13 +18,14 @@ import {
|
||||
AnalyticsContext,
|
||||
configApiRef,
|
||||
useApi,
|
||||
useApp,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import { TextFieldProps } from '@material-ui/core/TextField';
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
import DefaultSearchIcon from '@material-ui/icons/Search';
|
||||
import React, {
|
||||
ChangeEvent,
|
||||
ComponentType,
|
||||
@@ -146,6 +147,8 @@ export const SearchBarBase: ForwardRefExoticComponent<SearchBarBaseProps> =
|
||||
placeholder ??
|
||||
`Search in ${configApi.getOptionalString('app.title') || 'Backstage'}`;
|
||||
|
||||
const SearchIcon = useApp().getSystemIcon('search') || DefaultSearchIcon;
|
||||
|
||||
const startAdornment = (
|
||||
<InputAdornment position="start">
|
||||
<IconButton aria-label="Query" size="small" disabled>
|
||||
|
||||
Reference in New Issue
Block a user