pass the value to the input instead to downshift (#6235)

* pass the value to the input instead to downshift

Signed-off-by: blalov <boyko.lalov@tick42.com>

* adjust expression input tests

Signed-off-by: blalov <boyko.lalov@tick42.com>

* improve ExpressionInput test coverage

Signed-off-by: blalov <boyko.lalov@tick42.com>
This commit is contained in:
Boyko 2019-11-04 14:15:25 +02:00 committed by Julius Volz
parent 95554074d8
commit 7293c859ab
2 changed files with 107 additions and 22 deletions

View file

@ -1,5 +1,5 @@
import * as React from 'react';
import { mount } from 'enzyme';
import { mount, ReactWrapper } from 'enzyme';
import ExpressionInput from './ExpressionInput';
import Downshift from 'downshift';
import { Button, InputGroup, InputGroupAddon, Input } from 'reactstrap';
@ -25,11 +25,15 @@ describe('ExpressionInput', () => {
executeQuery: (): void => {},
loading: false,
};
const expressionInput = mount(<ExpressionInput {...expressionInputProps} />);
let expressionInput: ReactWrapper;
beforeEach(() => {
expressionInput = mount(<ExpressionInput {...expressionInputProps} />);
});
it('renders a downshift component', () => {
const downshift = expressionInput.find(Downshift);
expect(downshift.prop('inputValue')).toEqual('node_cpu');
expect(downshift).toHaveLength(1);
});
it('renders an InputGroup', () => {
@ -52,7 +56,6 @@ describe('ExpressionInput', () => {
});
it('renders an Input', () => {
const expressionInput = mount(<ExpressionInput {...expressionInputProps} />);
const input = expressionInput.find(Input);
expect(input.prop('style')).toEqual({ height: 0 });
expect(input.prop('autoFocus')).toEqual(true);
@ -84,6 +87,83 @@ describe('ExpressionInput', () => {
});
});
describe('handleInput', () => {
it('should call setState', () => {
const instance: any = expressionInput.instance();
const stateSpy = jest.spyOn(instance, 'setState');
instance.handleInput();
expect(stateSpy).toHaveBeenCalled();
});
});
describe('handleDropdownSelection', () => {
it('should call setState with selected value', () => {
const instance: any = expressionInput.instance();
const stateSpy = jest.spyOn(instance, 'setState');
instance.handleDropdownSelection('foo');
expect(stateSpy).toHaveBeenCalledWith({ value: 'foo', height: 'auto' }, expect.anything());
});
});
describe('handleKeyPress', () => {
it('should call executeQuery on Enter key pressed', () => {
const spyExecuteQuery = jest.fn();
const input = mount(<ExpressionInput executeQuery={spyExecuteQuery} {...({} as any)} />);
const instance: any = input.instance();
instance.handleKeyPress({ preventDefault: jest.fn, key: 'Enter' });
expect(spyExecuteQuery).toHaveBeenCalled();
});
it('should NOT call executeQuery on Enter + Shift', () => {
const spyExecuteQuery = jest.fn();
const input = mount(<ExpressionInput executeQuery={spyExecuteQuery} {...({} as any)} />);
const instance: any = input.instance();
instance.handleKeyPress({ preventDefault: jest.fn, key: 'Enter', shiftKey: true });
expect(spyExecuteQuery).not.toHaveBeenCalled();
});
});
describe('getSearchMatches', () => {
it('should return matched value', () => {
const instance: any = expressionInput.instance();
expect(instance.getSearchMatches('foo', ['barfoobaz', 'bazasdbaz'])).toHaveLength(1);
});
it('should return empty array if no match found', () => {
const instance: any = expressionInput.instance();
expect(instance.getSearchMatches('foo', ['barbaz', 'bazasdbaz'])).toHaveLength(0);
});
});
describe('createAutocompleteSection', () => {
it('should close menu if no matches found', () => {
const input = mount(<ExpressionInput autocompleteSections={{ title: ['foo', 'bar', 'baz'] }} {...({} as any)} />);
const instance: any = input.instance();
const spyCloseMenu = jest.fn();
instance.createAutocompleteSection({ inputValue: 'qqqqqq', closeMenu: spyCloseMenu });
setTimeout(() => {
expect(spyCloseMenu).toHaveBeenCalled();
});
});
it('should not render lsit if inputValue not exist', () => {
const input = mount(<ExpressionInput autocompleteSections={{ title: ['foo', 'bar', 'baz'] }} {...({} as any)} />);
const instance: any = input.instance();
const spyCloseMenu = jest.fn();
instance.createAutocompleteSection({ closeMenu: spyCloseMenu });
setTimeout(() => expect(spyCloseMenu).toHaveBeenCalled());
});
it('should render autosuggest-dropdown', () => {
const input = mount(<ExpressionInput autocompleteSections={{ title: ['foo', 'bar', 'baz'] }} {...({} as any)} />);
const instance: any = input.instance();
const spyGetMenuProps = jest.fn();
const sections = instance.createAutocompleteSection({
inputValue: 'foo',
highlightedIndex: 0,
getMenuProps: spyGetMenuProps,
getItemProps: jest.fn,
});
expect(sections.props.className).toEqual('autosuggest-dropdown');
});
});
describe('when downshift is open', () => {
it('closes the menu on "Enter"', () => {
const downshift = expressionInput.find(Downshift);
@ -94,6 +174,18 @@ describe('ExpressionInput', () => {
expect(downshift.state('isOpen')).toBe(false);
});
it('should blur input on escape', () => {
const downshift = expressionInput.find(Downshift);
const instance: any = expressionInput.instance();
const spyBlur = jest.fn();
instance.exprInputRef.current = { blur: spyBlur };
const input = downshift.find(Input);
downshift.setState({ isOpen: false });
const event = getKeyEvent('Escape');
input.simulate('keydown', event);
expect(spyBlur).toHaveBeenCalled();
});
it('noops on ArrowUp or ArrowDown', () => {
const downshift = expressionInput.find(Downshift);
const input = downshift.find(Input);
@ -107,16 +199,6 @@ describe('ExpressionInput', () => {
});
it('does not render an autosuggest if there are no matches', () => {
const expressionInputProps = {
value: 'foo',
autocompleteSections: {
'Query History': [],
'Metric Names': [],
},
executeQuery: (): void => {},
loading: false,
};
const expressionInput = mount(<ExpressionInput {...expressionInputProps} />);
const downshift = expressionInput.find(Downshift);
downshift.setState({ isOpen: true });
const ul = downshift.find('ul');
@ -126,12 +208,14 @@ describe('ExpressionInput', () => {
it('renders an autosuggest if there are matches', () => {
const downshift = expressionInput.find(Downshift);
downshift.setState({ isOpen: true });
const ul = downshift.find('ul');
expect(ul.prop('className')).toEqual('autosuggest-dropdown-list');
const items = ul.find(SanitizeHTML);
expect(items.map(item => item.text()).join(', ')).toEqual(
'node_cpu_guest_seconds_total, node_cpu_seconds_total, instance:node_cpu_utilisation:rate1m'
);
setTimeout(() => {
const ul = downshift.find('ul');
expect(ul.prop('className')).toEqual('card list-group');
const items = ul.find(SanitizeHTML);
expect(items.map(item => item.text()).join(', ')).toEqual(
'node_cpu_guest_seconds_total, node_cpu_seconds_total, instance:node_cpu_utilisation:rate1m'
);
});
});
});

View file

@ -57,7 +57,7 @@ class ExpressionInput extends Component<ExpressionInputProps, ExpressionInputSta
handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter' && !event.shiftKey) {
this.props.executeQuery(this.exprInputRef.current!.value);
this.executeQuery();
event.preventDefault();
}
};
@ -126,7 +126,7 @@ class ExpressionInput extends Component<ExpressionInputProps, ExpressionInputSta
render() {
const { value, height } = this.state;
return (
<Downshift inputValue={value} onSelect={this.handleDropdownSelection}>
<Downshift onSelect={this.handleDropdownSelection}>
{downshift => (
<div>
<InputGroup className="expression-input">
@ -171,6 +171,7 @@ class ExpressionInput extends Component<ExpressionInputProps, ExpressionInputSta
}
},
} as any)}
value={value}
/>
<InputGroupAddon addonType="append">
<Button className="execute-btn" color="primary" onClick={this.executeQuery}>