diff options
Diffstat (limited to 'spec/features/issues/gfm_autocomplete_spec.rb')
-rw-r--r-- | spec/features/issues/gfm_autocomplete_spec.rb | 198 |
1 files changed, 178 insertions, 20 deletions
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 0b2e8013304..3757985f99c 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -487,7 +487,7 @@ RSpec.describe 'GFM autocomplete', :js do wait_for_requests - find('.tribute-container .highlight').click + find('.tribute-container .highlight', visible: true).click click_button 'Save changes' @@ -501,30 +501,36 @@ RSpec.describe 'GFM autocomplete', :js do find('#note-body').native.send_keys('@') end - expect(page).to have_selector('.tribute-container') + expect(page).to have_selector('.tribute-container', visible: true) end - it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do + it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do + issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)<img src=x onerror=alert(1)>' + create(:issue, project: project, title: issue_xss_title) + page.within '.timeline-content-form' do - find('#note-body').native.send_keys('@ev') + find('#note-body').native.send_keys('#') end wait_for_requests - expect(page).to have_selector('.tribute-container') + expect(page).to have_selector('.tribute-container', visible: true) page.within '.tribute-container ul' do - expect(find('li').text).to have_content(user_xss.username) + expect(page.all('li').first.text).to include(issue_xss_title) end end - it 'doesnt open autocomplete menu character is prefixed with text' do + it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do page.within '.timeline-content-form' do - find('#note-body').native.send_keys('testing') - find('#note-body').native.send_keys('@') + find('#note-body').native.send_keys('@ev') end - expect(page).not_to have_selector('.tribute-container') + wait_for_requests + + expect(page).to have_selector('.tribute-container', visible: true) + + expect(find('.tribute-container ul', visible: true).text).to have_content(user_xss.username) end it 'selects the first item for assignee dropdowns' do @@ -532,11 +538,11 @@ RSpec.describe 'GFM autocomplete', :js do find('#note-body').native.send_keys('@') end - expect(page).to have_selector('.tribute-container') + expect(page).to have_selector('.tribute-container', visible: true) wait_for_requests - expect(find('.tribute-container ul')).to have_selector('.highlight:first-of-type') + expect(find('.tribute-container ul', visible: true)).to have_selector('.highlight:first-of-type') end it 'includes items for assignee dropdowns with non-ASCII characters in name' do @@ -545,14 +551,26 @@ RSpec.describe 'GFM autocomplete', :js do simulate_input('#note-body', "@#{user.name[0...8]}") end - expect(page).to have_selector('.tribute-container') + expect(page).to have_selector('.tribute-container', visible: true) wait_for_requests - expect(find('.tribute-container')).to have_content(user.name) + expect(find('.tribute-container ul', visible: true)).to have_content(user.name) end context 'if a selected value has special characters' do + it 'wraps the result in double quotes' do + note = find('#note-body') + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('') + simulate_input('#note-body', "~#{label.title[0]}") + end + + label_item = find('.tribute-container ul', text: label.title, visible: true) + + expect_to_wrap(true, label_item, note, label.title) + end + it "shows dropdown after a new line" do note = find('#note-body') page.within '.timeline-content-form' do @@ -562,7 +580,7 @@ RSpec.describe 'GFM autocomplete', :js do note.native.send_keys('@') end - expect(page).to have_selector('.tribute-container') + expect(page).to have_selector('.tribute-container', visible: true) end it "does not show dropdown when preceded with a special character" do @@ -571,12 +589,21 @@ RSpec.describe 'GFM autocomplete', :js do note.native.send_keys("@") end - expect(page).to have_selector('.tribute-container') + expect(page).to have_selector('.tribute-container', visible: true) page.within '.timeline-content-form' do note.native.send_keys("@") end + expect(page).not_to have_selector('.tribute-container') + end + + it "does not throw an error if no labels exist" do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('~') + end + expect(page).to have_selector('.tribute-container', visible: false) end @@ -586,7 +613,7 @@ RSpec.describe 'GFM autocomplete', :js do note.native.send_keys("@#{user.username[0]}") end - user_item = find('.tribute-container li', text: user.username) + user_item = find('.tribute-container ul', text: user.username, visible: true) expect_to_wrap(false, user_item, note, user.username) end @@ -611,7 +638,7 @@ RSpec.describe 'GFM autocomplete', :js do wait_for_requests - user_item = find('.tribute-container li', text: user.username) + user_item = find('.tribute-container ul', text: user.username, visible: true) expect(user_item).to have_content(user.username) end end @@ -640,8 +667,139 @@ RSpec.describe 'GFM autocomplete', :js do wait_for_requests - expect(find('.tribute-container ul')).not_to have_content(user.username) - expect(find('.tribute-container ul')).to have_content(unassigned_user.username) + expect(find('.tribute-container ul', visible: true)).not_to have_content(user.username) + expect(find('.tribute-container ul', visible: true)).to have_content(unassigned_user.username) + end + + it 'lists users who are currently not assigned to the issue when using /assign on the second line' do + visit project_issue_path(project, issue_assignee) + + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('/assign @user2') + note.native.send_keys(:enter) + note.native.send_keys('/assign @') + note.native.send_keys(:right) + end + + wait_for_requests + + expect(find('.tribute-container ul', visible: true)).not_to have_content(user.username) + expect(find('.tribute-container ul', visible: true)).to have_content(unassigned_user.username) + end + end + + context 'labels' do + it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do + label_xss_title = 'alert label <img src=x onerror="alert(\'Hello xss\');" a' + create(:label, project: project, title: label_xss_title) + + note = find('#note-body') + + # It should show all the labels on "~". + type(note, '~') + + wait_for_requests + + expect(find('.tribute-container ul', visible: true).text).to have_content('alert label') + end + + it 'allows colons when autocompleting scoped labels' do + create(:label, project: project, title: 'scoped:label') + + note = find('#note-body') + type(note, '~scoped:') + + wait_for_requests + + expect(find('.tribute-container ul', visible: true).text).to have_content('scoped:label') + end + + it 'allows colons when autocompleting scoped labels with double colons' do + create(:label, project: project, title: 'scoped::label') + + note = find('#note-body') + type(note, '~scoped::') + + wait_for_requests + + expect(find('.tribute-container ul', visible: true).text).to have_content('scoped::label') + end + + it 'autocompletes multi-word labels' do + create(:label, project: project, title: 'Accepting merge requests') + + note = find('#note-body') + type(note, '~Acceptingmerge') + + wait_for_requests + + expect(find('.tribute-container ul', visible: true).text).to have_content('Accepting merge requests') + end + + it 'only autocompletes the latest label' do + create(:label, project: project, title: 'documentation') + create(:label, project: project, title: 'feature') + + note = find('#note-body') + type(note, '~documentation foo bar ~feat') + note.native.send_keys(:right) + + wait_for_requests + + expect(find('.tribute-container ul', visible: true).text).to have_content('feature') + expect(find('.tribute-container ul', visible: true).text).not_to have_content('documentation') + end + + it 'does not autocomplete labels if no tilde is typed' do + create(:label, project: project, title: 'documentation') + + note = find('#note-body') + type(note, 'document') + + wait_for_requests + + expect(page).not_to have_selector('.tribute-container') + end + end + + context 'when other notes are destroyed' do + let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) } + + # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729 + it 'keeps autocomplete key listeners' do + visit project_issue_path(project, issue) + note = find('#note-body') + + start_comment_with_emoji(note) + + start_and_cancel_discussion + + note.fill_in(with: '') + start_comment_with_emoji(note) + note.native.send_keys(:enter) + + expect(note.value).to eql('Hello :100: ') + end + + def start_comment_with_emoji(note) + note.native.send_keys('Hello :10') + + wait_for_requests + + find('.atwho-view li', text: '100') + end + + def start_and_cancel_discussion + click_button('Reply...') + + fill_in('note_note', with: 'Whoops!') + + page.accept_alert 'Are you sure you want to cancel creating this comment?' do + click_button('Cancel') + end + + wait_for_requests end end end |