// These tests are functional simulations of
// user interaction, using syn.js. For more information:
//
// @see http://v3.javascriptmvc.com/docs.html#&who=syn
// @see http://bitovi.com/blog/2010/07/syn-a-standalone-synthetic-event-library.html
describe('Interaction', function() {
describe('dropdown', function() {
it_n('should keep dropdown open after selection made if closeAfterSelect: false', function(done) {
var test = setup_test('AB_Multi',{});
click(test.instance.control, function() {
click($('[data-value=a]', test.instance.dropdown_content), function() {
expect(test.instance.isOpen).to.be.equal(true);
expect(test.instance.isFocused).to.be.equal(true);
done();
});
});
});
it_n('should keep dropdown open when clicking on dropdown if dropdownParent=body', function(done) {
var test = setup_test('AB_Multi',{dropdownParent:'body'});
click(test.instance.control, function() {
click($('[data-value=a]', test.instance.dropdown_content), function() {
expect(test.instance.isOpen).to.be.equal(true);
expect(test.instance.isFocused).to.be.equal(true);
done();
});
});
});
it_n('should reopen dropdown if clicked after being closed by closeAfterSelect: true', function(done) {
var test = setup_test('AB_Multi',{closeAfterSelect: true});
click(test.instance.control, function() {
click($('[data-value=a]', test.instance.dropdown_content), function() {
assert.equal(test.instance.isOpen, false, 'should be closed after select');
assert.equal(test.instance.isFocused, true, 'should be closed w/ focus after select');
click(test.instance.control, function () {
assert.equal(test.instance.isOpen, true, 'should be open after click');
assert.equal(test.instance.isFocused, true, 'should be focused after click');
done();
});
});
});
});
it_n('should close dropdown after selection made if closeAfterSelect: true and in single mode' , function(done) {
var test = setup_test('AB_Single',{closeAfterSelect: true});
click(test.instance.control, function() {
expect(test.instance.isOpen).to.be.equal(true);
click($('[data-value=a]', test.instance.dropdown_content), function() {
expect(test.instance.isOpen).to.be.equal(false);
done();
});
});
});
it_n('should blur dropdown after selection made if closeAfterSelect: true and in single mode' , function(done) {
var test = setup_test('AB_Single',{closeAfterSelect: true});
click(test.instance.control, function() {
expect(test.instance.isFocused).to.be.equal(true);
click($('[data-value=a]', test.instance.dropdown_content), function() {
expect(test.instance.isFocused).to.be.equal(false);
done();
});
});
});
it_n('should close dropdown and clear active items after [escape] key press', async () => {
var test = setup_test('AB_Multi',{items:['a']});
await asyncClick(test.instance.control);
test.instance.setActiveItem(test.instance.getItem('a'));
assert.equal( test.instance.isOpen, true, 'not open' );
assert.equal( test.instance.items.length, 1 , 'should have 1 item' );
assert.equal( test.instance.activeItems.length, 1 , 'should 1 active item' );
await asyncType('[escape]', test.instance.control_input);
assert.equal( test.instance.isOpen, false, 'not closed' );
assert.equal( test.instance.activeItems.length, 0 , 'not cleared' );
assert.equal( test.instance.control_input.value,'','should clear control_input');
});
it_n('should close dropdown and clear control_input after [escape] key press', async () => {
var test = setup_test('AB_Multi',{items:['a']});
await asyncClick(test.instance.control);
await asyncType('b', test.instance.control_input);
assert.equal( test.instance.isOpen, true, 'not open' );
assert.equal( test.instance.control_input.value,'b','should type "b"');
await asyncType('[escape]', test.instance.control_input);
assert.equal( test.instance.isOpen, false, 'not closed' );
assert.equal( test.instance.control_input.value,'','should clear control_input');
});
it_n('should change activeOption with [down] and [up] keypress', function(done) {
var test = setup_test(`
`);
click(test.instance.control, function() {
assert.equal( test.instance.activeOption.dataset.value, 'a', 'activeOption should be "a" to start');
syn.type('[down]', test.instance.control_input, function() {
assert.equal( test.instance.activeOption.dataset.value, 'b', 'activeOption should be changed to "b"');
syn.type('[up]', test.instance.control_input, function() {
assert.equal( test.instance.activeOption.dataset.value, 'a', 'activeOption should be changed back to "a"');
done();
});
});
});
});
it_n('should not close dropdown when clicking on dropdown header', function(done) {
var select = ``;
var test = setup_test(select,{
render:{
'optgroup_header': function(data, escape) {
return '';
},
}
});
click(test.instance.control, function() {
expect(test.instance.isOpen).to.be.equal(true);
var header = test.instance.dropdown.querySelector('.optgroup-header')
click(header,function(){
expect(test.instance.isOpen).to.be.equal(true);
done();
});
});
});
});
describe('clicking control', function() {
it_n('should toggle focus', function(done) {
var test = setup_test('AB_Single_Long',{
items: ['p']
});
click(test.instance.control, function() {
assert.equal(test.instance.isFocused,true);
assert.equal(test.instance.isOpen,true);
expect( isVisible(test.instance.dropdown) ).to.be.equal(true);
assert.equal( test.instance.activeOption.dataset.value,'p','activeOption should be "p"');
assert.isAbove(test.instance.dropdown_content.scrollTop, 0, 'dropdown should be scrolled to activeOption');
click(test.instance.control, function() {
assert.equal(test.instance.isFocused,false);
assert.equal(test.instance.isOpen,false);
done();
});
});
});
it_n('should toggle focus clicking item in single mode control', function(done) {
var test = setup_test('AB_Single',{
items:['a']
});
var itema = test.instance.getItem('a');
click(itema, function() {
assert.equal(test.instance.isFocused,true);
assert.equal(test.instance.isOpen,true);
click(itema, function() {
assert.equal(test.instance.isFocused,false);
assert.equal(test.instance.isOpen,false);
done();
});
});
});
it_n('should remain open but clear active item on click', function(done) {
var test = setup_test('AB_Multi');
click(test.instance.control, () => {
test.instance.addItem('a');
test.instance.setActiveItem(test.instance.getItem('a'));
assert.equal( test.instance.activeItems.length, 1);
assert.equal( test.instance.isOpen, true);
click(test.instance.control_input, () => {
assert.equal( test.instance.activeItems.length, 0);
assert.equal( test.instance.isOpen, true);
assert.equal( test.instance.isFocused, true);
done();
});
});
});
});
describe('clicking label', function() {
it_n('should give focus to select', function(done) {
var test = setup_test(``);
var label = document.getElementById('select-label');
label.click();
setTimeout(()=>{
expect(test.instance.isFocused).to.be.equal(true);
done();
},1);
});
it_n('should give focus to input', function(done) {
var test = setup_test(`
`);
var label = document.getElementById('input-label');
label.click();
setTimeout(()=>{
expect(test.instance.isFocused).to.be.equal(true);
done();
},1);
});
});
describe('selecting option', function() {
it_n('should select option when clicked', async () =>{
var test = setup_test('
');
var clicked = false;
document.getElementById('test-wrap').addEventListener('click',()=>{
clicked = true;
});
await asyncClick(test.instance.control);
assert.equal(test.instance.input.querySelectorAll('option').length, 3,'should keep original options');
assert.isTrue( test.instance.isOpen, 'Should be open' );
var option_before = test.instance.input.querySelector('option[value="b"]');
await asyncClick( test.instance.dropdown.querySelector('[data-value="b"]') );
var option_after = test.instance.input.querySelector('option[value="b"]');
assert.equal(option_before, option_after,'should not recreate original a';
var option_b = document.createElement('option');
option_b.value = "b";
option_b.textContent = "b";
option_b.selected = true;
select.append(option_b);
var test = setup_test(select);
//test.instance.addItem('a');
//test.instance.addItem('b');
assert.equal( test.instance.items.length, 2 ,'items.length should = 2' );
assert.equal( Array.from(test.instance.input.options).filter(option => option.getAttribute('selected')).length, 2,'getAttribute(selected).length should = 2' );
assert.equal( Array.from(test.instance.input.options).filter(option => option.selected).length, 2,'option.selected.length should = 2' );
click(test.instance.control, function() {
syn.type('\b', test.instance.control_input, function() {
var option_after = test.instance.input.querySelector('option[value="b"]');
assert.equal( test.instance.items.length, 1 );
assert.equal( test.instance.items[0], 'a' );
assert.equal( option_b, option_after, 'should not remove original ' );
assert.equal( Array.from(test.instance.input.options).filter(option => option.getAttribute('selected') ).length, 1, 'getAttribute(selected).length should = 1' );
assert.equal( Array.from(test.instance.input.options).filter(option => option.selected).length, 1, 'option.selected.length should = 1' );
syn.type('\b', test.instance.control_input, function() {
var option_after = test.instance.input.querySelector('option[value="b"]');
assert.equal( test.instance.items.length, 0 );
assert.equal( option_b, option_after, 'should not remove original ' );
assert.equal( Array.from(test.instance.input.options).filter(option => option.getAttribute('selected') ).length, 0, 'getAttribute(selected).length should = 0' );
assert.equal( Array.from(test.instance.input.options).filter(option => option.selected).length, 0, 'option.selected.length should = 0' );
done();
});
});
});
});
it_n('should remove first item when left then backspace pressed', function(done) {
var test = setup_test('AB_Multi');
test.instance.addItem('a');
test.instance.addItem('b');
assert.equal( test.instance.items.length, 2 );
click(test.instance.control, function() {
syn.type('[left]\b', test.instance.control_input, function() {
assert.equal( test.instance.items.length, 1 );
assert.equal( test.instance.items[0], 'b' );
done();
});
});
});
it_n('should prevent typing when there are active items', function(done) {
var test = setup_test('AB_Multi');
test.instance.addItem('a');
click(test.instance.control, function() {
test.instance.setActiveItem(test.instance.getItem('a'));
syn.type('a', test.instance.control_input, function() {
assert.equal( test.instance.control_input.value, '' );
done();
});
});
});
it_n('should create item on [enter] when option_create template is null', function(done) {
var test = setup_test('AB_Single',{
create:true,
render:{
no_results: null,
option_create: null,
}
});
click(test.instance.control, function() {
syn.type('abcd[enter]',test.instance.control_input,function(){
assert.equal( test.instance.items.length, 1);
assert.equal( test.instance.items[0], 'abcd');
done();
});
});
});
it_n('should not create item on [tab] when option_create template is null', function(done) {
var test = setup_test('AB_Multi',{
create:true,
render:{
no_results: null,
option_create: null,
}
});
click(test.instance.control, function() {
syn.type('abcd[tab]',test.instance.control_input,function(){
assert.equal( test.instance.items.length, 0);
done();
});
});
});
});
describe('blurring the input', function() {
it_n('should close dropdown when createOnBlur is true', function(done) {
var test = setup_test('AB_Multi',{
createOnBlur: true,
create: function(value){
return {
value: value,
text: value
};
}
});
click(test.instance.control, function() {
syn
.type('fooo', test.instance.control_input)
.delay(0, function() {
expect(test.instance.isOpen).to.be.equal(true);
expect( isVisible(test.instance.dropdown) ).to.be.equal(true);
syn
.click(document.body)
.delay(5, function() {
expect(test.instance.isOpen).to.be.equal(false);
expect( isVisible(test.instance.dropdown) ).to.be.equal(false);
done();
});
});
});
});
});
describe('creating items',function(){
it_n('should create item when clicking on create option', function(done) {
var test = setup_test('AB_Multi', {create: true});
// 1) focus on control
click(test.instance.control, function() {
// 2) type "d"
syn.type('d', test.instance.control_input, function() {
// 3) click on create option to create
var create_option = test.instance.dropdown.querySelector('.create');
click(create_option,function(){
expect(test.instance.items[0]).to.be.equal('d');
done();
});
});
});
});
it_n('create item should be focused when addPrecedence=true', function(done) {
var test = setup_test('AB_Multi', {create: true,addPrecedence: true});
click(test.instance.control, function() {
syn.type('b', test.instance.control_input, function() {
assert.equal( test.instance.activeOption.classList.contains('create'), true);
done();
});
});
});
it_n('create item should be focused when addPrecedence=false (default)', function(done) {
var test = setup_test('AB_Multi', {create: true});
click(test.instance.control, function() {
syn.type('b', test.instance.control_input, function() {
assert.equal( test.instance.activeOption.classList.contains('create'), false);
done();
});
});
});
it_n('should focus create option with [up] keypress', function(done) {
var test = setup_test('',{create:true});
click(test.instance.control, function() {
assert.equal( test.instance.activeOption.dataset.value, 'aa', 'activeOption should be "aa" to start');
syn.type('a', test.instance.control_input, function() {
assert.equal( test.instance.activeOption.dataset.value, 'aa', 'activeOption should still be "aa"');
syn.type('[up]', test.instance.control_input, function() {
assert.equal( test.instance.activeOption.classList.contains('create'), true, 'activeOption should be create option');
syn.type('[enter]', test.instance.control_input, function() {
assert.equal(test.instance.items[0],'a','should create "a"');
done();
});
});
});
});
});
describe('filtering created items', function() {
var text = 'abc';
function execFilterTest(filter, done, expectation) {
var test = setup_test('', {create: true, createFilter: filter});
var instance = test.instance;
click(instance.control, function() {
syn
.type(text, instance.control_input)
.type(instance.settings.delimiter, instance.control_input )
.delay(0, function() {
expectation(instance);
done();
})
});
}
function execFilterTests(heading, filters, expectation) {
for (var i = 0; i < filters.length; i++) {
(function(filter) {
it_n(heading, function(done) {
execFilterTest(filter, done, expectation);
});
})(filters[i]);
}
}
execFilterTests('should add an item normally if there is no createFilter', [undefined, null, ''], function(instance) {
expect(instance.getItem(text)).to.be.ok;
});
execFilterTests('should add an item if the input matches the createFilter', ['a', /a/, function() { return true; }], function(instance) {
expect(instance.getItem(text)).to.be.ok;
});
execFilterTests(
'should not add an item or display the create label if the input does not match the createFilter (A)',
['foo', /foo/, function() { return false; }],
function(instance) {
expect(instance.getItem(text)).to.be.equal(null);
}
);
execFilterTests('should not add an item or display the create label if the input does not match the createFilter (B)', ['foo', /foo/, function() { return false; }], function(instance) {
expect($(instance.dropdown_content).filter('.create').length).to.be.equal(0);
});
});
});
describe('locking', function() {
it_n('typing should not show dropdown when locked', function(done) {
var test = setup_test('AB_Multi',{});
test.instance.lock();
syn.type('a', test.instance.control_input, function() {
expect(test.instance.isOpen).to.be.equal(false);
done();
});
});
});
describe('openOnFocus', function() {
it_n('only open after arrow down when openOnFocus=false', function(done) {
var test = setup_test('AB_Single',{
openOnFocus: false,
});
click(test.instance.control, function(){
expect(test.instance.isOpen).to.be.equal(false);
syn.type('[down]', test.instance.control_input, function() {
expect(test.instance.isOpen).to.be.equal(true);
done();
});
});
});
it_n('[enter] should not add item when dropdown isn\'t open', function(done) {
var test = setup_test('AB_Multi',{
openOnFocus: false,
});
click(test.instance.control, function(){
expect(test.instance.isOpen).to.be.equal(false);
syn.type('[enter]', test.instance.control_input, function() {
expect(test.instance.items.length).to.be.equal(0);
done();
});
});
});
});
describe('paste', function() {
it_n('create new items on paste', function(done) {
var test = setup_test('AB_Multi',{
create:true,
maxItems: 2,
});
const ev = new Event('input');
click(test.instance.control, function(){
assert.equal( test.instance.items.length, 0);
test.instance.control_input.value = 'a-new,b-new';
test.instance.onPaste(ev);
setTimeout(()=>{
assert.equal( test.instance.items.length, 2);
test.instance.control_input.value = 'c-new,d-new';
test.instance.onPaste(ev);
setTimeout(()=>{
assert.equal( test.instance.items.length, 2,'should not paste when full');
done();
},10);
},10);
});
});
});
it_n('shadow root',async ()=>{
setup_test('');
function styleText(href){
var sheet = document.querySelector(`link[href*="${href}"]`).sheet;
return Array.from(sheet.cssRules).map(rule => rule.cssText).join(' ');
}
var wrapper = document.getElementById('shadow-wrapper');
var select = document.getElementById('select-tags');
var shadowRoot = wrapper.attachShadow({mode: 'open'});
var style = document.createElement('style');
style.textContent = styleText('tom-select.default.css');
shadowRoot.appendChild(style);
shadowRoot.appendChild(select.parentNode.removeChild(select));
var instance = new TomSelect(select);
await asyncClick(instance.control_input);
assert.isTrue(instance.isOpen,'should be open');
});
});