diff options
Diffstat (limited to 'spec/frontend/gl_dropdown_spec.js')
-rw-r--r-- | spec/frontend/gl_dropdown_spec.js | 345 |
1 files changed, 0 insertions, 345 deletions
diff --git a/spec/frontend/gl_dropdown_spec.js b/spec/frontend/gl_dropdown_spec.js deleted file mode 100644 index 8bfe7f56e37..00000000000 --- a/spec/frontend/gl_dropdown_spec.js +++ /dev/null @@ -1,345 +0,0 @@ -/* eslint-disable no-param-reassign */ - -import $ from 'jquery'; -import '~/gl_dropdown'; -import '~/lib/utils/common_utils'; -import { visitUrl } from '~/lib/utils/url_utility'; - -jest.mock('~/lib/utils/url_utility', () => ({ - visitUrl: jest.fn().mockName('visitUrl'), -})); - -describe('glDropdown', () => { - preloadFixtures('static/gl_dropdown.html'); - - const NON_SELECTABLE_CLASSES = - '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item'; - 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`; - const ARROW_KEYS = { - DOWN: 40, - UP: 38, - ENTER: 13, - ESC: 27, - }; - - let remoteCallback; - - const test = {}; - - const navigateWithKeys = (direction, steps, cb, i) => { - i = i || 0; - if (!i) direction = direction.toUpperCase(); - $('body').trigger({ - type: 'keydown', - which: ARROW_KEYS[direction], - keyCode: ARROW_KEYS[direction], - }); - i += 1; - if (i <= steps) { - navigateWithKeys(direction, steps, cb, i); - } else { - cb(); - } - }; - - const remoteMock = (data, term, callback) => { - remoteCallback = callback.bind({}, data); - }; - - function initDropDown(hasRemote, isFilterable, extraOpts = {}) { - const options = { - selectable: true, - filterable: isFilterable, - data: hasRemote ? remoteMock.bind({}, test.projectsData) : test.projectsData, - search: { - fields: ['name'], - }, - text: project => project.name_with_namespace || project.name, - id: project => project.id, - ...extraOpts, - }; - test.dropdownButtonElement = $( - '#js-project-dropdown', - test.dropdownContainerElement, - ).glDropdown(options); - } - - beforeEach(() => { - loadFixtures('static/gl_dropdown.html'); - test.dropdownContainerElement = $('.dropdown.inline'); - test.$dropdownMenuElement = $('.dropdown-menu', test.dropdownContainerElement); - test.projectsData = getJSONFixture('static/projects.json'); - }); - - afterEach(() => { - $('body').off('keydown'); - test.dropdownContainerElement.off('keyup'); - }); - - it('should open on click', () => { - initDropDown.call(this, false); - - expect(test.dropdownContainerElement).not.toHaveClass('show'); - test.dropdownButtonElement.click(); - - expect(test.dropdownContainerElement).toHaveClass('show'); - }); - - it('escapes HTML as text', () => { - test.projectsData[0].name_with_namespace = '<script>alert("testing");</script>'; - - initDropDown.call(this, false); - - test.dropdownButtonElement.click(); - - expect($('.dropdown-content li:first-child').text()).toBe('<script>alert("testing");</script>'); - }); - - it('should output HTML when highlighting', () => { - test.projectsData[0].name_with_namespace = 'testing'; - $('.dropdown-input .dropdown-input-field').val('test'); - - initDropDown.call(this, false, true, { - highlight: true, - }); - - test.dropdownButtonElement.click(); - - expect($('.dropdown-content li:first-child').text()).toBe('testing'); - - expect($('.dropdown-content li:first-child a').html()).toBe( - '<b>t</b><b>e</b><b>s</b><b>t</b>ing', - ); - }); - - describe('that is open', () => { - beforeEach(() => { - initDropDown.call(this, false, false); - test.dropdownButtonElement.click(); - }); - - it('should select a following item on DOWN keypress', () => { - expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(0); - const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 1)) + 0; - navigateWithKeys('down', randomIndex, () => { - expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1); - expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, test.$dropdownMenuElement)).toHaveClass( - 'is-focused', - ); - }); - }); - - it('should select a previous item on UP keypress', () => { - expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(0); - navigateWithKeys('down', test.projectsData.length - 1, () => { - expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1); - const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 2)) + 0; - navigateWithKeys('up', randomIndex, () => { - expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1); - expect( - $( - `${ITEM_SELECTOR}:eq(${test.projectsData.length - 2 - randomIndex}) a`, - test.$dropdownMenuElement, - ), - ).toHaveClass('is-focused'); - }); - }); - }); - - it('should click the selected item on ENTER keypress', () => { - expect(test.dropdownContainerElement).toHaveClass('show'); - const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 1)) + 0; - navigateWithKeys('down', randomIndex, () => { - navigateWithKeys('enter', null, () => { - expect(test.dropdownContainerElement).not.toHaveClass('show'); - const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, test.$dropdownMenuElement); - - expect(link).toHaveClass('is-active'); - const linkedLocation = link.attr('href'); - if (linkedLocation && linkedLocation !== '#') { - expect(visitUrl).toHaveBeenCalledWith(linkedLocation); - } - }); - }); - }); - - it('should close on ESC keypress', () => { - expect(test.dropdownContainerElement).toHaveClass('show'); - test.dropdownContainerElement.trigger({ - type: 'keyup', - which: ARROW_KEYS.ESC, - keyCode: ARROW_KEYS.ESC, - }); - - expect(test.dropdownContainerElement).not.toHaveClass('show'); - }); - }); - - describe('opened and waiting for a remote callback', () => { - beforeEach(() => { - initDropDown.call(this, true, true); - test.dropdownButtonElement.click(); - }); - - it('should show loading indicator while search results are being fetched by backend', () => { - const dropdownMenu = document.querySelector('.dropdown-menu'); - - expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1); - remoteCallback(); - - expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1); - }); - - 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 after transition', () => { - remoteCallback(); - test.dropdownContainerElement.trigger({ - type: 'keyup', - which: ARROW_KEYS.ESC, - keyCode: ARROW_KEYS.ESC, - }); - test.dropdownButtonElement.click(); - test.dropdownContainerElement.trigger('transitionend'); - - 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); - test.dropdownButtonElement.click(); - test.dropdownContainerElement.trigger('transitionend'); - - expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR)); - }); - }); - - it('should still have input value on close and restore', () => { - const $searchInput = $(SEARCH_INPUT_SELECTOR); - initDropDown.call(this, false, true); - $searchInput - .trigger('focus') - .val('g') - .trigger('input'); - - expect($searchInput.val()).toEqual('g'); - test.dropdownButtonElement.trigger('hidden.bs.dropdown'); - $searchInput.trigger('blur').trigger('focus'); - - expect($searchInput.val()).toEqual('g'); - }); - - describe('renderItem', () => { - function dropdownWithOptions(options) { - const $dropdownDiv = $('<div />'); - - $dropdownDiv.glDropdown(options); - - return $dropdownDiv.data('glDropdown'); - } - - function basicDropdown() { - return dropdownWithOptions({}); - } - - describe('without selected value', () => { - let dropdown; - - beforeEach(() => { - dropdown = basicDropdown(); - }); - - it('marks items without ID as active', () => { - const dummyData = {}; - - const html = dropdown.renderItem(dummyData, null, null); - - const link = html.querySelector('a'); - - expect(link).toHaveClass('is-active'); - }); - - it('does not mark items with ID as active', () => { - const dummyData = { - id: 'ea', - }; - - const html = dropdown.renderItem(dummyData, null, null); - - const link = html.querySelector('a'); - - expect(link).not.toHaveClass('is-active'); - }); - }); - - it('should return an empty .separator li when when appropriate', () => { - const dropdown = basicDropdown(); - const sep = { type: 'separator' }; - const li = dropdown.renderItem(sep); - - expect(li).toHaveClass('separator'); - expect(li.childNodes.length).toEqual(0); - }); - - it('should return an empty .divider li when when appropriate', () => { - const dropdown = basicDropdown(); - const div = { type: 'divider' }; - const li = dropdown.renderItem(div); - - expect(li).toHaveClass('divider'); - expect(li.childNodes.length).toEqual(0); - }); - - it('should return a .dropdown-header li with the correct content when when appropriate', () => { - const dropdown = basicDropdown(); - const text = 'My Header'; - const header = { type: 'header', content: text }; - const li = dropdown.renderItem(header); - - expect(li).toHaveClass('dropdown-header'); - expect(li.childNodes.length).toEqual(1); - expect(li.textContent).toEqual(text); - }); - }); - - it('should keep selected item after selecting a second time', () => { - const options = { - isSelectable(item, $el) { - return !$el.hasClass('is-active'); - }, - toggleLabel(item) { - return item && item.id; - }, - }; - initDropDown.call(this, false, false, options); - const $item = $(`${ITEM_SELECTOR}:first() a`, test.$dropdownMenuElement); - - // select item the first time - test.dropdownButtonElement.click(); - $item.click(); - - expect($item).toHaveClass('is-active'); - // select item the second time - test.dropdownButtonElement.click(); - $item.click(); - - expect($item).toHaveClass('is-active'); - - expect($('.dropdown-toggle-text')).toHaveText(test.projectsData[0].id.toString()); - }); -}); |