virtual-select-plugin
Version:
A javascript plugin for dropdown with virtual scroll
778 lines (609 loc) • 19.8 kB
text/typescript
/** cSpell:ignore vscomp */
// // // // //
// // // // // Get started page
// // // // //
describe('Open page', () => {
it('opened', () => {
cy.visit('get-started');
});
});
describe('Open Get Started page for Dropdowns interaction test', () => {
const idSingle = 'single-select'
const idMultiple = 'multiple-select'
it('open the single-select dropdown', () => {
cy.open(idSingle);
cy.getVs(idSingle).find('.vscomp-ele-wrapper').should('not.have.class', 'closed');
});
it('open the multiple-select dropdown clicking directly in the DOM element', () => {
cy.getVs(idMultiple).find('.vscomp-toggle-button').click();
cy.getVs(idMultiple).find('.vscomp-ele-wrapper').should('not.have.class', 'closed');
});
it('should close single-select when opening single-select and multiple-select keep opened', () => {
cy.getVs(idSingle).find('.vscomp-ele-wrapper').should('have.class', 'closed');
cy.getVs(idMultiple).find('.vscomp-ele-wrapper').should('not.have.class', 'closed');
});
});
describe('Open Get Started page for Dropdowns interaction test clicking outside', () => {
const idSingle = 'single-select'
const idMultiple = 'multiple-select'
it('open the single-select dropdown', () => {
cy.open(idSingle);
cy.getVs(idSingle).find('.vscomp-ele-wrapper').should('not.have.class', 'closed');
});
it('click outside to close the single-select dropdown', () => {
cy.get('body').click(10, 10); // Click at coordinates 10,10
cy.getVs(idSingle).find('.vscomp-ele-wrapper').should('have.class', 'closed');
});
it('open the multiple-select dropdown', () => {
cy.open(idMultiple);
cy.getVs(idMultiple).find('.vscomp-ele-wrapper').should('not.have.class', 'closed');
});
it('click outside to close the multiple-select dropdown', () => {
cy.get('body').click(10, 10); // Click at coordinates 10,10
cy.getVs(idMultiple).find('.vscomp-ele-wrapper').should('have.class', 'closed');
});
});
// // // // //
// // // // // Examples page
// // // // //
describe('Open page', () => {
it('opened', () => {
cy.visit('examples');
});
});
describe('Default dropdown', () => {
const id = 'single-select';
it('go to section', () => {
cy.goToSection('Default dropdown');
});
it('check clear button not exist', () => {
cy.getVs(id).checkClearButton(false);
});
it('select available option', () => {
cy.open(id).selectOption(2).hasValueText('Option 2');
});
it('scroll and select option', () => {
cy.open(id).scrollOptions(600).selectOption(17).hasValueText('Option 17');
});
it('check clear button exist', () => {
cy.getVs(id).checkClearButton(true);
});
it('reset value', () => {
cy.resetValue(id);
});
});
describe('With search box', () => {
const id = 'single-search-select';
it('go to section', () => {
cy.goToSection('With search box');
});
it('search and select available option', () => {
cy.open(id).search('Option 234').selectOption(2340).hasValueText('Option 2340');
});
it('search, scroll, and select option', () => {
cy.open(id).search('Option 234').scrollOptions(600).selectOption(23406).hasValueText('Option 23406');
});
it('search wrong text', () => {
cy.open(id).search('Wrong text').hasNoOptions().close();
});
it('reset value', () => {
cy.resetValue(id);
});
});
describe('With search box - Clear search text', () => {
const id = 'single-search-select';
it('go to section', () => {
cy.goToSection('With search box');
});
it('search for a keyword', () => {
cy.open(id).search('Option');
});
it('check that clear button in search does not exists', () => {
cy.getVs(id).checkSearchClearButton(true);
});
it('reset value', () => {
cy.getVs(id).resetSearchValue();
});
it('check that clear button in search exists', () => {
cy.getVs(id).checkSearchClearButton(false);
});
});
describe('Multiple select', () => {
const id = 'sample-multi-select';
it('go to section', () => {
cy.goToSection('Multiple select');
});
it('search and select available option', () => {
cy.open(id)
.search('Option 2340')
.selectOption(2340)
.search('Option 2342')
.selectOption(2342)
.hasValueText('Option 2340, Option 2342');
});
it('search, scroll, and select option', () => {
cy.getVs(id)
.search('Option 987')
.selectOption(9872)
.scrollOptions(400)
.selectOption(98703)
.hasValueText('4 options selected');
});
it('reset value', () => {
cy.resetValue(id);
});
it('select/Unselect all options', () => {
cy.getVs(id).toggleSelectAll().hasValueText('All (100001)').toggleSelectAll().hasValueText('Select');
});
it('select all except one option', () => {
cy.getVs(id).toggleSelectAll().selectOption(3).hasValueText('100000 options selected').close();
});
});
describe('Multiple select without search', () => {
const id = 'multi-select-without-search';
it('go to section', () => {
cy.goToSection('Multiple select without search');
});
it('select/Unselect all options', () => {
cy.open(id).toggleSelectAll(true).hasValueText('All (100001)').toggleSelectAll(true).hasValueText('Select');
});
});
describe('Disabled options', () => {
const id = 'single-disabled-select';
it('go to section', () => {
cy.goToSection('Disabled options');
});
it('select disabled option', () => {
cy.open(id).selectOption(3).hasValueText('Option 3').selectOption(2, { force: true }).hasValueText('Option 3');
});
});
describe('Option group', () => {
const id = 'option-group-select';
it('go to section', () => {
cy.goToSection('Option group');
});
it('select 1 child option', () => {
cy.open(id).selectOption('1-1').hasValueText('Option 1-1').checkOptionGroup('Option group 1', false);
});
it('select all group options', () => {
cy.getVs(id)
.search('1-2')
.selectOption('1-2')
.search('1-3')
.selectOption('1-3')
.hasValueText('3 options selected')
.checkOptionGroup('Option group 1', true);
});
it('unselect/select option group', () => {
cy.getVs(id)
.selectOptionGroup('Option group 1')
.hasValueText('Select')
.selectOptionGroup('Option group 1')
.hasValueText('3 options selected');
});
it('select all options', () => {
cy.getVs(id)
.searchClear()
.toggleSelectAll()
.hasValueText('All (9)')
.checkOptionGroup('Option group 1', true)
.checkOptionGroup('Option group 2', true)
.checkOptionGroup('Option group 3', true);
});
});
describe('Preselect value', () => {
const id = 'preselect-single-select';
it('go to section', () => {
cy.goToSection('Preselect value');
});
it('preselected option', () => {
cy.getVs(id).hasValueText('Option 3');
});
});
describe('Preselect multiple values', () => {
const id = 'preselect-multiple-select';
it('go to section', () => {
cy.goToSection('Preselect multiple values');
});
it('preselected option', () => {
cy.getVs(id).hasValueText('Option 3, Option 4');
});
});
describe('Hide clear button', () => {
const id = 'hide-clear-select';
it('go to section', () => {
cy.goToSection('Hide clear button');
});
it('check clear button not exist before selecting value', () => {
cy.getVs(id).checkClearButton(false);
});
it('select option', () => {
cy.open(id).selectOption(3);
});
it('check clear button not exist after selecting value', () => {
cy.getVs(id).checkClearButton(false);
});
});
describe('Custom width for dropbox', () => {
const id = 'custom-width-select';
it('go to section', () => {
cy.goToSection('Custom width for dropbox');
});
it('check dropbox width', () => {
cy.open(id).checkDropboxWidth(130);
});
});
describe('Allow to add new option', () => {
const id = 'new-option-select';
it('go to section', () => {
cy.goToSection('Allow to add new option');
});
it('add a new option', () => {
cy.open(id).search('Option not exist').selectOption('Option not exist').hasValueText('Option not exist');
});
});
describe('Mark matched term in label', () => {
const id = 'mark-results-select';
it('go to section', () => {
cy.goToSection('Mark matched term in label');
});
it('check marked text', () => {
cy.open(id).search('on 32').hasMarkedText('on 32');
});
});
describe('Showing selected options first', () => {
const id = 'selected-first-select';
it('go to section', () => {
cy.goToSection('Showing selected options first');
});
it('check selected option moved to top', () => {
cy.open(id).scrollOptions(2300).selectOption(28).close();
cy.open(id).checkFirstOption('Option 28');
});
});
describe('Using alias for searching', () => {
const id = 'alias-select';
it('go to section', () => {
cy.goToSection('Showing selected options first');
});
it('search with label', () => {
cy.open(id)
.search('Col')
.checkFirstOption('Colors')
.search('Fru')
.checkFirstOption('Fruits')
.search('Mon')
.checkFirstOption('Months')
.search('Oth')
.checkFirstOption('Others');
});
it('search with alias', () => {
cy.getVs(id)
.search('Ora')
.checkFirstOption('Colors')
.search('App')
.checkFirstOption('Fruits')
.search('Jan')
.checkFirstOption('Months');
});
});
describe('Keep dropbox always open', () => {
const id = 'keep-open-select';
it('go to section', () => {
cy.goToSection('Keep dropbox always open');
});
it('select available option', () => {
cy.getVs(id).selectOption(2).hasValueText('Option 2');
});
it('scroll and select option', () => {
cy.getVs(id).scrollOptions(600).selectOption(17).hasValueText('Option 17');
});
it('reset value', () => {
cy.resetValue(id);
});
});
describe('Maximum values', () => {
const id = 'max-values-select';
it('go to section', () => {
cy.goToSection('Maximum values');
});
it('select less than allowed options', () => {
cy.open(id).selectOption([2, 4]).hasValueText('2 / 4 options selected');
});
it('select more than allowed options', () => {
cy.getVs(id).scrollOptions(1800).selectOption([46, 50, 49]).hasValueText('4 / 4 options selected');
});
});
describe('Label with description', () => {
const id = 'with-description-select';
it('go to section', () => {
cy.goToSection('Label with description');
});
it('has description on load', () => {
cy.open(id).checkFirstOption('Option 1 Description 1');
});
it('has description on scroll', () => {
cy.getVs(id).scrollOptions(5000).checkFirstOption('Option 99 Description 99');
});
});
describe('Show dropbox as popup - Clear search text', () => {
const id = 'multiple-show-as-popup-select';
it('go to section', () => {
cy.goToSection('Show dropbox as popup');
});
it('search for a keyword', () => {
cy.open(id).search('Option');
});
it('check clear button exist', () => {
cy.getVs(id).checkClearButtonPopup(true);
});
it('reset value', () => {
cy.getVs(id).resetValuePopup();
});
it('check clear button not exist', () => {
cy.getVs(id).checkClearButton(false);
});
});
describe('Show dropbox as popup - Multiple', () => {
const id = 'multiple-show-as-popup-select';
it('go to section', () => {
cy.goToSection('Show dropbox as popup');
});
it('select options', () => {
cy.open(id)
.search('1')
.selectOption(1)
.search('3')
.selectOption(3)
.search('7')
.selectOption(7)
.hasValueText('Option 1, Option 3, Option 7')
.searchClear();
});
it('dropbox is fixed', () => {
cy.dropboxIsFixed(id);
});
it('close popup', () => {
cy.closePopup(id);
});
});
describe('Show dropbox as popup - Single', () => {
const id = 'single-show-as-popup-select';
it('go to section', () => {
cy.goToSection('Show dropbox as popup');
});
it('select option', () => {
cy.open(id).selectOption(3).hasValueText('Option 3');
});
it('dropbox is fixed', () => {
cy.open(id).dropboxIsFixed(id);
});
it('close popup', () => {
cy.closePopup(id);
});
});
describe('Server search', () => {
const id = 'server-search-select';
it('go to section', () => {
cy.goToSection('Server search');
});
it('search and select', () => {
cy.open(id).search('349').selectOption([2349, 349]).hasValueText('Option 2349, Option 349');
});
});
describe('Show options only on search', () => {
const id = 'options-on-search-select';
it('go to section', () => {
cy.goToSection('Show options only on search');
});
it('empty on load', () => {
cy.open(id).hasNoOptions();
});
it('show options on search', () => {
cy.getVs(id).search('9876').selectOption('49876').hasValueText('Option 49876');
});
});
describe('Add image/icon', () => {
const id = 'with-image-select';
it('go to section', () => {
cy.goToSection('Add image/icon');
});
it('has flag icon on load', () => {
cy.open(id).hasFlagIcon();
});
it('has flag icon on scroll', () => {
cy.getVs(id).scrollOptions(700).hasFlagIcon().parent().contains('Option 16');
});
it('has flag icon on selected item', () => {
cy.open(id).selectOption(16).hasSelectedFlagIcon();
});
});
describe('Show values as tags', () => {
const id = 'show-value-as-tags-select';
it('go to section', () => {
cy.goToSection('Show values as tags');
});
it('select options', () => {
cy.open(id)
.search('3')
.selectOption(3)
.search('7')
.selectOption(7)
.scrollOptions(600)
.search('18')
.selectOption(18)
.search('20')
.selectOption(20)
.hasValueTags(['Option 3', 'Option 7', 'Option 18', 'Option 20'])
});
it('remove selected options', () => {
cy.getVs(id)
.checkValueTagsCount(4)
.removeValueTag('Option 7')
.checkValueTagsCount(3)
.removeValueTag('Option 18')
.checkValueTagsCount(2)
.removeValueTag('Option 20')
.checkValueTagsCount(1)
.removeValueTag('Option 3')
.checkValueTagsCount(0)
.hasValueText('Select')
.close()
});
it('reset value', () => {
const optsList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const vs = cy.open(id);
for (let i = 0; i < optsList.length; i++) {
vs
.search(`Option ${optsList[i]}`)
.selectOption(i+1);
}
vs.checkValueTagsCount(10).resetValue(id)
});
});
describe('Right-to-Left text', () => {
const id = 'direction-rtl-select';
it('go to section', () => {
cy.goToSection('Right-to-Left text');
});
it('options aligned to right', () => {
cy.getDropbox(null, id).find('.vscomp-option').first().should('have.css', 'text-align', 'right');
});
it('select available option', () => {
cy.open(id)
.search(`1`)
.selectOption(1)
.search(`3`)
.selectOption(3)
.hasValueText('Option 1, Option 3');
});
it('value aligned to right', () => {
cy.getVs(id).find('.vscomp-toggle-button').should('have.css', 'direction', 'rtl');
});
});
describe('Disable/Enable', () => {
const id = 'disable-enable';
it('go to section', () => {
cy.goToSection('Disable/Enable');
});
it('disable dropdown', () => {
cy.get('#disable-enable-switch').click();
cy.getVs(id).should('have.attr', 'disabled', 'disabled');
});
it('enable dropdown', () => {
cy.get('#disable-enable-switch').click();
cy.getVs(id).should('not.have.attr', 'disabled', 'disabled');
});
it('select option', () => {
cy.open(id).selectOption(7).hasValueText('Option 7');
});
it('reset value', () => {
cy.resetValue(id);
});
});
describe('Validation', () => {
const id = 'validation-select';
it('go to section', () => {
cy.goToSection('Validation');
});
it('submit without value', () => {
cy.get('#validation-form').find('[type=submit]').click();
cy.getVs(id).find('.vscomp-ele-wrapper').should('have.class', 'has-error');
});
it('submit with value', () => {
cy.open(id).selectOption([3, 5]).close();
cy.get('#validation-form').find('[type=submit]').click();
cy.getVs(id).find('.vscomp-ele-wrapper').should('not.have.class', 'has-error');
});
it('reset dropdown', () => {
cy.resetValue(id);
cy.getVs(id).find('.vscomp-ele-wrapper').should('have.class', 'has-error');
});
it('reset form', () => {
cy.get('#validation-form').find('[type=reset]').click();
cy.getVs(id).find('.vscomp-ele-wrapper').should('not.have.class', 'has-error');
});
});
// // // // //
// // // // // Events page
// // // // //
describe('To verify that the change event is not fired twice when selecting items after a search', () => {
const id = 'sample-select-onchange';
const resId = 'sample-select-changes';
it('go to section', () => {
cy.goToSection('Events');
});
it('select Option 1', () => {
cy.open(id).selectOption(1).hasValueText('Option 1');
cy.get(`#${resId}`).should('have.text', 'Selected = 1 | No.changes = 1');
});
it('search and select 123', () => {
cy.open(id).search('123').selectOption(123).hasValueText('Option 123');
cy.get(`#${resId}`).should('have.text', 'Selected = 123 | No.changes = 2');
});
});
describe('To verify that the reset event is fired', () => {
const id = 'sample-select-reset';
const resId = 'select-reset-res';
it('go to section', () => {
cy.goToSection('Events');
});
it('select Option 1', () => {
cy.open(id).selectOption(1).hasValueText('Option 1');
});
it('check clear button exist', () => {
cy.getVs(id).checkClearButton(true);
});
it('reset value', () => {
cy.resetValue(id);
cy.get(`#${resId}`).should('have.text', 'reset event triggered');
});
});
/**
* Focus management regression tests
*
* 1. When the dropdown is open and the user clicks another focusable element
* (e.g., an input), the focus must stay on that element – the dropdown
* should not steal it back.
* 2. When the dropdown is closed with the Escape key, focus should return to
* the dropdown wrapper to maintain keyboard accessibility.
*/
describe('Validate focus management clicking outside and pressing ESC', () => {
const id = 'sample-select-onchange';
it('go to section', () => {
cy.goToSection('Events');
});
it('keeps focus on external input when clicking outside', () => {
cy.open(id);
// Inject an external input into the DOM for testing
cy.document().then((doc) => {
const input = doc.createElement('input');
input.type = 'text';
input.id = 'external-input';
input.placeholder = 'External input';
input.setAttribute(
'style',
'position:fixed; top:20px; left:20px; z-index:9999;'
);
doc.body.appendChild(input);
});
// Click the external input and verify focus stays there
cy.get('#external-input').click({ force: true }).should('have.focus');
// Verify the dropdown is closed (wrapper has class "closed")
cy.getVs(id).find('.vscomp-ele-wrapper').should('have.class', 'closed');
// Clean up the injected input to avoid side effects
cy.get('#external-input').then($input => {
$input.remove();
});
});
it('refocuses dropdown wrapper when closed with ESC', () => {
// 1. Open the dropdown
cy.open(id);
// 2. Press ESC to close it
cy.getVs(id).find('.vscomp-toggle-button').type('{esc}');
// 3. Wrapper should now have focus
cy.getVs(id).find('.vscomp-ele-wrapper').should('have.focus');
// 4. Ensure it is closed
cy.getVs(id).find('.vscomp-ele-wrapper').should('have.class', 'closed');
});
});