Commit 22fd1137 authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch 'ntepluhina-fix-swimlanes-on-edit-board' into 'master'

Fixed editing labels on the swimlanes sidebar

See merge request gitlab-org/gitlab!47946
parents 6967dd6d 1113e09f
...@@ -64,9 +64,9 @@ export default { ...@@ -64,9 +64,9 @@ export default {
<gl-button <gl-button
v-if="canUpdate" v-if="canUpdate"
variant="link" variant="link"
class="gl-text-gray-900!" class="gl-text-gray-900! js-sidebar-dropdown-toggle"
data-testid="edit-button" data-testid="edit-button"
@click="expand()" @click="expand"
> >
{{ __('Edit') }} {{ __('Edit') }}
</gl-button> </gl-button>
...@@ -75,7 +75,7 @@ export default { ...@@ -75,7 +75,7 @@ export default {
<slot name="collapsed">{{ __('None') }}</slot> <slot name="collapsed">{{ __('None') }}</slot>
</div> </div>
<div v-show="edit" data-testid="expanded-content"> <div v-show="edit" data-testid="expanded-content">
<slot></slot> <slot :edit="edit"></slot>
</div> </div>
</div> </div>
</template> </template>
...@@ -92,7 +92,7 @@ export default { ...@@ -92,7 +92,7 @@ export default {
@close="removeLabel(label.id)" @close="removeLabel(label.id)"
/> />
</template> </template>
<template> <template #default="{ edit }">
<labels-select <labels-select
ref="labelsSelect" ref="labelsSelect"
:allow-label-edit="false" :allow-label-edit="false"
...@@ -105,6 +105,7 @@ export default { ...@@ -105,6 +105,7 @@ export default {
:labels-filter-base-path="labelsFilterBasePath" :labels-filter-base-path="labelsFilterBasePath"
:labels-list-title="__('Select label')" :labels-list-title="__('Select label')"
:dropdown-button-text="__('Choose labels')" :dropdown-button-text="__('Choose labels')"
:is-editing="edit"
variant="embedded" variant="embedded"
class="gl-display-block labels gl-w-full" class="gl-display-block labels gl-w-full"
@updateSelectedLabels="setLabels" @updateSelectedLabels="setLabels"
......
...@@ -105,6 +105,11 @@ export default { ...@@ -105,6 +105,11 @@ export default {
required: false, required: false,
default: __('Manage group labels'), default: __('Manage group labels'),
}, },
isEditing: {
type: Boolean,
required: false,
default: false,
},
}, },
data() { data() {
return { return {
...@@ -131,6 +136,11 @@ export default { ...@@ -131,6 +136,11 @@ export default {
showDropdownContents(showDropdownContents) { showDropdownContents(showDropdownContents) {
this.setContentIsOnViewport(showDropdownContents); this.setContentIsOnViewport(showDropdownContents);
}, },
isEditing(newVal) {
if (newVal) {
this.toggleDropdownContents();
}
},
}, },
mounted() { mounted() {
this.setInitialState({ this.setInitialState({
......
---
title: Fixed editing labels on the swimlanes sidebar
merge_request: 47946
author:
type: fixed
...@@ -20,22 +20,24 @@ jest.mock('~/lib/utils/common_utils', () => ({ ...@@ -20,22 +20,24 @@ jest.mock('~/lib/utils/common_utils', () => ({
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
const createComponent = (config = mockConfig, slots = {}) =>
shallowMount(LabelsSelectRoot, {
localVue,
slots,
store: new Vuex.Store(labelsSelectModule()),
propsData: config,
stubs: {
'dropdown-contents': DropdownContents,
},
});
describe('LabelsSelectRoot', () => { describe('LabelsSelectRoot', () => {
let wrapper; let wrapper;
let store;
const createComponent = (config = mockConfig, slots = {}) => {
wrapper = shallowMount(LabelsSelectRoot, {
localVue,
slots,
store,
propsData: config,
stubs: {
'dropdown-contents': DropdownContents,
},
});
};
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); store = new Vuex.Store(labelsSelectModule());
}); });
afterEach(() => { afterEach(() => {
...@@ -45,6 +47,7 @@ describe('LabelsSelectRoot', () => { ...@@ -45,6 +47,7 @@ describe('LabelsSelectRoot', () => {
describe('methods', () => { describe('methods', () => {
describe('handleVuexActionDispatch', () => { describe('handleVuexActionDispatch', () => {
it('calls `handleDropdownClose` when params `action.type` is `toggleDropdownContents` and state has `showDropdownButton` & `showDropdownContents` props `false`', () => { it('calls `handleDropdownClose` when params `action.type` is `toggleDropdownContents` and state has `showDropdownButton` & `showDropdownContents` props `false`', () => {
createComponent();
jest.spyOn(wrapper.vm, 'handleDropdownClose').mockImplementation(); jest.spyOn(wrapper.vm, 'handleDropdownClose').mockImplementation();
wrapper.vm.handleVuexActionDispatch( wrapper.vm.handleVuexActionDispatch(
...@@ -67,7 +70,7 @@ describe('LabelsSelectRoot', () => { ...@@ -67,7 +70,7 @@ describe('LabelsSelectRoot', () => {
}); });
it('calls `handleDropdownClose` with state.labels filterd using `set` prop when dropdown variant is `embedded`', () => { it('calls `handleDropdownClose` with state.labels filterd using `set` prop when dropdown variant is `embedded`', () => {
wrapper = createComponent({ createComponent({
...mockConfig, ...mockConfig,
variant: 'embedded', variant: 'embedded',
}); });
...@@ -95,6 +98,10 @@ describe('LabelsSelectRoot', () => { ...@@ -95,6 +98,10 @@ describe('LabelsSelectRoot', () => {
}); });
describe('handleDropdownClose', () => { describe('handleDropdownClose', () => {
beforeEach(() => {
createComponent();
});
it('emits `updateSelectedLabels` & `onDropdownClose` events on component when provided `labels` param is not empty', () => { it('emits `updateSelectedLabels` & `onDropdownClose` events on component when provided `labels` param is not empty', () => {
wrapper.vm.handleDropdownClose([{ id: 1 }, { id: 2 }]); wrapper.vm.handleDropdownClose([{ id: 1 }, { id: 2 }]);
...@@ -112,6 +119,7 @@ describe('LabelsSelectRoot', () => { ...@@ -112,6 +119,7 @@ describe('LabelsSelectRoot', () => {
describe('handleCollapsedValueClick', () => { describe('handleCollapsedValueClick', () => {
it('emits `toggleCollapse` event on component', () => { it('emits `toggleCollapse` event on component', () => {
createComponent();
wrapper.vm.handleCollapsedValueClick(); wrapper.vm.handleCollapsedValueClick();
expect(wrapper.emitted().toggleCollapse).toBeTruthy(); expect(wrapper.emitted().toggleCollapse).toBeTruthy();
...@@ -121,6 +129,7 @@ describe('LabelsSelectRoot', () => { ...@@ -121,6 +129,7 @@ describe('LabelsSelectRoot', () => {
describe('template', () => { describe('template', () => {
it('renders component with classes `labels-select-wrapper position-relative`', () => { it('renders component with classes `labels-select-wrapper position-relative`', () => {
createComponent();
expect(wrapper.attributes('class')).toContain('labels-select-wrapper position-relative'); expect(wrapper.attributes('class')).toContain('labels-select-wrapper position-relative');
}); });
...@@ -131,7 +140,7 @@ describe('LabelsSelectRoot', () => { ...@@ -131,7 +140,7 @@ describe('LabelsSelectRoot', () => {
`( `(
'renders component root element with CSS class `$cssClass` when `state.variant` is "$variant"', 'renders component root element with CSS class `$cssClass` when `state.variant` is "$variant"',
({ variant, cssClass }) => { ({ variant, cssClass }) => {
wrapper = createComponent({ createComponent({
...mockConfig, ...mockConfig,
variant, variant,
}); });
...@@ -142,57 +151,58 @@ describe('LabelsSelectRoot', () => { ...@@ -142,57 +151,58 @@ describe('LabelsSelectRoot', () => {
}, },
); );
it('renders `dropdown-value-collapsed` component when `allowLabelCreate` prop is `true`', () => { it('renders `dropdown-value-collapsed` component when `allowLabelCreate` prop is `true`', async () => {
createComponent();
await wrapper.vm.$nextTick;
expect(wrapper.find(DropdownValueCollapsed).exists()).toBe(true); expect(wrapper.find(DropdownValueCollapsed).exists()).toBe(true);
}); });
it('renders `dropdown-title` component', () => { it('renders `dropdown-title` component', async () => {
createComponent();
await wrapper.vm.$nextTick;
expect(wrapper.find(DropdownTitle).exists()).toBe(true); expect(wrapper.find(DropdownTitle).exists()).toBe(true);
}); });
it('renders `dropdown-value` component', () => { it('renders `dropdown-value` component', async () => {
const wrapperDropdownValue = createComponent(mockConfig, { createComponent(mockConfig, {
default: 'None', default: 'None',
}); });
await wrapper.vm.$nextTick;
return wrapperDropdownValue.vm.$nextTick(() => { const valueComp = wrapper.find(DropdownValue);
const valueComp = wrapperDropdownValue.find(DropdownValue);
expect(valueComp.exists()).toBe(true); expect(valueComp.exists()).toBe(true);
expect(valueComp.text()).toBe('None'); expect(valueComp.text()).toBe('None');
wrapperDropdownValue.destroy();
});
}); });
it('renders `dropdown-button` component when `showDropdownButton` prop is `true`', () => { it('renders `dropdown-button` component when `showDropdownButton` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownButton'); wrapper.vm.$store.dispatch('toggleDropdownButton');
await wrapper.vm.$nextTick;
expect(wrapper.find(DropdownButton).exists()).toBe(true); expect(wrapper.find(DropdownButton).exists()).toBe(true);
}); });
it('renders `dropdown-contents` component when `showDropdownButton` & `showDropdownContents` prop is `true`', () => { it('renders `dropdown-contents` component when `showDropdownButton` & `showDropdownContents` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownContents'); wrapper.vm.$store.dispatch('toggleDropdownContents');
await wrapper.vm.$nextTick;
return wrapper.vm.$nextTick(() => { expect(wrapper.find(DropdownContents).exists()).toBe(true);
expect(wrapper.find(DropdownContents).exists()).toBe(true);
});
}); });
describe('sets content direction based on viewport', () => { describe('sets content direction based on viewport', () => {
it('does not set direction when `state.variant` is not "embedded"', () => { it('does not set direction when `state.variant` is not "embedded"', async () => {
wrapper.vm.$store.dispatch('toggleDropdownContents'); createComponent();
wrapper.vm.$store.dispatch('toggleDropdownContents');
wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state); wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
await wrapper.vm.$nextTick;
return wrapper.vm.$nextTick().then(() => { expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false);
expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false);
});
}); });
describe('when `state.variant` is "embedded"', () => { describe('when `state.variant` is "embedded"', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent({ ...mockConfig, variant: 'embedded' }); createComponent({ ...mockConfig, variant: 'embedded' });
wrapper.vm.$store.dispatch('toggleDropdownContents'); wrapper.vm.$store.dispatch('toggleDropdownContents');
}); });
...@@ -216,4 +226,22 @@ describe('LabelsSelectRoot', () => { ...@@ -216,4 +226,22 @@ describe('LabelsSelectRoot', () => {
}); });
}); });
}); });
it('calls toggleDropdownContents action when isEditing prop is changing to true', async () => {
createComponent();
jest.spyOn(store, 'dispatch').mockResolvedValue();
await wrapper.setProps({ isEditing: true });
expect(store.dispatch).toHaveBeenCalledWith('toggleDropdownContents');
});
it('does not call toggleDropdownContents action when isEditing prop is changing to false', async () => {
createComponent();
jest.spyOn(store, 'dispatch').mockResolvedValue();
await wrapper.setProps({ isEditing: false });
expect(store.dispatch).not.toHaveBeenCalled();
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment