diff options
author | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2017-09-04 09:28:46 +0200 |
---|---|---|
committer | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2017-09-04 09:28:46 +0200 |
commit | a315e6025c702985b2f6390b29508de39383f52d (patch) | |
tree | f0d07d955092e4a218346c41f2942131dfcef91a /spec/features | |
parent | 78dad4cf321eb84aa5decdea34704145adca0c3e (diff) | |
parent | fd54a4678f23c9e18ce46b3803e5e57ffa1199a3 (diff) | |
download | gitlab-ce-a315e6025c702985b2f6390b29508de39383f52d.tar.gz |
Merge branch 'master' into zj-auto-devops-table
Diffstat (limited to 'spec/features')
40 files changed, 405 insertions, 757 deletions
diff --git a/spec/features/admin/admin_active_tab_spec.rb b/spec/features/admin/admin_active_tab_spec.rb index 07430ecd6e0..5ff791fc36a 100644 --- a/spec/features/admin/admin_active_tab_spec.rb +++ b/spec/features/admin/admin_active_tab_spec.rb @@ -7,15 +7,15 @@ RSpec.describe 'admin active tab' do shared_examples 'page has active tab' do |title| it "activates #{title} tab" do - expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 1) - expect(page.find('.layout-nav li.active')).to have_content(title) + expect(page).to have_selector('.nav-sidebar .sidebar-top-level-items > li.active', count: 1) + expect(page.find('.nav-sidebar .sidebar-top-level-items > li.active')).to have_content(title) end end shared_examples 'page has active sub tab' do |title| it "activates #{title} sub tab" do - expect(page).to have_selector('.sub-nav li.active', count: 1) - expect(page.find('.sub-nav li.active')).to have_content(title) + expect(page).to have_selector('.sidebar-sub-level-items li.active', count: 1) + expect(page.find('.sidebar-sub-level-items li.active')).to have_content(title) end end diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index 30fcb334b60..91f08dbad5d 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Admin::Hooks' do +describe 'Admin::Hooks', :js do before do @project = create(:project) sign_in(create(:admin)) @@ -12,7 +12,7 @@ describe 'Admin::Hooks' do it 'is ok' do visit admin_root_path - page.within '.layout-nav' do + page.within '.nav-sidebar' do click_on 'Hooks' end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index dbb0ae9c86e..563818e8761 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -79,6 +79,22 @@ feature 'Admin updates settings' do end end + scenario 'Change Keys settings' do + select 'Are forbidden', from: 'RSA SSH keys' + select 'Are allowed', from: 'DSA SSH keys' + select 'Must be at least 384 bits', from: 'ECDSA SSH keys' + select 'Are forbidden', from: 'ED25519 SSH keys' + click_on 'Save' + + forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE.to_s + + expect(page).to have_content 'Application settings saved successfully' + expect(find_field('RSA SSH keys').value).to eq(forbidden) + expect(find_field('DSA SSH keys').value).to eq('0') + expect(find_field('ECDSA SSH keys').value).to eq('384') + expect(find_field('ED25519 SSH keys').value).to eq(forbidden) + end + def check_all_events page.check('Active') page.check('Push') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index ce458431c55..913258ca40f 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -13,6 +13,8 @@ describe 'Issue Boards', js: true do project.team << [user, :master] project.team << [user2, :master] + allow_any_instance_of(ApplicationHelper).to receive(:collapsed_sidebar?).and_return(true) + sign_in(user) end @@ -145,6 +147,8 @@ describe 'Issue Boards', js: true do click_button 'Add list' wait_for_requests + find('.dropdown-menu-close').click + page.within(find('.board:nth-child(2)')) do find('.board-delete').click end diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb index 067e4337e6a..08d8cc7922b 100644 --- a/spec/features/dashboard/active_tab_spec.rb +++ b/spec/features/dashboard/active_tab_spec.rb @@ -7,9 +7,8 @@ RSpec.describe 'Dashboard Active Tab', js: true do shared_examples 'page has active tab' do |title| it "#{title} tab" do - find('.global-dropdown-toggle').trigger('click') - expect(page).to have_selector('.global-dropdown-menu li.active', count: 1) - expect(find('.global-dropdown-menu li.active')).to have_content(title) + expect(page).to have_selector('.navbar-sub-nav li.active', count: 1) + expect(find('.navbar-sub-nav li.active')).to have_content(title) end end @@ -21,27 +20,19 @@ RSpec.describe 'Dashboard Active Tab', js: true do it_behaves_like 'page has active tab', 'Projects' end - context 'on dashboard issues' do - before do - visit issues_dashboard_path - end - - it_behaves_like 'page has active tab', 'Issues' - end - - context 'on dashboard merge requests' do + context 'on dashboard groups' do before do - visit merge_requests_dashboard_path + visit dashboard_groups_path end - it_behaves_like 'page has active tab', 'Merge Requests' + it_behaves_like 'page has active tab', 'Groups' end - context 'on dashboard groups' do + context 'on activity projects' do before do - visit dashboard_groups_path + visit activity_dashboard_path end - it_behaves_like 'page has active tab', 'Groups' + it_behaves_like 'page has active tab', 'Activity' end end diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb index facb67ae787..ebc3d196118 100644 --- a/spec/features/dashboard/issues_filter_spec.rb +++ b/spec/features/dashboard/issues_filter_spec.rb @@ -50,7 +50,7 @@ feature 'Dashboard Issues filtering', :js do it 'updates atom feed link' do visit_issues(milestone_title: '', assignee_id: user.id) - link = find('.nav-controls a[title="Subscribe"]') + link = find('.breadcrumbs a[title="Subscribe"]') params = CGI.parse(URI.parse(link[:href]).query) auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb index 5f1f0c10339..e41bd7a8419 100644 --- a/spec/features/dashboard/shortcuts_spec.rb +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -50,6 +50,6 @@ feature 'Dashboard shortcuts', :js do end def check_page_title(title) - expect(find('.header-content .title')).to have_content(title) + expect(find('.breadcrumbs-sub-title')).to have_content(title) end end diff --git a/spec/features/groups/group_name_toggle_spec.rb b/spec/features/groups/group_name_toggle_spec.rb deleted file mode 100644 index a7b8b702ab7..00000000000 --- a/spec/features/groups/group_name_toggle_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'spec_helper' - -feature 'Group name toggle', js: true do - let(:group) { create(:group) } - let(:nested_group_1) { create(:group, parent: group) } - let(:nested_group_2) { create(:group, parent: nested_group_1) } - let(:nested_group_3) { create(:group, parent: nested_group_2) } - - SMALL_SCREEN = 300 - - before do - sign_in(create(:user)) - end - - it 'is not present if enough horizontal space' do - visit group_path(nested_group_3) - - container_width = page.evaluate_script("$('.title-container')[0].offsetWidth") - title_width = page.evaluate_script("$('.title')[0].offsetWidth") - - expect(container_width).to be > title_width - expect(page).not_to have_css('.group-name-toggle') - end - - it 'is present if the title is longer than the container', :nested_groups do - visit group_path(nested_group_3) - title_width = page.evaluate_script("$('.title')[0].offsetWidth") - - page_height = page.current_window.size[1] - page.current_window.resize_to(SMALL_SCREEN, page_height) - - find('.group-name-toggle') - container_width = page.evaluate_script("$('.title-container')[0].offsetWidth") - - expect(title_width).to be > container_width - end - - it 'should show the full group namespace when toggled', :nested_groups do - page_height = page.current_window.size[1] - page.current_window.resize_to(SMALL_SCREEN, page_height) - visit group_path(nested_group_3) - - expect(page).not_to have_content(group.name) - expect(page).to have_css('.group-path.hidable', visible: false) - - click_button '...' - - expect(page).to have_content(group.name) - expect(page).to have_css('.group-path.hidable', visible: true) - end -end diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb index d0316cfb18d..b83bad3befb 100644 --- a/spec/features/groups/group_settings_spec.rb +++ b/spec/features/groups/group_settings_spec.rb @@ -65,14 +65,14 @@ feature 'Edit group settings' do update_path(new_group_path) visit new_project_full_path expect(current_path).to eq(new_project_full_path) - expect(find('h1.title')).to have_content(project.path) + expect(find('.breadcrumbs')).to have_content(project.path) end scenario 'the old project path redirects to the new path' do update_path(new_group_path) visit old_project_full_path expect(current_path).to eq(new_project_full_path) - expect(find('h1.title')).to have_content(project.path) + expect(find('.breadcrumbs')).to have_content(project.path) end end end diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb index 9ba9f5686f7..2577d98df6f 100644 --- a/spec/features/groups/merge_requests_spec.rb +++ b/spec/features/groups/merge_requests_spec.rb @@ -25,7 +25,7 @@ feature 'Group merge requests page' do end it 'ignores archived merge request count badges in navbar' do - expect( page.find('[title="Merge Requests"] span.badge.count').text).to eq("1") + expect( page.find('[aria-label="Merge Requests"] span.badge.count').text).to eq("1") end it 'ignores archived merge request count badges in state-filters' do diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 20f9818b08b..4ec2e7e6012 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -158,7 +158,7 @@ feature 'Group' do expect(page).to have_content 'successfully updated' expect(find('#group_name').value).to eq(new_name) - page.within ".navbar-gitlab" do + page.within ".breadcrumbs" do expect(page).to have_content new_name end end diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index 134e618feac..a29acb30163 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -70,13 +70,13 @@ describe 'Awards Emoji' do it 'toggles the smiley emoji on a note', js: true do toggle_smiley_emoji(true) - within('.note-awards') do + within('.note-body') do expect(find(emoji_counter)).to have_text("1") end toggle_smiley_emoji(false) - within('.note-awards') do + within('.note-body') do expect(page).not_to have_selector(emoji_counter) end end diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index a64c1cf220b..3ea6e1c8863 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -1,26 +1,24 @@ require 'spec_helper' describe 'Filter issues', js: true do - include Devise::Test::IntegrationHelpers include FilteredSearchHelpers - let!(:group) { create(:group) } - let!(:project) { create(:project, group: group) } - let!(:user) { create(:user, username: 'joe', name: 'Joe') } - let!(:user2) { create(:user, username: 'jane') } - let!(:label) { create(:label, project: project) } - let!(:wontfix) { create(:label, project: project, title: "Won't fix") } + let(:project) { create(:project) } + + # NOTE: The short name here is actually important + # + # When the name is longer, the filtered search input can end up scrolling + # horizontally, and PhantomJS can't handle it. + let(:user) { create(:user, name: 'Ann') } let!(:bug_label) { create(:label, project: project, title: 'bug') } 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") } - - let!(:closed_issue) { create(:issue, title: 'bug that is closed', project: project, state: :closed) } + let!(:milestone) { create(:milestone, title: "8", project: project, start_date: 2.days.ago) } def expect_no_issues_list page.within '.issues-list' do - expect(page).not_to have_selector('.issue') + expect(page).to have_no_selector('.issue') end end @@ -33,63 +31,62 @@ describe 'Filter issues', js: true do end end - def select_search_at_index(pos) - evaluate_script("el = document.querySelector('.filtered-search'); el.focus(); el.setSelectionRange(#{pos}, #{pos});") - end - before do - project.team << [user, :master] - project.team << [user2, :master] - group.add_developer(user) - group.add_developer(user2) + project.add_master(user) - sign_in(user) + user2 = create(: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]) + create(:issue, project: project, author: user2, title: "Bug report 1") + create(:issue, project: project, author: user2, title: "Bug report 2") - issue = create(:issue, + create(:issue, project: project, author: user, title: "issue by assignee", milestone: milestone, assignees: [user]) + create(:issue, project: project, author: user, title: "issue by assignee with searchTerm", milestone: milestone, assignees: [user]) + + create(:labeled_issue, title: "Bug 2", project: project, milestone: milestone, author: user, - assignees: [user]) - issue.labels << bug_label + assignees: [user], + labels: [bug_label]) - issue_with_caps_label = create(:issue, + create(:labeled_issue, title: "issue by assignee with searchTerm and label", project: project, milestone: milestone, author: user, - assignees: [user]) - issue_with_caps_label.labels << caps_sensitive_label + assignees: [user], + labels: [caps_sensitive_label]) - issue_with_everything = create(:issue, + create(:labeled_issue, title: "Bug report foo was possible", project: project, milestone: milestone, author: user, - assignees: [user]) - issue_with_everything.labels << bug_label - issue_with_everything.labels << caps_sensitive_label + assignees: [user], + labels: [bug_label, caps_sensitive_label]) + + create(:labeled_issue, title: "Issue with multiple words label", project: project, labels: [multiple_words_label]) - multiple_words_label_issue = create(:issue, title: "Issue with multiple words label", project: project) - multiple_words_label_issue.labels << multiple_words_label + sign_in(user) + visit project_issues_path(project) + end - future_milestone = create(:milestone, title: "future", project: project, due_date: Time.now + 1.month) + it 'filters by all available tokens' do + search_term = 'issue' - create(:issue, - title: "Issue with future milestone", - milestone: future_milestone, - project: project) + input_filtered_search("assignee:@#{user.username} author:@#{user.username} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} #{search_term}") - visit project_issues_path(project) + wait_for_requests + + expect_tokens([ + assignee_token(user.name), + author_token(user.name), + label_token(caps_sensitive_label.title), + milestone_token(milestone.title) + ]) + expect_issues_list_count(1) + expect_filtered_search_input(search_term) end describe 'filter issues by author' do @@ -104,59 +101,6 @@ describe 'Filter issues', js: true do expect_filtered_search_input_empty end end - - context 'author with other filters' do - let(:search_term) { 'issue' } - - it 'filters issues by searched author and text' do - input_filtered_search("author:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([author_token(user.name)]) - expect_issues_list_count(3) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched author, assignee and text' do - input_filtered_search("author:@#{user.username} assignee:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([author_token(user.name), assignee_token(user.name)]) - expect_issues_list_count(3) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched author, assignee, label, and text' do - input_filtered_search("author:@#{user.username} assignee:@#{user.username} label:~#{caps_sensitive_label.title} #{search_term}") - - wait_for_requests - - expect_tokens([ - author_token(user.name), - assignee_token(user.name), - label_token(caps_sensitive_label.title) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched author, assignee, label, milestone and text' do - input_filtered_search("author:@#{user.username} assignee:@#{user.username} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} #{search_term}") - - wait_for_requests - - expect_tokens([ - author_token(user.name), - assignee_token(user.name), - label_token(caps_sensitive_label.title), - milestone_token(milestone.title) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - end end describe 'filter issues by assignee' do @@ -175,66 +119,13 @@ describe 'Filter issues', js: true do input_filtered_search('assignee:none') expect_tokens([assignee_token('none')]) - expect_issues_list_count(8, 1) + expect_issues_list_count(3) expect_filtered_search_input_empty end end - - context 'assignee with other filters' do - let(:search_term) { 'searchTerm' } - - it 'filters issues by searched assignee and text' do - input_filtered_search("assignee:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([assignee_token(user.name)]) - expect_issues_list_count(2) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched assignee, author and text' do - input_filtered_search("assignee:@#{user.username} author:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([assignee_token(user.name), author_token(user.name)]) - expect_issues_list_count(2) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched assignee, author, label, text' do - input_filtered_search("assignee:@#{user.username} author:@#{user.username} label:~#{caps_sensitive_label.title} #{search_term}") - - wait_for_requests - - expect_tokens([ - assignee_token(user.name), - author_token(user.name), - label_token(caps_sensitive_label.title) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched assignee, author, label, milestone and text' do - input_filtered_search("assignee:@#{user.username} author:@#{user.username} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} #{search_term}") - - expect_tokens([ - assignee_token(user.name), - author_token(user.name), - label_token(caps_sensitive_label.title), - milestone_token(milestone.title) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - end end describe 'filter issues by label' do - let(:search_term) { 'bug' } - context 'only label' do it 'filters issues by searched label' do input_filtered_search("label:~#{bug_label.title}") @@ -248,7 +139,7 @@ describe 'Filter issues', js: true do input_filtered_search('label:none') expect_tokens([label_token('none', false)]) - expect_issues_list_count(9, 1) + expect_issues_list_count(8) expect_filtered_search_input_empty end @@ -275,13 +166,13 @@ describe 'Filter issues', js: true do expect_filtered_search_input_empty end - it 'does not show issues' do + it 'does not show issues for unused labels' do new_label = create(:label, project: project, title: 'new_label') input_filtered_search("label:~#{new_label.title}") expect_tokens([label_token(new_label.title)]) - expect_no_issues_list() + expect_no_issues_list expect_filtered_search_input_empty end end @@ -344,95 +235,10 @@ describe 'Filter issues', js: true do end end - context 'label with other filters' do - it 'filters issues by searched label and text' do - input_filtered_search("label:~#{caps_sensitive_label.title} #{search_term}") - - expect_tokens([label_token(caps_sensitive_label.title)]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched label, author and text' do - input_filtered_search("label:~#{caps_sensitive_label.title} author:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([label_token(caps_sensitive_label.title), author_token(user.name)]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched label, author, assignee and text' do - input_filtered_search("label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([ - label_token(caps_sensitive_label.title), - author_token(user.name), - assignee_token(user.name) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched label, author, assignee, milestone and text' do - input_filtered_search("label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} milestone:%#{milestone.title} #{search_term}") - - expect_tokens([ - label_token(caps_sensitive_label.title), - author_token(user.name), - assignee_token(user.name), - milestone_token(milestone.title) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - end - context 'multiple labels with other filters' do - it 'filters issues by searched label, label2, and text' do - input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} #{search_term}") - - expect_tokens([ - label_token(bug_label.title), - label_token(caps_sensitive_label.title) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched label, label2, author and text' do - input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([ - label_token(bug_label.title), - label_token(caps_sensitive_label.title), - author_token(user.name) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched label, label2, author, assignee and text' do - input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([ - label_token(bug_label.title), - label_token(caps_sensitive_label.title), - author_token(user.name), - assignee_token(user.name) - ]) - expect_issues_list_count(1) - expect_filtered_search_input(search_term) - end - it 'filters issues by searched label, label2, author, assignee, milestone and text' do + search_term = 'bug' + input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} milestone:%#{milestone.title} #{search_term}") wait_for_requests @@ -450,15 +256,10 @@ describe 'Filter issues', js: true do end context 'issue label clicked' do - before do + it 'filters and displays in search bar' do find('.issues-list .issue .issue-main-info .issuable-info a .label', text: multiple_words_label.title).click - end - it 'filters' do expect_issues_list_count(1) - end - - it 'displays in search bar' do expect_tokens([label_token("\"#{multiple_words_label.title}\"")]) expect_filtered_search_input_empty end @@ -479,11 +280,15 @@ describe 'Filter issues', js: true do input_filtered_search("milestone:none") expect_tokens([milestone_token('none', false)]) - expect_issues_list_count(7, 1) + expect_issues_list_count(3) expect_filtered_search_input_empty end it 'filters issues by upcoming milestones' do + create(:milestone, project: project, due_date: 1.month.from_now) do |future_milestone| + create(:issue, project: project, milestone: future_milestone, author: user) + end + input_filtered_search("milestone:upcoming") expect_tokens([milestone_token('upcoming', false)]) @@ -501,7 +306,7 @@ describe 'Filter issues', js: true do it 'filters issues by milestone containing special characters' do special_milestone = create(:milestone, title: '!@\#{$%^&*()}', project: project) - create(:issue, title: "Issue with special character milestone", project: project, milestone: special_milestone) + create(:issue, project: project, milestone: special_milestone) input_filtered_search("milestone:%#{special_milestone.title}") @@ -510,70 +315,16 @@ describe 'Filter issues', js: true do expect_filtered_search_input_empty end - it 'does not show issues' do - new_milestone = create(:milestone, title: "new", project: project) + it 'does not show issues for unused milestones' do + new_milestone = create(:milestone, title: 'new', project: project) input_filtered_search("milestone:%#{new_milestone.title}") expect_tokens([milestone_token(new_milestone.title)]) - expect_no_issues_list() + expect_no_issues_list expect_filtered_search_input_empty end end - - context 'milestone with other filters' do - let(:search_term) { 'bug' } - - it 'filters issues by searched milestone and text' do - input_filtered_search("milestone:%#{milestone.title} #{search_term}") - - expect_tokens([milestone_token(milestone.title)]) - expect_issues_list_count(2) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched milestone, author and text' do - input_filtered_search("milestone:%#{milestone.title} author:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([ - milestone_token(milestone.title), - author_token(user.name) - ]) - expect_issues_list_count(2) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched milestone, author, assignee and text' do - input_filtered_search("milestone:%#{milestone.title} author:@#{user.username} assignee:@#{user.username} #{search_term}") - - wait_for_requests - - expect_tokens([ - milestone_token(milestone.title), - author_token(user.name), - assignee_token(user.name) - ]) - expect_issues_list_count(2) - expect_filtered_search_input(search_term) - end - - it 'filters issues by searched milestone, author, assignee, label and text' do - input_filtered_search("milestone:%#{milestone.title} author:@#{user.username} assignee:@#{user.username} label:~#{bug_label.title} #{search_term}") - - wait_for_requests - - expect_tokens([ - milestone_token(milestone.title), - author_token(user.name), - assignee_token(user.name), - label_token(bug_label.title) - ]) - expect_issues_list_count(2) - expect_filtered_search_input(search_term) - end - end end describe 'filter issues by text' do @@ -582,7 +333,7 @@ describe 'Filter issues', js: true do search = 'Bug' input_filtered_search(search) - expect_issues_list_count(4, 1) + expect_issues_list_count(4) expect_filtered_search_input(search) end @@ -603,112 +354,50 @@ describe 'Filter issues', js: true do end it 'filters issues by searched text containing single quotes' do - search = '\'single quotes\'' + issue = create(:issue, project: project, author: user, title: "issue with 'single quotes'") + + search = "'single quotes'" input_filtered_search(search) expect_issues_list_count(1) expect_filtered_search_input(search) + expect(page).to have_content(issue.title) end it 'filters issues by searched text containing double quotes' do + issue = create(:issue, project: project, author: user, title: "issue with \"double quotes\"") + search = '"double quotes"' input_filtered_search(search) expect_issues_list_count(1) expect_filtered_search_input(search) + expect(page).to have_content(issue.title) end it 'filters issues by searched text containing special characters' do + issue = create(:issue, project: project, author: user, title: "issue with !@\#{$%^&*()-+") + search = '!@#{$%^&*()-+' input_filtered_search(search) expect_issues_list_count(1) expect_filtered_search_input(search) + expect(page).to have_content(issue.title) end it 'does not show any issues' do search = 'testing' input_filtered_search(search) - expect_no_issues_list() + expect_no_issues_list expect_filtered_search_input(search) end end context 'searched text with other filters' do - it 'filters issues by searched text and author' do - # After searching, all search terms are placed at the end - input_filtered_search("bug author:@#{user.username}") - - expect_issues_list_count(2) - expect_filtered_search_input('bug') - end - - it 'filters issues by searched text, author and more text' do - input_filtered_search("bug author:@#{user.username} report") - - expect_issues_list_count(1) - expect_filtered_search_input('bug report') - end - - it 'filters issues by searched text, author and assignee' do - input_filtered_search("bug author:@#{user.username} assignee:@#{user.username}") - - expect_issues_list_count(2) - expect_filtered_search_input('bug') - end - - it 'filters issues by searched text, author, more text and assignee' do - input_filtered_search("bug author:@#{user.username} report assignee:@#{user.username}") - - expect_issues_list_count(1) - expect_filtered_search_input('bug report') - 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} foo") - - expect_issues_list_count(1) - expect_filtered_search_input('bug report foo') - end - - it 'filters issues by searched text, author, assignee and label' do - input_filtered_search("bug author:@#{user.username} assignee:@#{user.username} label:~#{bug_label.title}") - - expect_issues_list_count(2) - expect_filtered_search_input('bug') - end - - it 'filters issues by searched text, author, text, assignee, text, label and text' do - 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 foo') - end - - it 'filters issues by searched text, author, assignee, label and milestone' do - input_filtered_search("bug author:@#{user.username} assignee:@#{user.username} label:~#{bug_label.title} milestone:%#{milestone.title}") - - expect_issues_list_count(2) - expect_filtered_search_input('bug') - end - - it 'filters issues by searched text, author, text, assignee, text, label, text, milestone and text' do - 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 foo') - end - - it 'filters issues by searched text, author, assignee, multiple labels and milestone' do - input_filtered_search("bug author:@#{user.username} assignee:@#{user.username} label:~#{bug_label.title} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title}") - - expect_issues_list_count(1) - expect_filtered_search_input('bug') - 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} assignee:@#{user.username} report label:~#{bug_label.title} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} foo") + input_filtered_search("bug author:@#{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 foo') @@ -746,7 +435,9 @@ describe 'Filter issues', js: true do end end - describe 'retains filter when switching issue states' do + describe 'switching issue states' do + let!(:closed_issue) { create(:issue, :closed, project: project, title: 'closed bug') } + before do input_filtered_search('bug') @@ -754,25 +445,21 @@ describe 'Filter issues', js: true do expect_issues_list_count(4, 1) end - it 'open state' do + it 'maintains filter' do + # Closed find('.issues-state-filters [data-state="closed"]').click wait_for_requests + expect(page).to have_selector('.issues-list .issue', count: 1) + expect(page).to have_link(closed_issue.title) + + # Opened find('.issues-state-filters [data-state="opened"]').click wait_for_requests expect(page).to have_selector('.issues-list .issue', count: 4) - end - it 'closed state' do - find('.issues-state-filters [data-state="closed"]').click - wait_for_requests - - expect(page).to have_selector('.issues-list .issue', count: 1) - expect(find('.issues-list .issue:first-of-type .issue-title-text a')).to have_content(closed_issue.title) - end - - it 'all state' do + # All find('.issues-state-filters [data-state="all"]').click wait_for_requests @@ -781,34 +468,39 @@ describe 'Filter issues', js: true do end describe 'RSS feeds' do - it 'updates atom feed link for project issues' do - visit project_issues_path(project, milestone_title: milestone.title, assignee_id: user.id) - link = find_link('Subscribe') - params = CGI.parse(URI.parse(link[:href]).query) - auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) - auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) - - expect(params).to include('rss_token' => [user.rss_token]) - expect(params).to include('milestone_title' => [milestone.title]) - expect(params).to include('assignee_id' => [user.id.to_s]) - expect(auto_discovery_params).to include('rss_token' => [user.rss_token]) - expect(auto_discovery_params).to include('milestone_title' => [milestone.title]) - expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) + let(:group) { create(:group) } + let(:project) { create(:project, group: group) } + + before do + group.add_developer(user) + end + + shared_examples 'updates atom feed link' do |type| + it "for #{type}" do + visit path + + link = find_link('Subscribe') + params = CGI.parse(URI.parse(link[:href]).query) + auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) + auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) + + expected = { + 'rss_token' => [user.rss_token], + 'milestone_title' => [milestone.title], + 'assignee_id' => [user.id.to_s] + } + + expect(params).to include(expected) + expect(auto_discovery_params).to include(expected) + end + end + + it_behaves_like 'updates atom feed link', :project do + let(:path) { project_issues_path(project, milestone_title: milestone.title, assignee_id: user.id) } end - it 'updates atom feed link for group issues' do - visit issues_group_path(group, milestone_title: milestone.title, assignee_id: user.id) - link = find('.nav-controls a', text: 'Subscribe') - params = CGI.parse(URI.parse(link[:href]).query) - auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) - auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) - - expect(params).to include('rss_token' => [user.rss_token]) - expect(params).to include('milestone_title' => [milestone.title]) - expect(params).to include('assignee_id' => [user.id.to_s]) - expect(auto_discovery_params).to include('rss_token' => [user.rss_token]) - expect(auto_discovery_params).to include('milestone_title' => [milestone.title]) - expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) + it_behaves_like 'updates atom feed link', :group do + let(:path) { issues_group_path(group, milestone_title: milestone.title, assignee_id: user.id) } end end @@ -821,7 +513,7 @@ describe 'Filter issues', js: true do input_filtered_search("milestone:", submit: false) within('#js-dropdown-milestone') do - expect(page).to have_selector('.filter-dropdown .filter-dropdown-item', count: 2) + expect(page).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1) end end @@ -829,7 +521,7 @@ describe 'Filter issues', js: true do input_filtered_search("label:", submit: false) within('#js-dropdown-label') do - expect(page).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5) + expect(page).to have_selector('.filter-dropdown .filter-dropdown-item', count: 3) end end end diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb index 14a555fde10..4ae54fd6f4e 100644 --- a/spec/features/issues/filtered_search/visual_tokens_spec.rb +++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb @@ -28,6 +28,8 @@ describe 'Visual tokens', js: true do sign_in(user) create(:issue, project: project) + allow_any_instance_of(ApplicationHelper).to receive(:collapsed_sidebar?).and_return(true) + visit project_issues_path(project) end diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index b84635c5134..c6cf6265645 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -28,8 +28,8 @@ feature 'GFM autocomplete', js: true do it 'opens autocomplete menu when field starts with text' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys('') - find('#note_note').native.send_keys('@') + find('#note-body').native.send_keys('') + find('#note-body').native.send_keys('@') end expect(page).to have_selector('.atwho-container') @@ -37,8 +37,8 @@ feature 'GFM autocomplete', js: true do it 'doesnt open autocomplete menu character is prefixed with text' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys('testing') - find('#note_note').native.send_keys('@') + find('#note-body').native.send_keys('testing') + find('#note-body').native.send_keys('@') end expect(page).not_to have_selector('.atwho-view') @@ -46,8 +46,8 @@ feature 'GFM autocomplete', js: true do it 'doesnt select the first item for non-assignee dropdowns' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys('') - find('#note_note').native.send_keys(':') + find('#note-body').native.send_keys('') + find('#note-body').native.send_keys(':') end expect(page).to have_selector('.atwho-container') @@ -58,7 +58,7 @@ feature 'GFM autocomplete', js: true do end it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do - note = find('#note_note') + note = find('#note-body') # Number. page.within '.timeline-content-form' do @@ -86,8 +86,8 @@ feature 'GFM autocomplete', js: true do it 'selects the first item for assignee dropdowns' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys('') - find('#note_note').native.send_keys('@') + find('#note-body').native.send_keys('') + find('#note-body').native.send_keys('@') end expect(page).to have_selector('.atwho-container') @@ -99,8 +99,8 @@ feature 'GFM autocomplete', js: true do it 'includes items for assignee dropdowns with non-ASCII characters in name' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys('') - find('#note_note').native.send_keys("@#{user.name[0...8]}") + find('#note-body').native.send_keys('') + find('#note-body').native.send_keys("@#{user.name[0...8]}") end expect(page).to have_selector('.atwho-container') @@ -112,8 +112,8 @@ feature 'GFM autocomplete', js: true do it 'selects the first item for non-assignee dropdowns if a query is entered' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys('') - find('#note_note').native.send_keys(':1') + find('#note-body').native.send_keys('') + find('#note-body').native.send_keys(':1') end expect(page).to have_selector('.atwho-container') @@ -125,7 +125,7 @@ feature 'GFM autocomplete', js: true do context 'if a selected value has special characters' do it 'wraps the result in double quotes' do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('') note.native.send_keys("~#{label.title[0]}") @@ -138,7 +138,7 @@ feature 'GFM autocomplete', js: true do end it "shows dropdown after a new line" do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('test') note.native.send_keys(:enter) @@ -150,7 +150,7 @@ feature 'GFM autocomplete', js: true do end it "does not show dropdown when preceded with a special character" do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('') note.native.send_keys("@") @@ -168,7 +168,7 @@ feature 'GFM autocomplete', js: true do end it "does not throw an error if no labels exist" do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('') note.native.send_keys('~') @@ -179,7 +179,7 @@ feature 'GFM autocomplete', js: true do end it 'doesn\'t wrap for assignee values' do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('') note.native.send_keys("@#{user.username[0]}") @@ -192,7 +192,7 @@ feature 'GFM autocomplete', js: true do end it 'doesn\'t wrap for emoji values' do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('') note.native.send_keys(":cartwheel") @@ -206,7 +206,7 @@ feature 'GFM autocomplete', js: true do it 'doesn\'t open autocomplete after non-word character' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys("@#{user.username[0..2]}!") + find('#note-body').native.send_keys("@#{user.username[0..2]}!") end expect(page).not_to have_selector('.atwho-view') @@ -214,14 +214,14 @@ feature 'GFM autocomplete', js: true do it 'doesn\'t open autocomplete if there is no space before' do page.within '.timeline-content-form' do - find('#note_note').native.send_keys("hello:#{user.username[0..2]}") + find('#note-body').native.send_keys("hello:#{user.username[0..2]}") end expect(page).not_to have_selector('.atwho-view') end it 'triggers autocomplete after selecting a quick action' do - note = find('#note_note') + note = find('#note-body') page.within '.timeline-content-form' do note.native.send_keys('') note.native.send_keys('/as') diff --git a/spec/features/issues/markdown_toolbar_spec.rb b/spec/features/issues/markdown_toolbar_spec.rb index 8c23fcd483b..634ea111dc1 100644 --- a/spec/features/issues/markdown_toolbar_spec.rb +++ b/spec/features/issues/markdown_toolbar_spec.rb @@ -12,26 +12,26 @@ feature 'Issue markdown toolbar', js: true do end it "doesn't include first new line when adding bold" do - find('#note_note').native.send_keys('test') - find('#note_note').native.send_key(:enter) - find('#note_note').native.send_keys('bold') + find('#note-body').native.send_keys('test') + find('#note-body').native.send_key(:enter) + find('#note-body').native.send_keys('bold') - page.evaluate_script('document.querySelectorAll(".js-main-target-form #note_note")[0].setSelectionRange(4, 9)') + page.evaluate_script('document.querySelectorAll(".js-main-target-form #note-body")[0].setSelectionRange(4, 9)') first('.toolbar-btn').click - expect(find('#note_note')[:value]).to eq("test\n**bold**\n") + expect(find('#note-body')[:value]).to eq("test\n**bold**\n") end it "doesn't include first new line when adding underline" do - find('#note_note').native.send_keys('test') - find('#note_note').native.send_key(:enter) - find('#note_note').native.send_keys('underline') + find('#note-body').native.send_keys('test') + find('#note-body').native.send_key(:enter) + find('#note-body').native.send_keys('underline') - page.evaluate_script('document.querySelectorAll(".js-main-target-form #note_note")[0].setSelectionRange(4, 50)') + page.evaluate_script('document.querySelectorAll(".js-main-target-form #note-body")[0].setSelectionRange(4, 50)') find('.toolbar-btn:nth-child(2)').click - expect(find('#note_note')[:value]).to eq("test\n*underline*\n") + expect(find('#note-body')[:value]).to eq("test\n*underline*\n") end end diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb index 62dbc3efb01..793572851da 100644 --- a/spec/features/issues/note_polling_spec.rb +++ b/spec/features/issues/note_polling_spec.rb @@ -13,7 +13,7 @@ feature 'Issue notes polling', :js do it 'displays the new comment' do note = create(:note, noteable: issue, project: project, note: 'Looks good!') - page.execute_script('notes.refresh();') + wait_for_requests expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!') end @@ -31,16 +31,6 @@ feature 'Issue notes polling', :js do visit project_issue_path(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) @@ -49,24 +39,14 @@ feature 'Issue notes polling', :js do 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 + it 'when editing but have not changed anything, and an update comes in, show warning and does not update the note' do click_edit_action(existing_note) 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 - click_edit_action(existing_note) - - 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).not_to have_field("note[note]", with: updated_text) expect(page).to have_selector(".alert") end @@ -75,8 +55,6 @@ feature 'Issue notes polling', :js do 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 @@ -97,14 +75,12 @@ feature 'Issue notes polling', :js do visit project_issue_path(project, issue) end - it 'has .original-note-content to compare against' do + it 'displays the updated content' 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 @@ -118,16 +94,15 @@ feature 'Issue notes polling', :js do visit project_issue_path(project, issue) end - it 'has .original-note-content to compare against' do + it 'shows the system note' 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();') + wait_for_requests end def click_edit_action(note) diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index 4b63cc844f3..9261acda9dc 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -155,5 +155,114 @@ feature 'Issues > User uses quick actions', js: true do end end end + + describe 'move the issue to another project' do + let(:issue) { create(:issue, project: project) } + + context 'when the project is valid', js: true do + let(:target_project) { create(:project, :public) } + + before do + target_project.team << [user, :master] + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'moves the issue' do + write_note("/move #{target_project.full_path}") + + expect(page).to have_content 'Commands applied' + expect(issue.reload).to be_closed + + visit project_issue_path(target_project, issue) + + expect(page).to have_content 'Issues 1' + end + end + + context 'when the project is valid but the user not authorized', js: true do + let(:project_unauthorized) {create(:project, :public)} + + before do + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'does not move the issue' do + write_note("/move #{project_unauthorized.full_path}") + + expect(page).not_to have_content 'Commands applied' + expect(issue.reload).to be_open + end + end + + context 'when the project is invalid', js: true do + before do + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'does not move the issue' do + write_note("/move not/valid") + + expect(page).not_to have_content 'Commands applied' + expect(issue.reload).to be_open + end + end + + context 'when the user issues multiple commands', js: true do + let(:target_project) { create(:project, :public) } + let(:milestone) { create(:milestone, title: '1.0', project: project) } + let(:target_milestone) { create(:milestone, title: '1.0', project: target_project) } + let(:bug) { create(:label, project: project, title: 'bug') } + let(:wontfix) { create(:label, project: project, title: 'wontfix') } + let(:bug_target) { create(:label, project: target_project, title: 'bug') } + let(:wontfix_target) { create(:label, project: target_project, title: 'wontfix') } + + before do + target_project.team << [user, :master] + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'applies the commands to both issues and moves the issue' do + write_note("/label ~#{bug.title} ~#{wontfix.title}\n/milestone %\"#{milestone.title}\"\n/move #{target_project.full_path}") + + expect(page).to have_content 'Commands applied' + expect(issue.reload).to be_closed + + visit project_issue_path(target_project, issue) + + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + + visit project_issue_path(project, issue) + expect(page).to have_content 'Closed' + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + end + + it 'moves the issue and applies the commands to both issues' do + write_note("/move #{target_project.full_path}\n/label ~#{bug.title} ~#{wontfix.title}\n/milestone %\"#{milestone.title}\"") + + expect(page).to have_content 'Commands applied' + expect(issue.reload).to be_closed + + visit project_issue_path(target_project, issue) + + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + + visit project_issue_path(project, issue) + expect(page).to have_content 'Closed' + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + end + end + end end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 3ffc80622f5..11db1105d91 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -271,17 +271,21 @@ describe 'Issues' do it 'filters by none' do visit project_issues_path(project, due_date: Issue::NoDueDate.name) - expect(page).not_to have_content('foo') - expect(page).not_to have_content('bar') - expect(page).to have_content('baz') + page.within '.issues-holder' do + expect(page).not_to have_content('foo') + expect(page).not_to have_content('bar') + expect(page).to have_content('baz') + end end it 'filters by any' do visit project_issues_path(project, due_date: Issue::AnyDueDate.name) - expect(page).to have_content('foo') - expect(page).to have_content('bar') - expect(page).to have_content('baz') + page.within '.issues-holder' do + expect(page).to have_content('foo') + expect(page).to have_content('bar') + expect(page).to have_content('baz') + end end it 'filters by due this week' do @@ -291,9 +295,11 @@ describe 'Issues' do visit project_issues_path(project, due_date: Issue::DueThisWeek.name) - expect(page).to have_content('foo') - expect(page).to have_content('bar') - expect(page).not_to have_content('baz') + page.within '.issues-holder' do + expect(page).to have_content('foo') + expect(page).to have_content('bar') + expect(page).not_to have_content('baz') + end end it 'filters by due this month' do @@ -303,9 +309,11 @@ describe 'Issues' do visit project_issues_path(project, due_date: Issue::DueThisMonth.name) - expect(page).to have_content('foo') - expect(page).to have_content('bar') - expect(page).not_to have_content('baz') + page.within '.issues-holder' do + expect(page).to have_content('foo') + expect(page).to have_content('bar') + expect(page).not_to have_content('baz') + end end it 'filters by overdue' do @@ -315,9 +323,11 @@ describe 'Issues' do visit project_issues_path(project, due_date: Issue::Overdue.name) - expect(page).not_to have_content('foo') - expect(page).not_to have_content('bar') - expect(page).to have_content('baz') + page.within '.issues-holder' do + expect(page).not_to have_content('foo') + expect(page).not_to have_content('bar') + expect(page).to have_content('baz') + end end end @@ -567,7 +577,9 @@ describe 'Issues' do it 'redirects to signin then back to new issue after signin' do visit project_issues_path(project) - click_link 'New issue' + page.within '.breadcrumbs' do + click_link 'New issue' + end expect(current_path).to eq new_user_session_path diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb index d7f3d91e625..96e8027a54d 100644 --- a/spec/features/merge_requests/create_new_mr_spec.rb +++ b/spec/features/merge_requests/create_new_mr_spec.rb @@ -13,7 +13,9 @@ feature 'Create New Merge Request', js: true do it 'selects the source branch sha when a tag with the same name exists' do visit project_merge_requests_path(project) - click_link 'New merge request' + page.within '.content' do + click_link 'New merge request' + end expect(page).to have_content('Source branch') expect(page).to have_content('Target branch') @@ -26,7 +28,9 @@ feature 'Create New Merge Request', js: true do it 'selects the target branch sha when a tag with the same name exists' do visit project_merge_requests_path(project) - click_link 'New merge request' + page.within '.content' do + click_link 'New merge request' + end expect(page).to have_content('Source branch') expect(page).to have_content('Target branch') @@ -40,7 +44,9 @@ feature 'Create New Merge Request', js: true do it 'generates a diff for an orphaned branch' do visit project_merge_requests_path(project) - page.has_link?('New Merge Request') ? click_link("New Merge Request") : click_link('New merge request') + page.within '.content' do + click_link 'New merge request' + end expect(page).to have_content('Source branch') expect(page).to have_content('Target branch') diff --git a/spec/features/merge_requests/diff_notes_avatars_spec.rb b/spec/features/merge_requests/diff_notes_avatars_spec.rb index c4f02311f13..e77f1f92731 100644 --- a/spec/features/merge_requests/diff_notes_avatars_spec.rb +++ b/spec/features/merge_requests/diff_notes_avatars_spec.rb @@ -21,6 +21,8 @@ feature 'Diff note avatars', js: true do before do project.team << [user, :master] sign_in user + + allow_any_instance_of(ApplicationHelper).to receive(:collapsed_sidebar?).and_return(true) end context 'discussion tab' do diff --git a/spec/features/merge_requests/diffs_spec.rb b/spec/features/merge_requests/diffs_spec.rb index a8f5dc275e4..e9068f722d5 100644 --- a/spec/features/merge_requests/diffs_spec.rb +++ b/spec/features/merge_requests/diffs_spec.rb @@ -88,7 +88,7 @@ feature 'Diffs URL', js: true do visit diffs_project_merge_request_path(project, merge_request) # Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax - find("[id=\"#{changelog_id}\"] .js-edit-blob").click + find("[id=\"#{changelog_id}\"] .js-edit-blob").trigger('click') expect(page).to have_selector('.js-fork-suggestion-button', count: 1) expect(page).to have_selector('.js-cancel-fork-suggestion-button', count: 1) diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb index b1215f9ba63..dcc70338d7f 100644 --- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb +++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb @@ -70,7 +70,7 @@ feature 'Mini Pipeline Graph', :js do it 'should show tooltip when hovered' do toggle.hover - expect(toggle.find(:xpath, '..')).to have_selector('.tooltip') + expect(page).to have_selector('.tooltip') end end @@ -117,7 +117,7 @@ feature 'Mini Pipeline Graph', :js do it 'should show tooltip when hovered' do build_item.hover - expect(build_item.find(:xpath, '..')).to have_selector('.tooltip') + expect(page).to have_selector('.tooltip') end end end diff --git a/spec/features/merge_requests/user_posts_diff_notes_spec.rb b/spec/features/merge_requests/user_posts_diff_notes_spec.rb index f89dd38e5cd..877f305120e 100644 --- a/spec/features/merge_requests/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_requests/user_posts_diff_notes_spec.rb @@ -6,6 +6,8 @@ feature 'Merge requests > User posts diff notes', :js do let(:project) { merge_request.source_project } before do + allow_any_instance_of(ApplicationHelper).to receive(:collapsed_sidebar?).and_return(true) + project.add_developer(user) sign_in(user) end diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb index a22d548eef3..96f6df587e1 100644 --- a/spec/features/participants_autocomplete_spec.rb +++ b/spec/features/participants_autocomplete_spec.rb @@ -11,10 +11,14 @@ feature 'Member autocomplete', :js do sign_in(user) end - shared_examples "open suggestions when typing @" do + shared_examples "open suggestions when typing @" do |resource_name| before do page.within('.new-note') do - find('#note_note').send_keys('@') + if resource_name == 'issue' + find('#note-body').send_keys('@') + else + find('#note_note').send_keys('@') + end end end @@ -32,7 +36,7 @@ feature 'Member autocomplete', :js do visit project_issue_path(project, noteable) end - include_examples "open suggestions when typing @" + include_examples "open suggestions when typing @", 'issue' end context 'adding a new note on a Merge Request' do @@ -45,7 +49,7 @@ feature 'Member autocomplete', :js do visit project_merge_request_path(project, noteable) end - include_examples "open suggestions when typing @" + include_examples "open suggestions when typing @", 'merge_request' end context 'adding a new note on a Commit' do @@ -60,6 +64,6 @@ feature 'Member autocomplete', :js do visit project_commit_path(project, noteable) end - include_examples "open suggestions when typing @" + include_examples "open suggestions when typing @", 'commit' end end diff --git a/spec/features/profiles/account_spec.rb b/spec/features/profiles/account_spec.rb index dcd0449dbcb..171e061e60e 100644 --- a/spec/features/profiles/account_spec.rb +++ b/spec/features/profiles/account_spec.rb @@ -43,14 +43,14 @@ feature 'Profile > Account' do update_username(new_username) visit new_project_path expect(current_path).to eq(new_project_path) - expect(find('h1.title')).to have_content(project.path) + expect(find('.breadcrumbs-sub-title')).to have_content(project.path) end scenario 'the old project path redirects to the new path' do update_username(new_username) visit old_project_path expect(current_path).to eq(new_project_path) - expect(find('h1.title')).to have_content(project.path) + expect(find('.breadcrumbs-sub-title')).to have_content(project.path) end end end diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index 6541ea6bf57..aa71c4dbba4 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -28,6 +28,23 @@ feature 'Profile > SSH Keys' do expect(page).to have_content("Title: #{attrs[:title]}") expect(page).to have_content(attrs[:key]) end + + context 'when only DSA and ECDSA keys are allowed' do + before do + forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE + stub_application_setting(rsa_key_restriction: forbidden, ed25519_key_restriction: forbidden) + end + + scenario 'shows a validation error' do + attrs = attributes_for(:key) + + fill_in('Key', with: attrs[:key]) + fill_in('Title', with: attrs[:title]) + click_button('Add key') + + expect(page).to have_content('Key type is forbidden. Must be DSA or ECDSA') + end + end end scenario 'User sees their keys' do diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index 2c757f99a27..225d4c16841 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -53,12 +53,12 @@ describe 'Profile > Password' do context 'Regular user' do let(:user) { create(:user) } - it 'renders 404 when sign-in is disabled' do + it 'renders 200 when sign-in is disabled' do stub_application_setting(password_authentication_enabled: false) visit edit_profile_password_path - expect(page).to have_http_status(404) + expect(page).to have_http_status(200) end end diff --git a/spec/features/projects/guest_navigation_menu_spec.rb b/spec/features/projects/guest_navigation_menu_spec.rb index 2385e1d9333..98c7ef57a51 100644 --- a/spec/features/projects/guest_navigation_menu_spec.rb +++ b/spec/features/projects/guest_navigation_menu_spec.rb @@ -13,8 +13,8 @@ describe 'Guest navigation menu' do it 'shows allowed tabs only' do visit project_path(project) - within('.layout-nav') do - expect(page).to have_content 'Project' + within('.nav-sidebar') do + expect(page).to have_content 'Overview' expect(page).to have_content 'Issues' expect(page).to have_content 'Wiki' diff --git a/spec/features/projects/issuable_counts_caching_spec.rb b/spec/features/projects/issuable_counts_caching_spec.rb deleted file mode 100644 index 1804d9dc244..00000000000 --- a/spec/features/projects/issuable_counts_caching_spec.rb +++ /dev/null @@ -1,132 +0,0 @@ -require 'spec_helper' - -describe 'Issuable counts caching', :use_clean_rails_memory_store_caching do - let!(:member) { create(:user) } - let!(:member_2) { create(:user) } - let!(:non_member) { create(:user) } - let!(:project) { create(:project, :public) } - let!(:open_issue) { create(:issue, project: project) } - let!(:confidential_issue) { create(:issue, :confidential, project: project, author: non_member) } - let!(:closed_issue) { create(:issue, :closed, project: project) } - - before do - project.add_developer(member) - project.add_developer(member_2) - end - - it 'caches issuable counts correctly for non-members' do - # We can't use expect_any_instance_of because that uses a single instance. - counts = 0 - - allow_any_instance_of(IssuesFinder).to receive(:count_by_state).and_wrap_original do |m, *args| - counts += 1 - - m.call(*args) - end - - aggregate_failures 'only counts once on first load with no params, and caches for later loads' do - expect { visit project_issues_path(project) } - .to change { counts }.by(1) - - expect { visit project_issues_path(project) } - .not_to change { counts } - end - - aggregate_failures 'uses counts from cache on load from non-member' do - sign_in(non_member) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_out(non_member) - end - - aggregate_failures 'does not use the same cache for a member' do - sign_in(member) - - expect { visit project_issues_path(project) } - .to change { counts }.by(1) - - sign_out(member) - end - - aggregate_failures 'uses the same cache for all members' do - sign_in(member_2) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_out(member_2) - end - - aggregate_failures 'shares caches when params are passed' do - expect { visit project_issues_path(project, author_username: non_member.username) } - .to change { counts }.by(1) - - sign_in(member) - - expect { visit project_issues_path(project, author_username: non_member.username) } - .to change { counts }.by(1) - - sign_in(non_member) - - expect { visit project_issues_path(project, author_username: non_member.username) } - .not_to change { counts } - - sign_in(member_2) - - expect { visit project_issues_path(project, author_username: non_member.username) } - .not_to change { counts } - - sign_out(member_2) - end - - aggregate_failures 'resets caches on issue close' do - Issues::CloseService.new(project, member).execute(open_issue) - - expect { visit project_issues_path(project) } - .to change { counts }.by(1) - - sign_in(member) - - expect { visit project_issues_path(project) } - .to change { counts }.by(1) - - sign_in(non_member) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_in(member_2) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_out(member_2) - end - - aggregate_failures 'does not reset caches on issue update' do - Issues::UpdateService.new(project, member, title: 'new title').execute(open_issue) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_in(member) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_in(non_member) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_in(member_2) - - expect { visit project_issues_path(project) } - .not_to change { counts } - - sign_out(member_2) - end - end -end diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index 24c9f708456..0fbe1ddb2a5 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Projects > Members > User requests access' do +feature 'Projects > Members > User requests access', :js do let(:user) { create(:user) } let(:project) { create(:project, :public, :access_requestable, :repository) } let(:master) { project.owner } @@ -46,11 +46,10 @@ feature 'Projects > Members > User requests access' do expect(project.requesters.exists?(user_id: user)).to be_truthy - page.within('.layout-nav .nav-links') do + page.within('.nav-sidebar') do click_link('Members') end - visit project_project_members_path(project) page.within('.content') do expect(page).not_to have_content(user.name) end diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb index 80d91e5915f..5d77cd1ccd5 100644 --- a/spec/features/projects/project_settings_spec.rb +++ b/spec/features/projects/project_settings_spec.rb @@ -46,7 +46,7 @@ describe 'Edit Project Settings' do context 'when changing project name' do it 'renames the repository' do rename_project(project, name: 'bar') - expect(find('h1.title')).to have_content(project.name) + expect(find('.breadcrumbs')).to have_content(project.name) end context 'with emojis' do @@ -74,7 +74,7 @@ describe 'Edit Project Settings' do new_path = namespace_project_path(project.namespace, 'bar') visit new_path expect(current_path).to eq(new_path) - expect(find('h1.title')).to have_content(project.name) + expect(find('.breadcrumbs')).to have_content(project.name) end specify 'the project is accessible via a redirect from the old path' do @@ -83,7 +83,7 @@ describe 'Edit Project Settings' do new_path = namespace_project_path(project.namespace, 'bar') visit old_path expect(current_path).to eq(new_path) - expect(find('h1.title')).to have_content(project.name) + expect(find('.breadcrumbs')).to have_content(project.name) end context 'and a new project is added with the same path' do @@ -93,7 +93,7 @@ describe 'Edit Project Settings' do new_project = create(:project, namespace: user.namespace, path: 'gitlabhq', name: 'quz') visit old_path expect(current_path).to eq(old_path) - expect(find('h1.title')).to have_content(new_project.name) + expect(find('.breadcrumbs')).to have_content(new_project.name) end end end @@ -120,7 +120,7 @@ describe 'Edit Project Settings' do new_path = namespace_project_path(group, project) visit new_path expect(current_path).to eq(new_path) - expect(find('h1.title')).to have_content(project.name) + expect(find('.breadcrumbs')).to have_content(project.name) end specify 'the project is accessible via a redirect from the old path' do @@ -129,7 +129,7 @@ describe 'Edit Project Settings' do new_path = namespace_project_path(group, project) visit old_path expect(current_path).to eq(new_path) - expect(find('h1.title')).to have_content(project.name) + expect(find('.breadcrumbs')).to have_content(project.name) end context 'and a new project is added with the same path' do @@ -139,7 +139,7 @@ describe 'Edit Project Settings' do new_project = create(:project, namespace: user.namespace, path: 'gitlabhq', name: 'quz') visit old_path expect(current_path).to eq(old_path) - expect(find('h1.title')).to have_content(new_project.name) + expect(find('.breadcrumbs')).to have_content(new_project.name) end end end diff --git a/spec/features/projects/sub_group_issuables_spec.rb b/spec/features/projects/sub_group_issuables_spec.rb index aaf64d42515..b2b39dbd24c 100644 --- a/spec/features/projects/sub_group_issuables_spec.rb +++ b/spec/features/projects/sub_group_issuables_spec.rb @@ -24,7 +24,7 @@ describe 'Subgroup Issuables', :js, :nested_groups do end def expect_to_have_full_subgroup_title - title = find('.title-container') + title = find('.breadcrumbs-links') expect(title).not_to have_selector '.initializing' expect(title).to have_content 'group / subgroup / project' diff --git a/spec/features/reportable_note/commit_spec.rb b/spec/features/reportable_note/commit_spec.rb index 3bf25221e36..9b6864eb90f 100644 --- a/spec/features/reportable_note/commit_spec.rb +++ b/spec/features/reportable_note/commit_spec.rb @@ -18,7 +18,7 @@ describe 'Reportable note on commit', :js do visit project_commit_path(project, sample_commit.id) end - it_behaves_like 'reportable note' + it_behaves_like 'reportable note', 'commit' end context 'a diff note' do @@ -28,6 +28,6 @@ describe 'Reportable note on commit', :js do visit project_commit_path(project, sample_commit.id) end - it_behaves_like 'reportable note' + it_behaves_like 'reportable note', 'commit' end end diff --git a/spec/features/reportable_note/issue_spec.rb b/spec/features/reportable_note/issue_spec.rb index 21e96f6f103..f5a1950e48e 100644 --- a/spec/features/reportable_note/issue_spec.rb +++ b/spec/features/reportable_note/issue_spec.rb @@ -13,5 +13,5 @@ describe 'Reportable note on issue', :js do visit project_issue_path(project, issue) end - it_behaves_like 'reportable note' + it_behaves_like 'reportable note', 'issue' end diff --git a/spec/features/reportable_note/merge_request_spec.rb b/spec/features/reportable_note/merge_request_spec.rb index bb296546e06..1f69257f7ed 100644 --- a/spec/features/reportable_note/merge_request_spec.rb +++ b/spec/features/reportable_note/merge_request_spec.rb @@ -15,12 +15,12 @@ describe 'Reportable note on merge request', :js do context 'a normal note' do let!(:note) { create(:note_on_merge_request, noteable: merge_request, project: project) } - it_behaves_like 'reportable note' + it_behaves_like 'reportable note', 'merge_request' end context 'a diff note' do let!(:note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project) } - it_behaves_like 'reportable note' + it_behaves_like 'reportable note', 'merge_request' end end diff --git a/spec/features/reportable_note/snippets_spec.rb b/spec/features/reportable_note/snippets_spec.rb index f1e48ed46be..98ef50b78de 100644 --- a/spec/features/reportable_note/snippets_spec.rb +++ b/spec/features/reportable_note/snippets_spec.rb @@ -17,6 +17,6 @@ describe 'Reportable note on snippets', :js do visit project_snippet_path(project, snippet) end - it_behaves_like 'reportable note' + it_behaves_like 'reportable note', 'snippet' end end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index 31d509455ba..05a089641f1 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -160,7 +160,7 @@ describe "Search" do fill_in 'search', with: 'gitlab' find('#search').native.send_keys(:enter) - page.within '.title' do + page.within '.breadcrumbs-sub-title' do expect(page).to have_content 'Search' end end diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb index 580258f77eb..ff6f71d7528 100644 --- a/spec/features/task_lists_spec.rb +++ b/spec/features/task_lists_spec.rb @@ -181,7 +181,7 @@ feature 'Task Lists' do project: project, author: user) end - it 'renders for note body' do + it 'renders for note body', :js do visit_issue(project, issue) expect(page).to have_selector('.note ul.task-list', count: 1) @@ -189,15 +189,14 @@ feature 'Task Lists' do expect(page).to have_selector('.note ul input[checked]', count: 2) end - it 'contains the required selectors' do + it 'contains the required selectors', :js do visit_issue(project, issue) expect(page).to have_selector('.note .js-task-list-container') expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox') - expect(page).to have_selector('.note .js-task-list-container .js-task-list-field') end - it 'is only editable by author' do + it 'is only editable by author', :js do visit_issue(project, issue) expect(page).to have_selector('.js-task-list-container') @@ -215,7 +214,7 @@ feature 'Task Lists' do project: project, author: user) end - it 'renders for note body' do + it 'renders for note body', :js do visit_issue(project, issue) expect(page).to have_selector('.note ul.task-list', count: 1) @@ -230,7 +229,7 @@ feature 'Task Lists' do project: project, author: user) end - it 'renders for note body' do + it 'renders for note body', :js do visit_issue(project, issue) expect(page).to have_selector('.note ul.task-list', count: 1) diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb index 53cad623a35..e1c95590af1 100644 --- a/spec/features/uploads/user_uploads_file_to_note_spec.rb +++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb @@ -10,6 +10,7 @@ feature 'User uploads file to note' do before do sign_in(user) visit project_issue_path(project, issue) + wait_for_requests end context 'before uploading' do |