diff options
Diffstat (limited to 'spec/features/issues')
24 files changed, 640 insertions, 186 deletions
diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index 16e453bc328..853632614c4 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -1,13 +1,13 @@ require 'rails_helper' describe 'Awards Emoji', feature: true do - include WaitForAjax + include WaitForVueResource let!(:project) { create(:project, :public) } let!(:user) { create(:user) } let(:issue) do create(:issue, - assignee: @user, + assignees: [user], project: project) end @@ -22,10 +22,11 @@ describe 'Awards Emoji', feature: true do # The `heart_tip` emoji is not valid anymore so we need to skip validation issue.award_emoji.build(user: user, name: 'heart_tip').save!(validate: false) visit namespace_project_issue_path(project.namespace, project, issue) + wait_for_vue_resource end # Regression test: https://gitlab.com/gitlab-org/gitlab-ce/issues/29529 - it 'does not shows a 500 page' do + it 'does not shows a 500 page', js: true do expect(page).to have_text(issue.title) end end @@ -35,6 +36,7 @@ describe 'Awards Emoji', feature: true do before do visit namespace_project_issue_path(project.namespace, project, issue) + wait_for_vue_resource end it 'increments the thumbsdown emoji', js: true do diff --git a/spec/features/issues/award_spec.rb b/spec/features/issues/award_spec.rb index 401e1ea2b89..08e3f99e29f 100644 --- a/spec/features/issues/award_spec.rb +++ b/spec/features/issues/award_spec.rb @@ -6,9 +6,12 @@ feature 'Issue awards', js: true, feature: true do let(:issue) { create(:issue, project: project) } describe 'logged in' do + include WaitForVueResource + before do login_as(user) visit namespace_project_issue_path(project.namespace, project, issue) + wait_for_vue_resource end it 'adds award to issue' do @@ -38,8 +41,11 @@ feature 'Issue awards', js: true, feature: true do end describe 'logged out' do + include WaitForVueResource + before do visit namespace_project_issue_path(project.namespace, project, issue) + wait_for_vue_resource end it 'does not see award menu button' do diff --git a/spec/features/issues/bulk_assignment_labels_spec.rb b/spec/features/issues/bulk_assignment_labels_spec.rb index 2f59630b4fb..1de50d6d77e 100644 --- a/spec/features/issues/bulk_assignment_labels_spec.rb +++ b/spec/features/issues/bulk_assignment_labels_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Issues > Labels bulk assignment', feature: true do - include WaitForAjax - let(:user) { create(:user) } let!(:project) { create(:project) } let!(:issue1) { create(:issue, project: project, title: "Issue 1") } diff --git a/spec/features/issues/create_branch_merge_request_spec.rb b/spec/features/issues/create_branch_merge_request_spec.rb new file mode 100644 index 00000000000..44c19275ae5 --- /dev/null +++ b/spec/features/issues/create_branch_merge_request_spec.rb @@ -0,0 +1,91 @@ +require 'rails_helper' + +feature 'Create Branch/Merge Request Dropdown on issue page', feature: true, js: true do + let(:user) { create(:user) } + let!(:project) { create(:project) } + let(:issue) { create(:issue, project: project, title: 'Cherry-Coloured Funk') } + + context 'for team members' do + before do + project.team << [user, :developer] + login_as(user) + end + + it 'allows creating a merge request from the issue page' do + visit namespace_project_issue_path(project.namespace, project, issue) + + select_dropdown_option('create-mr') + + wait_for_ajax + + expect(page).to have_content("created branch 1-cherry-coloured-funk") + expect(page).to have_content("mentioned in merge request !1") + + visit namespace_project_merge_request_path(project.namespace, project, MergeRequest.first) + + expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"') + expect(current_path).to eq(namespace_project_merge_request_path(project.namespace, project, MergeRequest.first)) + end + + it 'allows creating a branch from the issue page' do + visit namespace_project_issue_path(project.namespace, project, issue) + + select_dropdown_option('create-branch') + + wait_for_ajax + + expect(page).to have_selector('.dropdown-toggle-text ', text: '1-cherry-coloured-funk') + expect(current_path).to eq namespace_project_tree_path(project.namespace, project, '1-cherry-coloured-funk') + end + + context "when there is a referenced merge request" do + let!(:note) do + create(:note, :on_issue, :system, project: project, noteable: issue, + note: "mentioned in #{referenced_mr.to_reference}") + end + + let(:referenced_mr) do + create(:merge_request, :simple, source_project: project, target_project: project, + description: "Fixes #{issue.to_reference}", author: user) + end + + before do + referenced_mr.cache_merge_request_closes_issues!(user) + + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'disables the create branch button' do + expect(page).to have_css('.create-mr-dropdown-wrap .unavailable:not(.hide)') + expect(page).to have_css('.create-mr-dropdown-wrap .available.hide', visible: false) + expect(page).to have_content /1 Related Merge Request/ + end + end + + context 'when issue is confidential' do + it 'disables the create branch button' do + issue = create(:issue, :confidential, project: project) + + visit namespace_project_issue_path(project.namespace, project, issue) + + expect(page).not_to have_css('.create-mr-dropdown-wrap') + end + end + end + + context 'for visitors' do + before do + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'shows no buttons' do + expect(page).not_to have_selector('.create-mr-dropdown-wrap') + end + end + + def select_dropdown_option(option) + find('.create-mr-dropdown-wrap .dropdown-toggle').click + find("li[data-value='#{option}']").click + find('.js-create-merge-request').click + end +end diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb index 572bca3de21..24e2419b5ce 100644 --- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb @@ -4,7 +4,7 @@ feature 'Resolving all open discussions in a merge request from an issue', featu let(:user) { create(:user) } let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project) } - let!(:discussion) { Discussion.for_diff_notes([create(:diff_note_on_merge_request, noteable: merge_request, project: project)]).first } + let!(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion } describe 'as a user with access to the project' do before do @@ -14,7 +14,7 @@ feature 'Resolving all open discussions in a merge request from an issue', featu end it 'shows a button to resolve all discussions by creating a new issue' do - within('li#resolve-count-app') do + within('#resolve-count-app') do expect(page).to have_link "Resolve all discussions in new issue", href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) end end @@ -49,7 +49,7 @@ feature 'Resolving all open discussions in a merge request from an issue', featu end it 'does not show a link to create a new issue' do - expect(page).not_to have_link 'open an issue to resolve them later' + expect(page).not_to have_link 'Create an issue to resolve them later' end end @@ -59,18 +59,18 @@ feature 'Resolving all open discussions in a merge request from an issue', featu end it 'shows a warning that the merge request contains unresolved discussions' do - expect(page).to have_content 'This merge request has unresolved discussions' + expect(page).to have_content 'There are unresolved discussions.' end it 'has a link to resolve all discussions by creating an issue' do page.within '.mr-widget-body' do - expect(page).to have_link 'open an issue to resolve them later', href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + expect(page).to have_link 'Create an issue to resolve them later', href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) end end context 'creating an issue for discussions' do before do - page.click_link 'open an issue to resolve them later', href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) + page.click_link 'Create an issue to resolve them later', href: new_namespace_project_issue_path(project.namespace, project, merge_request_to_resolve_discussions_of: merge_request.iid) end it_behaves_like 'creating an issue for a discussion' diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb index 88e2cc60d79..3a5a79e03f4 100644 --- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request.rb +++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb @@ -4,7 +4,7 @@ feature 'Resolve an open discussion in a merge request by creating an issue', fe let(:user) { create(:user) } let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: true) } let(:merge_request) { create(:merge_request, source_project: project) } - let!(:discussion) { Discussion.for_diff_notes([create(:diff_note_on_merge_request, noteable: merge_request, project: project)]).first } + let!(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion } describe 'As a user with access to the project' do before do @@ -74,8 +74,8 @@ feature 'Resolve an open discussion in a merge request by creating an issue', fe it 'Shows a notice to ask someone else to resolve the discussions' do expect(page).to have_content("The discussion at #{merge_request.to_reference}"\ - "(discussion #{discussion.first_note.id}) will stay unresolved."\ - "Ask someone with permission to resolve it.") + " (discussion #{discussion.first_note.id}) will stay unresolved."\ + " Ask someone with permission to resolve it.") end end end diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb index 4dcc56a97d1..0b573d7cef4 100644 --- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Dropdown assignee', :feature, :js do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } @@ -194,7 +193,7 @@ describe 'Dropdown assignee', :feature, :js do new_user = create(:user) project.team << [new_user, :master] - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click filtered_search.set('assignee') filtered_search.send_keys(':') diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb index 1772a120045..0579d6c80ab 100644 --- a/spec/features/issues/filtered_search/dropdown_author_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Dropdown author', js: true, feature: true do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } @@ -172,7 +171,7 @@ describe 'Dropdown author', js: true, feature: true do new_user = create(:user) project.team << [new_user, :master] - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click filtered_search.set('author') send_keys_to_filtered_search(':') diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb index bc8cbe30e66..b9a37cfcc22 100644 --- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb @@ -1,18 +1,13 @@ require 'rails_helper' -describe 'Dropdown hint', js: true, feature: true do +describe 'Dropdown hint', :js, :feature do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user) } let(:filtered_search) { find('.filtered-search') } let(:js_dropdown_hint) { '#js-dropdown-hint' } - def dropdown_hint_size - page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size - end - def click_hint(text) find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: text).click end @@ -46,14 +41,16 @@ describe 'Dropdown hint', js: true, feature: true do it 'does not filter `Press Enter or click to search`' do filtered_search.set('randomtext') - expect(page).to have_css(js_dropdown_hint, text: 'Press Enter or click to search', visible: false) - expect(dropdown_hint_size).to eq(0) + hint_dropdown = find(js_dropdown_hint) + + expect(hint_dropdown).to have_content('Press Enter or click to search') + expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0) end it 'filters with text' do filtered_search.set('a') - expect(dropdown_hint_size).to eq(3) + expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 3) end end diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb index b192064b693..abe5d61e38c 100644 --- a/spec/features/issues/filtered_search/dropdown_label_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb @@ -28,12 +28,8 @@ describe 'Dropdown label', js: true, feature: true do filter_dropdown.find('.filter-dropdown-item', text: text).click end - def dropdown_label_size - filter_dropdown.all('.filter-dropdown-item').size - end - def clear_search_field - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click end before do @@ -81,7 +77,7 @@ describe 'Dropdown label', js: true, feature: true do filtered_search.set('label:') expect(filter_dropdown).to have_content(bug_label.title) - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) end end @@ -97,7 +93,8 @@ describe 'Dropdown label', js: true, feature: true do expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible - expect(dropdown_label_size).to eq(2) + + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 2) clear_search_field init_label_search @@ -106,14 +103,14 @@ describe 'Dropdown label', js: true, feature: true do expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible - expect(dropdown_label_size).to eq(2) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 2) end it 'filters by multiple words with or without symbol' do filtered_search.send_keys('Hig') expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) clear_search_field init_label_search @@ -121,14 +118,14 @@ describe 'Dropdown label', js: true, feature: true do filtered_search.send_keys('~Hig') expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) end it 'filters by multiple words containing single quotes with or without symbol' do filtered_search.send_keys('won\'t') expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) clear_search_field init_label_search @@ -136,14 +133,14 @@ describe 'Dropdown label', js: true, feature: true do filtered_search.send_keys('~won\'t') expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) end it 'filters by multiple words containing double quotes with or without symbol' do filtered_search.send_keys('won"t') expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) clear_search_field init_label_search @@ -151,14 +148,14 @@ describe 'Dropdown label', js: true, feature: true do filtered_search.send_keys('~won"t') expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) end it 'filters by special characters with or without symbol' do filtered_search.send_keys('^+') expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) clear_search_field init_label_search @@ -166,7 +163,7 @@ describe 'Dropdown label', js: true, feature: true do filtered_search.send_keys('~^+') expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) end end @@ -280,13 +277,13 @@ describe 'Dropdown label', js: true, feature: true do create(:label, project: project, title: 'bug-label') init_label_search - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) create(:label, project: project) clear_search_field init_label_search - expect(dropdown_label_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1) end end end diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb index ce96a420699..448259057b0 100644 --- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb @@ -65,7 +65,7 @@ describe 'Dropdown milestone', :feature, :js do it 'should load all the milestones when opened' do filtered_search.set('milestone:') - expect(dropdown_milestone_size).to be > 0 + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6) end end @@ -84,37 +84,37 @@ describe 'Dropdown milestone', :feature, :js do it 'filters by name' do filtered_search.send_keys('v1') - expect(dropdown_milestone_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end it 'filters by case insensitive name' do filtered_search.send_keys('V1') - expect(dropdown_milestone_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end it 'filters by name with symbol' do filtered_search.send_keys('%v1') - expect(dropdown_milestone_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end it 'filters by case insensitive name with symbol' do filtered_search.send_keys('%V1') - expect(dropdown_milestone_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end it 'filters by special characters' do filtered_search.send_keys('(+') - expect(dropdown_milestone_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end it 'filters by special characters with symbol' do filtered_search.send_keys('%(+') - expect(dropdown_milestone_size).to eq(1) + expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end end @@ -252,7 +252,7 @@ describe 'Dropdown milestone', :feature, :js do expect(initial_size).to be > 0 create(:milestone, project: project) - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click filtered_search.set('milestone:') expect(dropdown_milestone_size).to eq(initial_size) diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index f463312bf57..a8f4e2d7e10 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' describe 'Filter issues', js: true, feature: true do + include Devise::Test::IntegrationHelpers include FilteredSearchHelpers - include WaitForAjax let!(:group) { create(:group) } let!(:project) { create(:project, group: group) } - let!(:user) { create(:user) } - let!(:user2) { create(:user) } + let!(:user) { create(:user, username: 'joe') } + let!(:user2) { create(:user, username: 'jane') } let!(:label) { create(:label, project: project) } let!(:wontfix) { create(:label, project: project, title: "Won't fix") } let!(:bug_label) { create(:label, project: project, title: 'bug') } - let!(:caps_sensitive_label) { create(:label, project: project, title: 'CAPS_sensitive') } + let!(:caps_sensitive_label) { create(:label, project: project, title: 'CaPs') } let!(:milestone) { create(:milestone, title: "8", project: project, start_date: 2.days.ago) } let!(:multiple_words_label) { create(:label, project: project, title: "Two words") } @@ -42,23 +42,24 @@ describe 'Filter issues', js: true, feature: true do project.team << [user2, :master] group.add_developer(user) group.add_developer(user2) - login_as(user) - create(:issue, project: project) - create(:issue, title: "Bug report 1", project: project) - create(:issue, title: "Bug report 2", project: project) - create(:issue, title: "issue with 'single quotes'", project: project) - create(:issue, title: "issue with \"double quotes\"", project: project) - create(:issue, title: "issue with !@\#{$%^&*()-+", project: project) - create(:issue, title: "issue by assignee", project: project, milestone: milestone, author: user, assignee: user) - create(:issue, title: "issue by assignee with searchTerm", project: project, milestone: milestone, author: user, assignee: user) + sign_in(user) + + create(:issue, project: project) + create(:issue, project: project, title: "Bug report 1") + create(:issue, project: project, title: "Bug report 2") + create(:issue, project: project, title: "issue with 'single quotes'") + create(:issue, project: project, title: "issue with \"double quotes\"") + create(:issue, project: project, title: "issue with !@\#{$%^&*()-+") + create(:issue, project: project, title: "issue by assignee", milestone: milestone, author: user, assignees: [user]) + create(:issue, project: project, title: "issue by assignee with searchTerm", milestone: milestone, author: user, assignees: [user]) issue = create(:issue, title: "Bug 2", project: project, milestone: milestone, author: user, - assignee: user) + assignees: [user]) issue.labels << bug_label issue_with_caps_label = create(:issue, @@ -66,15 +67,15 @@ describe 'Filter issues', js: true, feature: true do project: project, milestone: milestone, author: user, - assignee: user) + assignees: [user]) issue_with_caps_label.labels << caps_sensitive_label issue_with_everything = create(:issue, - title: "Bug report with everything you thought was possible", + title: "Bug report foo was possible", project: project, milestone: milestone, author: user, - assignee: user) + assignees: [user]) issue_with_everything.labels << bug_label issue_with_everything.labels << caps_sensitive_label @@ -687,10 +688,10 @@ describe 'Filter issues', js: true, feature: true do end it 'filters issues by searched text, author, more text, assignee and even more text' do - input_filtered_search("bug author:@#{user.username} report assignee:@#{user.username} with") + input_filtered_search("bug author:@#{user.username} report assignee:@#{user.username} foo") expect_issues_list_count(1) - expect_filtered_search_input('bug report with') + expect_filtered_search_input('bug report foo') end it 'filters issues by searched text, author, assignee and label' do @@ -701,10 +702,10 @@ describe 'Filter issues', js: true, feature: true do end it 'filters issues by searched text, author, text, assignee, text, label and text' do - input_filtered_search("bug author:@#{user.username} report assignee:@#{user.username} with label:~#{bug_label.title} everything") + input_filtered_search("bug author:@#{user.username} assignee:@#{user.username} report label:~#{bug_label.title} foo") expect_issues_list_count(1) - expect_filtered_search_input('bug report with everything') + expect_filtered_search_input('bug report foo') end it 'filters issues by searched text, author, assignee, label and milestone' do @@ -715,10 +716,10 @@ describe 'Filter issues', js: true, feature: true do end it 'filters issues by searched text, author, text, assignee, text, label, text, milestone and text' do - input_filtered_search("bug author:@#{user.username} report assignee:@#{user.username} with label:~#{bug_label.title} everything milestone:%#{milestone.title} you") + input_filtered_search("bug author:@#{user.username} assignee:@#{user.username} report label:~#{bug_label.title} milestone:%#{milestone.title} foo") expect_issues_list_count(1) - expect_filtered_search_input('bug report with everything you') + expect_filtered_search_input('bug report foo') end it 'filters issues by searched text, author, assignee, multiple labels and milestone' do @@ -729,10 +730,10 @@ describe 'Filter issues', js: true, feature: true do end it 'filters issues by searched text, author, text, assignee, text, label1, text, label2, text, milestone and text' do - input_filtered_search("bug author:@#{user.username} report assignee:@#{user.username} with label:~#{bug_label.title} everything label:~#{caps_sensitive_label.title} you milestone:%#{milestone.title} thought") + input_filtered_search("bug author:@#{user.username} assignee:@#{user.username} report label:~#{bug_label.title} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} foo") expect_issues_list_count(1) - expect_filtered_search_input('bug report with everything you thought') + expect_filtered_search_input('bug report foo') end end @@ -756,10 +757,10 @@ describe 'Filter issues', js: true, feature: true do expect_issues_list_count(2) - sort_toggle = find('.filtered-search-container .dropdown-toggle') + sort_toggle = find('.filtered-search-wrapper .dropdown-toggle') sort_toggle.click - find('.filtered-search-container .dropdown-menu li a', text: 'Oldest updated').click + find('.filtered-search-wrapper .dropdown-menu li a', text: 'Oldest updated').click wait_for_ajax expect(find('.issues-list .issue:first-of-type .issue-title-text a')).to have_content(old_issue.title) diff --git a/spec/features/issues/filtered_search/recent_searches_spec.rb b/spec/features/issues/filtered_search/recent_searches_spec.rb new file mode 100644 index 00000000000..09f228bcf49 --- /dev/null +++ b/spec/features/issues/filtered_search/recent_searches_spec.rb @@ -0,0 +1,109 @@ +require 'spec_helper' + +describe 'Recent searches', js: true, feature: true do + include FilteredSearchHelpers + + let(:project_1) { create(:empty_project, :public) } + let(:project_2) { create(:empty_project, :public) } + let(:project_1_local_storage_key) { "#{project_1.full_path}-issue-recent-searches" } + + before do + Capybara.ignore_hidden_elements = false + create(:issue, project: project_1) + create(:issue, project: project_2) + + # Visit any fast-loading page so we can clear local storage without a DOM exception + visit '/404' + remove_recent_searches + end + + after do + Capybara.ignore_hidden_elements = true + end + + it 'searching adds to recent searches' do + visit namespace_project_issues_path(project_1.namespace, project_1) + + input_filtered_search('foo', submit: true) + input_filtered_search('bar', submit: true) + + items = all('.filtered-search-history-dropdown-item', visible: false) + + expect(items.count).to eq(2) + expect(items[0].text).to eq('bar') + expect(items[1].text).to eq('foo') + end + + it 'visiting URL with search params adds to recent searches' do + visit namespace_project_issues_path(project_1.namespace, project_1, label_name: 'foo', search: 'bar') + visit namespace_project_issues_path(project_1.namespace, project_1, label_name: 'qux', search: 'garply') + + items = all('.filtered-search-history-dropdown-item', visible: false) + + expect(items.count).to eq(2) + expect(items[0].text).to eq('label:~qux garply') + expect(items[1].text).to eq('label:~foo bar') + end + + it 'saved recent searches are restored last on the list' do + set_recent_searches(project_1_local_storage_key, '["saved1", "saved2"]') + + visit namespace_project_issues_path(project_1.namespace, project_1, search: 'foo') + + items = all('.filtered-search-history-dropdown-item', visible: false) + + expect(items.count).to eq(3) + expect(items[0].text).to eq('foo') + expect(items[1].text).to eq('saved1') + expect(items[2].text).to eq('saved2') + end + + it 'searches are scoped to projects' do + visit namespace_project_issues_path(project_1.namespace, project_1) + + input_filtered_search('foo', submit: true) + input_filtered_search('bar', submit: true) + + visit namespace_project_issues_path(project_2.namespace, project_2) + + input_filtered_search('more', submit: true) + input_filtered_search('things', submit: true) + + items = all('.filtered-search-history-dropdown-item', visible: false) + + expect(items.count).to eq(2) + expect(items[0].text).to eq('things') + expect(items[1].text).to eq('more') + end + + it 'clicking item fills search input' do + set_recent_searches(project_1_local_storage_key, '["foo", "bar"]') + visit namespace_project_issues_path(project_1.namespace, project_1) + + all('.filtered-search-history-dropdown-item', visible: false)[0].trigger('click') + wait_for_filtered_search('foo') + + expect(find('.filtered-search').value.strip).to eq('foo') + end + + it 'clear recent searches button, clears recent searches' do + set_recent_searches(project_1_local_storage_key, '["foo"]') + visit namespace_project_issues_path(project_1.namespace, project_1) + + items_before = all('.filtered-search-history-dropdown-item', visible: false) + + expect(items_before.count).to eq(1) + + find('.filtered-search-history-clear-button', visible: false).trigger('click') + items_after = all('.filtered-search-history-dropdown-item', visible: false) + + expect(items_after.count).to eq(0) + end + + it 'shows flash error when failed to parse saved history' do + set_recent_searches(project_1_local_storage_key, 'fail') + visit namespace_project_issues_path(project_1.namespace, project_1) + + expect(find('.flash-alert')).to have_text('An error occured while parsing recent searches') + end +end diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb index 59244d65eec..3ea95aed0a6 100644 --- a/spec/features/issues/filtered_search/search_bar_spec.rb +++ b/spec/features/issues/filtered_search/search_bar_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Search bar', js: true, feature: true do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user) } @@ -26,7 +25,7 @@ describe 'Search bar', js: true, feature: true do filtered_search.native.send_keys(:down) page.within '#js-dropdown-hint' do - expect(page).to have_selector('.dropdown-active') + expect(page).to have_selector('.droplab-item-active') end end @@ -44,7 +43,7 @@ describe 'Search bar', js: true, feature: true do filtered_search.set(search_text) expect(filtered_search.value).to eq(search_text) - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click expect(filtered_search.value).to eq('') end @@ -55,7 +54,7 @@ describe 'Search bar', js: true, feature: true do it 'hides after clicked' do filtered_search.set('a') - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click expect(page).to have_css('.clear-search', visible: false) end @@ -79,28 +78,30 @@ describe 'Search bar', js: true, feature: true do filtered_search.set('author') - expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to eq(1) + expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click filtered_search.click - expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to eq(original_size) + expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: original_size) end it 'resets the dropdown filters' do + filtered_search.click + + hint_offset = get_left_style(find('#js-dropdown-hint')['style']) + filtered_search.set('a') - hint_style = page.find('#js-dropdown-hint')['style'] - hint_offset = get_left_style(hint_style) filtered_search.set('author:') - expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to eq(0) + find('#js-dropdown-hint', visible: false) - find('.filtered-search-input-container .clear-search').click + find('.filtered-search-box .clear-search').click filtered_search.click - expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to be > 0 - expect(get_left_style(page.find('#js-dropdown-hint')['style'])).to eq(hint_offset) + expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4) + expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset) end end end diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index 755992069ff..5c0907e26df 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -1,7 +1,9 @@ require 'rails_helper' -describe 'New/edit issue', feature: true, js: true do +describe 'New/edit issue', :feature, :js do include GitlabRoutingHelper + include ActionView::Helpers::JavaScriptHelper + include WaitForAjax let!(:project) { create(:project) } let!(:user) { create(:user)} @@ -9,7 +11,7 @@ describe 'New/edit issue', feature: true, js: true do let!(:milestone) { create(:milestone, project: project) } let!(:label) { create(:label, project: project) } let!(:label2) { create(:label, project: project) } - let!(:issue) { create(:issue, project: project, assignee: user, milestone: milestone) } + let!(:issue) { create(:issue, project: project, assignees: [user], milestone: milestone) } before do project.team << [user, :master] @@ -22,23 +24,67 @@ describe 'New/edit issue', feature: true, js: true do visit new_namespace_project_issue_path(project.namespace, project) end + describe 'single assignee' do + before do + click_button 'Unassigned' + + wait_for_ajax + end + + it 'unselects other assignees when unassigned is selected' do + page.within '.dropdown-menu-user' do + click_link user2.name + end + + click_button user2.name + + page.within '.dropdown-menu-user' do + click_link 'Unassigned' + end + + expect(find('input[name="issue[assignee_ids][]"]', visible: false).value).to match('0') + end + + it 'toggles assign to me when current user is selected and unselected' do + page.within '.dropdown-menu-user' do + click_link user.name + end + + expect(find('a', text: 'Assign to me', visible: false)).not_to be_visible + + click_button user.name + + page.within('.dropdown-menu-user') do + click_link user.name + end + + expect(page.find('.dropdown-menu-user', visible: false)).not_to be_visible + end + end + it 'allows user to create new issue' do fill_in 'issue_title', with: 'title' fill_in 'issue_description', with: 'title' expect(find('a', text: 'Assign to me')).to be_visible - click_button 'Assignee' + click_button 'Unassigned' + + wait_for_ajax + page.within '.dropdown-menu-user' do click_link user2.name end - expect(find('input[name="issue[assignee_id]"]', visible: false).value).to match(user2.id.to_s) + expect(find('input[name="issue[assignee_ids][]"]', visible: false).value).to match(user2.id.to_s) page.within '.js-assignee-search' do expect(page).to have_content user2.name end expect(find('a', text: 'Assign to me')).to be_visible click_link 'Assign to me' - expect(find('input[name="issue[assignee_id]"]', visible: false).value).to match(user.id.to_s) + assignee_ids = page.all('input[name="issue[assignee_ids][]"]', visible: false) + + expect(assignee_ids[0].value).to match(user.id.to_s) + page.within '.js-assignee-search' do expect(page).to have_content user.name end @@ -68,7 +114,7 @@ describe 'New/edit issue', feature: true, js: true do page.within '.issuable-sidebar' do page.within '.assignee' do - expect(page).to have_content user.name + expect(page).to have_content "Assignee" end page.within '.milestone' do @@ -105,6 +151,25 @@ describe 'New/edit issue', feature: true, js: true do expect(find('.js-label-select')).to have_content('Labels') end + + it 'correctly updates the selected user when changing assignee' do + click_button 'Unassigned' + + wait_for_ajax + + page.within '.dropdown-menu-user' do + click_link user.name + end + + expect(find('.js-assignee-search')).to have_content(user.name) + click_button user.name + + page.within '.dropdown-menu-user' do + click_link user2.name + end + + expect(find('.js-assignee-search')).to have_content(user2.name) + end end context 'edit issue' do @@ -113,7 +178,7 @@ describe 'New/edit issue', feature: true, js: true do end it 'allows user to update issue' do - expect(find('input[name="issue[assignee_id]"]', visible: false).value).to match(user.id.to_s) + expect(find('input[name="issue[assignee_ids][]"]', visible: false).value).to match(user.id.to_s) expect(find('input[name="issue[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) expect(find('a', text: 'Assign to me', visible: false)).not_to be_visible @@ -154,4 +219,14 @@ describe 'New/edit issue', feature: true, js: true do end end end + + def before_for_selector(selector) + js = <<-JS.strip_heredoc + (function(selector) { + var el = document.querySelector(selector); + return window.getComputedStyle(el, '::before').getPropertyValue('content'); + })("#{escape_javascript(selector)}") + JS + page.evaluate_script(js) + end end diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 7135565294b..ad29911248f 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' feature 'GFM autocomplete', feature: true, js: true do - include WaitForAjax let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } let(:project) { create(:project) } let(:label) { create(:label, project: project, title: 'special+') } @@ -46,6 +45,33 @@ feature 'GFM autocomplete', feature: true, js: true do expect(find('#at-view-58')).not_to have_selector('.cur:first-of-type') end + it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do + note = find('#note_note') + + # Number. + page.within '.timeline-content-form' do + note.native.send_keys('7:') + end + + expect(page).not_to have_selector('.atwho-view') + + # ASCII letter. + page.within '.timeline-content-form' do + note.set('') + note.native.send_keys('w:') + end + + expect(page).not_to have_selector('.atwho-view') + + # Non-ASCII letter. + page.within '.timeline-content-form' do + note.set('') + note.native.send_keys('Ё:') + end + + expect(page).not_to have_selector('.atwho-view') + end + it 'selects the first item for assignee dropdowns' do page.within '.timeline-content-form' do find('#note_note').native.send_keys('') diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 7b9d4534ada..0de0f93089a 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' feature 'Issue Sidebar', feature: true do - include WaitForAjax include MobileHelpers - let(:project) { create(:project, :public) } + let(:group) { create(:group, :nested) } + let(:project) { create(:project, :public, namespace: group) } let(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} let!(:label) { create(:label, project: project, title: 'bug') } @@ -42,6 +42,21 @@ feature 'Issue Sidebar', feature: true do expect(page).to have_content(user2.name) end end + + it 'assigns yourself' do + find('.block.assignee .dropdown-menu-toggle').click + + click_button 'assign yourself' + + wait_for_ajax + + find('.block.assignee .edit-link').click + + page.within '.dropdown-menu-user' do + expect(page.find('.dropdown-header')).to be_visible + expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name) + end + end end context 'as a allowed user' do @@ -56,10 +71,12 @@ feature 'Issue Sidebar', feature: true do # Resize the window resize_screen_sm # Make sure the sidebar is collapsed + find(sidebar_selector) expect(page).to have_css(sidebar_selector) # Once is collapsed let's open the sidebard and reload open_issue_sidebar refresh + find(sidebar_selector) expect(page).to have_css(sidebar_selector) # Restore the window size as it was including the sidebar restore_window_size @@ -120,6 +137,20 @@ feature 'Issue Sidebar', feature: true do end end + context 'as a allowed mobile user', js: true do + before do + project.team << [user, :developer] + resize_screen_xs + visit_issue(project, issue) + end + + context 'mobile sidebar' do + it 'collapses the sidebar for small screens' do + expect(page).not_to have_css('aside.right-sidebar.right-sidebar-collapsed') + end + end + end + context 'as a guest' do before do project.team << [user, :guest] @@ -136,9 +167,7 @@ feature 'Issue Sidebar', feature: true do end def open_issue_sidebar - page.within('aside.right-sidebar.right-sidebar-collapsed') do - find('.js-sidebar-toggle').click - sleep 1 - end + find('aside.right-sidebar.right-sidebar-collapsed .js-sidebar-toggle').trigger('click') + find('aside.right-sidebar.right-sidebar-expanded') end end diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb index f89b4db9e62..6c09903a2f6 100644 --- a/spec/features/issues/move_spec.rb +++ b/spec/features/issues/move_spec.rb @@ -37,8 +37,8 @@ feature 'issue move to another project' do edit_issue(issue) end - scenario 'moving issue to another project' do - first('#move_to_project_id', visible: false).set(new_project.id) + scenario 'moving issue to another project', js: true do + find('#move_to_project_id', visible: false).set(new_project.id) click_button('Save changes') expect(current_url).to include project_path(new_project) diff --git a/spec/features/issues/new_branch_button_spec.rb b/spec/features/issues/new_branch_button_spec.rb deleted file mode 100644 index c0ab42c6822..00000000000 --- a/spec/features/issues/new_branch_button_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -require 'rails_helper' - -feature 'Start new branch from an issue', feature: true, js: true do - let!(:project) { create(:project) } - let!(:issue) { create(:issue, project: project) } - let!(:user) { create(:user)} - - context "for team members" do - before do - project.team << [user, :master] - login_as(user) - end - - it 'shows the new branch button' do - visit namespace_project_issue_path(project.namespace, project, issue) - - expect(page).to have_css('#new-branch .available') - end - - context "when there is a referenced merge request" do - let!(:note) do - create(:note, :on_issue, :system, project: project, noteable: issue, - note: "mentioned in #{referenced_mr.to_reference}") - end - - let(:referenced_mr) do - create(:merge_request, :simple, source_project: project, target_project: project, - description: "Fixes #{issue.to_reference}", author: user) - end - - before do - referenced_mr.cache_merge_request_closes_issues!(user) - - visit namespace_project_issue_path(project.namespace, project, issue) - end - - it "hides the new branch button" do - expect(page).to have_css('#new-branch .unavailable') - expect(page).not_to have_css('#new-branch .available') - expect(page).to have_content /1 Related Merge Request/ - end - end - - context 'when issue is confidential' do - it 'hides the new branch button' do - issue = create(:issue, :confidential, project: project) - - visit namespace_project_issue_path(project.namespace, project, issue) - - expect(page).not_to have_css('#new-branch') - end - end - end - - context 'for visitors' do - it 'shows no buttons' do - visit namespace_project_issue_path(project.namespace, project, issue) - - expect(page).not_to have_css('#new-branch') - end - end -end diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb index f5cfe2d666e..80f57906506 100644 --- a/spec/features/issues/note_polling_spec.rb +++ b/spec/features/issues/note_polling_spec.rb @@ -1,19 +1,131 @@ require 'spec_helper' -feature 'Issue notes polling' do - let!(:project) { create(:project, :public) } - let!(:issue) { create(:issue, project: project) } +feature 'Issue notes polling', :feature, :js do + let(:project) { create(:empty_project, :public) } + let(:issue) { create(:issue, project: project) } - background do - visit namespace_project_issue_path(project.namespace, project, issue) + describe 'creates' do + before do + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'displays the new comment' do + note = create(:note, noteable: issue, project: project, note: 'Looks good!') + page.execute_script('notes.refresh();') + + expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!') + end end - scenario 'Another user adds a comment to an issue', js: true do - note = create(:note, noteable: issue, project: project, - note: 'Looks good!') + describe 'updates' do + context 'when from own user' do + let(:user) { create(:user) } + let(:note_text) { "Hello World" } + let(:updated_text) { "Bye World" } + let!(:existing_note) { create(:note, noteable: issue, project: project, author: user, note: note_text) } - page.execute_script('notes.refresh();') + before do + login_as(user) + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'has .original-note-content to compare against' do + expect(page).to have_selector("#note_#{existing_note.id}", text: note_text) + expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false) + + update_note(existing_note, updated_text) + + expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text) + expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false) + end + + it 'displays the updated content' do + expect(page).to have_selector("#note_#{existing_note.id}", text: note_text) + + update_note(existing_note, updated_text) + + expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text) + end + + it 'when editing but have not changed anything, and an update comes in, show the updated content in the textarea' do + find("#note_#{existing_note.id} .js-note-edit").click + + expect(page).to have_field("note[note]", with: note_text) + + update_note(existing_note, updated_text) + + expect(page).to have_field("note[note]", with: updated_text) + end + + it 'when editing but you changed some things, and an update comes in, show a warning' do + find("#note_#{existing_note.id} .js-note-edit").click + + expect(page).to have_field("note[note]", with: note_text) + + find("#note_#{existing_note.id} .js-note-text").set('something random') + + update_note(existing_note, updated_text) - expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!') + expect(page).to have_selector(".alert") + end + + it 'when editing but you changed some things, an update comes in, and you press cancel, show the updated content' do + find("#note_#{existing_note.id} .js-note-edit").click + + expect(page).to have_field("note[note]", with: note_text) + + find("#note_#{existing_note.id} .js-note-text").set('something random') + + update_note(existing_note, updated_text) + + find("#note_#{existing_note.id} .note-edit-cancel").click + + expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text) + end + end + + context 'when from another user' do + let(:user1) { create(:user) } + let(:user2) { create(:user) } + let(:note_text) { "Hello World" } + let(:updated_text) { "Bye World" } + let!(:existing_note) { create(:note, noteable: issue, project: project, author: user1, note: note_text) } + + before do + login_as(user2) + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'has .original-note-content to compare against' do + expect(page).to have_selector("#note_#{existing_note.id}", text: note_text) + expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false) + + update_note(existing_note, updated_text) + + expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text) + expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false) + end + end + + context 'system notes' do + let(:user) { create(:user) } + let(:note_text) { "Some system note" } + let!(:system_note) { create(:system_note, noteable: issue, project: project, author: user, note: note_text) } + + before do + login_as(user) + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'has .original-note-content to compare against' do + expect(page).to have_selector("#note_#{system_note.id}", text: note_text) + expect(page).to have_selector("#note_#{system_note.id} .original-note-content", count: 1, visible: false) + end + end + end + + def update_note(note, new_text) + note.update(note: new_text) + page.execute_script('notes.refresh();') end end diff --git a/spec/features/issues/notes_on_issues_spec.rb b/spec/features/issues/notes_on_issues_spec.rb new file mode 100644 index 00000000000..a4035324d2b --- /dev/null +++ b/spec/features/issues/notes_on_issues_spec.rb @@ -0,0 +1,77 @@ +require 'spec_helper' + +describe 'Create notes on issues', :js, :feature do + let(:user) { create(:user) } + + shared_examples 'notes with reference' do + let(:issue) { create(:issue, project: project) } + let(:note_text) { "Check #{mention.to_reference}" } + + before do + project.team << [user, :developer] + login_as(user) + visit namespace_project_issue_path(project.namespace, project, issue) + + fill_in 'note[note]', with: note_text + click_button 'Comment' + + wait_for_ajax + end + + it 'creates a note with reference and cross references the issue' do + page.within('div#notes li.note div.note-text') do + expect(page).to have_content(note_text) + expect(page.find('a')).to have_content(mention.to_reference) + end + + find('div#notes li.note div.note-text a').click + + page.within('div#notes li.note .system-note-message') do + expect(page).to have_content('mentioned in issue') + expect(page.find('a')).to have_content(issue.to_reference) + end + end + end + + context 'mentioning issue on a private project' do + it_behaves_like 'notes with reference' do + let(:project) { create(:project, :private) } + let(:mention) { create(:issue, project: project) } + end + end + + context 'mentioning issue on an internal project' do + it_behaves_like 'notes with reference' do + let(:project) { create(:project, :internal) } + let(:mention) { create(:issue, project: project) } + end + end + + context 'mentioning issue on a public project' do + it_behaves_like 'notes with reference' do + let(:project) { create(:project, :public) } + let(:mention) { create(:issue, project: project) } + end + end + + context 'mentioning merge request on a private project' do + it_behaves_like 'notes with reference' do + let(:project) { create(:project, :private) } + let(:mention) { create(:merge_request, source_project: project) } + end + end + + context 'mentioning merge request on an internal project' do + it_behaves_like 'notes with reference' do + let(:project) { create(:project, :internal) } + let(:mention) { create(:merge_request, source_project: project) } + end + end + + context 'mentioning merge request on a public project' do + it_behaves_like 'notes with reference' do + let(:project) { create(:project, :public) } + let(:mention) { create(:merge_request, source_project: project) } + end + end +end diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb index 4bc9b49f889..6001476d0ca 100644 --- a/spec/features/issues/spam_issues_spec.rb +++ b/spec/features/issues/spam_issues_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'New issue', feature: true do +describe 'New issue', feature: true, js: true do include StubENV let(:project) { create(:project, :public) } diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb index ae5da3877a8..b250fa2ed3c 100644 --- a/spec/features/issues/update_issues_spec.rb +++ b/spec/features/issues/update_issues_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Multiple issue updating from issues#index', feature: true do - include WaitForAjax - let!(:project) { create(:project) } let!(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} @@ -101,7 +99,7 @@ feature 'Multiple issue updating from issues#index', feature: true do end def create_assigned - create(:issue, project: project, assignee: user) + create(:issue, project: project, assignees: [user]) end def create_with_milestone diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index 0a9cd11ad6e..4cd6c1171ac 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' feature 'Issues > User uses slash commands', feature: true, js: true do include SlashCommandsHelpers - include WaitForAjax it_behaves_like 'issuable record that supports slash commands in its description and notes', :issue do let(:issuable) { create(:issue, project: project) } |