diff --git a/plugins/search/src/components/SearchBarNext/SearchBarNext.test.tsx b/plugins/search/src/components/SearchBarNext/SearchBarNext.test.tsx
index f29cc53b71..a5075c5593 100644
--- a/plugins/search/src/components/SearchBarNext/SearchBarNext.test.tsx
+++ b/plugins/search/src/components/SearchBarNext/SearchBarNext.test.tsx
@@ -15,7 +15,8 @@
*/
import React from 'react';
-import { renderInTestApp } from '@backstage/test-utils';
+import { screen, render, waitFor, act } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import { useApi } from '@backstage/core';
import { SearchContextProvider } from '../SearchContext';
@@ -23,12 +24,10 @@ import { SearchBarNext } from './SearchBarNext';
jest.mock('@backstage/core', () => ({
...jest.requireActual('@backstage/core'),
- useApi: jest.fn(),
+ useApi: jest.fn().mockReturnValue({}),
}));
-describe('', () => {
- const _alphaPerformSearch = jest.fn();
-
+describe('SearchBarNext', () => {
const initialState = {
term: '',
pageCursor: '',
@@ -36,24 +35,119 @@ describe('', () => {
types: ['*'],
};
- beforeEach(() => {
- _alphaPerformSearch.mockResolvedValue([]);
- (useApi as jest.Mock).mockReturnValue({ _alphaPerformSearch });
- });
+ const name = 'Search term';
+ const term = 'term';
+
+ const _alphaPerformSearch = jest.fn().mockResolvedValue({});
+ (useApi as jest.Mock).mockReturnValue({ _alphaPerformSearch });
afterAll(() => {
jest.resetAllMocks();
});
- it('renders without exploding', async () => {
- const { getByRole } = await renderInTestApp(
+ it('Renders without exploding', async () => {
+ render(
,
);
- expect(
- getByRole('textbox', { name: 'search backstage' }),
- ).toBeInTheDocument();
+ await waitFor(() => {
+ expect(screen.getByRole('textbox', { name })).toBeInTheDocument();
+ });
+ });
+
+ it('Renders based on initial search', async () => {
+ render(
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByRole('textbox', { name })).toHaveValue(term);
+ });
+ });
+
+ it('Updates term state when text is entered', async () => {
+ render(
+
+
+ ,
+ );
+
+ const textbox = screen.getByRole('textbox', { name });
+
+ const value = 'value';
+
+ userEvent.type(textbox, value);
+
+ await waitFor(() => {
+ expect(textbox).toHaveValue(value);
+ });
+
+ expect(_alphaPerformSearch).toHaveBeenLastCalledWith(
+ expect.objectContaining({ term: value }),
+ );
+ });
+
+ it('Clear button clears term state', async () => {
+ render(
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByRole('textbox', { name })).toHaveValue(term);
+ });
+
+ userEvent.click(screen.getByRole('button', { name: 'Clear term' }));
+
+ await waitFor(() => {
+ expect(screen.getByRole('textbox', { name })).toHaveValue('');
+ });
+
+ expect(_alphaPerformSearch).toHaveBeenLastCalledWith(
+ expect.objectContaining({ term: '' }),
+ );
+ });
+
+ it('Adheres to provided debounceTime', async () => {
+ jest.useFakeTimers();
+
+ const debounceTime = 600;
+
+ render(
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByRole('textbox', { name })).toBeInTheDocument();
+ });
+
+ const textbox = screen.getByRole('textbox', { name });
+
+ const value = 'value';
+
+ userEvent.type(textbox, value);
+
+ expect(_alphaPerformSearch).not.toHaveBeenLastCalledWith(
+ expect.objectContaining({ term: value }),
+ );
+
+ act(() => {
+ jest.advanceTimersByTime(debounceTime);
+ });
+
+ await waitFor(() => {
+ expect(textbox).toHaveValue(value);
+ });
+
+ expect(_alphaPerformSearch).toHaveBeenLastCalledWith(
+ expect.objectContaining({ term: value }),
+ );
});
});
diff --git a/plugins/search/src/components/SearchBarNext/SearchBarNext.tsx b/plugins/search/src/components/SearchBarNext/SearchBarNext.tsx
index 014e3d6ee4..b223e6c2cd 100644
--- a/plugins/search/src/components/SearchBarNext/SearchBarNext.tsx
+++ b/plugins/search/src/components/SearchBarNext/SearchBarNext.tsx
@@ -14,17 +14,26 @@
* limitations under the License.
*/
-import React, { useState } from 'react';
+import React, { ChangeEvent, useState } from 'react';
import { useDebounce } from 'react-use';
-import { Paper, InputBase, IconButton, makeStyles } from '@material-ui/core';
+import {
+ Theme,
+ Paper,
+ InputBase,
+ InputAdornment,
+ IconButton,
+ makeStyles,
+} from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search';
import ClearButton from '@material-ui/icons/Clear';
+
import { useSearch } from '../SearchContext';
-const useStyles = makeStyles(() => ({
+const useStyles = makeStyles((theme: Theme) => ({
root: {
display: 'flex',
alignItems: 'center',
+ padding: theme.spacing(0, 0, 0, 1.5),
},
input: {
flex: 1,
@@ -40,36 +49,29 @@ export const SearchBarNext = ({ debounceTime = 0 }: Props) => {
const { term, setTerm } = useSearch();
const [value, setValue] = useState(term);
- useDebounce(
- () => {
- setTerm(value);
- },
- debounceTime,
- [value],
- );
+ useDebounce(() => setTerm(value), debounceTime, [value]);
- const handleSearch = (event: React.ChangeEvent | React.FormEvent) => {
- event.preventDefault();
- setValue((event.target as HTMLInputElement).value as string);
+ const handleSearch = (e: ChangeEvent) => {
+ setValue(e.target.value);
};
- const handleClearSearchBar = () => {
- setTerm('');
- };
+ const handleClear = () => setValue('');
return (
-
-
-
-
+
+
+
+ }
/>
-
+
diff --git a/plugins/search/src/components/SearchFilterNext/SearchFilterNext.test.tsx b/plugins/search/src/components/SearchFilterNext/SearchFilterNext.test.tsx
index ed9c0ecd74..1a35bf54d4 100644
--- a/plugins/search/src/components/SearchFilterNext/SearchFilterNext.test.tsx
+++ b/plugins/search/src/components/SearchFilterNext/SearchFilterNext.test.tsx
@@ -24,9 +24,7 @@ import { SearchContextProvider } from '../SearchContext';
jest.mock('@backstage/core', () => ({
...jest.requireActual('@backstage/core'),
- useApi: jest.fn().mockReturnValue({
- _alphaPerformSearch: jest.fn().mockResolvedValue({}),
- }),
+ useApi: jest.fn().mockReturnValue({}),
}));
describe('SearchFilterNext', () => {
@@ -44,6 +42,10 @@ describe('SearchFilterNext', () => {
const _alphaPerformSearch = jest.fn().mockResolvedValue({});
(useApi as jest.Mock).mockReturnValue({ _alphaPerformSearch });
+ afterAll(() => {
+ jest.resetAllMocks();
+ });
+
it('Check that element was rendered and received props', async () => {
const CustomFilter = (props: { name: string }) => {props.name}
;