diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-11 03:17:04 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-11 03:17:04 +0300 |
commit | 18ad304adc191b31f11a311fc4b89e3ea8f0f328 (patch) | |
tree | 8a47b5a381887386705e3c3e4afc893c7eee2b37 /spec/frontend/listbox | |
parent | 9abffa14d6395d56b77313541d63e0c12ae2b602 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/listbox')
-rw-r--r-- | spec/frontend/listbox/index_spec.js | 111 | ||||
-rw-r--r-- | spec/frontend/listbox/redirect_behavior_spec.js | 51 |
2 files changed, 162 insertions, 0 deletions
diff --git a/spec/frontend/listbox/index_spec.js b/spec/frontend/listbox/index_spec.js new file mode 100644 index 00000000000..45659a0e523 --- /dev/null +++ b/spec/frontend/listbox/index_spec.js @@ -0,0 +1,111 @@ +import { nextTick } from 'vue'; +import { getAllByRole, getByRole } from '@testing-library/dom'; +import { GlDropdown } from '@gitlab/ui'; +import { createWrapper } from '@vue/test-utils'; +import { initListbox, parseAttributes } from '~/listbox'; +import { getFixture, setHTMLFixture } from 'helpers/fixtures'; + +jest.mock('~/lib/utils/url_utility'); + +const fixture = getFixture('listbox/redirect_listbox.html'); + +const parsedAttributes = (() => { + const div = document.createElement('div'); + div.innerHTML = fixture; + return parseAttributes(div.firstChild); +})(); + +describe('initListbox', () => { + let instance; + + afterEach(() => { + if (instance) { + instance.$destroy(); + } + }); + + const setup = (...args) => { + instance = initListbox(...args); + }; + + // TODO: Rewrite these finders to use better semantics once the + // implementation is switched to GlListbox + // https://gitlab.com/gitlab-org/gitlab/-/issues/348738 + const findToggleButton = () => document.body.querySelector('.gl-dropdown-toggle'); + const findItem = (text) => getByRole(document.body, 'menuitem', { name: text }); + const findItems = () => getAllByRole(document.body, 'menuitem'); + const findSelectedItems = () => + findItems().filter( + (menuitem) => + !menuitem + .querySelector('.gl-new-dropdown-item-check-icon') + .classList.contains('gl-visibility-hidden'), + ); + + it('returns null given no element', () => { + setup(); + + expect(instance).toBe(null); + }); + + it('throws given an invalid element', () => { + expect(() => setup(document.body)).toThrow(); + }); + + describe('given a valid element', () => { + let onChangeSpy; + + beforeEach(async () => { + setHTMLFixture(fixture); + onChangeSpy = jest.fn(); + setup(document.querySelector('.js-redirect-listbox'), { onChange: onChangeSpy }); + + await nextTick(); + }); + + it('returns an instance', () => { + expect(instance).not.toBe(null); + }); + + it('renders button with selected item text', () => { + expect(findToggleButton().textContent.trim()).toBe('Bar'); + }); + + it('has the correct item selected', () => { + const selectedItems = findSelectedItems(); + expect(selectedItems).toHaveLength(1); + expect(selectedItems[0].textContent.trim()).toBe('Bar'); + }); + + it('applies additional classes from the original element', () => { + expect(instance.$el.classList).toContain('test-class-1', 'test-class-2'); + }); + + describe.each(parsedAttributes.items)('clicking on an item', (item) => { + beforeEach(async () => { + findItem(item.text).click(); + + await nextTick(); + }); + + it('calls the onChange callback with the item', () => { + expect(onChangeSpy).toHaveBeenCalledWith(item); + }); + + it('updates the toggle button text', () => { + expect(findToggleButton().textContent.trim()).toBe(item.text); + }); + + it('marks the item as selected', () => { + const selectedItems = findSelectedItems(); + expect(selectedItems).toHaveLength(1); + expect(selectedItems[0].textContent.trim()).toBe(item.text); + }); + }); + + it('passes the "right" prop through to the underlying component', () => { + const wrapper = createWrapper(instance).findComponent(GlDropdown); + expect(wrapper.props('right')).toBe(parsedAttributes.right); + }); + }); +}); diff --git a/spec/frontend/listbox/redirect_behavior_spec.js b/spec/frontend/listbox/redirect_behavior_spec.js new file mode 100644 index 00000000000..7b2a40b65ce --- /dev/null +++ b/spec/frontend/listbox/redirect_behavior_spec.js @@ -0,0 +1,51 @@ +import { initListbox } from '~/listbox'; +import { initRedirectListboxBehavior } from '~/listbox/redirect_behavior'; +import { redirectTo } from '~/lib/utils/url_utility'; +import { getFixture, setHTMLFixture } from 'helpers/fixtures'; + +jest.mock('~/lib/utils/url_utility'); +jest.mock('~/listbox', () => ({ + initListbox: jest.fn().mockReturnValue({ foo: true }), +})); + +const fixture = getFixture('listbox/redirect_listbox.html'); + +describe('initRedirectListboxBehavior', () => { + let instances; + + beforeEach(() => { + setHTMLFixture(` + ${fixture} + ${fixture} + `); + + instances = initRedirectListboxBehavior(); + }); + + it('calls initListbox for each .js-redirect-listbox', () => { + expect(instances).toEqual([{ foo: true }, { foo: true }]); + + expect(initListbox).toHaveBeenCalledTimes(2); + + initListbox.mock.calls.forEach((callArgs, i) => { + const elements = document.querySelectorAll('.js-redirect-listbox'); + + expect(callArgs[0]).toBe(elements[i]); + expect(callArgs[1]).toEqual({ + onChange: expect.any(Function), + }); + }); + }); + + it('passes onChange handler to initListbox that calls redirectTo', () => { + const [firstCallArgs] = initListbox.mock.calls; + const { onChange } = firstCallArgs[1]; + const mockItem = { href: '/foo' }; + + expect(redirectTo).not.toHaveBeenCalled(); + + onChange(mockItem); + + expect(redirectTo).toHaveBeenCalledWith(mockItem.href); + }); +}); |