diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/sidebar')
7 files changed, 141 insertions, 72 deletions
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js index c33cffb421d..53e8a0e1278 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils'; -import DropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue'; import { GlLabel } from '@gitlab/ui'; +import DropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue'; import { mockConfig, mockLabels } from './mock_data'; diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js index 68c9d26bb1a..cb758797c63 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js @@ -41,23 +41,20 @@ describe('DropdownButton', () => { describe('methods', () => { describe('handleButtonClick', () => { it.each` - variant - ${'standalone'} - ${'embedded'} + variant | expectPropagationStopped + ${'standalone'} | ${true} + ${'embedded'} | ${false} `( - 'toggles dropdown content and stops event propagation when `state.variant` is "$variant"', - ({ variant }) => { + 'toggles dropdown content and handles event propagation when `state.variant` is "$variant"', + ({ variant, expectPropagationStopped }) => { const event = { stopPropagation: jest.fn() }; - wrapper = createComponent({ - ...mockConfig, - variant, - }); + wrapper = createComponent({ ...mockConfig, variant }); findDropdownButton().vm.$emit('click', event); expect(store.state.showDropdownContents).toBe(true); - expect(event.stopPropagation).toHaveBeenCalled(); + expect(event.stopPropagation).toHaveBeenCalledTimes(expectPropagationStopped ? 1 : 0); }, ); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js index 9b01e0b9637..589be0ad7a4 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js @@ -17,53 +17,47 @@ import { mockConfig, mockLabels, mockRegularLabel } from './mock_data'; const localVue = createLocalVue(); localVue.use(Vuex); -const createComponent = (initialState = mockConfig) => { - const store = new Vuex.Store({ - getters, - mutations, - state: { - ...defaultState(), - footerCreateLabelTitle: 'Create label', - footerManageLabelTitle: 'Manage labels', - }, - actions: { - ...actions, - fetchLabels: jest.fn(), - }, - }); - - store.dispatch('setInitialState', initialState); - store.dispatch('receiveLabelsSuccess', mockLabels); - - return shallowMount(DropdownContentsLabelsView, { - localVue, - store, - }); -}; - describe('DropdownContentsLabelsView', () => { let wrapper; - let wrapperStandalone; - let wrapperEmbedded; - beforeEach(() => { - wrapper = createComponent(); - wrapperStandalone = createComponent({ - ...mockConfig, - variant: 'standalone', + const createComponent = (initialState = mockConfig) => { + const store = new Vuex.Store({ + getters, + mutations, + state: { + ...defaultState(), + footerCreateLabelTitle: 'Create label', + footerManageLabelTitle: 'Manage labels', + }, + actions: { + ...actions, + fetchLabels: jest.fn(), + }, }); - wrapperEmbedded = createComponent({ - ...mockConfig, - variant: 'embedded', + + store.dispatch('setInitialState', initialState); + store.dispatch('receiveLabelsSuccess', mockLabels); + + wrapper = shallowMount(DropdownContentsLabelsView, { + localVue, + store, }); + }; + + beforeEach(() => { + createComponent(); }); afterEach(() => { wrapper.destroy(); - wrapperStandalone.destroy(); - wrapperEmbedded.destroy(); + wrapper = null; }); + const findDropdownContent = () => wrapper.find('[data-testid="dropdown-content"]'); + const findDropdownTitle = () => wrapper.find('[data-testid="dropdown-title"]'); + const findDropdownFooter = () => wrapper.find('[data-testid="dropdown-footer"]'); + const findLoadingIcon = () => wrapper.find(GlLoadingIcon); + describe('computed', () => { describe('visibleLabels', () => { it('returns matching labels filtered with `searchKey`', () => { @@ -83,6 +77,24 @@ describe('DropdownContentsLabelsView', () => { expect(wrapper.vm.visibleLabels.length).toBe(mockLabels.length); }); }); + + describe('showListContainer', () => { + it.each` + variant | loading | showList + ${'sidebar'} | ${false} | ${true} + ${'sidebar'} | ${true} | ${false} + ${'not-sidebar'} | ${true} | ${true} + ${'not-sidebar'} | ${false} | ${true} + `( + 'returns $showList if `state.variant` is "$variant" and `labelsFetchInProgress` is $loading', + ({ variant, loading, showList }) => { + createComponent({ ...mockConfig, variant }); + wrapper.vm.$store.state.labelsFetchInProgress = loading; + + expect(wrapper.vm.showListContainer).toBe(showList); + }, + ); + }); }); describe('methods', () => { @@ -199,7 +211,7 @@ describe('DropdownContentsLabelsView', () => { wrapper.vm.$store.dispatch('requestLabels'); return wrapper.vm.$nextTick(() => { - const loadingIconEl = wrapper.find(GlLoadingIcon); + const loadingIconEl = findLoadingIcon(); expect(loadingIconEl.exists()).toBe(true); expect(loadingIconEl.attributes('class')).toContain('labels-fetch-loading'); @@ -207,22 +219,24 @@ describe('DropdownContentsLabelsView', () => { }); it('renders dropdown title element', () => { - const titleEl = wrapper.find('.dropdown-title > span'); + const titleEl = findDropdownTitle(); expect(titleEl.exists()).toBe(true); expect(titleEl.text()).toBe('Assign labels'); }); it('does not render dropdown title element when `state.variant` is "standalone"', () => { - expect(wrapperStandalone.find('.dropdown-title').exists()).toBe(false); + createComponent({ ...mockConfig, variant: 'standalone' }); + expect(findDropdownTitle().exists()).toBe(false); }); it('renders dropdown title element when `state.variant` is "embedded"', () => { - expect(wrapperEmbedded.find('.dropdown-title').exists()).toBe(true); + createComponent({ ...mockConfig, variant: 'embedded' }); + expect(findDropdownTitle().exists()).toBe(true); }); it('renders dropdown close button element', () => { - const closeButtonEl = wrapper.find('.dropdown-title').find(GlButton); + const closeButtonEl = findDropdownTitle().find(GlButton); expect(closeButtonEl.exists()).toBe(true); expect(closeButtonEl.props('icon')).toBe('close'); @@ -249,8 +263,7 @@ describe('DropdownContentsLabelsView', () => { }); return wrapper.vm.$nextTick(() => { - const labelsEl = wrapper.findAll('.dropdown-content li'); - const labelItemEl = labelsEl.at(0).find(LabelItem); + const labelItemEl = findDropdownContent().find(LabelItem); expect(labelItemEl.props('highlight')).toBe(true); }); @@ -262,22 +275,28 @@ describe('DropdownContentsLabelsView', () => { }); return wrapper.vm.$nextTick(() => { - const noMatchEl = wrapper.find('.dropdown-content li'); + const noMatchEl = findDropdownContent().find('li'); expect(noMatchEl.isVisible()).toBe(true); expect(noMatchEl.text()).toContain('No matching results'); }); }); + it('renders empty content while loading', () => { + wrapper.vm.$store.state.labelsFetchInProgress = true; + + return wrapper.vm.$nextTick(() => { + const dropdownContent = findDropdownContent(); + + expect(dropdownContent.exists()).toBe(true); + expect(dropdownContent.isVisible()).toBe(false); + }); + }); + it('renders footer list items', () => { - const createLabelLink = wrapper - .find('.dropdown-footer') - .findAll(GlLink) - .at(0); - const manageLabelsLink = wrapper - .find('.dropdown-footer') - .findAll(GlLink) - .at(1); + const footerLinks = findDropdownFooter().findAll(GlLink); + const createLabelLink = footerLinks.at(0); + const manageLabelsLink = footerLinks.at(1); expect(createLabelLink.exists()).toBe(true); expect(createLabelLink.text()).toBe('Create label'); @@ -289,8 +308,7 @@ describe('DropdownContentsLabelsView', () => { wrapper.vm.$store.state.allowLabelCreate = false; return wrapper.vm.$nextTick(() => { - const createLabelLink = wrapper - .find('.dropdown-footer') + const createLabelLink = findDropdownFooter() .findAll(GlLink) .at(0); @@ -299,11 +317,12 @@ describe('DropdownContentsLabelsView', () => { }); it('does not render footer list items when `state.variant` is "standalone"', () => { - expect(wrapperStandalone.find('.dropdown-footer').exists()).toBe(false); + createComponent({ ...mockConfig, variant: 'standalone' }); + expect(findDropdownFooter().exists()).toBe(false); }); it('renders footer list items when `state.variant` is "embedded"', () => { - expect(wrapperEmbedded.find('.dropdown-footer').exists()).toBe(true); + expect(findDropdownFooter().exists()).toBe(true); }); }); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js index bb462acf11c..97946993857 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js @@ -10,12 +10,13 @@ import { mockConfig } from './mock_data'; const localVue = createLocalVue(); localVue.use(Vuex); -const createComponent = (initialState = mockConfig) => { +const createComponent = (initialState = mockConfig, propsData = {}) => { const store = new Vuex.Store(labelsSelectModule()); store.dispatch('setInitialState', initialState); return shallowMount(DropdownContents, { + propsData, localVue, store, }); @@ -47,8 +48,15 @@ describe('DropdownContent', () => { }); describe('template', () => { - it('renders component container element with class `labels-select-dropdown-contents`', () => { + it('renders component container element with class `labels-select-dropdown-contents` and no styles', () => { expect(wrapper.attributes('class')).toContain('labels-select-dropdown-contents'); + expect(wrapper.attributes('style')).toBe(undefined); + }); + + it('renders component container element with styles when `renderOnTop` is true', () => { + wrapper = createComponent(mockConfig, { renderOnTop: true }); + + expect(wrapper.attributes('style')).toContain('bottom: 100%'); }); }); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js index 0717fd829a0..c1d9be7393c 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js @@ -1,7 +1,7 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; -import { GlDeprecatedButton, GlLoadingIcon } from '@gitlab/ui'; +import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue'; import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store'; @@ -42,7 +42,7 @@ describe('DropdownTitle', () => { }); it('renders edit link', () => { - const editBtnEl = wrapper.find(GlDeprecatedButton); + const editBtnEl = wrapper.find(GlButton); expect(editBtnEl.exists()).toBe(true); expect(editBtnEl.text()).toBe('Edit'); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js index 6e97b046be2..a1e0db4d29e 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js @@ -9,9 +9,14 @@ import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dr import DropdownContents from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue'; import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store'; +import { isInViewport } from '~/lib/utils/common_utils'; import { mockConfig } from './mock_data'; +jest.mock('~/lib/utils/common_utils', () => ({ + isInViewport: jest.fn().mockReturnValue(true), +})); + const localVue = createLocalVue(); localVue.use(Vuex); @@ -21,6 +26,9 @@ const createComponent = (config = mockConfig, slots = {}) => slots, store: new Vuex.Store(labelsSelectModule()), propsData: config, + stubs: { + 'dropdown-contents': DropdownContents, + }, }); describe('LabelsSelectRoot', () => { @@ -144,5 +152,42 @@ describe('LabelsSelectRoot', () => { expect(wrapper.find(DropdownContents).exists()).toBe(true); }); }); + + describe('sets content direction based on viewport', () => { + it('does not set direction when `state.variant` is not "embedded"', () => { + wrapper.vm.$store.dispatch('toggleDropdownContents'); + + wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false); + }); + }); + + describe('when `state.variant` is "embedded"', () => { + beforeEach(() => { + wrapper = createComponent({ ...mockConfig, variant: 'embedded' }); + wrapper.vm.$store.dispatch('toggleDropdownContents'); + }); + + it('set direction when out of viewport', () => { + isInViewport.mockImplementation(() => false); + wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(true); + }); + }); + + it('does not set direction when inside of viewport', () => { + isInViewport.mockImplementation(() => true); + wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false); + }); + }); + }); + }); }); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js index 072d8fe2fe2..c742220ba8a 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js @@ -1,10 +1,10 @@ import MockAdapter from 'axios-mock-adapter'; +import testAction from 'helpers/vuex_action_helper'; import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state'; import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types'; import * as actions from '~/vue_shared/components/sidebar/labels_select_vue/store/actions'; -import testAction from 'helpers/vuex_action_helper'; import axios from '~/lib/utils/axios_utils'; describe('LabelsSelect Actions', () => { |