1 | import React from 'react';
|
2 |
|
3 | import { shallowWithIntl, mountWithIntl } from 'terra-enzyme-intl';
|
4 | import SearchField from '../../src/SearchField';
|
5 |
|
6 | describe('Snapshots', () => {
|
7 | it('renders a basic search field', () => {
|
8 | const searchField = shallowWithIntl(<SearchField />).dive();
|
9 | expect(searchField).toMatchSnapshot();
|
10 | });
|
11 |
|
12 | it('renders a search field with a placeholder', () => {
|
13 | const searchField = shallowWithIntl(<SearchField placeholder="Test" />).dive();
|
14 | expect(searchField).toMatchSnapshot();
|
15 | });
|
16 |
|
17 | it('renders a search field with a value', () => {
|
18 | const searchField = shallowWithIntl(<SearchField value="Test" />).dive();
|
19 | expect(searchField).toMatchSnapshot();
|
20 | });
|
21 |
|
22 | it('renders a search field with a defaulted value', () => {
|
23 | const searchField = shallowWithIntl(<SearchField defaultValue="Default" />).dive();
|
24 | expect(searchField).toMatchSnapshot();
|
25 | });
|
26 |
|
27 | it('renders a disabled search field with a value', () => {
|
28 | const searchField = shallowWithIntl(<SearchField isDisabled />).dive();
|
29 | searchField.setState({ searchText: 'Test' });
|
30 |
|
31 | expect(searchField).toMatchSnapshot();
|
32 | });
|
33 |
|
34 | it('renders a search field that displays as a block to fill its container', () => {
|
35 | const searchField = shallowWithIntl(<SearchField isBlock />).dive();
|
36 | searchField.setState({ searchText: 'Test' });
|
37 |
|
38 | expect(searchField).toMatchSnapshot();
|
39 | });
|
40 |
|
41 | it('passes in inputRefCallback as the refCallback prop of the Input component', () => {
|
42 | const inputRefCallback = jest.fn();
|
43 | const searchField = mountWithIntl(<SearchField inputRefCallback={inputRefCallback} />).children();
|
44 | expect(inputRefCallback).toBeCalled();
|
45 | expect(searchField).toMatchSnapshot();
|
46 | });
|
47 |
|
48 | it('renders a search field with an aria-label', () => {
|
49 | const searchField = shallowWithIntl(<SearchField inputAttributes={{ 'aria-label': 'Search Field' }} />).dive();
|
50 | expect(searchField).toMatchSnapshot();
|
51 | });
|
52 |
|
53 | it('renders a search field with an aria-label using prop', () => {
|
54 | const searchField = shallowWithIntl(<SearchField inputAttributes={{ ariaLabel: 'Search Field' }} />).dive();
|
55 | expect(searchField).toMatchSnapshot();
|
56 | });
|
57 |
|
58 | it('clears form with clear method', () => {
|
59 | const searchField = shallowWithIntl(<SearchField />).dive();
|
60 | searchField.setState({ searchText: 'amp' });
|
61 |
|
62 | expect(searchField.state('searchText')).toBe('amp');
|
63 | searchField.instance().handleClear();
|
64 | expect(searchField.state('searchText')).toBe('');
|
65 | });
|
66 | });
|
67 |
|
68 | describe('Manual Search', () => {
|
69 | it('triggers search on button click', () => {
|
70 | const onSearch = jest.fn();
|
71 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} />).dive();
|
72 | searchField.setState({ searchText: 'Te' });
|
73 |
|
74 | expect(onSearch).not.toBeCalled();
|
75 | searchField.childAt(1).simulate('click');
|
76 | expect(onSearch).toBeCalledWith('Te');
|
77 | });
|
78 |
|
79 | it('does not trigger search if default minimum search text has not been met', () => {
|
80 | const onSearch = jest.fn();
|
81 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} />).dive();
|
82 | searchField.setState({ searchText: 'T' });
|
83 |
|
84 | expect(onSearch).not.toBeCalled();
|
85 | searchField.childAt(1).simulate('click');
|
86 | expect(onSearch).not.toBeCalled();
|
87 | });
|
88 |
|
89 | it('does not trigger search if minimum search text has not been met', () => {
|
90 | const onSearch = jest.fn();
|
91 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} minimumSearchTextLength={5} />).dive();
|
92 | searchField.setState({ searchText: 'Sear' });
|
93 |
|
94 | expect(onSearch).not.toBeCalled();
|
95 | searchField.childAt(1).simulate('click');
|
96 | expect(onSearch).not.toBeCalled();
|
97 | });
|
98 |
|
99 | it('does not search when callback is not provided', () => {
|
100 | const searchField = shallowWithIntl(<SearchField minimumSearchTextLength={5} />).dive();
|
101 | searchField.setState({ searchText: 'Searc' });
|
102 |
|
103 | searchField.childAt(1).simulate('click'); // Verifies we do not attempt to call an undefined function.
|
104 | });
|
105 | });
|
106 |
|
107 | describe('Auto Search', () => {
|
108 | beforeAll(() => {
|
109 | jest.useFakeTimers();
|
110 | });
|
111 |
|
112 | afterAll(() => {
|
113 | jest.useRealTimers();
|
114 | });
|
115 |
|
116 | it('triggers search after delay on text change', () => {
|
117 | const onSearch = jest.fn();
|
118 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} />).dive();
|
119 |
|
120 | searchField.find('.input').simulate('change', { target: { value: 'Te' } });
|
121 |
|
122 | expect(onSearch).not.toBeCalled();
|
123 | jest.runAllTimers();
|
124 | expect(onSearch).toBeCalledWith('Te');
|
125 | });
|
126 |
|
127 | it('only triggers one search if a manual search is triggered before automatic search', () => {
|
128 | const onSearch = jest.fn();
|
129 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} />).dive();
|
130 |
|
131 | searchField.find('.input').simulate('change', { target: { value: 'Te' } });
|
132 |
|
133 | expect(onSearch).not.toBeCalled();
|
134 |
|
135 | searchField.childAt(1).simulate('click');
|
136 | expect(onSearch).toBeCalledWith('Te');
|
137 |
|
138 | jest.runAllTimers();
|
139 | expect(onSearch.mock.calls.length).toBe(1);
|
140 | });
|
141 |
|
142 | it('does not trigger search if minimum text length is not met', () => {
|
143 | jest.useFakeTimers();
|
144 | const onSearch = jest.fn();
|
145 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} minimumSearchTextLength={5} />).dive();
|
146 |
|
147 | searchField.find('.input').simulate('change', { target: { value: 'Sear' } });
|
148 |
|
149 | expect(onSearch).not.toBeCalled();
|
150 | jest.runAllTimers();
|
151 | expect(onSearch).not.toBeCalled();
|
152 | });
|
153 |
|
154 | it('triggers onInvalidSearch if minimum text length is not met', () => {
|
155 | jest.useFakeTimers();
|
156 | const onSearch = jest.fn();
|
157 | const onInvalidSearch = jest.fn();
|
158 | const searchField = shallowWithIntl(<SearchField onSearch={onSearch} onInvalidSearch={onInvalidSearch} minimumSearchTextLength={5} />).dive();
|
159 |
|
160 | searchField.find('.input').simulate('change', { target: { value: 'Sear' } });
|
161 |
|
162 | jest.runAllTimers();
|
163 | expect(onSearch).not.toBeCalled();
|
164 | expect(onInvalidSearch).toBeCalledWith('Sear');
|
165 | });
|
166 |
|
167 | it('uses standard timeout for search delay when not provided', () => {
|
168 | const searchField = shallowWithIntl(<SearchField />).dive();
|
169 |
|
170 | searchField.find('.input').simulate('change', { target: {} });
|
171 | expect(setTimeout).toBeCalledWith(expect.anything(), 250);
|
172 | });
|
173 |
|
174 | it('uses custom timeout for search delay when provided', () => {
|
175 | const onSearch = jest.fn();
|
176 | const searchField = shallowWithIntl(<SearchField searchDelay={1000} onSearch={onSearch} />).dive();
|
177 |
|
178 | searchField.childAt(0).simulate('change', { target: {} });
|
179 |
|
180 | for (let i = 0; i < 3; i += 1) {
|
181 | jest.advanceTimersByTime(250);
|
182 | expect(onSearch).not.toBeCalled();
|
183 | }
|
184 |
|
185 | jest.advanceTimersByTime(250);
|
186 | // 1000ms has been passed by jest by now
|
187 | expect(setTimeout).toBeCalled();
|
188 | });
|
189 |
|
190 | it('should call onChange when button is selected', () => {
|
191 | const onChange = jest.fn();
|
192 | const searchField = shallowWithIntl(<SearchField onChange={onChange} />).dive();
|
193 |
|
194 | searchField.find('.input').simulate('change', { target: {} });
|
195 | expect(onChange).toBeCalled();
|
196 |
|
197 | searchField.find('.input').simulate('change', { target: {} });
|
198 | expect(onChange).toBeCalled();
|
199 | });
|
200 | });
|