Commit ba1e3c2b authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '339596-disable-issue-epic-autocomplete-when-not-applicable' into 'master'

Fix incorrect trigger of issue/epic autocomplete

See merge request gitlab-org/gitlab!71191
parents 933c35c6 09faec22
...@@ -74,6 +74,16 @@ export default { ...@@ -74,6 +74,16 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
autoCompleteEpics: {
type: Boolean,
required: false,
default: true,
},
autoCompleteIssues: {
type: Boolean,
required: false,
default: true,
},
}, },
data() { data() {
return { return {
...@@ -177,7 +187,7 @@ export default { ...@@ -177,7 +187,7 @@ export default {
:path-id-separator="pathIdSeparator" :path-id-separator="pathIdSeparator"
:input-value="inputValue" :input-value="inputValue"
:auto-complete-sources="transformedAutocompleteSources" :auto-complete-sources="transformedAutocompleteSources"
:auto-complete-options="{ issues: true, epics: true }" :auto-complete-options="{ issues: autoCompleteIssues, epics: autoCompleteEpics }"
:issuable-type="issuableType" :issuable-type="issuableType"
@pendingIssuableRemoveRequest="onPendingIssuableRemoveRequest" @pendingIssuableRemoveRequest="onPendingIssuableRemoveRequest"
@formCancel="onFormCancel" @formCancel="onFormCancel"
......
...@@ -5,6 +5,7 @@ import { mapState, mapActions, mapGetters } from 'vuex'; ...@@ -5,6 +5,7 @@ import { mapState, mapActions, mapGetters } from 'vuex';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
import AddItemForm from '~/related_issues/components/add_issuable_form.vue'; import AddItemForm from '~/related_issues/components/add_issuable_form.vue';
import SlotSwitch from '~/vue_shared/components/slot_switch.vue'; import SlotSwitch from '~/vue_shared/components/slot_switch.vue';
import { issuableTypesMap } from '~/related_issues/constants';
import { OVERFLOW_AFTER } from '../constants'; import { OVERFLOW_AFTER } from '../constants';
import CreateEpicForm from './create_epic_form.vue'; import CreateEpicForm from './create_epic_form.vue';
import CreateIssueForm from './create_issue_form.vue'; import CreateIssueForm from './create_issue_form.vue';
...@@ -93,6 +94,12 @@ export default { ...@@ -93,6 +94,12 @@ export default {
{ name: createIssue, value: this.createIssuableText }, { name: createIssue, value: this.createIssuableText },
]; ];
}, },
enableEpicsAutoComplete() {
return this.issuableType === issuableTypesMap.EPIC && this.autoCompleteEpics;
},
enableIssuesAutoComplete() {
return this.issuableType === issuableTypesMap.ISSUE && this.autoCompleteIssues;
},
}, },
mounted() { mounted() {
this.fetchItems({ this.fetchItems({
...@@ -205,6 +212,8 @@ export default { ...@@ -205,6 +212,8 @@ export default {
:is-submitting="itemAddInProgress" :is-submitting="itemAddInProgress"
:pending-references="pendingReferences" :pending-references="pendingReferences"
:auto-complete-sources="itemAutoCompleteSources" :auto-complete-sources="itemAutoCompleteSources"
:auto-complete-epics="enableEpicsAutoComplete"
:auto-complete-issues="enableIssuesAutoComplete"
:path-id-separator="itemPathIdSeparator" :path-id-separator="itemPathIdSeparator"
:has-error="itemAddFailure" :has-error="itemAddFailure"
:item-add-failure-type="itemAddFailureType" :item-add-failure-type="itemAddFailureType"
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
group_name: @group.name, group_name: @group.name,
group_id: @group.id, group_id: @group.id,
full_path: @group.full_path, full_path: @group.full_path,
auto_complete_epics: 'true', auto_complete_epics: allow_sub_epics,
auto_complete_issues: 'true', auto_complete_issues: 'true',
user_signed_in: current_user.present? ? 'true' : 'false', user_signed_in: current_user.present? ? 'true' : 'false',
allow_sub_epics: allow_sub_epics, allow_sub_epics: allow_sub_epics,
......
...@@ -33,6 +33,18 @@ RSpec.describe 'Epic show', :js do ...@@ -33,6 +33,18 @@ RSpec.describe 'Epic show', :js do
sign_in(user) sign_in(user)
end end
def add_existing_item(type)
button_name = type == 'issue' ? 'Add an existing issue' : 'Add an existing epic'
input_character = type == 'issue' ? '#' : '&'
page.within('.js-epic-tabs-content #tree') do
find('.js-add-epics-issues-button .dropdown-toggle').click
click_button button_name
find('.js-add-issuable-form-input').native.send_keys(input_character)
wait_for_requests
end
end
describe 'when sub-epics feature is available' do describe 'when sub-epics feature is available' do
before do before do
visit group_epic_path(group, epic) visit group_epic_path(group, epic)
...@@ -59,6 +71,24 @@ RSpec.describe 'Epic show', :js do ...@@ -59,6 +71,24 @@ RSpec.describe 'Epic show', :js do
end end
end end
end end
it 'autocompletes issues when "#" is input in the add item form', :aggregate_failures do
add_existing_item('issue')
page.within('#atwho-ground-add-related-issues-form-input') do
expect(page).to have_selector('#at-view-issues', visible: true)
expect(page).not_to have_selector('#at-view-epics')
expect(page).to have_selector('.atwho-view-ul li', count: 1)
end
end
it 'autocompletes epics when "&" is input in the add item form', :aggregate_failures do
add_existing_item('epic')
page.within('#atwho-ground-add-related-issues-form-input') do
expect(page).not_to have_selector('#at-view-issues')
expect(page).to have_selector('#at-view-epics', visible: true)
expect(page).to have_selector('.atwho-view-ul li', count: 4)
end
end
end end
describe 'Roadmap tab' do describe 'Roadmap tab' do
......
...@@ -4,6 +4,8 @@ import AxiosMockAdapter from 'axios-mock-adapter'; ...@@ -4,6 +4,8 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex'; import Vuex from 'vuex';
import CreateIssueForm from 'ee/related_items_tree/components/create_issue_form.vue'; import CreateIssueForm from 'ee/related_items_tree/components/create_issue_form.vue';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
import SlotSwitch from '~/vue_shared/components/slot_switch.vue';
import RelatedItemsTreeApp from 'ee/related_items_tree/components/related_items_tree_app.vue'; import RelatedItemsTreeApp from 'ee/related_items_tree/components/related_items_tree_app.vue';
import RelatedItemsTreeHeader from 'ee/related_items_tree/components/related_items_tree_header.vue'; import RelatedItemsTreeHeader from 'ee/related_items_tree/components/related_items_tree_header.vue';
import createDefaultStore from 'ee/related_items_tree/store'; import createDefaultStore from 'ee/related_items_tree/store';
...@@ -31,6 +33,9 @@ const createComponent = () => { ...@@ -31,6 +33,9 @@ const createComponent = () => {
return shallowMount(RelatedItemsTreeApp, { return shallowMount(RelatedItemsTreeApp, {
localVue, localVue,
store, store,
stubs: {
SlotSwitch,
},
}); });
}; };
...@@ -39,6 +44,7 @@ describe('RelatedItemsTreeApp', () => { ...@@ -39,6 +44,7 @@ describe('RelatedItemsTreeApp', () => {
let wrapper; let wrapper;
const findCreateIssueForm = () => wrapper.find(CreateIssueForm); const findCreateIssueForm = () => wrapper.find(CreateIssueForm);
const findAddItemForm = () => wrapper.find(AddIssuableForm);
beforeEach(() => { beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios); axiosMock = new AxiosMockAdapter(axios);
...@@ -230,7 +236,7 @@ describe('RelatedItemsTreeApp', () => { ...@@ -230,7 +236,7 @@ describe('RelatedItemsTreeApp', () => {
it('renders item add/create form container element', () => { it('renders item add/create form container element', () => {
wrapper.vm.$store.dispatch('toggleAddItemForm', { wrapper.vm.$store.dispatch('toggleAddItemForm', {
toggleState: true, toggleState: true,
issuableType: issuableTypesMap.Epic, issuableType: issuableTypesMap.EPIC,
}); });
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
...@@ -241,5 +247,34 @@ describe('RelatedItemsTreeApp', () => { ...@@ -241,5 +247,34 @@ describe('RelatedItemsTreeApp', () => {
it('does not render create issue form', () => { it('does not render create issue form', () => {
expect(findCreateIssueForm().exists()).toBe(false); expect(findCreateIssueForm().exists()).toBe(false);
}); });
it.each`
issuableType | autoCompleteIssues | autoCompleteEpics | expectedAutoCompleteIssues | expectedAutoCompleteEpics
${issuableTypesMap.ISSUE} | ${true} | ${true} | ${true} | ${false}
${issuableTypesMap.EPIC} | ${true} | ${true} | ${false} | ${true}
`(
'enables $issuableType autocomplete only when "issuableType" is "$issuableType" and autocomplete for it is supported',
async ({
issuableType,
autoCompleteIssues,
autoCompleteEpics,
expectedAutoCompleteIssues,
expectedAutoCompleteEpics,
}) => {
wrapper.vm.$store.dispatch('toggleAddItemForm', {
toggleState: true,
issuableType,
});
wrapper.vm.$store.state.autoCompleteIssues = autoCompleteIssues;
wrapper.vm.$store.state.autoCompleteEpics = autoCompleteEpics;
await wrapper.vm.$nextTick();
expect(findAddItemForm().props()).toMatchObject({
autoCompleteIssues: expectedAutoCompleteIssues,
autoCompleteEpics: expectedAutoCompleteEpics,
});
},
);
}); });
}); });
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