Skip to content
This repository has been archived by the owner on Dec 21, 2021. It is now read-only.

Commit

Permalink
Add SearchBar unit tests
Browse files Browse the repository at this point in the history
The <SearchBar /> component debounces searches. Normally that would be
tested using Jest's fake timers, however due to this issue
jestjs/jest#3465 it's using real timers and
a timeout of 500ms.

A placeholder prop to be passed onto the <InputText /> was also added.
  • Loading branch information
matijs committed Nov 27, 2019
1 parent 81ed541 commit 42a1e51
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 7 deletions.
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -68,6 +68,7 @@
"@types/enzyme-adapter-react-16": "^1.0.5",
"@types/history": "^4.7.0",
"@types/jest": "^23.3.14",
"@types/lodash.debounce": "^4.0.6",
"@types/node": "^11.9.3",
"@types/react-dom": "^16.0.7",
"@types/react-router": "^4.0.30",
Expand Down
@@ -0,0 +1,50 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`search_bar.tsx snapshot and instance 1`] = `
<SearchBar
emitDelay={0}
onChange={[MockFunction]}
placeholder="For example…"
>
<div
className="search-bar"
>
<span
className="search-bar__icon"
>
<MagnifierIconSmall>
<svg
aria-hidden="true"
fill="currentColor"
focusable="false"
height="24px"
viewBox="0 0 24 24"
width="24px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15,1.99999996 C11.1,1.99999996 7.99999996,5.09999997 7.99999996,8.99999996 C7.99999996,10.6 8.49999996,12 9.39999999,13.2 L1.99999996,20.6 L3.39999996,22 L10.8,14.6 C12,15.5 13.4,16 15,16 C18.9,16 22,12.9 22,8.99999996 C22,5.09999997 18.9,1.99999996 15,1.99999996 Z M15,14 C12.2,14 9.99999999,11.8 9.99999999,8.99999997 C9.99999999,6.19999998 12.2,3.99999997 15,3.99999997 C17.8,3.99999997 20,6.19999998 20,8.99999997 C20,11.8 17.8,14 15,14 Z"
fill="currentColor"
/>
</svg>
</MagnifierIconSmall>
</span>
<ForwardRef
className="search-bar__input"
hasError={false}
onChange={[Function]}
placeholder="For example…"
type="text"
value=""
>
<input
className="input-text search-bar__input"
onChange={[Function]}
placeholder="For example…"
type="text"
value=""
/>
</ForwardRef>
</div>
</SearchBar>
`;
58 changes: 58 additions & 0 deletions src/components/search_bar/__tests__/search_bar.spec.tsx
@@ -0,0 +1,58 @@
import React from 'react';
import { mount, ReactWrapper } from 'enzyme';
import { SearchBar } from '..';

// Use real timers for this one because https://github.com/facebook/jest/issues/3465

describe('search_bar.tsx', () => {
let wrapper: ReactWrapper;
let emitDelay: number;
const query = 'hello world';
const placeholder = 'For example…';
const onChange: jest.Mock<any, any> = jest.fn();

afterEach(() => {
onChange.mockReset();
wrapper.unmount();
});

test('snapshot and instance', () => {
wrapper = mount(<SearchBar onChange={onChange} placeholder={placeholder} />);
expect(wrapper.instance()).toBeInstanceOf(SearchBar);
expect(wrapper).toMatchSnapshot();
});

test('with "query" prop', (done) => {
wrapper = mount(
<SearchBar
onChange={onChange}
placeholder={placeholder}
query={query}
/>,
);
expect(onChange).not.toHaveBeenCalled();
setTimeout(() => {
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith(query);
done();
}, 0);
});

test('with "emitDelay" prop', (done) => {
emitDelay = 500;
wrapper = mount(
<SearchBar
onChange={onChange}
placeholder={placeholder}
emitDelay={emitDelay}
query={query}
/>,
);
expect(onChange).not.toHaveBeenCalled();
setTimeout(() => {
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith(query);
done();
}, emitDelay);
});
});
1 change: 1 addition & 0 deletions src/components/search_bar/index.ts
@@ -0,0 +1 @@
export { SearchBar } from './search_bar';
@@ -1,12 +1,13 @@
import React from 'react';
import debounce from 'lodash.debounce';
import * as Input from './input';
import * as Icon from './icons';
import * as Input from '../input';
import * as Icon from '../icons';

interface SearchBarProps {
query?: string;
emitDelay?: number;
onChangeHandler: (value: string) => void;
onChange: (value: string) => void;
placeholder?: string;
}

interface SearchBarState {
Expand All @@ -18,8 +19,8 @@ class SearchBar extends React.Component<SearchBarProps, SearchBarState> {
emitDelay: 0,
}

debouncedEmit = (({ onChangeHandler, emitDelay }) => debounce(
onChangeHandler, emitDelay,
debouncedEmit = (({ onChange, emitDelay }) => debounce(
onChange, emitDelay,
))(this.props);

constructor(props: Readonly<SearchBarProps>) {
Expand Down Expand Up @@ -55,12 +56,18 @@ class SearchBar extends React.Component<SearchBarProps, SearchBarState> {
render() {
const { query } = this.state;
const { onChange } = this;
const { placeholder } = this.props;
return (
<div className="search-bar">
<span className="search-bar__icon">
<Icon.MagnifierSmall />
</span>
<Input.Text className="search-bar__input" value={query} onChange={onChange} />
<Input.Text
className="search-bar__input"
value={query}
onChange={onChange}
placeholder={placeholder}
/>
</div>
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/stories/search_bar.stories.tsx
Expand Up @@ -21,7 +21,8 @@ stories.addDecorator(withKnobs)

stories.add('SearchBar', () => (
<SearchBar
onChangeHandler={action('query')}
onChange={action('query')}
emitDelay={500}
placeholder="Search for…"
/>
));

0 comments on commit 42a1e51

Please sign in to comment.