diff options
author | Luke Bennett <lukeeeebennettplus@gmail.com> | 2016-05-15 02:50:15 +0300 |
---|---|---|
committer | Luke Bennett <lukeeeebennettplus@gmail.com> | 2016-08-18 20:17:56 +0300 |
commit | b4398de5c5381a81f225c390e32f99d4e0e7d627 (patch) | |
tree | c563e58bef6e9c59462941585f07037c3b5b517d /spec/javascripts | |
parent | 9e7231bd1f3a934614bfee23c32f19157991ff5b (diff) |
Added new non-selectable selector exclusions to fix arrow key events, fixed the simulated clicking of a row and fixed the conflict between enter key form submit and enter key row selection
Added bootstrap dropdown event triggers to invoke the open and close methods of the dropdown, allowing for the binding of array key events
Added #17465 fix entry to CHANGELOG
Fixed multi-dropdown selected row index conflict
Fixed whitespace diff
Added padding to the dropdown content iterative scroll as well as new conditional scrolls to scroll all the way to the top when the first item of a list is selected and to scroll all the way to the bottom when the last item of a list is selected
Added conditionals to the enable and disable autocomplete methods to stop multiple invocations without any enabled/disabled state change
Fixes some incorrect firing of requests. The dropdown box was invoking a new query every time it closed and the GitLabDropdownRemote callback was invoking a new query which was causing the dropdown double render issue.
Added .selectable css class to dropdown list items that are not dividers or headers and altered selectors to account for that. Moved scroll padding Number to variable.
Removed unused method
Started Dropdown tests
Added fixture and began first test
Almost finished, navigation done, action and close needed
YAY. TESTS DONE.
Altered test and fixed click
started removing selectable class use
Fixed as reviewed
altered selection method
Fixed autocomplete shutting dropdown on arrow key use
patched XSS vulns
updated tests
f
Added click fixes
Diffstat (limited to 'spec/javascripts')
-rw-r--r-- | spec/javascripts/fixtures/gl_dropdown.html.haml | 16 | ||||
-rw-r--r-- | spec/javascripts/gl_dropdown_spec.js.coffee | 96 |
2 files changed, 112 insertions, 0 deletions
diff --git a/spec/javascripts/fixtures/gl_dropdown.html.haml b/spec/javascripts/fixtures/gl_dropdown.html.haml new file mode 100644 index 00000000000..a20390c08ee --- /dev/null +++ b/spec/javascripts/fixtures/gl_dropdown.html.haml @@ -0,0 +1,16 @@ +%div + .dropdown.inline + %button#js-project-dropdown.dropdown-menu-toggle{type: 'button', data: {toggle: 'dropdown'}} + Projects + %i.fa.fa-chevron-down.dropdown-toggle-caret.js-projects-dropdown-toggle + .dropdown-menu.dropdown-select.dropdown-menu-selectable + .dropdown-title + %span Go to project + %button.dropdown-title-button.dropdown-menu-close{aria: {label: 'Close'}} + %i.fa.fa-times.dropdown-menu-close-icon + .dropdown-input + %input.dropdown-input-field{type: 'search', placeholder: 'Filter results'} + %i.fa.fa-search.dropdown-input-search + .dropdown-content + .dropdown-loading + %i.fa.fa-spinner.fa-spin diff --git a/spec/javascripts/gl_dropdown_spec.js.coffee b/spec/javascripts/gl_dropdown_spec.js.coffee new file mode 100644 index 00000000000..46a0af32a7d --- /dev/null +++ b/spec/javascripts/gl_dropdown_spec.js.coffee @@ -0,0 +1,96 @@ +#= require jquery +#= require gl_dropdown +#= require turbolinks +#= require lib/utils/common_utils +#= require lib/utils/type_utility + +NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link' +ITEM_SELECTOR = ".dropdown-content li:not(#{NON_SELECTABLE_CLASSES})" +FOCUSED_ITEM_SELECTOR = ITEM_SELECTOR + ' a.is-focused' + +ARROW_KEYS = + DOWN: 40 + UP: 38 + ENTER: 13 + ESC: 27 + +navigateWithKeys = (direction, steps, cb, i) -> + i = i || 0 + $('body').trigger + type: 'keydown' + which: ARROW_KEYS[direction.toUpperCase()] + keyCode: ARROW_KEYS[direction.toUpperCase()] + i++ + if i <= steps + navigateWithKeys direction, steps, cb, i + else + cb() + +initDropdown = -> + @dropdownContainerElement = $('.dropdown.inline') + @dropdownMenuElement = $('.dropdown-menu', @dropdownContainerElement) + @projectsData = fixture.load('projects.json')[0] + @dropdownButtonElement = $('#js-project-dropdown', @dropdownContainerElement).glDropdown + selectable: true + data: @projectsData + text: (project) -> + (project.name_with_namespace or project.name) + id: (project) -> + project.id + +describe 'Dropdown', -> + fixture.preload 'gl_dropdown.html' + fixture.preload 'projects.json' + + beforeEach -> + fixture.load 'gl_dropdown.html' + initDropdown.call this + + afterEach -> + $('body').unbind 'keydown' + @dropdownContainerElement.unbind 'keyup' + + it 'should open on click', -> + expect(@dropdownContainerElement).not.toHaveClass 'open' + @dropdownButtonElement.click() + expect(@dropdownContainerElement).toHaveClass 'open' + + describe 'that is open', -> + beforeEach -> + @dropdownButtonElement.click() + + it 'should select a following item on DOWN keypress', -> + expect($(FOCUSED_ITEM_SELECTOR, @dropdownMenuElement).length).toBe 0 + randomIndex = Math.floor(Math.random() * (@projectsData.length - 1)) + 0 + navigateWithKeys 'down', randomIndex, => + expect($(FOCUSED_ITEM_SELECTOR, @dropdownMenuElement).length).toBe 1 + expect($("#{ITEM_SELECTOR}:eq(#{randomIndex}) a", @dropdownMenuElement)).toHaveClass 'is-focused' + + it 'should select a previous item on UP keypress', -> + expect($(FOCUSED_ITEM_SELECTOR, @dropdownMenuElement).length).toBe 0 + navigateWithKeys 'down', (@projectsData.length - 1), => + expect($(FOCUSED_ITEM_SELECTOR, @dropdownMenuElement).length).toBe 1 + randomIndex = Math.floor(Math.random() * (@projectsData.length - 2)) + 0 + navigateWithKeys 'up', randomIndex, => + expect($(FOCUSED_ITEM_SELECTOR, @dropdownMenuElement).length).toBe 1 + expect($("#{ITEM_SELECTOR}:eq(#{((@projectsData.length - 2) - randomIndex)}) a", @dropdownMenuElement)).toHaveClass 'is-focused' + + it 'should click the selected item on ENTER keypress', -> + expect(@dropdownContainerElement).toHaveClass 'open' + randomIndex = Math.floor(Math.random() * (@projectsData.length - 1)) + 0 + navigateWithKeys 'down', randomIndex, => + spyOn(Turbolinks, 'visit').and.stub() + navigateWithKeys 'enter', null, => + link = $("#{ITEM_SELECTOR}:eq(#{randomIndex}) a", @dropdownMenuElement) + expect(link).toHaveClass 'is-active' + if link.attr 'href' + expect(Turbolinks.visit).toHaveBeenCalledWith link.attr 'href' + expect(@dropdownContainerElement).not.toHaveClass 'open' + + it 'should close on ESC keypress', -> + expect(@dropdownContainerElement).toHaveClass 'open' + @dropdownContainerElement.trigger + type: 'keyup' + which: ARROW_KEYS.ESC + keyCode: ARROW_KEYS.ESC + expect(@dropdownContainerElement).not.toHaveClass 'open' |