diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/actions_button_spec.js')
-rw-r--r-- | spec/frontend/vue_shared/components/actions_button_spec.js | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/actions_button_spec.js b/spec/frontend/vue_shared/components/actions_button_spec.js new file mode 100644 index 00000000000..4dde9d726d1 --- /dev/null +++ b/spec/frontend/vue_shared/components/actions_button_spec.js @@ -0,0 +1,203 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlDropdown, GlLink } from '@gitlab/ui'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; +import ActionsButton from '~/vue_shared/components/actions_button.vue'; + +const TEST_ACTION = { + key: 'action1', + text: 'Sample', + secondaryText: 'Lorem ipsum.', + tooltip: '', + href: '/sample', + attrs: { 'data-test': '123' }, +}; +const TEST_ACTION_2 = { + key: 'action2', + text: 'Sample 2', + secondaryText: 'Dolar sit amit.', + tooltip: 'Dolar sit amit.', + href: '#', + attrs: { 'data-test': '456' }, +}; +const TEST_TOOLTIP = 'Lorem ipsum dolar sit'; + +describe('Actions button component', () => { + let wrapper; + + function createComponent(props) { + wrapper = shallowMount(ActionsButton, { + propsData: { ...props }, + directives: { GlTooltip: createMockDirective() }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + const getTooltip = child => { + const directiveBinding = getBinding(child.element, 'gl-tooltip'); + + return directiveBinding.value; + }; + const findLink = () => wrapper.find(GlLink); + const findLinkTooltip = () => getTooltip(findLink()); + const findDropdown = () => wrapper.find(GlDropdown); + const findDropdownTooltip = () => getTooltip(findDropdown()); + const parseDropdownItems = () => + findDropdown() + .findAll('gl-dropdown-item-stub,gl-dropdown-divider-stub') + .wrappers.map(x => { + if (x.is('gl-dropdown-divider-stub')) { + return { type: 'divider' }; + } + + const { isCheckItem, isChecked, secondaryText } = x.props(); + + return { + type: 'item', + isCheckItem, + isChecked, + secondaryText, + text: x.text(), + }; + }); + const clickOn = (child, evt = new Event('click')) => child.vm.$emit('click', evt); + const clickLink = (...args) => clickOn(findLink(), ...args); + const clickDropdown = (...args) => clickOn(findDropdown(), ...args); + + describe('with 1 action', () => { + beforeEach(() => { + createComponent({ actions: [TEST_ACTION] }); + }); + + it('should not render dropdown', () => { + expect(findDropdown().exists()).toBe(false); + }); + + it('should render single button', () => { + const link = findLink(); + + expect(link.attributes()).toEqual({ + class: expect.any(String), + href: TEST_ACTION.href, + ...TEST_ACTION.attrs, + }); + expect(link.text()).toBe(TEST_ACTION.text); + }); + + it('should have tooltip', () => { + expect(findLinkTooltip()).toBe(TEST_ACTION.tooltip); + }); + + it('should have attrs', () => { + expect(findLink().attributes()).toMatchObject(TEST_ACTION.attrs); + }); + + it('can click', () => { + expect(clickLink).not.toThrow(); + }); + }); + + describe('with 1 action with tooltip', () => { + it('should have tooltip', () => { + createComponent({ actions: [{ ...TEST_ACTION, tooltip: TEST_TOOLTIP }] }); + + expect(findLinkTooltip()).toBe(TEST_TOOLTIP); + }); + }); + + describe('with 1 action with handle', () => { + it('can click and trigger handle', () => { + const handleClick = jest.fn(); + createComponent({ actions: [{ ...TEST_ACTION, handle: handleClick }] }); + + const event = new Event('click'); + clickLink(event); + + expect(handleClick).toHaveBeenCalledWith(event); + }); + }); + + describe('with multiple actions', () => { + let handleAction; + + beforeEach(() => { + handleAction = jest.fn(); + + createComponent({ actions: [{ ...TEST_ACTION, handle: handleAction }, TEST_ACTION_2] }); + }); + + it('should default to selecting first action', () => { + expect(findDropdown().attributes()).toMatchObject({ + text: TEST_ACTION.text, + 'split-href': TEST_ACTION.href, + }); + }); + + it('should handle first action click', () => { + const event = new Event('click'); + + clickDropdown(event); + + expect(handleAction).toHaveBeenCalledWith(event); + }); + + it('should render dropdown items', () => { + expect(parseDropdownItems()).toEqual([ + { + type: 'item', + isCheckItem: true, + isChecked: true, + secondaryText: TEST_ACTION.secondaryText, + text: TEST_ACTION.text, + }, + { type: 'divider' }, + { + type: 'item', + isCheckItem: true, + isChecked: false, + secondaryText: TEST_ACTION_2.secondaryText, + text: TEST_ACTION_2.text, + }, + ]); + }); + + it('should select action 2 when clicked', () => { + expect(wrapper.emitted('select')).toBeUndefined(); + + const action2 = wrapper.find(`[data-testid="action_${TEST_ACTION_2.key}"]`); + action2.vm.$emit('click'); + + expect(wrapper.emitted('select')).toEqual([[TEST_ACTION_2.key]]); + }); + + it('should have tooltip value', () => { + expect(findDropdownTooltip()).toBe(TEST_ACTION.tooltip); + }); + }); + + describe('with multiple actions and selectedKey', () => { + beforeEach(() => { + createComponent({ actions: [TEST_ACTION, TEST_ACTION_2], selectedKey: TEST_ACTION_2.key }); + }); + + it('should show action 2 as selected', () => { + expect(parseDropdownItems()).toEqual([ + expect.objectContaining({ + type: 'item', + isChecked: false, + }), + { type: 'divider' }, + expect.objectContaining({ + type: 'item', + isChecked: true, + }), + ]); + }); + + it('should have tooltip value', () => { + expect(findDropdownTooltip()).toBe(TEST_ACTION_2.tooltip); + }); + }); +}); |