diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js')
-rw-r--r-- | spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js new file mode 100644 index 00000000000..9bc01d8723f --- /dev/null +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js @@ -0,0 +1,223 @@ +import Vuex from 'vuex'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; + +import { GlButton, GlIcon, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui'; +import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue'; + +import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store'; + +import { mockConfig, mockSuggestedColors } from './mock_data'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +const createComponent = (initialState = mockConfig) => { + const store = new Vuex.Store(labelSelectModule()); + + store.dispatch('setInitialState', initialState); + + return shallowMount(DropdownContentsCreateView, { + localVue, + store, + }); +}; + +describe('DropdownContentsCreateView', () => { + let wrapper; + const colors = Object.keys(mockSuggestedColors).map(color => ({ + [color]: mockSuggestedColors[color], + })); + + beforeEach(() => { + gon.suggested_label_colors = mockSuggestedColors; + wrapper = createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('computed', () => { + describe('disableCreate', () => { + it('returns `true` when label title and color is not defined', () => { + expect(wrapper.vm.disableCreate).toBe(true); + }); + + it('returns `true` when `labelCreateInProgress` is true', () => { + wrapper.setData({ + labelTitle: 'Foo', + selectedColor: '#ff0000', + }); + wrapper.vm.$store.dispatch('requestCreateLabel'); + + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.disableCreate).toBe(true); + }); + }); + + it('returns `false` when label title and color is defined and create request is not already in progress', () => { + wrapper.setData({ + labelTitle: 'Foo', + selectedColor: '#ff0000', + }); + + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.disableCreate).toBe(false); + }); + }); + }); + + describe('suggestedColors', () => { + it('returns array of color objects containing color code and name', () => { + colors.forEach((color, index) => { + expect(wrapper.vm.suggestedColors[index]).toEqual(expect.objectContaining(color)); + }); + }); + }); + }); + + describe('methods', () => { + describe('getColorCode', () => { + it('returns color code from color object', () => { + expect(wrapper.vm.getColorCode(colors[0])).toBe(Object.keys(colors[0]).pop()); + }); + }); + + describe('getColorName', () => { + it('returns color name from color object', () => { + expect(wrapper.vm.getColorName(colors[0])).toBe(Object.values(colors[0]).pop()); + }); + }); + + describe('handleColorClick', () => { + it('sets provided `color` param to `selectedColor` prop', () => { + wrapper.vm.handleColorClick(colors[0]); + + expect(wrapper.vm.selectedColor).toBe(Object.keys(colors[0]).pop()); + }); + }); + + describe('handleCreateClick', () => { + it('calls action `createLabel` with object containing `labelTitle` & `selectedColor`', () => { + jest.spyOn(wrapper.vm, 'createLabel').mockImplementation(); + wrapper.setData({ + labelTitle: 'Foo', + selectedColor: '#ff0000', + }); + + wrapper.vm.handleCreateClick(); + + return wrapper.vm.$nextTick(() => { + expect(wrapper.vm.createLabel).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Foo', + color: '#ff0000', + }), + ); + }); + }); + }); + }); + + describe('template', () => { + it('renders component container element with class "labels-select-contents-create"', () => { + expect(wrapper.attributes('class')).toContain('labels-select-contents-create'); + }); + + it('renders dropdown back button element', () => { + const backBtnEl = wrapper + .find('.dropdown-title') + .findAll(GlButton) + .at(0); + + expect(backBtnEl.exists()).toBe(true); + expect(backBtnEl.attributes('aria-label')).toBe('Go back'); + expect(backBtnEl.find(GlIcon).props('name')).toBe('arrow-left'); + }); + + it('renders dropdown title element', () => { + const headerEl = wrapper.find('.dropdown-title > span'); + + expect(headerEl.exists()).toBe(true); + expect(headerEl.text()).toBe('Create label'); + }); + + it('renders dropdown close button element', () => { + const closeBtnEl = wrapper + .find('.dropdown-title') + .findAll(GlButton) + .at(1); + + expect(closeBtnEl.exists()).toBe(true); + expect(closeBtnEl.attributes('aria-label')).toBe('Close'); + expect(closeBtnEl.find(GlIcon).props('name')).toBe('close'); + }); + + it('renders label title input element', () => { + const titleInputEl = wrapper.find('.dropdown-input').find(GlFormInput); + + expect(titleInputEl.exists()).toBe(true); + expect(titleInputEl.attributes('placeholder')).toBe('Name new label'); + expect(titleInputEl.attributes('autofocus')).toBe('true'); + }); + + it('renders color block element for all suggested colors', () => { + const colorBlocksEl = wrapper.find('.dropdown-content').findAll(GlLink); + + colorBlocksEl.wrappers.forEach((colorBlock, index) => { + expect(colorBlock.attributes('style')).toContain('background-color'); + expect(colorBlock.attributes('title')).toBe(Object.values(colors[index]).pop()); + }); + }); + + it('renders color input element', () => { + wrapper.setData({ + selectedColor: '#ff0000', + }); + + return wrapper.vm.$nextTick(() => { + const colorPreviewEl = wrapper.find( + '.color-input-container > .dropdown-label-color-preview', + ); + const colorInputEl = wrapper.find('.color-input-container').find(GlFormInput); + + expect(colorPreviewEl.exists()).toBe(true); + expect(colorPreviewEl.attributes('style')).toContain('background-color'); + expect(colorInputEl.exists()).toBe(true); + expect(colorInputEl.attributes('placeholder')).toBe('Use custom color #FF0000'); + expect(colorInputEl.attributes('value')).toBe('#ff0000'); + }); + }); + + it('renders create button element', () => { + const createBtnEl = wrapper + .find('.dropdown-actions') + .findAll(GlButton) + .at(0); + + expect(createBtnEl.exists()).toBe(true); + expect(createBtnEl.text()).toContain('Create'); + }); + + it('shows gl-loading-icon within create button element when `labelCreateInProgress` is `true`', () => { + wrapper.vm.$store.dispatch('requestCreateLabel'); + + return wrapper.vm.$nextTick(() => { + const loadingIconEl = wrapper.find('.dropdown-actions').find(GlLoadingIcon); + + expect(loadingIconEl.exists()).toBe(true); + expect(loadingIconEl.isVisible()).toBe(true); + }); + }); + + it('renders cancel button element', () => { + const cancelBtnEl = wrapper + .find('.dropdown-actions') + .findAll(GlButton) + .at(1); + + expect(cancelBtnEl.exists()).toBe(true); + expect(cancelBtnEl.text()).toContain('Cancel'); + }); + }); +}); |