import _ from 'lodash';
import React from 'react';
import { mount, shallow } from 'enzyme';
import assert from 'assert';
import sinon from 'sinon';
import { findTypes } from '../../util/component-types';
import { common } from '../../util/generic-tests';
import { AutocompleteDumb as Autocomplete } from './Autocomplete';
import { DropMenuDumb as DropMenu } from '../DropMenu/DropMenu';
import * as KEYCODE from '../../constants/key-code';
describe('Autocomplete', () => {
common(Autocomplete);
describe('render', () => {
it('should render a DropMenu', () => {
const wrapper = shallow(, {
disableLifecycleMethods: true,
});
assert.strictEqual(wrapper.find('DropMenu').length, 1);
});
});
describe('props', () => {
describe('isDisabled', () => {
it('should pass the `isDisabled` prop thru to the underlying DropMenu', () => {
const wrapper = shallow(, {
disableLifecycleMethods: true,
});
const dropMenuWrapper = wrapper.find('DropMenu');
assert.strictEqual(dropMenuWrapper.prop('isDisabled'), true);
});
it('should apply the appropriate classNames to the control', () => {
const wrapper = shallow(, {
disableLifecycleMethods: true,
});
const controlWrapper = wrapper.find('.lucid-Autocomplete-Control');
assert(
controlWrapper.hasClass('lucid-Autocomplete-Control-is-disabled')
);
});
});
describe('suggestions', () => {
it('should create `DropMenu.Option`s for each suggestion and pass thru to underlying DropMenu', () => {
const wrapper = shallow(
,
{ disableLifecycleMethods: true }
);
const options = _.map(
findTypes(wrapper.find(DropMenu).props(), DropMenu.Option),
'props'
);
assert.strictEqual('Portland', options[0].children);
assert.strictEqual('portal', options[1].children);
assert.strictEqual('porridge', options[2].children);
assert.strictEqual('potent', options[3].children);
assert.strictEqual('please', options[4].children);
});
});
describe('value', () => {
let wrapper: any;
let rootMountNode: any;
beforeEach(() => {
rootMountNode = document.createElement('div');
document.body.appendChild(rootMountNode);
});
afterEach(() => {
if (wrapper) {
wrapper.unmount();
}
document.body.removeChild(rootMountNode);
});
it('should set the text value of the input', () => {
wrapper = mount(, {
attachTo: rootMountNode,
});
const inputDOMNode: any = document.querySelector(
'.lucid-Autocomplete-Control-input'
);
assert.strictEqual(
inputDOMNode.value,
'Portland',
'input value must match prop value'
);
});
it('should change the text value of the input when the prop changes', () => {
wrapper = mount(, {
attachTo: rootMountNode,
});
wrapper.setProps({
...wrapper.props(),
value: 'Boston',
});
const inputDOMNode: any = document.querySelector(
'.lucid-Autocomplete-Control-input'
);
assert.strictEqual(
inputDOMNode.value,
'Boston',
'input value must match bew prop value'
);
});
});
describe('DropMenu', () => {
it('should pass thru all DropMenu props to the underlying DropMenu', () => {
const explicitDropMenuProps = {
isExpanded: true,
// direction: 'up',
focusedIndex: 2,
};
const wrapper = shallow(
,
{ disableLifecycleMethods: true }
);
const dropMenuProps: any = wrapper.find('DropMenu').props();
_.forEach(explicitDropMenuProps, (value, key) => {
assert(_.isEqual(dropMenuProps[key], value));
});
});
});
describe('onChange', () => {
let wrapper: any;
let rootMountNode: any;
beforeEach(() => {
rootMountNode = document.createElement('div');
document.body.appendChild(rootMountNode);
});
afterEach(() => {
if (wrapper) {
wrapper.unmount();
}
document.body.removeChild(rootMountNode);
});
describe('suggestion', () => {
/* eslint-disable no-console */
let error: any;
beforeEach(() => {
error = console.error;
console.error = jest.fn();
});
afterEach(() => {
console.error = error;
});
it('should be called when a suggestion is selected from the menu', () => {
const onChange = sinon.spy();
wrapper = mount(
);
const menuDOMNode: any = document.querySelector(
'.lucid-ContextMenu-FlyOut .lucid-DropMenu-option-container'
);
menuDOMNode.children[2].click();
assert(onChange.called);
const [textValue, { props, event }] = onChange.lastCall.args;
assert.strictEqual(textValue, 'porridge');
assert(props);
assert.strictEqual(props.testProp, 'foo');
assert(event);
expect(console.error).toHaveBeenCalledTimes(1);
});
it('should be called when user types into the text box', () => {
const onChange = sinon.spy();
wrapper = mount(
,
{
attachTo: rootMountNode,
}
);
const inputDOMNode: any = document.querySelector(
'.lucid-Autocomplete-Control-input'
);
// set the input value and dispatch an `input` event
inputDOMNode.value = 'aaa';
const inputEvent = document.createEvent('Event');
inputEvent.initEvent('input', true, true);
inputDOMNode.dispatchEvent(inputEvent);
assert(onChange.called, 'onChange must be called');
const [textValue, { props, event }] = onChange.lastCall.args;
assert.strictEqual(textValue, 'aaa', 'value must match input');
assert(props, 'props must be passed');
assert.strictEqual(
props.testProp,
'foo',
'aditional props must be included'
);
assert(event, 'event must be passed');
});
/* eslint-enable no-console */
});
});
describe('onSelect', () => {
let wrapper: any;
afterEach(() => {
if (wrapper) {
wrapper.unmount();
}
});
it('should be called when a suggestion is selected from the menu', () => {
const onSelect: any = sinon.spy();
wrapper = mount(
);
const menuDOMNode: any = document.querySelector(
'.lucid-ContextMenu-FlyOut .lucid-DropMenu-option-container'
);
menuDOMNode.children[2].click();
assert(onSelect.called, 'onSelect must be called');
const [optionIndex, { props, event }] = onSelect.lastCall.args;
assert.strictEqual(optionIndex, 2, 'optionIndex must be accurate');
assert(props, 'props must be passed');
assert.strictEqual(
props.testProp,
'foo',
'aditional props must be included'
);
assert(event, 'event must be passed');
});
});
describe('onExpand', () => {
let wrapper: any;
let rootMountNode: any;
beforeEach(() => {
rootMountNode = document.createElement('div');
document.body.appendChild(rootMountNode);
});
afterEach(() => {
if (wrapper && wrapper.exists()) {
wrapper.unmount();
}
document.body.removeChild(rootMountNode);
});
it('should be called when the input value changes to a non-empty value', () => {
const onExpand = sinon.spy();
wrapper = mount(
,
{ attachTo: rootMountNode }
);
const inputDOMNode: any = document.querySelector(
'.lucid-Autocomplete-Control-input'
);
// set the input value and dispatch an `input` event
inputDOMNode.value = 'aaa';
const inputEvent = document.createEvent('Event');
inputEvent.initEvent('input', true, true);
inputDOMNode.dispatchEvent(inputEvent);
assert(onExpand.called, 'onExpand must be called');
const [{ props, event }] = onExpand.lastCall.args;
assert(props, 'props must be passed');
assert.strictEqual(
props.testProp,
'foo',
'aditional props must be included'
);
assert(event, 'event must be passed');
});
it('should be called when not expanded and down array key is pressed', () => {
const onExpand = sinon.spy();
const wrapper = shallow(
,
{ disableLifecycleMethods: true }
);
wrapper.find('.lucid-Autocomplete-Control-input').simulate('keydown', {
keyCode: KEYCODE.ArrowDown,
stopPropagation: _.noop,
});
assert(onExpand.called, 'onExpand must be called');
const [{ props, event }] = onExpand.lastCall.args;
assert(props, 'props must be passed');
assert.strictEqual(
props.testProp,
'foo',
'aditional props must be included'
);
assert(event, 'event must be passed');
});
it('should be called when the control input is clicked', () => {
const onExpand = sinon.spy();
wrapper = mount(
,
{ attachTo: rootMountNode }
);
wrapper.find('.lucid-Autocomplete-Control-input').simulate('click');
assert(onExpand.called, 'onExpand must be called');
const [{ props, event }] = onExpand.lastCall.args;
assert(props, 'props must be passed');
assert.strictEqual(
props.testProp,
'foo',
'aditional props must be included'
);
assert(event, 'event must be passed');
});
it('should be called when not expanded the non-input control is clicked', () => {
const onExpand = sinon.spy();
wrapper = mount(
,
{ attachTo: rootMountNode }
);
wrapper.find('.lucid-Autocomplete-Control').simulate('click');
assert(onExpand.called, 'onExpand must be called');
const [{ props, event }] = onExpand.lastCall.args;
assert(props, 'props must be passed');
assert.strictEqual(
props.testProp,
'foo',
'aditional props must be included'
);
assert(event, 'event must be passed');
});
});
});
});