lucid-ui
Version:
A UI component library from AppNexus.
363 lines (331 loc) • 16.5 kB
JavaScript
import _noop from "lodash/noop";
import _isEqual from "lodash/isEqual";
import _forEach from "lodash/forEach";
import _map from "lodash/map";
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
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', function () {
common(Autocomplete);
describe('render', function () {
it('should render a DropMenu', function () {
var wrapper = shallow( /*#__PURE__*/React.createElement(Autocomplete, null), {
disableLifecycleMethods: true
});
assert.equal(wrapper.find('DropMenu').length, 1);
});
});
describe('props', function () {
describe('isDisabled', function () {
it('should pass the `isDisabled` prop thru to the underlying DropMenu', function () {
var wrapper = shallow( /*#__PURE__*/React.createElement(Autocomplete, {
isDisabled: true
}), {
disableLifecycleMethods: true
});
var dropMenuWrapper = wrapper.find('DropMenu');
assert.equal(dropMenuWrapper.prop('isDisabled'), true);
});
it('should apply the appropriate classNames to the control', function () {
var wrapper = shallow( /*#__PURE__*/React.createElement(Autocomplete, {
isDisabled: true
}), {
disableLifecycleMethods: true
});
var controlWrapper = wrapper.find('.lucid-Autocomplete-Control');
assert(controlWrapper.hasClass('lucid-Autocomplete-Control-is-disabled'));
});
});
describe('suggestions', function () {
it('should create `DropMenu.Option`s for each suggestion and pass thru to underlying DropMenu', function () {
var wrapper = shallow( /*#__PURE__*/React.createElement(Autocomplete, {
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please']
}), {
disableLifecycleMethods: true
});
var options = _map(findTypes(wrapper.find(DropMenu).props(), DropMenu.Option), 'props');
assert.equal('Portland', options[0].children);
assert.equal('portal', options[1].children);
assert.equal('porridge', options[2].children);
assert.equal('potent', options[3].children);
assert.equal('please', options[4].children);
});
});
describe('value', function () {
var wrapper;
var rootMountNode;
beforeEach(function () {
rootMountNode = document.createElement('div');
document.body.appendChild(rootMountNode);
});
afterEach(function () {
if (wrapper) {
wrapper.unmount();
}
document.body.removeChild(rootMountNode);
});
it('should set the text value of the input', function () {
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
value: "Portland"
}), {
attachTo: rootMountNode
});
var inputDOMNode = document.querySelector('.lucid-Autocomplete-Control-input');
assert.equal(inputDOMNode.value, 'Portland', 'input value must match prop value');
});
it('should change the text value of the input when the prop changes', function () {
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
value: "Portland"
}), {
attachTo: rootMountNode
});
wrapper.setProps(_objectSpread(_objectSpread({}, wrapper.props()), {}, {
value: 'Boston'
}));
var inputDOMNode = document.querySelector('.lucid-Autocomplete-Control-input');
assert.equal(inputDOMNode.value, 'Boston', 'input value must match bew prop value');
});
});
describe('DropMenu', function () {
it('should pass thru all DropMenu props to the underlying DropMenu', function () {
var explicitDropMenuProps = {
isExpanded: true,
// direction: 'up',
focusedIndex: 2
};
var wrapper = shallow( /*#__PURE__*/React.createElement(Autocomplete, {
DropMenu: explicitDropMenuProps
}), {
disableLifecycleMethods: true
});
var dropMenuProps = wrapper.find('DropMenu').props();
_forEach(explicitDropMenuProps, function (value, key) {
assert(_isEqual(dropMenuProps[key], value));
});
});
});
describe('onChange', function () {
var wrapper;
var rootMountNode;
beforeEach(function () {
rootMountNode = document.createElement('div');
document.body.appendChild(rootMountNode);
});
afterEach(function () {
if (wrapper) {
wrapper.unmount();
}
document.body.removeChild(rootMountNode);
});
describe('suggestion', function () {
/* eslint-disable no-console */
var error;
beforeEach(function () {
error = console.error;
console.error = jest.fn();
});
afterEach(function () {
console.error = error;
});
it('should be called when a suggestion is selected from the menu', function () {
var onChange = sinon.spy();
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
onChange: onChange,
DropMenu: {
isExpanded: true
},
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please'],
testProp: 'foo'
}));
var menuDOMNode = document.querySelector('.lucid-ContextMenu-FlyOut .lucid-DropMenu-option-container');
menuDOMNode.children[2].click();
assert(onChange.called);
var _onChange$lastCall$ar = _slicedToArray(onChange.lastCall.args, 2),
textValue = _onChange$lastCall$ar[0],
_onChange$lastCall$ar2 = _onChange$lastCall$ar[1],
props = _onChange$lastCall$ar2.props,
event = _onChange$lastCall$ar2.event;
assert.equal(textValue, 'porridge');
assert(props);
assert.equal(props.testProp, 'foo');
assert(event);
expect(console.error).toHaveBeenCalledTimes(1);
});
it('should be called when user types into the text box', function () {
var onChange = sinon.spy();
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
onChange: onChange,
testProp: 'foo'
}), {
attachTo: rootMountNode
});
var inputDOMNode = document.querySelector('.lucid-Autocomplete-Control-input'); // set the input value and dispatch an `input` event
inputDOMNode.value = 'aaa';
var inputEvent = document.createEvent('Event');
inputEvent.initEvent('input', true, true);
inputDOMNode.dispatchEvent(inputEvent);
assert(onChange.called, 'onChange must be called');
var _onChange$lastCall$ar3 = _slicedToArray(onChange.lastCall.args, 2),
textValue = _onChange$lastCall$ar3[0],
_onChange$lastCall$ar4 = _onChange$lastCall$ar3[1],
props = _onChange$lastCall$ar4.props,
event = _onChange$lastCall$ar4.event;
assert.equal(textValue, 'aaa', 'value must match input');
assert(props, 'props must be passed');
assert.equal(props.testProp, 'foo', 'aditional props must be included');
assert(event, 'event must be passed');
});
/* eslint-enable no-console */
});
});
describe('onSelect', function () {
var wrapper;
afterEach(function () {
if (wrapper) {
wrapper.unmount();
}
});
it('should be called when a suggestion is selected from the menu', function () {
var onSelect = sinon.spy();
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
onSelect: onSelect,
DropMenu: {
isExpanded: true
},
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please'],
testProp: 'foo'
}));
var menuDOMNode = document.querySelector('.lucid-ContextMenu-FlyOut .lucid-DropMenu-option-container');
menuDOMNode.children[2].click();
assert(onSelect.called, 'onSelect must be called');
var _onSelect$lastCall$ar = _slicedToArray(onSelect.lastCall.args, 2),
optionIndex = _onSelect$lastCall$ar[0],
_onSelect$lastCall$ar2 = _onSelect$lastCall$ar[1],
props = _onSelect$lastCall$ar2.props,
event = _onSelect$lastCall$ar2.event;
assert.equal(optionIndex, 2, 'optionIndex must be accurate');
assert(props, 'props must be passed');
assert.equal(props.testProp, 'foo', 'aditional props must be included');
assert(event, 'event must be passed');
});
});
describe('onExpand', function () {
var wrapper;
var rootMountNode;
beforeEach(function () {
rootMountNode = document.createElement('div');
document.body.appendChild(rootMountNode);
});
afterEach(function () {
if (wrapper && wrapper.exists()) {
wrapper.unmount();
}
document.body.removeChild(rootMountNode);
});
it('should be called when the input value changes to a non-empty value', function () {
var onExpand = sinon.spy();
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
onExpand: onExpand,
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please'],
testProp: 'foo'
}), {
attachTo: rootMountNode
});
var inputDOMNode = document.querySelector('.lucid-Autocomplete-Control-input'); // set the input value and dispatch an `input` event
inputDOMNode.value = 'aaa';
var inputEvent = document.createEvent('Event');
inputEvent.initEvent('input', true, true);
inputDOMNode.dispatchEvent(inputEvent);
assert(onExpand.called, 'onExpand must be called');
var _onExpand$lastCall$ar = _slicedToArray(onExpand.lastCall.args, 1),
_onExpand$lastCall$ar2 = _onExpand$lastCall$ar[0],
props = _onExpand$lastCall$ar2.props,
event = _onExpand$lastCall$ar2.event;
assert(props, 'props must be passed');
assert.equal(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', function () {
var onExpand = sinon.spy();
var wrapper = shallow( /*#__PURE__*/React.createElement(Autocomplete, {
onExpand: onExpand,
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please'],
testProp: 'foo',
DropMenu: {
isExpanded: false
}
}), {
disableLifecycleMethods: true
});
wrapper.find('.lucid-Autocomplete-Control-input').simulate('keydown', {
keyCode: KEYCODE.ArrowDown,
stopPropagation: _noop
});
assert(onExpand.called, 'onExpand must be called');
var _onExpand$lastCall$ar3 = _slicedToArray(onExpand.lastCall.args, 1),
_onExpand$lastCall$ar4 = _onExpand$lastCall$ar3[0],
props = _onExpand$lastCall$ar4.props,
event = _onExpand$lastCall$ar4.event;
assert(props, 'props must be passed');
assert.equal(props.testProp, 'foo', 'aditional props must be included');
assert(event, 'event must be passed');
});
it('should be called when the control input is clicked', function () {
var onExpand = sinon.spy();
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
onExpand: onExpand,
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please'],
testProp: 'foo'
}), {
attachTo: rootMountNode
});
wrapper.find('.lucid-Autocomplete-Control-input').simulate('click');
assert(onExpand.called, 'onExpand must be called');
var _onExpand$lastCall$ar5 = _slicedToArray(onExpand.lastCall.args, 1),
_onExpand$lastCall$ar6 = _onExpand$lastCall$ar5[0],
props = _onExpand$lastCall$ar6.props,
event = _onExpand$lastCall$ar6.event;
assert(props, 'props must be passed');
assert.equal(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', function () {
var onExpand = sinon.spy();
wrapper = mount( /*#__PURE__*/React.createElement(Autocomplete, {
onExpand: onExpand,
suggestions: ['Portland', 'portal', 'porridge', 'potent', 'please'],
testProp: 'foo',
DropMenu: {
isExpanded: false
}
}), {
attachTo: rootMountNode
});
wrapper.find('.lucid-Autocomplete-Control').simulate('click');
assert(onExpand.called, 'onExpand must be called');
var _onExpand$lastCall$ar7 = _slicedToArray(onExpand.lastCall.args, 1),
_onExpand$lastCall$ar8 = _onExpand$lastCall$ar7[0],
props = _onExpand$lastCall$ar8.props,
event = _onExpand$lastCall$ar8.event;
assert(props, 'props must be passed');
assert.equal(props.testProp, 'foo', 'aditional props must be included');
assert(event, 'event must be passed');
});
});
});
});