diff options
Diffstat (limited to 'spec/features/issues/gfm_autocomplete_spec.rb')
-rw-r--r-- | spec/features/issues/gfm_autocomplete_spec.rb | 752 |
1 files changed, 472 insertions, 280 deletions
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 4a7e1ba99e9..0b2e8013304 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -3,455 +3,647 @@ require 'spec_helper' RSpec.describe 'GFM autocomplete', :js do - let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } - let(:user_xss_title) { 'eve <img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } - let(:label_xss_title) { 'alert label <img src=x onerror="alert(\'Hello xss\');" a' } - let(:milestone_xss_title) { 'alert milestone <img src=x onerror="alert(\'Hello xss\');" a' } - - let(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') } - let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } - let(:project) { create(:project) } - let(:label) { create(:label, project: project, title: 'special+') } + let_it_be(:user_xss_title) { 'eve <img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } + let_it_be(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') } + let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } + let_it_be(:project) { create(:project) } + let_it_be(:label) { create(:label, project: project, title: 'special+') } + let(:issue) { create(:issue, project: project) } - before do + before_all do project.add_maintainer(user) project.add_maintainer(user_xss) + end - sign_in(user) - visit project_issue_path(project, issue) + describe 'when tribute_autocomplete feature flag is off' do + before do + stub_feature_flags(tribute_autocomplete: false) - wait_for_requests - end + sign_in(user) + visit project_issue_path(project, issue) - it 'updates issue description with GFM reference' do - find('.js-issuable-edit').click + wait_for_requests + end - wait_for_requests + it 'updates issue description with GFM reference' do + find('.js-issuable-edit').click - simulate_input('#issue-description', "@#{user.name[0...3]}") + wait_for_requests - wait_for_requests + simulate_input('#issue-description', "@#{user.name[0...3]}") - find('.atwho-view .cur').click + wait_for_requests - click_button 'Save changes' + find('.atwho-view .cur').click - wait_for_requests + click_button 'Save changes' - expect(find('.description')).to have_content(user.to_reference) - end + wait_for_requests - it 'opens autocomplete menu when field starts with text' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys('@') + expect(find('.description')).to have_content(user.to_reference) end - expect(page).to have_selector('.atwho-container') - end + it 'opens quick action autocomplete when updating description' do + find('.js-issuable-edit').click - it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do - create(:issue, project: project, title: issue_xss_title) + find('#issue-description').native.send_keys('/') - page.within '.timeline-content-form' do - find('#note-body').native.send_keys('#') + expect(page).to have_selector('.atwho-container') end - wait_for_requests - - expect(page).to have_selector('.atwho-container') + it 'opens autocomplete menu when field starts with text' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@') + end - page.within '.atwho-container #at-view-issues' do - expect(page.all('li').first.text).to include(issue_xss_title) + expect(page).to have_selector('.atwho-container') end - end - 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('@ev') - end + 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('#') + end - wait_for_requests + wait_for_requests - expect(page).to have_selector('.atwho-container') + expect(page).to have_selector('.atwho-container') - page.within '.atwho-container #at-view-users' do - expect(find('li').text).to have_content(user_xss.username) + page.within '.atwho-container #at-view-issues' do + expect(page.all('li').first.text).to include(issue_xss_title) + end end - end - it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do - create(:milestone, project: project, title: milestone_xss_title) + 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('@ev') + end + + wait_for_requests + + expect(page).to have_selector('.atwho-container') - page.within '.timeline-content-form' do - find('#note-body').native.send_keys('%') + page.within '.atwho-container #at-view-users' do + expect(find('li').text).to have_content(user_xss.username) + end end - wait_for_requests + it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do + milestone_xss_title = 'alert milestone <img src=x onerror="alert(\'Hello xss\');" a' + create(:milestone, project: project, title: milestone_xss_title) + + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('%') + end + + wait_for_requests - expect(page).to have_selector('.atwho-container') + expect(page).to have_selector('.atwho-container') - page.within '.atwho-container #at-view-milestones' do - expect(find('li').text).to have_content('alert milestone') + page.within '.atwho-container #at-view-milestones' do + expect(find('li').text).to have_content('alert milestone') + end end - end - it 'doesnt open autocomplete menu character is prefixed with text' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys('testing') - find('#note-body').native.send_keys('@') + it 'doesnt open autocomplete menu character is prefixed with text' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('testing') + find('#note-body').native.send_keys('@') + end + + expect(page).not_to have_selector('.atwho-view') end - expect(page).not_to have_selector('.atwho-view') - end + it 'doesnt select the first item for non-assignee dropdowns' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys(':') + end + + expect(page).to have_selector('.atwho-container') - it 'doesnt select the first item for non-assignee dropdowns' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys(':') + wait_for_requests + + expect(find('#at-view-58')).not_to have_selector('.cur:first-of-type') end - expect(page).to have_selector('.atwho-container') + it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do + note = find('#note-body') - wait_for_requests + # Number. + page.within '.timeline-content-form' do + note.native.send_keys('7:') + end - expect(find('#at-view-58')).not_to have_selector('.cur:first-of-type') - end + expect(page).not_to have_selector('.atwho-view') - it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do - note = find('#note-body') + # ASCII letter. + page.within '.timeline-content-form' do + note.set('') + note.native.send_keys('w:') + end - # Number. - page.within '.timeline-content-form' do - note.native.send_keys('7:') - end + expect(page).not_to have_selector('.atwho-view') - expect(page).not_to have_selector('.atwho-view') + # Non-ASCII letter. + page.within '.timeline-content-form' do + note.set('') + note.native.send_keys('Ё:') + end - # ASCII letter. - page.within '.timeline-content-form' do - note.set('') - note.native.send_keys('w:') + expect(page).not_to have_selector('.atwho-view') end - expect(page).not_to have_selector('.atwho-view') + it 'selects the first item for assignee dropdowns' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@') + end - # Non-ASCII letter. - page.within '.timeline-content-form' do - note.set('') - note.native.send_keys('Ё:') - end + expect(page).to have_selector('.atwho-container') - expect(page).not_to have_selector('.atwho-view') - end + wait_for_requests - it 'selects the first item for assignee dropdowns' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys('@') + expect(find('#at-view-users')).to have_selector('.cur:first-of-type') end - expect(page).to have_selector('.atwho-container') + it 'includes items for assignee dropdowns with non-ASCII characters in name' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('') + simulate_input('#note-body', "@#{user.name[0...8]}") + end - wait_for_requests + expect(page).to have_selector('.atwho-container') - expect(find('#at-view-users')).to have_selector('.cur:first-of-type') - end + wait_for_requests - it 'includes items for assignee dropdowns with non-ASCII characters in name' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys('') - simulate_input('#note-body', "@#{user.name[0...8]}") + expect(find('#at-view-users')).to have_content(user.name) end - expect(page).to have_selector('.atwho-container') + it 'selects the first item for non-assignee dropdowns if a query is entered' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys(':1') + end - wait_for_requests + expect(page).to have_selector('.atwho-container') - expect(find('#at-view-users')).to have_content(user.name) - end + wait_for_requests - it 'selects the first item for non-assignee dropdowns if a query is entered' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys(':1') + expect(find('#at-view-58')).to have_selector('.cur:first-of-type') end - expect(page).to have_selector('.atwho-container') + 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 - wait_for_requests + label_item = find('.atwho-view li', text: label.title) - expect(find('#at-view-58')).to have_selector('.cur:first-of-type') - end + expect_to_wrap(true, label_item, note, label.title) + 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]}") + it "shows dropdown after a new line" do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('test') + note.native.send_keys(:enter) + note.native.send_keys(:enter) + note.native.send_keys('@') + end + + expect(page).to have_selector('.atwho-container') end - label_item = find('.atwho-view li', text: label.title) + it "does not show dropdown when preceded with a special character" do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys("@") + end - expect_to_wrap(true, label_item, note, label.title) - end + expect(page).to have_selector('.atwho-container') - it "shows dropdown after a new line" do - note = find('#note-body') - page.within '.timeline-content-form' do - note.native.send_keys('test') - note.native.send_keys(:enter) - note.native.send_keys(:enter) - note.native.send_keys('@') + page.within '.timeline-content-form' do + note.native.send_keys("@") + end + + expect(page).to have_selector('.atwho-container', visible: false) end - expect(page).to have_selector('.atwho-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 - it "does not show dropdown when preceded with a special character" do - note = find('#note-body') - page.within '.timeline-content-form' do - note.native.send_keys("@") + expect(page).to have_selector('.atwho-container', visible: false) end - expect(page).to have_selector('.atwho-container') + it 'doesn\'t wrap for assignee values' do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys("@#{user.username[0]}") + end - page.within '.timeline-content-form' do - note.native.send_keys("@") + user_item = find('.atwho-view li', text: user.username) + + expect_to_wrap(false, user_item, note, user.username) end - expect(page).to have_selector('.atwho-container', visible: false) - end + it 'doesn\'t wrap for emoji values' do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys(":cartwheel_") + 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('~') + emoji_item = find('.atwho-view li', text: 'cartwheel_tone1') + + expect_to_wrap(false, emoji_item, note, 'cartwheel_tone1') end - expect(page).to have_selector('.atwho-container', visible: false) - end + it 'doesn\'t open autocomplete after non-word character' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys("@#{user.username[0..2]}!") + end - it 'doesn\'t wrap for assignee values' do - note = find('#note-body') - page.within '.timeline-content-form' do - note.native.send_keys("@#{user.username[0]}") + expect(page).not_to have_selector('.atwho-view') + end + + it 'doesn\'t open autocomplete if there is no space before' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys("hello:#{user.username[0..2]}") + end + + expect(page).not_to have_selector('.atwho-view') end - user_item = find('.atwho-view li', text: user.username) + it 'triggers autocomplete after selecting a quick action' do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('/as') + end + + find('.atwho-view li', text: '/assign') + note.native.send_keys(:tab) - expect_to_wrap(false, user_item, note, user.username) + user_item = find('.atwho-view li', text: user.username) + expect(user_item).to have_content(user.username) + end end - it 'doesn\'t wrap for emoji values' do - note = find('#note-body') - page.within '.timeline-content-form' do - note.native.send_keys(":cartwheel_") + context 'assignees' do + let(:issue_assignee) { create(:issue, project: project) } + let(:unassigned_user) { create(:user) } + + before do + issue_assignee.update(assignees: [user]) + + project.add_maintainer(unassigned_user) end - emoji_item = find('.atwho-view li', text: 'cartwheel_tone1') + it 'lists users who are currently not assigned to the issue when using /assign' do + visit project_issue_path(project, issue_assignee) - expect_to_wrap(false, emoji_item, note, 'cartwheel_tone1') - end + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('/as') + end - it 'doesn\'t open autocomplete after non-word character' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys("@#{user.username[0..2]}!") + find('.atwho-view li', text: '/assign') + note.native.send_keys(:tab) + + wait_for_requests + + expect(find('#at-view-users .atwho-view-ul')).not_to have_content(user.username) + expect(find('#at-view-users .atwho-view-ul')).to have_content(unassigned_user.username) end - expect(page).not_to have_selector('.atwho-view') + it 'shows dropdown on new issue form' do + visit new_project_issue_path(project) + + textarea = find('#issue_description') + textarea.native.send_keys('/ass') + find('.atwho-view li', text: '/assign') + textarea.native.send_keys(:tab) + + expect(find('#at-view-users .atwho-view-ul')).to have_content(unassigned_user.username) + expect(find('#at-view-users .atwho-view-ul')).to have_content(user.username) + end end - it 'doesn\'t open autocomplete if there is no space before' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys("hello:#{user.username[0..2]}") + 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 + + page.within '.atwho-container #at-view-labels' do + expect(find('.atwho-view-ul').text).to have_content('alert label') + end end - expect(page).not_to have_selector('.atwho-view') - end + it 'allows colons when autocompleting scoped labels' do + create(:label, project: project, title: 'scoped:label') - it 'triggers autocomplete after selecting a quick action' do - note = find('#note-body') - page.within '.timeline-content-form' do - note.native.send_keys('/as') + note = find('#note-body') + type(note, '~scoped:') + + wait_for_requests + + page.within '.atwho-container #at-view-labels' do + expect(find('.atwho-view-ul').text).to have_content('scoped:label') + end end - find('.atwho-view li', text: '/assign') - note.native.send_keys(:tab) + it 'allows colons when autocompleting scoped labels with double colons' do + create(:label, project: project, title: 'scoped::label') - user_item = find('.atwho-view li', text: user.username) - expect(user_item).to have_content(user.username) - end - end + note = find('#note-body') + type(note, '~scoped::') - context 'assignees' do - let(:issue_assignee) { create(:issue, project: project) } - let(:unassigned_user) { create(:user) } + wait_for_requests - before do - issue_assignee.update(assignees: [user]) + page.within '.atwho-container #at-view-labels' do + expect(find('.atwho-view-ul').text).to have_content('scoped::label') + end + end + + it 'allows spaces when autocompleting multi-word labels' do + create(:label, project: project, title: 'Accepting merge requests') - project.add_maintainer(unassigned_user) + note = find('#note-body') + type(note, '~Accepting merge') + + wait_for_requests + + page.within '.atwho-container #at-view-labels' do + expect(find('.atwho-view-ul').text).to have_content('Accepting merge requests') + end + end + + it 'only autocompletes the latest label' do + create(:label, project: project, title: 'Accepting merge requests') + create(:label, project: project, title: 'Accepting job applicants') + + note = find('#note-body') + type(note, '~Accepting merge requests foo bar ~Accepting job') + + wait_for_requests + + page.within '.atwho-container #at-view-labels' do + expect(find('.atwho-view-ul').text).to have_content('Accepting job applicants') + end + end + + it 'does not autocomplete labels if no tilde is typed' do + create(:label, project: project, title: 'Accepting merge requests') + + note = find('#note-body') + type(note, 'Accepting merge') + + wait_for_requests + + expect(page).not_to have_css('.atwho-container #at-view-labels') + end end - it 'lists users who are currently not assigned to the issue when using /assign' do - visit project_issue_path(project, issue_assignee) + shared_examples 'autocomplete suggestions' do + it 'suggests objects correctly' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys(object.class.reference_prefix) + end - note = find('#note-body') - page.within '.timeline-content-form' do - note.native.send_keys('/as') + page.within '.atwho-container' do + expect(page).to have_content(object.title) + + find('ul li').click + end + + expect(find('.new-note #note-body').value).to include(expected_body) end + end - find('.atwho-view li', text: '/assign') - note.native.send_keys(:tab) + context 'issues' do + let(:object) { issue } + let(:expected_body) { object.to_reference } - wait_for_requests + it_behaves_like 'autocomplete suggestions' + end + + context 'merge requests' do + let(:object) { create(:merge_request, source_project: project) } + let(:expected_body) { object.to_reference } - expect(find('#at-view-users .atwho-view-ul')).not_to have_content(user.username) - expect(find('#at-view-users .atwho-view-ul')).to have_content(unassigned_user.username) + it_behaves_like 'autocomplete suggestions' end - it 'shows dropdown on new issue form' do - visit new_project_issue_path(project) + context 'project snippets' do + let!(:object) { create(:project_snippet, project: project, title: 'code snippet') } + let(:expected_body) { object.to_reference } - textarea = find('#issue_description') - textarea.native.send_keys('/ass') - find('.atwho-view li', text: '/assign') - textarea.native.send_keys(:tab) + it_behaves_like 'autocomplete suggestions' + end + + context 'label' do + let!(:object) { label } + let(:expected_body) { object.title } + + it_behaves_like 'autocomplete suggestions' + end + + context 'milestone' do + let!(:object) { create(:milestone, project: project) } + let(:expected_body) { object.to_reference } - expect(find('#at-view-users .atwho-view-ul')).to have_content(unassigned_user.username) - expect(find('#at-view-users .atwho-view-ul')).to have_content(user.username) + it_behaves_like 'autocomplete suggestions' end end - context 'labels' do - it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do - create(:label, project: project, title: label_xss_title) + describe 'when tribute_autocomplete feature flag is on' do + before do + stub_feature_flags(tribute_autocomplete: true) + + sign_in(user) + visit project_issue_path(project, issue) - note = find('#note-body') + wait_for_requests + end - # It should show all the labels on "~". - type(note, '~') + it 'updates issue description with GFM reference' do + find('.js-issuable-edit').click wait_for_requests - page.within '.atwho-container #at-view-labels' do - expect(find('.atwho-view-ul').text).to have_content('alert label') - end - end + simulate_input('#issue-description', "@#{user.name[0...3]}") + + wait_for_requests - it 'allows colons when autocompleting scoped labels' do - create(:label, project: project, title: 'scoped:label') + find('.tribute-container .highlight').click - note = find('#note-body') - type(note, '~scoped:') + click_button 'Save changes' wait_for_requests - page.within '.atwho-container #at-view-labels' do - expect(find('.atwho-view-ul').text).to have_content('scoped:label') - end + expect(find('.description')).to have_content(user.to_reference) end - it 'allows colons when autocompleting scoped labels with double colons' do - create(:label, project: project, title: 'scoped::label') + it 'opens autocomplete menu when field starts with text' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@') + end - note = find('#note-body') - type(note, '~scoped::') + expect(page).to have_selector('.tribute-container') + end + + 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('@ev') + end wait_for_requests - page.within '.atwho-container #at-view-labels' do - expect(find('.atwho-view-ul').text).to have_content('scoped::label') + expect(page).to have_selector('.tribute-container') + + page.within '.tribute-container ul' do + expect(find('li').text).to have_content(user_xss.username) end end - it 'allows spaces when autocompleting multi-word labels' do - create(:label, project: project, title: 'Accepting merge requests') + it 'doesnt open autocomplete menu character is prefixed with text' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('testing') + find('#note-body').native.send_keys('@') + end - note = find('#note-body') - type(note, '~Accepting merge') + expect(page).not_to have_selector('.tribute-container') + end + + it 'selects the first item for assignee dropdowns' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@') + end + + expect(page).to have_selector('.tribute-container') wait_for_requests - page.within '.atwho-container #at-view-labels' do - expect(find('.atwho-view-ul').text).to have_content('Accepting merge requests') - end + expect(find('.tribute-container ul')).to have_selector('.highlight:first-of-type') end - it 'only autocompletes the latest label' do - create(:label, project: project, title: 'Accepting merge requests') - create(:label, project: project, title: 'Accepting job applicants') + it 'includes items for assignee dropdowns with non-ASCII characters in name' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('') + simulate_input('#note-body', "@#{user.name[0...8]}") + end - note = find('#note-body') - type(note, '~Accepting merge requests foo bar ~Accepting job') + expect(page).to have_selector('.tribute-container') wait_for_requests - page.within '.atwho-container #at-view-labels' do - expect(find('.atwho-view-ul').text).to have_content('Accepting job applicants') - end + expect(find('.tribute-container')).to have_content(user.name) end - it 'does not autocomplete labels if no tilde is typed' do - create(:label, project: project, title: 'Accepting merge requests') + context 'if a selected value has special characters' do + it "shows dropdown after a new line" do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('test') + note.native.send_keys(:enter) + note.native.send_keys(:enter) + note.native.send_keys('@') + end - note = find('#note-body') - type(note, 'Accepting merge') + expect(page).to have_selector('.tribute-container') + end - wait_for_requests + it "does not show dropdown when preceded with a special character" do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys("@") + end - expect(page).not_to have_css('.atwho-container #at-view-labels') - end - end + expect(page).to have_selector('.tribute-container') - shared_examples 'autocomplete suggestions' do - it 'suggests objects correctly' do - page.within '.timeline-content-form' do - find('#note-body').native.send_keys(object.class.reference_prefix) + page.within '.timeline-content-form' do + note.native.send_keys("@") + end + + expect(page).to have_selector('.tribute-container', visible: false) end - page.within '.atwho-container' do - expect(page).to have_content(object.title) + it 'doesn\'t wrap for assignee values' do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys("@#{user.username[0]}") + end - find('ul li').click + user_item = find('.tribute-container li', text: user.username) + + expect_to_wrap(false, user_item, note, user.username) end - expect(find('.new-note #note-body').value).to include(expected_body) - end - end + it 'doesn\'t open autocomplete after non-word character' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys("@#{user.username[0..2]}!") + end - context 'issues' do - let(:object) { issue } - let(:expected_body) { object.to_reference } + expect(page).not_to have_selector('.tribute-container') + end - it_behaves_like 'autocomplete suggestions' - end + it 'triggers autocomplete after selecting a quick action' do + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('/as') + end - context 'merge requests' do - let(:object) { create(:merge_request, source_project: project) } - let(:expected_body) { object.to_reference } + find('.atwho-view li', text: '/assign') + note.native.send_keys(:tab) + note.native.send_keys(:right) - it_behaves_like 'autocomplete suggestions' - end + wait_for_requests - context 'project snippets' do - let!(:object) { create(:project_snippet, project: project, title: 'code snippet') } - let(:expected_body) { object.to_reference } + user_item = find('.tribute-container li', text: user.username) + expect(user_item).to have_content(user.username) + end + end - it_behaves_like 'autocomplete suggestions' - end + context 'assignees' do + let(:issue_assignee) { create(:issue, project: project) } + let(:unassigned_user) { create(:user) } - context 'label' do - let!(:object) { label } - let(:expected_body) { object.title } + before do + issue_assignee.update(assignees: [user]) - it_behaves_like 'autocomplete suggestions' - end + project.add_maintainer(unassigned_user) + end + + it 'lists users who are currently not assigned to the issue when using /assign' do + visit project_issue_path(project, issue_assignee) + + note = find('#note-body') + page.within '.timeline-content-form' do + note.native.send_keys('/as') + end - context 'milestone' do - let!(:object) { create(:milestone, project: project) } - let(:expected_body) { object.to_reference } + find('.atwho-view li', text: '/assign') + note.native.send_keys(:tab) + note.native.send_keys(:right) - it_behaves_like 'autocomplete suggestions' + 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) + end + end end private |