diff options
Diffstat (limited to 'spec/features')
45 files changed, 723 insertions, 233 deletions
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index c33014cbb31..be8754a5315 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -62,7 +62,7 @@ describe "Admin Runners" do context 'group runner' do let(:group) { create(:group) } - let!(:runner) { create(:ci_runner, groups: [group], runner_type: :group_type) } + let!(:runner) { create(:ci_runner, :group, groups: [group]) } it 'shows the label and does not show the project count' do visit admin_runners_path @@ -76,7 +76,7 @@ describe "Admin Runners" do context 'shared runner' do it 'shows the label and does not show the project count' do - runner = create :ci_runner, :shared + runner = create :ci_runner, :instance visit admin_runners_path @@ -90,7 +90,7 @@ describe "Admin Runners" do context 'specific runner' do it 'shows the label and the project count' do project = create :project - runner = create :ci_runner, projects: [project] + runner = create :ci_runner, :project, projects: [project] visit admin_runners_path @@ -149,8 +149,9 @@ describe "Admin Runners" do end context 'with specific runner' do + let(:runner) { create(:ci_runner, :project, projects: [@project1]) } + before do - @project1.runners << runner visit admin_runner_path(runner) end @@ -158,9 +159,9 @@ describe "Admin Runners" do end context 'with locked runner' do + let(:runner) { create(:ci_runner, :project, projects: [@project1], locked: true) } + before do - runner.update(locked: true) - @project1.runners << runner visit admin_runner_path(runner) end @@ -168,9 +169,10 @@ describe "Admin Runners" do end context 'with shared runner' do + let(:runner) { create(:ci_runner, :instance) } + before do @project1.destroy - runner.update(is_shared: true) visit admin_runner_path(runner) end @@ -179,8 +181,9 @@ describe "Admin Runners" do end describe 'disable/destroy' do + let(:runner) { create(:ci_runner, :project, projects: [@project1]) } + before do - @project1.runners << runner visit admin_runner_path(runner) end diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb index fb6c71ce997..da7749b42d2 100644 --- a/spec/features/atom/dashboard_issues_spec.rb +++ b/spec/features/atom/dashboard_issues_spec.rb @@ -31,20 +31,20 @@ describe "Dashboard Issues Feed" do expect(body).to have_selector('title', text: "#{user.name} issues") end - it "renders atom feed via RSS token" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: user.id) + it "renders atom feed via feed token" do + visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: user.id) expect(response_headers['Content-Type']).to have_content('application/atom+xml') expect(body).to have_selector('title', text: "#{user.name} issues") end it "renders atom feed with url parameters" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id) + visit issues_dashboard_path(:atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id) link = find('link[type="application/atom+xml"]') params = CGI.parse(URI.parse(link[:href]).query) - expect(params).to include('rss_token' => [user.rss_token]) + expect(params).to include('feed_token' => [user.feed_token]) expect(params).to include('state' => ['opened']) expect(params).to include('assignee_id' => [user.id.to_s]) end @@ -53,7 +53,7 @@ describe "Dashboard Issues Feed" do let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') } it "renders issue fields" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: assignee.id) + visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id) entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]") @@ -76,7 +76,7 @@ describe "Dashboard Issues Feed" do end it "renders issue label and milestone info" do - visit issues_dashboard_path(:atom, rss_token: user.rss_token, assignee_id: assignee.id) + visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id) entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]") diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb index c6683bb3bc9..462eab07a75 100644 --- a/spec/features/atom/dashboard_spec.rb +++ b/spec/features/atom/dashboard_spec.rb @@ -13,9 +13,9 @@ describe "Dashboard Feed" do end end - context "projects atom feed via RSS token" do + context "projects atom feed via feed token" do it "renders projects atom feed" do - visit dashboard_projects_path(:atom, rss_token: user.rss_token) + visit dashboard_projects_path(:atom, feed_token: user.feed_token) expect(body).to have_selector('feed title') end end @@ -29,7 +29,7 @@ describe "Dashboard Feed" do project.add_master(user) issue_event(issue, user) note_event(note, user) - visit dashboard_projects_path(:atom, rss_token: user.rss_token) + visit dashboard_projects_path(:atom, feed_token: user.feed_token) end it "has issue opened event" do diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb index 525ce23aa56..ee3570a5b2b 100644 --- a/spec/features/atom/issues_spec.rb +++ b/spec/features/atom/issues_spec.rb @@ -45,10 +45,10 @@ describe 'Issues Feed' do end end - context 'when authenticated via RSS token' do + context 'when authenticated via feed token' do it 'renders atom feed' do visit project_issues_path(project, :atom, - rss_token: user.rss_token) + feed_token: user.feed_token) expect(response_headers['Content-Type']) .to have_content('application/atom+xml') @@ -61,24 +61,23 @@ describe 'Issues Feed' do end it "renders atom feed with url parameters for project issues" do - visit project_issues_path(project, - :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id) + visit project_issues_path(project, :atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id) link = find('link[type="application/atom+xml"]') params = CGI.parse(URI.parse(link[:href]).query) - expect(params).to include('rss_token' => [user.rss_token]) + expect(params).to include('feed_token' => [user.feed_token]) expect(params).to include('state' => ['opened']) expect(params).to include('assignee_id' => [user.id.to_s]) end it "renders atom feed with url parameters for group issues" do - visit issues_group_path(group, :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id) + visit issues_group_path(group, :atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id) link = find('link[type="application/atom+xml"]') params = CGI.parse(URI.parse(link[:href]).query) - expect(params).to include('rss_token' => [user.rss_token]) + expect(params).to include('feed_token' => [user.feed_token]) expect(params).to include('state' => ['opened']) expect(params).to include('assignee_id' => [user.id.to_s]) end diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb index 2d074c115dd..eeaaa40fe21 100644 --- a/spec/features/atom/users_spec.rb +++ b/spec/features/atom/users_spec.rb @@ -13,9 +13,9 @@ describe "User Feed" do end end - context 'user atom feed via RSS token' do + context 'user atom feed via feed token' do it "renders user atom feed" do - visit user_path(user, :atom, rss_token: user.rss_token) + visit user_path(user, :atom, feed_token: user.feed_token) expect(body).to have_selector('feed title') end end @@ -51,7 +51,7 @@ describe "User Feed" do issue_event(issue, user) note_event(note, user) merge_request_event(merge_request, user) - visit user_path(user, :atom, rss_token: user.rss_token) + visit user_path(user, :atom, feed_token: user.feed_token) end it 'has issue opened event' do diff --git a/spec/features/boards/issue_ordering_spec.rb b/spec/features/boards/issue_ordering_spec.rb index 193b1dfabbd..32bd7b88840 100644 --- a/spec/features/boards/issue_ordering_spec.rb +++ b/spec/features/boards/issue_ordering_spec.rb @@ -35,7 +35,7 @@ describe 'Issue Boards', :js do end it 'moves un-ordered issue to top of list' do - drag(from_index: 3, to_index: 0) + drag(from_index: 3, to_index: 0, duration: 1180) wait_for_requests @@ -156,12 +156,13 @@ describe 'Issue Boards', :js do end end - def drag(selector: '.board-list', list_from_index: 1, from_index: 0, to_index: 0, list_to_index: 1) + def drag(selector: '.board-list', list_from_index: 1, from_index: 0, to_index: 0, list_to_index: 1, duration: 1000) drag_to(selector: selector, scrollable: '#board-app', list_from_index: list_from_index, from_index: from_index, to_index: to_index, - list_to_index: list_to_index) + list_to_index: list_to_index, + duration: duration) end end diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb index a74a8aac2b2..941208fa244 100644 --- a/spec/features/dashboard/activity_spec.rb +++ b/spec/features/dashboard/activity_spec.rb @@ -12,8 +12,8 @@ feature 'Dashboard > Activity' do visit activity_dashboard_path end - it_behaves_like "it has an RSS button with current_user's RSS token" - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'event filters', :js do diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb index bab34ac9346..8d0b0be1bd4 100644 --- a/spec/features/dashboard/issues_filter_spec.rb +++ b/spec/features/dashboard/issues_filter_spec.rb @@ -47,15 +47,15 @@ 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('.nav-controls a[title="Subscribe to RSS feed"]') 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('feed_token' => [user.feed_token]) expect(params).to include('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('feed_token' => [user.feed_token]) expect(auto_discovery_params).to include('milestone_title' => ['']) expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) end diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb index e41a2e4ce09..3cc7b38550d 100644 --- a/spec/features/dashboard/issues_spec.rb +++ b/spec/features/dashboard/issues_spec.rb @@ -56,8 +56,8 @@ RSpec.describe 'Dashboard Issues' do expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, state: 'closed'), url: true) end - it_behaves_like "it has an RSS button with current_user's RSS token" - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end describe 'new issue dropdown' do diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb index 257a3822503..ef2f0b5b31a 100644 --- a/spec/features/dashboard/projects_spec.rb +++ b/spec/features/dashboard/projects_spec.rb @@ -10,7 +10,7 @@ feature 'Dashboard Projects' do sign_in(user) end - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" do + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" do before do visit dashboard_projects_path end diff --git a/spec/features/error_pages_spec.rb b/spec/features/error_pages_spec.rb new file mode 100644 index 00000000000..cd7bcf29cc9 --- /dev/null +++ b/spec/features/error_pages_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe 'Error Pages' do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + + before do + sign_in(user) + end + + shared_examples 'shows nav links' do + it 'shows nav links' do + expect(page).to have_link("Home", href: root_path) + expect(page).to have_link("Help", href: help_path) + expect(page).to have_link(nil, href: destroy_user_session_path) + end + end + + describe '404' do + before do + visit '/not-a-real-page' + end + + it 'allows user to search' do + fill_in 'search', with: 'something' + click_button 'Search' + + expect(page).to have_current_path(%r{^/search\?.*search=something.*}) + end + + it_behaves_like 'shows nav links' + end + + describe '403' do + before do + visit '/' + visit edit_project_path(project) + end + + it_behaves_like 'shows nav links' + end +end diff --git a/spec/features/groups/activity_spec.rb b/spec/features/groups/activity_spec.rb index 7bc809b3104..0d7d3771071 100644 --- a/spec/features/groups/activity_spec.rb +++ b/spec/features/groups/activity_spec.rb @@ -15,8 +15,8 @@ feature 'Group activity page' do visit path end - it_behaves_like "it has an RSS button with current_user's RSS token" - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'when project is in the group', :js do @@ -39,7 +39,7 @@ feature 'Group activity page' do visit path end - it_behaves_like "it has an RSS button without an RSS token" - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "it has an RSS button without a feed token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end end diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb index 1ce30015e81..bf329b0bb94 100644 --- a/spec/features/groups/group_settings_spec.rb +++ b/spec/features/groups/group_settings_spec.rb @@ -83,7 +83,7 @@ feature 'Edit group settings' do attach_file(:group_avatar, Rails.root.join('spec', 'fixtures', 'banana_sample.gif')) - expect { click_button 'Save group' }.to change { group.reload.avatar? }.to(true) + expect { save_group }.to change { group.reload.avatar? }.to(true) end it 'uploads new group avatar' do @@ -97,10 +97,19 @@ feature 'Edit group settings' do expect(page).not_to have_link('Remove avatar') end end -end -def update_path(new_group_path) - visit edit_group_path(group) - fill_in 'group_path', with: new_group_path - click_button 'Save group' + def update_path(new_group_path) + visit edit_group_path(group) + + page.within('.gs-advanced') do + fill_in 'group_path', with: new_group_path + click_button 'Change group path' + end + end + + def save_group + page.within('.gs-general') do + click_button 'Save group' + end + end end diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb index 90bf7ba49f6..111a24c0d94 100644 --- a/spec/features/groups/issues_spec.rb +++ b/spec/features/groups/issues_spec.rb @@ -16,17 +16,21 @@ feature 'Group issues page' do let(:access_level) { ProjectFeature::ENABLED } context 'when signed in' do - let(:user) { user_in_group } - - it_behaves_like "it has an RSS button with current_user's RSS token" - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + let(:user) do + user_in_group.ensure_feed_token + user_in_group.save! + user_in_group + end + + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'when signed out' do let(:user) { nil } - it_behaves_like "it has an RSS button without an RSS token" - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "it has an RSS button without a feed token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end end diff --git a/spec/features/groups/share_lock_spec.rb b/spec/features/groups/share_lock_spec.rb index 8842d1391aa..cefbc15e068 100644 --- a/spec/features/groups/share_lock_spec.rb +++ b/spec/features/groups/share_lock_spec.rb @@ -15,9 +15,8 @@ feature 'Group share with group lock' do context 'when enabling the parent group share with group lock' do scenario 'the subgroup share with group lock becomes enabled' do visit edit_group_path(root_group) - check 'group_share_with_group_lock' - click_on 'Save group' + enable_group_lock expect(subgroup.reload.share_with_group_lock?).to be_truthy end @@ -26,16 +25,15 @@ feature 'Group share with group lock' do context 'when disabling the parent group share with group lock (which was already enabled)' do background do visit edit_group_path(root_group) - check 'group_share_with_group_lock' - click_on 'Save group' + + enable_group_lock end context 'and the subgroup share with group lock is enabled' do scenario 'the subgroup share with group lock does not change' do visit edit_group_path(root_group) - uncheck 'group_share_with_group_lock' - click_on 'Save group' + disable_group_lock expect(subgroup.reload.share_with_group_lock?).to be_truthy end @@ -44,19 +42,32 @@ feature 'Group share with group lock' do context 'but the subgroup share with group lock is disabled' do background do visit edit_group_path(subgroup) - uncheck 'group_share_with_group_lock' - click_on 'Save group' + + disable_group_lock end scenario 'the subgroup share with group lock does not change' do visit edit_group_path(root_group) - uncheck 'group_share_with_group_lock' - click_on 'Save group' + disable_group_lock expect(subgroup.reload.share_with_group_lock?).to be_falsey end end end end + + def enable_group_lock + page.within('.gs-permissions') do + check 'group_share_with_group_lock' + click_on 'Save group' + end + end + + def disable_group_lock + page.within('.gs-permissions') do + uncheck 'group_share_with_group_lock' + click_on 'Save group' + end + end end diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb index 3a0424d60f8..b7a7aa0e174 100644 --- a/spec/features/groups/show_spec.rb +++ b/spec/features/groups/show_spec.rb @@ -14,7 +14,7 @@ feature 'Group show page' do visit path end - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" context 'when group does not exist' do let(:path) { group_path('not-exist') } @@ -29,7 +29,7 @@ feature 'Group show page' do visit path end - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end context 'when group has a public project', :js do diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index c1f3d94bc20..236768b5d7f 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -141,8 +141,10 @@ feature 'Group' do end it 'saves new settings' do - fill_in 'group_name', with: new_name - click_button 'Save group' + page.within('.gs-general') do + fill_in 'group_name', with: new_name + click_button 'Save group' + end expect(page).to have_content 'successfully updated' expect(find('#group_name').value).to eq(new_name) diff --git a/spec/features/ics/dashboard_issues_spec.rb b/spec/features/ics/dashboard_issues_spec.rb new file mode 100644 index 00000000000..5d6cd44ad1c --- /dev/null +++ b/spec/features/ics/dashboard_issues_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe 'Dashboard Issues Calendar Feed' do + describe 'GET /issues' do + let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') } + let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') } + let!(:project) { create(:project) } + + before do + project.add_master(user) + end + + context 'when authenticated' do + it 'renders calendar feed' do + sign_in user + visit issues_dashboard_path(:ics) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'when authenticated via personal access token' do + it 'renders calendar feed' do + personal_access_token = create(:personal_access_token, user: user) + + visit issues_dashboard_path(:ics, private_token: personal_access_token.token) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'when authenticated via feed token' do + it 'renders calendar feed' do + visit issues_dashboard_path(:ics, feed_token: user.feed_token) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'issue with due date' do + let!(:issue) do + create(:issue, author: user, assignees: [assignee], project: project, title: 'test title', + description: 'test desc', due_date: Date.tomorrow) + end + + it 'renders issue fields' do + visit issues_dashboard_path(:ics, feed_token: user.feed_token) + + expect(body).to have_text("SUMMARY:test title (in #{project.full_path})") + # line length for ics is 75 chars + expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n") + expect(body).to have_text(expected_description) + expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}") + expect(body).to have_text("URL:#{issue_url(issue)}") + expect(body).to have_text('TRANSP:TRANSPARENT') + end + end + end +end diff --git a/spec/features/ics/group_issues_spec.rb b/spec/features/ics/group_issues_spec.rb new file mode 100644 index 00000000000..0a049be2ffe --- /dev/null +++ b/spec/features/ics/group_issues_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +describe 'Group Issues Calendar Feed' do + describe 'GET /issues' do + let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') } + let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') } + let!(:group) { create(:group) } + let!(:project) { create(:project, group: group) } + + before do + project.add_developer(user) + group.add_developer(user) + end + + context 'when authenticated' do + it 'renders calendar feed' do + sign_in user + visit issues_group_path(group, :ics) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'when authenticated via personal access token' do + it 'renders calendar feed' do + personal_access_token = create(:personal_access_token, user: user) + + visit issues_group_path(group, :ics, private_token: personal_access_token.token) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'when authenticated via feed token' do + it 'renders calendar feed' do + visit issues_group_path(group, :ics, feed_token: user.feed_token) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'issue with due date' do + let!(:issue) do + create(:issue, author: user, assignees: [assignee], project: project, title: 'test title', + description: 'test desc', due_date: Date.tomorrow) + end + + it 'renders issue fields' do + visit issues_group_path(group, :ics, feed_token: user.feed_token) + + expect(body).to have_text("SUMMARY:test title (in #{project.full_path})") + # line length for ics is 75 chars + expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n") + expect(body).to have_text(expected_description) + expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}") + expect(body).to have_text("URL:#{issue_url(issue)}") + expect(body).to have_text('TRANSP:TRANSPARENT') + end + end + end +end diff --git a/spec/features/ics/project_issues_spec.rb b/spec/features/ics/project_issues_spec.rb new file mode 100644 index 00000000000..b99e9607f1d --- /dev/null +++ b/spec/features/ics/project_issues_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +describe 'Project Issues Calendar Feed' do + describe 'GET /issues' do + let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') } + let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') } + let!(:project) { create(:project) } + let!(:issue) { create(:issue, author: user, assignees: [assignee], project: project) } + + before do + project.add_developer(user) + end + + context 'when authenticated' do + it 'renders calendar feed' do + sign_in user + visit project_issues_path(project, :ics) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'when authenticated via personal access token' do + it 'renders calendar feed' do + personal_access_token = create(:personal_access_token, user: user) + + visit project_issues_path(project, :ics, private_token: personal_access_token.token) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'when authenticated via feed token' do + it 'renders calendar feed' do + visit project_issues_path(project, :ics, feed_token: user.feed_token) + + expect(response_headers['Content-Type']).to have_content('text/calendar') + expect(response_headers['Content-Disposition']).to have_content('inline') + expect(body).to have_text('BEGIN:VCALENDAR') + end + end + + context 'issue with due date' do + let!(:issue) do + create(:issue, author: user, assignees: [assignee], project: project, title: 'test title', + description: 'test desc', due_date: Date.tomorrow) + end + + it 'renders issue fields' do + visit project_issues_path(project, :ics, feed_token: user.feed_token) + + expect(body).to have_text("SUMMARY:test title (in #{project.full_path})") + # line length for ics is 75 chars + expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n") + expect(body).to have_text(expected_description) + expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}") + expect(body).to have_text("URL:#{issue_url(issue)}") + expect(body).to have_text('TRANSP:TRANSPARENT') + end + end + 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 483122ae463..bc42618306f 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -468,13 +468,13 @@ describe 'Filter issues', :js do it "for #{type}" do visit path - link = find_link('Subscribe') + link = find_link('Subscribe to RSS feed') 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], + 'feed_token' => [user.feed_token], 'milestone_title' => [milestone.title], 'assignee_id' => [user.id.to_s] } diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 314bd19f586..c6dcd97631d 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -340,6 +340,20 @@ describe 'Issues' do expect(page).to have_content('baz') end end + + it 'filters by due next month and previous two weeks' do + foo.update(due_date: Date.today - 4.weeks) + bar.update(due_date: (Date.today + 2.months).beginning_of_month) + baz.update(due_date: Date.yesterday) + + visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name) + + 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 describe 'sorting by milestone' do @@ -591,6 +605,20 @@ describe 'Issues' do end end + it 'clears local storage after creating a new issue', :js do + 2.times do + visit new_project_issue_path(project) + wait_for_requests + + expect(page).to have_field('Title', with: '') + + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + + click_button 'Submit issue' + end + end + context 'dropzone upload file', :js do before do visit new_project_issue_path(project) diff --git a/spec/features/merge_requests/user_squashes_merge_request_spec.rb b/spec/features/merge_requests/user_squashes_merge_request_spec.rb new file mode 100644 index 00000000000..6c952791591 --- /dev/null +++ b/spec/features/merge_requests/user_squashes_merge_request_spec.rb @@ -0,0 +1,124 @@ +require 'spec_helper' + +feature 'User squashes a merge request', :js do + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + let(:source_branch) { 'csv' } + + let!(:original_head) { project.repository.commit('master') } + + shared_examples 'squash' do + it 'squashes the commits into a single commit, and adds a merge commit' do + expect(page).to have_content('Merged') + + latest_master_commits = project.repository.commits_between(original_head.sha, 'master').map(&:raw) + + squash_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/), + message: "Csv\n", + author_name: user.name, + committer_name: user.name) + + merge_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/), + message: a_string_starting_with("Merge branch 'csv' into 'master'"), + author_name: user.name, + committer_name: user.name) + + expect(project.repository).not_to be_merged_to_root_ref(source_branch) + expect(latest_master_commits).to match([squash_commit, merge_commit]) + end + end + + shared_examples 'no squash' do + it 'accepts the merge request without squashing' do + expect(page).to have_content('Merged') + expect(project.repository).to be_merged_to_root_ref(source_branch) + end + end + + def accept_mr + expect(page).to have_button('Merge') + + uncheck 'Remove source branch' + click_on 'Merge' + end + + before do + # Prevent source branch from being removed so we can use be_merged_to_root_ref + # method to check if squash was performed or not + allow_any_instance_of(MergeRequest).to receive(:force_remove_source_branch?).and_return(false) + project.add_master(user) + + sign_in user + end + + context 'when the MR has only one commit' do + before do + merge_request = create(:merge_request, source_project: project, target_project: project, source_branch: 'master', target_branch: 'branch-merged') + + visit project_merge_request_path(project, merge_request) + end + + it 'does not show the squash checkbox' do + expect(page).not_to have_field('squash') + end + end + + context 'when squash is enabled on merge request creation' do + before do + visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch }) + check 'merge_request[squash]' + click_on 'Submit merge request' + wait_for_requests + end + + it 'shows the squash checkbox as checked' do + expect(page).to have_checked_field('squash') + end + + context 'when accepting with squash checked' do + before do + accept_mr + end + + include_examples 'squash' + end + + context 'when accepting and unchecking squash' do + before do + uncheck 'squash' + accept_mr + end + + include_examples 'no squash' + end + end + + context 'when squash is not enabled on merge request creation' do + before do + visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch }) + click_on 'Submit merge request' + wait_for_requests + end + + it 'shows the squash checkbox as unchecked' do + expect(page).to have_unchecked_field('squash') + end + + context 'when accepting and checking squash' do + before do + check 'squash' + accept_mr + end + + include_examples 'squash' + end + + context 'when accepting with squash unchecked' do + before do + accept_mr + end + + include_examples 'no squash' + end + end +end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 15dcb30cbdd..2e0753c3bfb 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -56,21 +56,21 @@ describe 'Profile account page', :js do end end - describe 'when I reset RSS token' do + describe 'when I reset feed token' do before do visit profile_personal_access_tokens_path end - it 'resets RSS token' do - within('.rss-token-reset') do - previous_token = find("#rss_token").value + it 'resets feed token' do + within('.feed-token-reset') do + previous_token = find("#feed_token").value accept_confirm { click_link('reset it') } - expect(find('#rss_token').value).not_to eq(previous_token) + expect(find('#feed_token').value).not_to eq(previous_token) end - expect(page).to have_content 'RSS token was successfully reset' + expect(page).to have_content 'Feed token was successfully reset' end end diff --git a/spec/features/projects/activity/rss_spec.rb b/spec/features/projects/activity/rss_spec.rb index cd1cfe07998..4ac34adde0e 100644 --- a/spec/features/projects/activity/rss_spec.rb +++ b/spec/features/projects/activity/rss_spec.rb @@ -15,7 +15,7 @@ feature 'Project Activity RSS' do visit path end - it_behaves_like "it has an RSS button with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" end context 'when signed out' do @@ -23,6 +23,6 @@ feature 'Project Activity RSS' do visit path end - it_behaves_like "it has an RSS button without an RSS token" + it_behaves_like "it has an RSS button without a feed token" end end diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index a8a627d8806..c85b82b2090 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -22,152 +22,123 @@ feature 'Gcp Cluster', :js do .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s) end - context 'when user has a GCP project with billing enabled' do + context 'when user does not have a cluster and visits cluster index page' do before do - allow_any_instance_of(Projects::Clusters::GcpController).to receive(:authorize_google_project_billing) - allow_any_instance_of(Projects::Clusters::GcpController).to receive(:google_project_billing_status).and_return(true) - end - - context 'when user does not have a cluster and visits cluster index page' do - before do - visit project_clusters_path(project) - - click_link 'Add Kubernetes cluster' - click_link 'Create on Google Kubernetes Engine' - end - - context 'when user filled form with valid parameters' do - before do - allow_any_instance_of(GoogleApi::CloudPlatform::Client) - .to receive(:projects_zones_clusters_create) do - OpenStruct.new( - self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', - status: 'RUNNING' - ) - end - - allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil) - - fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123' - fill_in 'cluster_name', with: 'dev-cluster' - click_button 'Create Kubernetes cluster' - end + visit project_clusters_path(project) - it 'user sees a cluster details page and creation status' do - expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...') + click_link 'Add Kubernetes cluster' + click_link 'Create on Google Kubernetes Engine' + end - Clusters::Cluster.last.provider.make_created! + context 'when user filled form with valid parameters' do + subject { click_button 'Create Kubernetes cluster' } - expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine') + before do + allow_any_instance_of(GoogleApi::CloudPlatform::Client) + .to receive(:projects_zones_clusters_create) do + OpenStruct.new( + self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', + status: 'RUNNING' + ) end - it 'user sees a error if something worng during creation' do - expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...') + allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil) - Clusters::Cluster.last.provider.make_errored!('Something wrong!') + execute_script('document.querySelector(".js-gke-cluster-creation-submit").removeAttribute("disabled")') + sleep 2 # wait for ajax + execute_script('document.querySelector(".js-gcp-project-id-dropdown input").setAttribute("type", "text")') + execute_script('document.querySelector(".js-gcp-zone-dropdown input").setAttribute("type", "text")') + execute_script('document.querySelector(".js-gcp-machine-type-dropdown input").setAttribute("type", "text")') - expect(page).to have_content('Something wrong!') - end + fill_in 'cluster[name]', with: 'dev-cluster' + fill_in 'cluster[provider_gcp_attributes][gcp_project_id]', with: 'gcp-project-123' + fill_in 'cluster[provider_gcp_attributes][zone]', with: 'us-central1-a' + fill_in 'cluster[provider_gcp_attributes][machine_type]', with: 'n1-standard-2' end - context 'when user filled form with invalid parameters' do - before do - click_button 'Create Kubernetes cluster' - end - - it 'user sees a validation error' do - expect(page).to have_css('#error_explanation') - end + it 'users sees a form with the GCP token' do + expect(page).to have_selector(:css, 'form[data-token="token"]') end - end - context 'when user does have a cluster and visits cluster page' do - let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } + it 'user sees a cluster details page and creation status' do + subject - before do - visit project_cluster_path(project, cluster) - end + expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...') + + Clusters::Cluster.last.provider.make_created! - it 'user sees a cluster details page' do - expect(page).to have_button('Save changes') - expect(page.find(:css, '.cluster-name').value).to eq(cluster.name) + expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine') end - context 'when user disables the cluster' do - before do - page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click - page.within('#cluster-integration') { click_button 'Save changes' } - end + it 'user sees a error if something wrong during creation' do + subject - it 'user sees the successful message' do - expect(page).to have_content('Kubernetes cluster was successfully updated.') - end - end + expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...') - context 'when user changes cluster parameters' do - before do - fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace' - page.within('#js-cluster-details') { click_button 'Save changes' } - end + Clusters::Cluster.last.provider.make_errored!('Something wrong!') - it 'user sees the successful message' do - expect(page).to have_content('Kubernetes cluster was successfully updated.') - expect(cluster.reload.platform_kubernetes.namespace).to eq('my-namespace') - end + expect(page).to have_content('Something wrong!') end + end - context 'when user destroy the cluster' do - before do - page.accept_confirm do - click_link 'Remove integration' - end - end + context 'when user filled form with invalid parameters' do + before do + execute_script('document.querySelector(".js-gke-cluster-creation-submit").removeAttribute("disabled")') + click_button 'Create Kubernetes cluster' + end - it 'user sees creation form with the successful message' do - expect(page).to have_content('Kubernetes cluster integration was successfully removed.') - expect(page).to have_link('Add Kubernetes cluster') - end + it 'user sees a validation error' do + expect(page).to have_css('#error_explanation') end end end - context 'when user does not have a GCP project with billing enabled' do - before do - allow_any_instance_of(Projects::Clusters::GcpController).to receive(:authorize_google_project_billing) - allow_any_instance_of(Projects::Clusters::GcpController).to receive(:google_project_billing_status).and_return(false) - - visit project_clusters_path(project) - - click_link 'Add Kubernetes cluster' - click_link 'Create on Google Kubernetes Engine' + context 'when user does have a cluster and visits cluster page' do + let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } - fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123' - fill_in 'cluster_name', with: 'dev-cluster' - click_button 'Create Kubernetes cluster' + before do + visit project_cluster_path(project, cluster) end - it 'user sees form with error' do - expect(page).to have_content('Please enable billing for one of your projects to be able to create a Kubernetes cluster, then try again.') + it 'user sees a cluster details page' do + expect(page).to have_button('Save changes') + expect(page.find(:css, '.cluster-name').value).to eq(cluster.name) end - end - context 'when gcp billing status is not in redis' do - before do - allow_any_instance_of(Projects::Clusters::GcpController).to receive(:authorize_google_project_billing) - allow_any_instance_of(Projects::Clusters::GcpController).to receive(:google_project_billing_status).and_return(nil) + context 'when user disables the cluster' do + before do + page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click + page.within('#cluster-integration') { click_button 'Save changes' } + end - visit project_clusters_path(project) + it 'user sees the successful message' do + expect(page).to have_content('Kubernetes cluster was successfully updated.') + end + end - click_link 'Add Kubernetes cluster' - click_link 'Create on Google Kubernetes Engine' + context 'when user changes cluster parameters' do + before do + fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace' + page.within('#js-cluster-details') { click_button 'Save changes' } + end - fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123' - fill_in 'cluster_name', with: 'dev-cluster' - click_button 'Create Kubernetes cluster' + it 'user sees the successful message' do + expect(page).to have_content('Kubernetes cluster was successfully updated.') + expect(cluster.reload.platform_kubernetes.namespace).to eq('my-namespace') + end end - it 'user sees form with error' do - expect(page).to have_content('We could not verify that one of your projects on GCP has billing enabled. Please try again.') + context 'when user destroy the cluster' do + before do + page.accept_confirm do + click_link 'Remove integration' + end + end + + it 'user sees creation form with the successful message' do + expect(page).to have_content('Kubernetes cluster integration was successfully removed.') + expect(page).to have_link('Add Kubernetes cluster') + end end end end diff --git a/spec/features/projects/commits/rss_spec.rb b/spec/features/projects/commits/rss_spec.rb index 0d9c7355ddd..0bc207da970 100644 --- a/spec/features/projects/commits/rss_spec.rb +++ b/spec/features/projects/commits/rss_spec.rb @@ -12,8 +12,8 @@ feature 'Project Commits RSS' do visit path end - it_behaves_like "it has an RSS button with current_user's RSS token" - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'when signed out' do @@ -21,7 +21,7 @@ feature 'Project Commits RSS' do visit path end - it_behaves_like "it has an RSS button without an RSS token" - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "it has an RSS button without a feed token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end end diff --git a/spec/features/projects/issues/rss_spec.rb b/spec/features/projects/issues/rss_spec.rb index ff91aabc311..8b1f7d432ee 100644 --- a/spec/features/projects/issues/rss_spec.rb +++ b/spec/features/projects/issues/rss_spec.rb @@ -17,8 +17,8 @@ feature 'Project Issues RSS' do visit path end - it_behaves_like "it has an RSS button with current_user's RSS token" - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'when signed out' do @@ -26,7 +26,7 @@ feature 'Project Issues RSS' do visit path end - it_behaves_like "it has an RSS button without an RSS token" - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "it has an RSS button without a feed token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end end diff --git a/spec/features/projects/merge_requests/user_views_diffs_spec.rb b/spec/features/projects/merge_requests/user_views_diffs_spec.rb index 295eb02b625..d36aafdbc54 100644 --- a/spec/features/projects/merge_requests/user_views_diffs_spec.rb +++ b/spec/features/projects/merge_requests/user_views_diffs_spec.rb @@ -26,6 +26,10 @@ describe 'User views diffs', :js do expect(page).to have_css('#inline-diff-btn', count: 1) end + it 'hides loading spinner after load' do + expect(page).not_to have_selector('.mr-loading-status .loading', visible: true) + end + context 'when in the inline view' do include_examples 'unfold diffs' end diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb index 30de3e83fbb..20a52d6011f 100644 --- a/spec/features/projects/milestones/milestone_spec.rb +++ b/spec/features/projects/milestones/milestone_spec.rb @@ -17,8 +17,8 @@ feature 'Project milestone' do it 'shows issues tab' do within('#content-body') do expect(page).to have_link 'Issues', href: '#tab-issues' - expect(page).to have_selector '.nav-links li.active', count: 1 - expect(find('.nav-links li.active')).to have_content 'Issues' + expect(page).to have_selector '.nav-links li a.active', count: 1 + expect(find('.nav-links li a.active')).to have_content 'Issues' end end @@ -44,8 +44,8 @@ feature 'Project milestone' do it 'hides issues tab' do within('#content-body') do expect(page).not_to have_link 'Issues', href: '#tab-issues' - expect(page).to have_selector '.nav-links li.active', count: 1 - expect(find('.nav-links li.active')).to have_content 'Merge Requests' + expect(page).to have_selector '.nav-links li a.active', count: 1 + expect(find('.nav-links li a.active')).to have_content 'Merge Requests' end end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index af2a9567a47..35776a5f23b 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -379,7 +379,7 @@ describe 'Pipeline', :js do end it 'fails to access the page' do - expect(page).to have_content('Access Denied') + expect(page).to have_title('Access Denied') end end end diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb index b2906e315f7..fce41ce347f 100644 --- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb +++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb @@ -64,7 +64,7 @@ feature 'Setup Mattermost slash commands', :js do click_link 'Add to Mattermost' expect(page).to have_content('The team where the slash commands will be used in') - expect(page).to have_content('This is the only available team.') + expect(page).to have_content('This is the only available team that you are a member of.') end it 'shows a disabled prefilled select if user is a member of 1 team' do @@ -94,7 +94,7 @@ feature 'Setup Mattermost slash commands', :js do click_link 'Add to Mattermost' expect(page).to have_content('Select the team where the slash commands will be used in') - expect(page).to have_content('The list shows all available teams.') + expect(page).to have_content('The list shows all available teams that you are a member of.') end it 'shows a select with team options user is a member of multiple teams' do diff --git a/spec/features/projects/show/rss_spec.rb b/spec/features/projects/show/rss_spec.rb index d02eaf34533..52164d30c40 100644 --- a/spec/features/projects/show/rss_spec.rb +++ b/spec/features/projects/show/rss_spec.rb @@ -12,7 +12,7 @@ feature 'Projects > Show > RSS' do visit path end - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'when signed out' do @@ -20,6 +20,6 @@ feature 'Projects > Show > RSS' do visit path end - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end end diff --git a/spec/features/projects/tree/rss_spec.rb b/spec/features/projects/tree/rss_spec.rb index 6407370ac0d..f52b3cc1d86 100644 --- a/spec/features/projects/tree/rss_spec.rb +++ b/spec/features/projects/tree/rss_spec.rb @@ -12,7 +12,7 @@ feature 'Project Tree RSS' do visit path end - it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" end context 'when signed out' do @@ -20,6 +20,6 @@ feature 'Project Tree RSS' do visit path end - it_behaves_like "an autodiscoverable RSS feed without an RSS token" + it_behaves_like "an autodiscoverable RSS feed without a feed token" end end diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb index 8a9255db9e8..ee5734a9bf1 100644 --- a/spec/features/projects/user_sees_sidebar_spec.rb +++ b/spec/features/projects/user_sees_sidebar_spec.rb @@ -44,6 +44,18 @@ describe 'Projects > User sees sidebar' do expect(page).not_to have_content 'Repository' expect(page).not_to have_content 'CI / CD' expect(page).not_to have_content 'Merge Requests' + expect(page).not_to have_content 'Operations' + end + end + + it 'shows build tab if builds are public' do + project.public_builds = true + project.save + + visit project_path(project) + + within('.nav-sidebar') do + expect(page).to have_content 'CI / CD' end end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb index e473739a6aa..bbdd98a7623 100644 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -19,6 +19,7 @@ feature 'Projects > Wiki > User previews markdown changes', :js do visit project_path(project) find('.shortcuts-wiki').click + click_link "Create your first page" end context "while creating a new wiki page" do diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb index 9989e1ffda7..706894f4b32 100644 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb @@ -8,6 +8,7 @@ describe "User creates wiki page" do sign_in(user) visit(project_wikis_path(project)) + click_link "Create your first page" end context "when wiki is empty" do diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb index e019e3ce5a5..272dac127dd 100644 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb @@ -11,6 +11,7 @@ describe 'User updates wiki page' do context 'when wiki is empty' do before do visit(project_wikis_path(project)) + click_link "Create your first page" end context 'in a user namespace' do diff --git a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb new file mode 100644 index 00000000000..83ffbb4a94e --- /dev/null +++ b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +describe 'User views empty wiki' do + let(:user) { create(:user) } + + shared_examples 'empty wiki and accessible issues' do + it 'show "issue tracker" message' do + visit(project_wikis_path(project)) + + element = page.find('.row.empty-state') + + expect(element).to have_content('This project has no wiki pages') + expect(element).to have_link("issue tracker", href: project_issues_path(project)) + expect(element).to have_link("Suggest wiki improvement", href: new_project_issue_path(project)) + end + end + + shared_examples 'empty wiki and non-accessible issues' do + it 'does not show "issue tracker" message' do + visit(project_wikis_path(project)) + + element = page.find('.row.empty-state') + + expect(element).to have_content('This project has no wiki pages') + expect(element).to have_no_link('Suggest wiki improvement') + end + end + + context 'when user is logged out and issue tracker is public' do + let(:project) { create(:project, :public, :wiki_repo) } + + it_behaves_like 'empty wiki and accessible issues' + end + + context 'when user is logged in and not a member' do + let(:project) { create(:project, :public, :wiki_repo) } + + before do + sign_in(user) + end + + it_behaves_like 'empty wiki and accessible issues' + end + + context 'when issue tracker is private' do + let(:project) { create(:project, :public, :wiki_repo, :issues_private) } + + it_behaves_like 'empty wiki and non-accessible issues' + end + + context 'when issue tracker is disabled' do + let(:project) { create(:project, :public, :wiki_repo, :issues_disabled) } + + it_behaves_like 'empty wiki and non-accessible issues' + end + + context 'when user is logged in and a memeber' do + let(:project) { create(:project, :public, :wiki_repo) } + + before do + sign_in(user) + project.add_developer(user) + end + + it 'show "create first page" message' do + visit(project_wikis_path(project)) + + element = page.find('.row.empty-state') + + element.click_link 'Create your first page' + + expect(page).to have_button('Create page') + end + end +end diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb index 6661714222a..1de7d9a56a8 100644 --- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb @@ -18,6 +18,7 @@ describe 'User views a wiki page' do context 'when wiki is empty' do before do visit(project_wikis_path(project)) + click_link "Create your first page" click_on('New page') @@ -140,6 +141,7 @@ describe 'User views a wiki page' do visit(project_path(project)) find('.shortcuts-wiki').click + click_link "Create your first page" expect(page).to have_content('Home ยท Create Page') end diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index e0cd963fe39..9ce7d538004 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -28,12 +28,8 @@ feature 'Runners' do project.add_master(user) end - context 'when a specific runner is activated on the project' do - given(:specific_runner) { create(:ci_runner, :specific) } - - background do - project.runners << specific_runner - end + context 'when a project_type runner is activated on the project' do + given!(:specific_runner) { create(:ci_runner, :project, projects: [project]) } scenario 'user sees the specific runner' do visit project_runners_path(project) @@ -114,7 +110,7 @@ feature 'Runners' do end context 'when a shared runner is activated on the project' do - given!(:shared_runner) { create(:ci_runner, :shared) } + given!(:shared_runner) { create(:ci_runner, :instance) } scenario 'user sees CI/CD setting page' do visit project_runners_path(project) @@ -126,11 +122,10 @@ feature 'Runners' do context 'when a specific runner exists in another project' do given(:another_project) { create(:project) } - given(:specific_runner) { create(:ci_runner, :specific) } + given!(:specific_runner) { create(:ci_runner, :project, projects: [another_project]) } background do another_project.add_master(user) - another_project.runners << specific_runner end scenario 'user enables and disables a specific runner' do @@ -220,8 +215,8 @@ feature 'Runners' do end context 'project with a group but no group runner' do - given(:group) { create :group } - given(:project) { create :project, group: group } + given(:group) { create(:group) } + given(:project) { create(:project, group: group) } scenario 'group runners are not available' do visit project_runners_path(project) @@ -234,9 +229,9 @@ feature 'Runners' do end context 'project with a group and a group runner' do - given(:group) { create :group } - given(:project) { create :project, group: group } - given!(:ci_runner) { create :ci_runner, groups: [group], description: 'group-runner' } + given(:group) { create(:group) } + given(:project) { create(:project, group: group) } + given!(:ci_runner) { create(:ci_runner, :group, groups: [group], description: 'group-runner') } scenario 'group runners are available' do visit project_runners_path(project) @@ -263,7 +258,7 @@ feature 'Runners' do end context 'group runners in group settings' do - given(:group) { create :group } + given(:group) { create(:group) } background do group.add_master(user) end @@ -277,7 +272,7 @@ feature 'Runners' do end context 'group with a runner' do - let!(:runner) { create :ci_runner, groups: [group], description: 'group-runner' } + let!(:runner) { create(:ci_runner, :group, groups: [group], description: 'group-runner') } scenario 'the runner is visible' do visit group_settings_ci_cd_path(group) diff --git a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb index e8884bc1a00..c8db82a562f 100644 --- a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb @@ -14,7 +14,9 @@ feature 'User uploads avatar to group' do visible: false ) - click_button 'Save group' + page.within('.gs-general') do + click_button 'Save group' + end visit group_path(group) diff --git a/spec/features/users/rss_spec.rb b/spec/features/users/rss_spec.rb index 7c5abe54d56..c3734b5c808 100644 --- a/spec/features/users/rss_spec.rb +++ b/spec/features/users/rss_spec.rb @@ -10,7 +10,7 @@ feature 'User RSS' do visit path end - it_behaves_like "it has an RSS button with current_user's RSS token" + it_behaves_like "it has an RSS button with current_user's feed token" end context 'when signed out' do @@ -18,6 +18,6 @@ feature 'User RSS' do visit path end - it_behaves_like "it has an RSS button without an RSS token" + it_behaves_like "it has an RSS button without a feed token" end end diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb index f9469adbfe3..1efa5cd5490 100644 --- a/spec/features/users/terms_spec.rb +++ b/spec/features/users/terms_spec.rb @@ -62,7 +62,8 @@ describe 'Users > Terms' do expect(current_path).to eq(project_issues_path(project)) end - it 'redirects back to the page the user was trying to save' do + # Disabled until https://gitlab.com/gitlab-org/gitlab-ce/issues/37162 is solved properly + xit 'redirects back to the page the user was trying to save' do visit new_project_issue_path(project) fill_in :issue_title, with: 'Hello world, a new issue' diff --git a/spec/features/users/user_browses_projects_on_user_page_spec.rb b/spec/features/users/user_browses_projects_on_user_page_spec.rb index 7bede0b0d48..5478e38ce70 100644 --- a/spec/features/users/user_browses_projects_on_user_page_spec.rb +++ b/spec/features/users/user_browses_projects_on_user_page_spec.rb @@ -26,18 +26,23 @@ describe 'Users > User browses projects on user page', :js do end end + it 'hides loading spinner after load', :js do + visit user_path(user) + click_nav_link('Personal projects') + + wait_for_requests + + expect(page).not_to have_selector('.loading-status .loading', visible: true) + end + it 'paginates projects', :js do project = create(:project, namespace: user.namespace, updated_at: 2.minutes.since) project2 = create(:project, namespace: user.namespace, updated_at: 1.minute.since) allow(Project).to receive(:default_per_page).and_return(1) sign_in(user) - visit user_path(user) - - page.within('.user-profile-nav') do - click_link('Personal projects') - end + click_nav_link('Personal projects') wait_for_requests @@ -92,7 +97,6 @@ describe 'Users > User browses projects on user page', :js do click_nav_link('Personal projects') expect(title).to start_with(user.name) - expect(page).to have_content(private_project.name) expect(page).to have_content(public_project.name) expect(page).to have_content(internal_project.name) |