diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 index a64818497c1..031e4f9b127 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 @@ -62,18 +62,33 @@ // Get the string to replace const selectionStart = input.selectionStart; - const { left } = gl.DropdownUtils.getInputSelectionPosition(input); + let { left, right } = gl.DropdownUtils.getInputSelectionPosition(input); + + if (right < 0) { + right = inputValue.length; + } + + if (left < 0) { + left += 1; + } + + input.value = `${inputValue.substr(0, left)}${word}${inputValue.substr(right + selectionStart)}`; + gl.FilteredSearchDropdownManager.updateInputCaretPosition(selectionStart, input); + } + + static updateInputCaretPosition(selectionStart, input) { + // Reset the position + // Sometimes can end up at end of input + input.setSelectionRange(selectionStart, selectionStart); + + const inputValue = input.value; let { right } = gl.DropdownUtils.getInputSelectionPosition(input); if (right < 0) { right = inputValue.length; } - if (left !== -1) { - input.value = `${inputValue.substr(0, left)}${word}${inputValue.substr(right + selectionStart)}`; - } else { - input.value += word; - } + input.setSelectionRange(selectionStart + right, selectionStart + right); } updateCurrentDropdownOffset() { diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 index f1912a83e81..c7b72b36561 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 @@ -194,17 +194,12 @@ return usernamesById; } - tokenChange(e) { + tokenChange() { const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown]; const currentDropdownRef = dropdown.reference; this.setDropdownWrapper(); currentDropdownRef.dispatchInputEvent(); - - if (e.type === 'click') { - // If click event, we need to trigger filter - this.filteredSearchInput.dispatchEvent(new Event('keyup')); - } } } diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index ead43d6784a..dff25b53e08 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -19,9 +19,12 @@ describe 'Filter issues', js: true, feature: true do let!(:closed_issue) { create(:issue, title: 'bug that is closed', project: project, state: :closed) } let(:filtered_search) { find('.filtered-search') } - def input_filtered_search(search_term) + def input_filtered_search(search_term, submit: true) filtered_search.set(search_term) - filtered_search.send_keys(:enter) + + if submit + filtered_search.send_keys(:enter) + end end def expect_filtered_search_input(input) @@ -43,6 +46,10 @@ describe 'Filter issues', js: true, feature: true do end end + def select_search_at_index(pos) + evaluate_script("el = document.querySelector('.filtered-search'); el.focus(); el.setSelectionRange(#{pos}, #{pos});") + end + before do project.team << [user, :master] project.team << [user2, :master] @@ -522,6 +529,32 @@ describe 'Filter issues', js: true, feature: true do end end + describe 'overwrites selected filter' do + it 'changes author' do + input_filtered_search("author:@#{user.username}", submit: false) + + select_search_at_index(3) + + page.within '#js-dropdown-author' do + click_button user2.username + end + + expect(filtered_search.value).to eq("author:@#{user2.username}") + end + + it 'changes label' do + input_filtered_search("author:@#{user.username} label:~#{bug_label.title}", submit: false) + + select_search_at_index(27) + + page.within '#js-dropdown-label' do + click_button label.name + end + + expect(filtered_search.value).to eq("author:@#{user.username} label:~#{label.name}") + end + end + describe 'filter issues by text' do context 'only text' do it 'filters issues by searched text' do