summaryrefslogtreecommitdiff
path: root/spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view_spec.js')
-rw-r--r--spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view_spec.js211
1 files changed, 211 insertions, 0 deletions
diff --git a/spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view_spec.js b/spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view_spec.js
new file mode 100644
index 00000000000..59e95edfa20
--- /dev/null
+++ b/spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view_spec.js
@@ -0,0 +1,211 @@
+import { GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import Vuex from 'vuex';
+
+import DropdownContentsCreateView from '~/sidebar/components/labels/labels_select_vue/dropdown_contents_create_view.vue';
+
+import labelSelectModule from '~/sidebar/components/labels/labels_select_vue/store';
+
+import { mockConfig, mockSuggestedColors } from './mock_data';
+
+Vue.use(Vuex);
+
+const createComponent = (initialState = mockConfig) => {
+ const store = new Vuex.Store(labelSelectModule());
+
+ store.dispatch('setInitialState', initialState);
+
+ return shallowMount(DropdownContentsCreateView, {
+ 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', async () => {
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({
+ labelTitle: 'Foo',
+ selectedColor: '#ff0000',
+ });
+ wrapper.vm.$store.dispatch('requestCreateLabel');
+
+ await 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', async () => {
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({
+ labelTitle: 'Foo',
+ selectedColor: '#ff0000',
+ });
+
+ await 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`', async () => {
+ jest.spyOn(wrapper.vm, 'createLabel').mockImplementation();
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({
+ labelTitle: 'Foo',
+ selectedColor: '#ff0000',
+ });
+
+ wrapper.vm.handleCreateClick();
+
+ await 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').findAllComponents(GlButton).at(0);
+
+ expect(backBtnEl.exists()).toBe(true);
+ expect(backBtnEl.attributes('aria-label')).toBe('Go back');
+ expect(backBtnEl.props('icon')).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').findAllComponents(GlButton).at(1);
+
+ expect(closeBtnEl.exists()).toBe(true);
+ expect(closeBtnEl.attributes('aria-label')).toBe('Close');
+ expect(closeBtnEl.props('icon')).toBe('close');
+ });
+
+ it('renders label title input element', () => {
+ const titleInputEl = wrapper.find('.dropdown-input').findComponent(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').findAllComponents(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', async () => {
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({
+ selectedColor: '#ff0000',
+ });
+
+ await nextTick();
+ const colorPreviewEl = wrapper.find('.color-input-container > .dropdown-label-color-preview');
+ const colorInputEl = wrapper.find('.color-input-container').findComponent(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').findAllComponents(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`', async () => {
+ wrapper.vm.$store.dispatch('requestCreateLabel');
+
+ await nextTick();
+ const loadingIconEl = wrapper.find('.dropdown-actions').findComponent(GlLoadingIcon);
+
+ expect(loadingIconEl.exists()).toBe(true);
+ expect(loadingIconEl.isVisible()).toBe(true);
+ });
+
+ it('renders cancel button element', () => {
+ const cancelBtnEl = wrapper.find('.dropdown-actions').findAllComponents(GlButton).at(1);
+
+ expect(cancelBtnEl.exists()).toBe(true);
+ expect(cancelBtnEl.text()).toContain('Cancel');
+ });
+ });
+});