diff options
author | Fatih Acet <acetfatih@gmail.com> | 2016-10-28 22:02:46 +0000 |
---|---|---|
committer | Fatih Acet <acetfatih@gmail.com> | 2016-10-28 22:02:46 +0000 |
commit | 4d3a08036416a235873d8841a2924febc37c3414 (patch) | |
tree | e0d859d9e6dc11312f996872a77101fcdf0a1394 /spec | |
parent | dcc699afc214dab1e27541ac35a9d57ef20f2cb9 (diff) | |
parent | 3acfbcaea0aef39e257b2f6668db361fef3ac43c (diff) | |
download | gitlab-ce-4d3a08036416a235873d8841a2924febc37c3414.tar.gz |
Merge branch 'dropdown-input-fix' into 'master'
Do not allow text input in dropdown while loading
## What does this MR do?
It moves the focus event of the text input of a filterable dropdown to after loading of options is complete. After the fix, the user cannot edit the while it's greyed out and loading.
## Are there points in the code the reviewer needs to double check?
## Why was this MR needed?
It fixes the bug in https://gitlab.com/gitlab-org/gitlab-ce/issues/23496.
## Screenshots (if relevant)
![https://gitlab.com/gitlab-org/gitlab-ce/uploads/a7bc2f0228fcde5a85cccb333b52f0e3/2016-10-18_12.00.54.gif](https://gitlab.com/gitlab-org/gitlab-ce/uploads/a7bc2f0228fcde5a85cccb333b52f0e3/2016-10-18_12.00.54.gif)
## What are the relevant issue numbers?
Fixes #23496
See merge request !7054
Diffstat (limited to 'spec')
-rw-r--r-- | spec/javascripts/gl_dropdown_spec.js.es6 | 78 |
1 files changed, 64 insertions, 14 deletions
diff --git a/spec/javascripts/gl_dropdown_spec.js.es6 b/spec/javascripts/gl_dropdown_spec.js.es6 index 685e662edd3..8ba238018cd 100644 --- a/spec/javascripts/gl_dropdown_spec.js.es6 +++ b/spec/javascripts/gl_dropdown_spec.js.es6 @@ -7,6 +7,7 @@ (() => { const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link'; + const SEARCH_INPUT_SELECTOR = '.dropdown-input-field'; const ITEM_SELECTOR = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`; const FOCUSED_ITEM_SELECTOR = `${ITEM_SELECTOR} a.is-focused`; @@ -17,6 +18,8 @@ ESC: 27 }; + let remoteCallback; + let navigateWithKeys = function navigateWithKeys(direction, steps, cb, i) { i = i || 0; if (!i) direction = direction.toUpperCase(); @@ -33,18 +36,19 @@ } }; + let remoteMock = function remoteMock(data, term, callback) { + remoteCallback = callback.bind({}, data); + } + describe('Dropdown', function describeDropdown() { fixture.preload('gl_dropdown.html'); fixture.preload('projects.json'); - beforeEach(() => { - fixture.load('gl_dropdown.html'); - this.dropdownContainerElement = $('.dropdown.inline'); - this.dropdownMenuElement = $('.dropdown-menu', this.dropdownContainerElement); - this.projectsData = fixture.load('projects.json')[0]; + function initDropDown(hasRemote, isFilterable) { this.dropdownButtonElement = $('#js-project-dropdown', this.dropdownContainerElement).glDropdown({ selectable: true, - data: this.projectsData, + filterable: isFilterable, + data: hasRemote ? remoteMock.bind({}, this.projectsData) : this.projectsData, text: (project) => { (project.name_with_namespace || project.name); }, @@ -52,6 +56,13 @@ project.id; } }); + } + + beforeEach(() => { + fixture.load('gl_dropdown.html'); + this.dropdownContainerElement = $('.dropdown.inline'); + this.$dropdownMenuElement = $('.dropdown-menu', this.dropdownContainerElement); + this.projectsData = fixture.load('projects.json')[0]; }); afterEach(() => { @@ -60,6 +71,7 @@ }); it('should open on click', () => { + initDropDown.call(this, false); expect(this.dropdownContainerElement).not.toHaveClass('open'); this.dropdownButtonElement.click(); expect(this.dropdownContainerElement).toHaveClass('open'); @@ -67,26 +79,27 @@ describe('that is open', () => { beforeEach(() => { + initDropDown.call(this, false, false); this.dropdownButtonElement.click(); }); it('should select a following item on DOWN keypress', () => { - expect($(FOCUSED_ITEM_SELECTOR, this.dropdownMenuElement).length).toBe(0); + expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(0); let randomIndex = (Math.floor(Math.random() * (this.projectsData.length - 1)) + 0); navigateWithKeys('down', randomIndex, () => { - expect($(FOCUSED_ITEM_SELECTOR, this.dropdownMenuElement).length).toBe(1); - expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.dropdownMenuElement)).toHaveClass('is-focused'); + expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1); + expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement)).toHaveClass('is-focused'); }); }); it('should select a previous item on UP keypress', () => { - expect($(FOCUSED_ITEM_SELECTOR, this.dropdownMenuElement).length).toBe(0); + expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(0); navigateWithKeys('down', (this.projectsData.length - 1), () => { - expect($(FOCUSED_ITEM_SELECTOR, this.dropdownMenuElement).length).toBe(1); + expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1); let randomIndex = (Math.floor(Math.random() * (this.projectsData.length - 2)) + 0); navigateWithKeys('up', randomIndex, () => { - expect($(FOCUSED_ITEM_SELECTOR, this.dropdownMenuElement).length).toBe(1); - expect($(`${ITEM_SELECTOR}:eq(${((this.projectsData.length - 2) - randomIndex)}) a`, this.dropdownMenuElement)).toHaveClass('is-focused'); + expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1); + expect($(`${ITEM_SELECTOR}:eq(${((this.projectsData.length - 2) - randomIndex)}) a`, this.$dropdownMenuElement)).toHaveClass('is-focused'); }); }); }); @@ -98,7 +111,7 @@ spyOn(Turbolinks, 'visit').and.stub(); navigateWithKeys('enter', null, () => { expect(this.dropdownContainerElement).not.toHaveClass('open'); - let link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.dropdownMenuElement); + let link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement); expect(link).toHaveClass('is-active'); let linkedLocation = link.attr('href'); if (linkedLocation && linkedLocation !== '#') expect(Turbolinks.visit).toHaveBeenCalledWith(linkedLocation); @@ -116,5 +129,42 @@ expect(this.dropdownContainerElement).not.toHaveClass('open'); }); }); + + describe('opened and waiting for a remote callback', () => { + beforeEach(() => { + initDropDown.call(this, true, true); + this.dropdownButtonElement.click(); + }); + + it('should not focus search input while remote task is not complete', ()=> { + expect($(document.activeElement)).not.toEqual($(SEARCH_INPUT_SELECTOR)); + remoteCallback(); + expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); + }); + + it('should focus search input after remote task is complete', ()=> { + remoteCallback(); + expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); + }); + + it('should focus on input when opening for the second time', ()=> { + remoteCallback(); + this.dropdownContainerElement.trigger({ + type: 'keyup', + which: ARROW_KEYS.ESC, + keyCode: ARROW_KEYS.ESC + }); + this.dropdownButtonElement.click(); + expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); + }); + }); + + describe('input focus with array data', () => { + it('should focus input when passing array data to drop down', ()=> { + initDropDown.call(this, false, true); + this.dropdownButtonElement.click(); + expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); + }); + }); }); })(); |