From 1d59a6fb13d21d8d5c3ff82ebdfc5c7e04b26366 Mon Sep 17 00:00:00 2001 From: Simon Knox <simon@gitlab.com> Date: Thu, 4 Mar 2021 06:49:11 +0000 Subject: [PATCH] Split new column form into data/display components Makes it easier to extend for different types of list in EE --- .../components/board_add_new_column.vue | 216 ++++++------------ .../components/board_add_new_column_form.vue | 122 ++++++++++ .../javascripts/boards/stores/actions.js | 4 +- .../javascripts/boards/stores/mutations.js | 7 +- .../javascripts/boards/stores/actions.js | 2 +- .../frontend/boards/stores/actions_spec.js | 4 +- locale/gitlab.pot | 7 +- .../board_add_new_column_form_spec.js | 166 ++++++++++++++ .../components/board_add_new_column_spec.js | 70 ++---- spec/frontend/boards/stores/actions_spec.js | 4 +- 10 files changed, 383 insertions(+), 219 deletions(-) create mode 100644 app/assets/javascripts/boards/components/board_add_new_column_form.vue create mode 100644 spec/frontend/boards/components/board_add_new_column_form_spec.js diff --git a/app/assets/javascripts/boards/components/board_add_new_column.vue b/app/assets/javascripts/boards/components/board_add_new_column.vue index 7818d45507e..ce4590bd755 100644 --- a/app/assets/javascripts/boards/components/board_add_new_column.vue +++ b/app/assets/javascripts/boards/components/board_add_new_column.vue @@ -1,38 +1,23 @@ <script> import { - GlButton, - GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLabel, - GlSearchBoxByType, - GlSkeletonLoader, GlTooltipDirective as GlTooltip, } from '@gitlab/ui'; import { mapActions, mapGetters, mapState } from 'vuex'; +import BoardAddNewColumnForm from '~/boards/components/board_add_new_column_form.vue'; +import { ListType } from '~/boards/constants'; +import boardsStore from '~/boards/stores/boards_store'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { isScopedLabel } from '~/lib/utils/common_utils'; -import { __ } from '~/locale'; -import boardsStore from '../stores/boards_store'; export default { - i18n: { - add: __('Add'), - cancel: __('Cancel'), - formDescription: __('A label list displays all issues with the selected label.'), - newLabelList: __('New label list'), - noLabelSelected: __('No label selected'), - searchPlaceholder: __('Search labels'), - selectLabel: __('Select label'), - selected: __('Selected'), - }, components: { - GlButton, - GlFormGroup, + BoardAddNewColumnForm, GlFormRadio, GlFormRadioGroup, GlLabel, - GlSearchBoxByType, - GlSkeletonLoader, }, directives: { GlTooltip, @@ -40,31 +25,27 @@ export default { inject: ['scopedLabelsAvailable'], data() { return { - searchTerm: '', - selectedLabelId: null, + selectedId: null, }; }, computed: { ...mapState(['labels', 'labelsLoading', 'isEpicBoard']), ...mapGetters(['getListByLabelId', 'shouldUseGraphQL']), selectedLabel() { - return this.labels.find(({ id }) => id === this.selectedLabelId); + if (!this.selectedId) { + return null; + } + return this.labels.find(({ id }) => id === this.selectedId); + }, + columnForSelected() { + return this.getListByLabelId(this.selectedId); }, }, created() { - this.filterLabels(); + this.filterItems(); }, methods: { ...mapActions(['createList', 'fetchLabels', 'highlightList', 'setAddColumnFormVisibility']), - getListByLabel(label) { - if (this.shouldUseGraphQL || this.isEpicBoard) { - return this.getListByLabelId(label); - } - return boardsStore.findListByLabelId(label.id); - }, - columnExists(label) { - return Boolean(this.getListByLabel(label)); - }, highlight(listId) { if (this.shouldUseGraphQL || this.isEpicBoard) { this.highlightList(listId); @@ -77,44 +58,35 @@ export default { } }, addList() { - if (!this.selectedLabelId) { - return; - } - - const label = this.selectedLabel; - - if (!label) { + if (!this.selectedLabel) { return; } this.setAddColumnFormVisibility(false); - if (this.columnExists({ id: this.selectedLabelId })) { - const listId = this.getListByLabel(label).id; + if (this.columnForSelected) { + const listId = this.columnForSelected.id; this.highlight(listId); return; } if (this.shouldUseGraphQL || this.isEpicBoard) { - this.createList({ labelId: this.selectedLabelId }); + this.createList({ labelId: this.selectedId }); } else { - boardsStore.new({ - title: label.title, + const listObj = { + labelId: getIdFromGraphQLId(this.selectedId), + title: this.selectedLabel.title, position: boardsStore.state.lists.length - 2, - list_type: 'label', - label: { - id: label.id, - title: label.title, - color: label.color, - }, - }); + list_type: ListType.label, + label: this.selectedLabel, + }; - this.highlight(boardsStore.findListByLabelId(label.id).id); + boardsStore.new(listObj); } }, - filterLabels() { - this.fetchLabels(this.searchTerm); + filterItems(searchTerm) { + this.fetchLabels(searchTerm); }, showScopedLabels(label) { @@ -125,103 +97,43 @@ export default { </script> <template> - <div - class="board-add-new-list board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal gl-flex-shrink-0" - data-testid="board-add-new-column" - data-qa-selector="board_add_new_list" + <board-add-new-column-form + :loading="labelsLoading" + :form-description="__('A label list displays issues with the selected label.')" + :search-label="__('Select label')" + :search-placeholder="__('Search labels')" + :selected-id="selectedId" + @filter-items="filterItems" + @add-list="addList" > - <div - class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base gl-bg-white" - > - <h3 - class="gl-font-base gl-px-5 gl-py-5 gl-m-0 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100" - data-testid="board-add-column-form-title" - > - {{ $options.i18n.newLabelList }} - </h3> - - <div class="gl-display-flex gl-flex-direction-column gl-h-full gl-overflow-hidden"> - <!-- selectbox is here in EE --> - - <p class="gl-m-5">{{ $options.i18n.formDescription }}</p> - - <div class="gl-px-5 gl-pb-4"> - <label class="gl-mb-2">{{ $options.i18n.selected }}</label> - <div> - <gl-label - v-if="selectedLabel" - v-gl-tooltip - :title="selectedLabel.title" - :description="selectedLabel.description" - :background-color="selectedLabel.color" - :scoped="showScopedLabels(selectedLabel)" - /> - <div v-else class="gl-text-gray-500">{{ $options.i18n.noLabelSelected }}</div> - </div> - </div> - - <gl-form-group - class="gl-mx-5 gl-mb-3" - :label="$options.i18n.selectLabel" - label-for="board-available-labels" - > - <gl-search-box-by-type - id="board-available-labels" - v-model.trim="searchTerm" - debounce="250" - :placeholder="$options.i18n.searchPlaceholder" - @input="filterLabels" - /> - </gl-form-group> - - <div v-if="labelsLoading" class="gl-m-5"> - <gl-skeleton-loader :width="500" :height="172"> - <rect width="480" height="20" x="10" y="15" rx="4" /> - <rect width="380" height="20" x="10" y="50" rx="4" /> - <rect width="430" height="20" x="10" y="85" rx="4" /> - </gl-skeleton-loader> - </div> - - <gl-form-radio-group - v-else - v-model="selectedLabelId" - class="gl-overflow-y-auto gl-px-5 gl-pt-3" - > - <label - v-for="label in labels" - :key="label.id" - class="gl-display-flex gl-flex-align-items-center gl-mb-5 gl-font-weight-normal" - > - <gl-form-radio :value="label.id" class="gl-mb-0 gl-mr-3" /> - <span - class="dropdown-label-box gl-top-0" - :style="{ - backgroundColor: label.color, - }" - ></span> - <span>{{ label.title }}</span> - </label> - </gl-form-radio-group> - </div> - - <div - class="gl-display-flex gl-p-3 gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10" - > - <gl-button - data-testid="cancelAddNewColumn" - class="gl-ml-auto gl-mr-3" - @click="setAddColumnFormVisibility(false)" - >{{ $options.i18n.cancel }}</gl-button - > - <gl-button - data-testid="addNewColumnButton" - :disabled="!selectedLabelId" - variant="success" - class="gl-mr-4" - @click="addList" - >{{ $options.i18n.add }}</gl-button + <template slot="selected"> + <gl-label + v-if="selectedLabel" + v-gl-tooltip + :title="selectedLabel.title" + :description="selectedLabel.description" + :background-color="selectedLabel.color" + :scoped="showScopedLabels(selectedLabel)" + /> + </template> + + <template slot="items"> + <gl-form-radio-group v-model="selectedId" class="gl-overflow-y-auto gl-px-5 gl-pt-3"> + <label + v-for="label in labels" + :key="label.id" + class="gl-display-flex gl-flex-align-items-center gl-mb-5 gl-font-weight-normal" > - </div> - </div> - </div> + <gl-form-radio :value="label.id" class="gl-mb-0 gl-mr-3" /> + <span + class="dropdown-label-box gl-top-0" + :style="{ + backgroundColor: label.color, + }" + ></span> + <span>{{ label.title }}</span> + </label> + </gl-form-radio-group> + </template> + </board-add-new-column-form> </template> diff --git a/app/assets/javascripts/boards/components/board_add_new_column_form.vue b/app/assets/javascripts/boards/components/board_add_new_column_form.vue new file mode 100644 index 00000000000..99699943e02 --- /dev/null +++ b/app/assets/javascripts/boards/components/board_add_new_column_form.vue @@ -0,0 +1,122 @@ +<script> +import { GlButton, GlFormGroup, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui'; +import { mapActions } from 'vuex'; +import { __ } from '~/locale'; + +export default { + i18n: { + add: __('Add'), + cancel: __('Cancel'), + newList: __('New list'), + noneSelected: __('None'), + selected: __('Selected'), + }, + components: { + GlButton, + GlFormGroup, + GlSearchBoxByType, + GlSkeletonLoader, + }, + props: { + loading: { + type: Boolean, + required: true, + }, + formDescription: { + type: String, + required: true, + }, + searchLabel: { + type: String, + required: true, + }, + searchPlaceholder: { + type: String, + required: true, + }, + selectedId: { + type: [Number, String], + required: false, + default: null, + }, + }, + methods: { + ...mapActions(['setAddColumnFormVisibility']), + }, +}; +</script> + +<template> + <div + class="board-add-new-list board gl-display-inline-block gl-h-full gl-px-3 gl-vertical-align-top gl-white-space-normal gl-flex-shrink-0" + data-testid="board-add-new-column" + data-qa-selector="board_add_new_list" + > + <div + class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base gl-bg-white" + > + <h3 + class="gl-font-base gl-px-5 gl-py-5 gl-m-0 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100" + data-testid="board-add-column-form-title" + > + {{ $options.i18n.newList }} + </h3> + + <div class="gl-display-flex gl-flex-direction-column gl-h-full gl-overflow-hidden"> + <slot name="select-list-type"> + <div class="gl-mb-5"></div> + </slot> + + <p class="gl-px-5">{{ formDescription }}</p> + + <div class="gl-px-5 gl-pb-4"> + <label class="gl-mb-2">{{ $options.i18n.selected }}</label> + <slot name="selected"> + <div class="gl-text-gray-500">{{ $options.i18n.noneSelected }}</div> + </slot> + </div> + + <gl-form-group + class="gl-mx-5 gl-mb-3" + :label="searchLabel" + label-for="board-available-column-entities" + > + <gl-search-box-by-type + id="board-available-column-entities" + debounce="250" + :placeholder="searchPlaceholder" + @input="$emit('filter-items', $event)" + /> + </gl-form-group> + + <div v-if="loading" class="gl-px-5"> + <gl-skeleton-loader :width="500" :height="172"> + <rect width="480" height="20" x="10" y="15" rx="4" /> + <rect width="380" height="20" x="10" y="50" rx="4" /> + <rect width="430" height="20" x="10" y="85" rx="4" /> + </gl-skeleton-loader> + </div> + + <slot v-else name="items"></slot> + </div> + <div + class="gl-display-flex gl-p-3 gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10" + > + <gl-button + data-testid="cancelAddNewColumn" + class="gl-ml-auto gl-mr-3" + @click="setAddColumnFormVisibility(false)" + >{{ $options.i18n.cancel }}</gl-button + > + <gl-button + data-testid="addNewColumnButton" + :disabled="!selectedId" + variant="success" + class="gl-mr-4" + @click="$emit('add-list')" + >{{ $options.i18n.add }}</gl-button + > + </div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index f5f2bd6b74c..e84f1b3359a 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -157,8 +157,8 @@ export default { }, }) .then(({ data }) => { - if (data?.boardListCreate?.errors.length) { - commit(types.CREATE_LIST_FAILURE); + if (data.boardListCreate?.errors.length) { + commit(types.CREATE_LIST_FAILURE, data.boardListCreate.errors[0]); } else { const list = data.boardListCreate?.list; dispatch('addList', list); diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js index 99a3f3c8f86..96e7812fbe2 100644 --- a/app/assets/javascripts/boards/stores/mutations.js +++ b/app/assets/javascripts/boards/stores/mutations.js @@ -60,8 +60,11 @@ export default { state.filterParams = filterParams; }, - [mutationTypes.CREATE_LIST_FAILURE]: (state) => { - state.error = s__('Boards|An error occurred while creating the list. Please try again.'); + [mutationTypes.CREATE_LIST_FAILURE]: ( + state, + error = s__('Boards|An error occurred while creating the list. Please try again.'), + ) => { + state.error = error; }, [mutationTypes.RECEIVE_LABELS_REQUEST]: (state) => { diff --git a/ee/app/assets/javascripts/boards/stores/actions.js b/ee/app/assets/javascripts/boards/stores/actions.js index 8afff0d93cc..38f04c4b192 100644 --- a/ee/app/assets/javascripts/boards/stores/actions.js +++ b/ee/app/assets/javascripts/boards/stores/actions.js @@ -587,7 +587,7 @@ export default { }) .then(({ data }) => { if (data?.epicBoardListCreate?.errors.length) { - commit(types.CREATE_LIST_FAILURE); + commit(types.CREATE_LIST_FAILURE, data.epicBoardListCreate.errors[0]); } else { const list = data.epicBoardListCreate?.list; dispatch('addList', list); diff --git a/ee/spec/frontend/boards/stores/actions_spec.js b/ee/spec/frontend/boards/stores/actions_spec.js index 694f9e3c624..8e96a22c4df 100644 --- a/ee/spec/frontend/boards/stores/actions_spec.js +++ b/ee/spec/frontend/boards/stores/actions_spec.js @@ -1026,14 +1026,14 @@ describe('moveIssue', () => { data: { epicBoardListCreate: { list: {}, - errors: [{ foo: 'bar' }], + errors: ['foo'], }, }, }); await actions.createEpicList({ getters, state, commit, dispatch }, { backlog: true }); - expect(commit).toHaveBeenCalledWith(types.CREATE_LIST_FAILURE); + expect(commit).toHaveBeenCalledWith(types.CREATE_LIST_FAILURE, 'foo'); }); it('highlights list and does not re-query if it already exists', async () => { diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e7916e963f7..31e844d7d31 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1330,7 +1330,7 @@ msgstr "" msgid "A job artifact is an archive of files and directories saved by a job when it finishes." msgstr "" -msgid "A label list displays all issues with the selected label." +msgid "A label list displays issues with the selected label." msgstr "" msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies." @@ -20298,7 +20298,7 @@ msgstr "" msgid "New label" msgstr "" -msgid "New label list" +msgid "New list" msgstr "" msgid "New merge request" @@ -20520,9 +20520,6 @@ msgstr "" msgid "No label" msgstr "" -msgid "No label selected" -msgstr "" - msgid "No labels with such name or description" msgstr "" diff --git a/spec/frontend/boards/components/board_add_new_column_form_spec.js b/spec/frontend/boards/components/board_add_new_column_form_spec.js new file mode 100644 index 00000000000..3702f55f17b --- /dev/null +++ b/spec/frontend/boards/components/board_add_new_column_form_spec.js @@ -0,0 +1,166 @@ +import { GlFormGroup, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; +import Vuex from 'vuex'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import BoardAddNewColumnForm from '~/boards/components/board_add_new_column_form.vue'; +import defaultState from '~/boards/stores/state'; +import { mockLabelList } from '../mock_data'; + +Vue.use(Vuex); + +describe('Board card layout', () => { + let wrapper; + + const createStore = ({ actions = {}, getters = {}, state = {} } = {}) => { + return new Vuex.Store({ + state: { + ...defaultState, + ...state, + }, + actions, + getters, + }); + }; + + const mountComponent = ({ + loading = false, + formDescription = '', + searchLabel = '', + searchPlaceholder = '', + selectedId, + actions, + slots, + } = {}) => { + wrapper = extendedWrapper( + shallowMount(BoardAddNewColumnForm, { + stubs: { + GlFormGroup: true, + }, + propsData: { + loading, + formDescription, + searchLabel, + searchPlaceholder, + selectedId, + }, + slots, + store: createStore({ + actions: { + setAddColumnFormVisibility: jest.fn(), + ...actions, + }, + }), + }), + ); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const formTitle = () => wrapper.findByTestId('board-add-column-form-title').text(); + const findSearchInput = () => wrapper.find(GlSearchBoxByType); + const findSearchLabel = () => wrapper.find(GlFormGroup); + const cancelButton = () => wrapper.findByTestId('cancelAddNewColumn'); + const submitButton = () => wrapper.findByTestId('addNewColumnButton'); + + it('shows form title & search input', () => { + mountComponent(); + + expect(formTitle()).toEqual(BoardAddNewColumnForm.i18n.newList); + expect(findSearchInput().exists()).toBe(true); + }); + + it('clicking cancel hides the form', () => { + const setAddColumnFormVisibility = jest.fn(); + mountComponent({ + actions: { + setAddColumnFormVisibility, + }, + }); + + cancelButton().vm.$emit('click'); + + expect(setAddColumnFormVisibility).toHaveBeenCalledWith(expect.anything(), false); + }); + + it('sets placeholder and description from props', () => { + const props = { + formDescription: 'Some description of a list', + }; + + mountComponent(props); + + expect(wrapper.html()).toHaveText(props.formDescription); + }); + + describe('items', () => { + const mountWithItems = (loading) => + mountComponent({ + loading, + slots: { + items: '<div class="item-slot">Some kind of list</div>', + }, + }); + + it('hides items slot and shows skeleton while loading', () => { + mountWithItems(true); + + expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true); + expect(wrapper.find('.item-slot').exists()).toBe(false); + }); + + it('shows items slot and hides skeleton while not loading', () => { + mountWithItems(false); + + expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false); + expect(wrapper.find('.item-slot').exists()).toBe(true); + }); + }); + + describe('search box', () => { + it('sets label and placeholder text from props', () => { + const props = { + searchLabel: 'Some items', + searchPlaceholder: 'Search for an item', + }; + + mountComponent(props); + + expect(findSearchLabel().attributes('label')).toEqual(props.searchLabel); + expect(findSearchInput().attributes('placeholder')).toEqual(props.searchPlaceholder); + }); + + it('emits filter event on input', () => { + mountComponent(); + + const searchText = 'some text'; + + findSearchInput().vm.$emit('input', searchText); + + expect(wrapper.emitted('filter-items')).toEqual([[searchText]]); + }); + }); + + describe('Add list button', () => { + it('is disabled if no item is selected', () => { + mountComponent(); + + expect(submitButton().props('disabled')).toBe(true); + }); + + it('emits add-list event on click', async () => { + mountComponent({ + selectedId: mockLabelList.label.id, + }); + + await nextTick(); + + submitButton().vm.$emit('click'); + + expect(wrapper.emitted('add-list')).toEqual([[]]); + }); + }); +}); diff --git a/spec/frontend/boards/components/board_add_new_column_spec.js b/spec/frontend/boards/components/board_add_new_column_spec.js index 84b6d7abb1e..60584eaf6cf 100644 --- a/spec/frontend/boards/components/board_add_new_column_spec.js +++ b/spec/frontend/boards/components/board_add_new_column_spec.js @@ -1,9 +1,9 @@ -import { GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import BoardAddNewColumn from '~/boards/components/board_add_new_column.vue'; +import BoardAddNewColumnForm from '~/boards/components/board_add_new_column_form.vue'; import defaultState from '~/boards/stores/state'; import { mockLabelList } from '../mock_data'; @@ -11,7 +11,6 @@ Vue.use(Vuex); describe('Board card layout', () => { let wrapper; - let shouldUseGraphQL; const createStore = ({ actions = {}, getters = {}, state = {} } = {}) => { return new Vuex.Store({ @@ -25,19 +24,16 @@ describe('Board card layout', () => { }; const mountComponent = ({ - selectedLabelId, + selectedId, labels = [], getListByLabelId = jest.fn(), actions = {}, } = {}) => { wrapper = extendedWrapper( shallowMount(BoardAddNewColumn, { - stubs: { - GlFormGroup: true, - }, data() { return { - selectedLabelId, + selectedId, }; }, store: createStore({ @@ -47,12 +43,13 @@ describe('Board card layout', () => { ...actions, }, getters: { - shouldUseGraphQL: () => shouldUseGraphQL, + shouldUseGraphQL: () => true, getListByLabelId: () => getListByLabelId, }, state: { labels, labelsLoading: false, + isEpicBoard: false, }, }), provide: { @@ -64,65 +61,32 @@ describe('Board card layout', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; - }); - - const formTitle = () => wrapper.findByTestId('board-add-column-form-title').text(); - const findSearchInput = () => wrapper.find(GlSearchBoxByType); - const cancelButton = () => wrapper.findByTestId('cancelAddNewColumn'); - const submitButton = () => wrapper.findByTestId('addNewColumnButton'); - - beforeEach(() => { - shouldUseGraphQL = true; - }); - - it('shows form title & search input', () => { - mountComponent(); - - expect(formTitle()).toEqual(BoardAddNewColumn.i18n.newLabelList); - expect(findSearchInput().exists()).toBe(true); - }); - - it('clicking cancel hides the form', () => { - const setAddColumnFormVisibility = jest.fn(); - mountComponent({ - actions: { - setAddColumnFormVisibility, - }, - }); - - cancelButton().vm.$emit('click'); - - expect(setAddColumnFormVisibility).toHaveBeenCalledWith(expect.anything(), false); }); describe('Add list button', () => { - it('is disabled if no item is selected', () => { - mountComponent(); - - expect(submitButton().props('disabled')).toBe(true); - }); - - it('adds a new list on click', async () => { - const labelId = mockLabelList.label.id; + it('calls addList', async () => { + const getListByLabelId = jest.fn().mockReturnValue(null); const highlightList = jest.fn(); const createList = jest.fn(); mountComponent({ labels: [mockLabelList.label], - selectedLabelId: labelId, + selectedId: mockLabelList.label.id, + getListByLabelId, actions: { createList, highlightList, }, }); - await nextTick(); + wrapper.findComponent(BoardAddNewColumnForm).vm.$emit('add-list'); - submitButton().vm.$emit('click'); + await nextTick(); expect(highlightList).not.toHaveBeenCalled(); - expect(createList).toHaveBeenCalledWith(expect.anything(), { labelId }); + expect(createList).toHaveBeenCalledWith(expect.anything(), { + labelId: mockLabelList.label.id, + }); }); it('highlights existing list if trying to re-add', async () => { @@ -132,7 +96,7 @@ describe('Board card layout', () => { mountComponent({ labels: [mockLabelList.label], - selectedLabelId: mockLabelList.label.id, + selectedId: mockLabelList.label.id, getListByLabelId, actions: { createList, @@ -140,9 +104,9 @@ describe('Board card layout', () => { }, }); - await nextTick(); + wrapper.findComponent(BoardAddNewColumnForm).vm.$emit('add-list'); - submitButton().vm.$emit('click'); + await nextTick(); expect(highlightList).toHaveBeenCalledWith(expect.anything(), mockLabelList.id); expect(createList).not.toHaveBeenCalled(); diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index 9e1b5018cc1..377c606ac92 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -293,7 +293,7 @@ describe('createIssueList', () => { data: { boardListCreate: { list: {}, - errors: [{ foo: 'bar' }], + errors: ['foo'], }, }, }), @@ -301,7 +301,7 @@ describe('createIssueList', () => { await actions.createIssueList({ getters, state, commit, dispatch }, { backlog: true }); - expect(commit).toHaveBeenCalledWith(types.CREATE_LIST_FAILURE); + expect(commit).toHaveBeenCalledWith(types.CREATE_LIST_FAILURE, 'foo'); }); it('highlights list and does not re-query if it already exists', async () => { -- 2.30.9