react-select-extended
Version:
A Select control built with and for ReactJS
275 lines (240 loc) • 8.78 kB
JavaScript
/* global describe, it, beforeEach */
/* eslint react/jsx-boolean-value: 0 */
// Copied from Async-test verbatim; may need to be reevaluated later.
var jsdomHelper = require('../testHelpers/jsdomHelper');
jsdomHelper();
var unexpected = require('unexpected');
var unexpectedDom = require('unexpected-dom');
var unexpectedReact = require('unexpected-react');
var expect = unexpected
.clone()
.installPlugin(unexpectedDom)
.installPlugin(unexpectedReact);
var React = require('react');
var ReactDOM = require('react-dom');
var TestUtils = require('react-addons-test-utils');
var Select = require('../src');
describe('Creatable', () => {
let creatableInstance, creatableNode, filterInputNode, innerSelectInstance, renderer;
beforeEach(() => renderer = TestUtils.createRenderer());
const defaultOptions = [
{ value: 'one', label: 'One' },
{ value: 'two', label: '222' },
{ value: 'three', label: 'Three' },
{ value: 'four', label: 'AbcDef' }
];
function createControl (props = {}) {
props.options = props.options || defaultOptions;
creatableInstance = TestUtils.renderIntoDocument(
<Select.Creatable {...props} />
);
creatableNode = ReactDOM.findDOMNode(creatableInstance);
innerSelectInstance = creatableInstance.select;
findAndFocusInputControl();
};
function findAndFocusInputControl () {
filterInputNode = creatableNode.querySelector('input');
if (filterInputNode) {
TestUtils.Simulate.focus(filterInputNode);
}
};
function typeSearchText (text) {
TestUtils.Simulate.change(filterInputNode, { target: { value: text } });
};
it('should render a decorated Select (with passed through properties)', () => {
createControl({
inputProps: {
className: 'foo'
}
});
expect(creatableNode.querySelector('.Select-input'), 'to have attributes', {
class: ['foo']
});
});
it('should add a placeholder "create..." prompt when filter text is entered that does not match any existing options', () => {
createControl();
typeSearchText('foo');
expect(creatableNode.querySelector('.Select-create-option-placeholder'), 'to have text', Select.Creatable.promptTextCreator('foo'));
});
it('should not show a "create..." prompt if current filter text is an exact match for an existing option', () => {
createControl({
isOptionUnique: () => false
});
typeSearchText('existing');
expect(creatableNode.querySelector('.Select-menu-outer').textContent, 'not to equal', Select.Creatable.promptTextCreator('existing'));
});
it('should filter the "create..." prompt using both filtered options and currently-selected options', () => {
let isOptionUniqueParams;
createControl({
filterOptions: () => [
{ value: 'one', label: 'One' }
],
isOptionUnique: (params) => {
isOptionUniqueParams = params;
},
multi: true,
options: [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
],
value: [
{ value: 'three', label: 'Three' }
]
});
typeSearchText('test');
const { options } = isOptionUniqueParams;
const values = options.map(option => option.value);
expect(values, 'to have length', 2);
expect(values, 'to contain', 'one');
expect(values, 'to contain', 'three');
});
it('should guard against invalid values returned by filterOptions', () => {
createControl({
filterOptions: () => null
});
typeSearchText('test');
});
it('should not show a "create..." prompt if current filter text is not a valid option (as determined by :isValidNewOption prop)', () => {
createControl({
isValidNewOption: () => false
});
typeSearchText('invalid');
expect(creatableNode.querySelector('.Select-menu-outer').textContent, 'not to equal', Select.Creatable.promptTextCreator('invalid'));
});
it('should create (and auto-select) a new option when placeholder option is clicked', () => {
let selectedOption;
const options = [];
createControl({
onChange: (option) => selectedOption = option,
options
});
typeSearchText('foo');
TestUtils.Simulate.mouseDown(creatableNode.querySelector('.Select-create-option-placeholder'));
expect(options, 'to have length', 1);
expect(options[0].label, 'to equal', 'foo');
expect(selectedOption, 'to be', options[0]);
});
it('should create (and auto-select) a new option when ENTER is pressed while placeholder option is selected', () => {
let selectedOption;
const options = [];
createControl({
onChange: (option) => selectedOption = option,
options,
shouldKeyDownEventCreateNewOption: () => true
});
typeSearchText('foo');
TestUtils.Simulate.keyDown(filterInputNode, { keyCode: 13 });
expect(options, 'to have length', 1);
expect(options[0].label, 'to equal', 'foo');
expect(selectedOption, 'to be', options[0]);
});
it('should not create a new option if the placeholder option is not selected but should select the focused option', () => {
const options = [{ label: 'One', value: 1 }];
createControl({
options,
});
typeSearchText('on'); // ['Create option "on"', 'One']
TestUtils.Simulate.keyDown(filterInputNode, { keyCode: 40, key: 'ArrowDown' }); // Select 'One'
TestUtils.Simulate.keyDown(filterInputNode, { keyCode: 13 });
expect(options, 'to have length', 1);
});
it('should remove the new option after closing on selecting option', () => {
createControl();
typeSearchText('9');
TestUtils.Simulate.keyDown(filterInputNode, { keyCode: 40, key: 'ArrowDown' });
TestUtils.Simulate.keyDown(filterInputNode, { keyCode: 13 });
expect(creatableInstance.inputValue, 'to equal', '');
});
it('should remove the new option after closing on escape', () => {
createControl();
typeSearchText('9');
TestUtils.Simulate.keyDown(filterInputNode, { keyCode: 27 });
expect(creatableInstance.inputValue, 'to equal', '');
});
it('should remove the new option after closing on blur', () => {
createControl();
typeSearchText('9');
TestUtils.Simulate.blur(filterInputNode);
expect(creatableInstance.inputValue, 'to equal', '');
});
it('should allow a custom select type to be rendered via the :children property', () => {
let childProps;
createControl({
children: (props) => {
childProps = props;
return <div>faux select</div>;
}
});
expect(creatableNode.textContent, 'to equal', 'faux select');
expect(childProps.allowCreate, 'to equal', true);
});
it('default :children function renders a Select component', () => {
createControl();
expect(creatableNode.className, 'to contain', 'Select');
});
it('default :isOptionUnique function should do a simple equality check for value and label', () => {
const options = [
newOption('foo', 1),
newOption('bar', 2),
newOption('baz', 3)
];
function newOption (label, value) {
return { label, value };
};
function test (option) {
return Select.Creatable.isOptionUnique({
labelKey: 'label',
option,
options,
valueKey: 'value'
});
};
expect(test(newOption('foo', 0)), 'to be', false);
expect(test(newOption('qux', 1)), 'to be', false);
expect(test(newOption('qux', 4)), 'to be', true);
expect(test(newOption('Foo', 11)), 'to be', true);
});
it('default :isValidNewOption function should just ensure a non-empty string is provided', () => {
function test (label) {
return Select.Creatable.isValidNewOption({ label });
};
expect(test(''), 'to be', false);
expect(test('a'), 'to be', true);
expect(test(' '), 'to be', true);
});
it('default :newOptionCreator function should create an option with a :label and :value equal to the label string', () => {
const option = Select.Creatable.newOptionCreator({
label: 'foo',
labelKey: 'label',
valueKey: 'value'
});
expect(option.className, 'to equal', 'Select-create-option-placeholder');
expect(option.label, 'to equal', 'foo');
expect(option.value, 'to equal', 'foo');
});
it('default :shouldKeyDownEventCreateNewOption function should accept TAB, ENTER, and comma keys', () => {
function test (keyCode) {
return Select.Creatable.shouldKeyDownEventCreateNewOption({ keyCode });
};
expect(test(9), 'to be', true);
expect(test(13), 'to be', true);
expect(test(188), 'to be', true);
expect(test(1), 'to be', false);
});
it('default :onInputKeyDown should run user provided handler.', (done) => {
createControl({ onInputKeyDown: event => done() });
return creatableInstance.onInputKeyDown({ keyCode: 97 });
});
describe('.focus()', () => {
beforeEach(() => {
createControl({});
TestUtils.Simulate.blur(filterInputNode);
});
it('focuses the search input', () => {
expect(filterInputNode, 'not to equal', document.activeElement);
creatableInstance.focus();
expect(filterInputNode, 'to equal', document.activeElement);
});
});
});
;