diff options
Diffstat (limited to 'spec/features')
28 files changed, 547 insertions, 89 deletions
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index ed9c0ea9ac0..97b432a6751 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -141,6 +141,56 @@ describe "Admin Runners" do end end + describe 'filter by tag', :js do + it 'shows correct runner when tag matches' do + create :ci_runner, description: 'runner-blue', tag_list: ['blue'] + create :ci_runner, description: 'runner-red', tag_list: ['red'] + + visit admin_runners_path + + expect(page).to have_content 'runner-blue' + expect(page).to have_content 'runner-red' + + input_filtered_search_keys('tag:blue') + + expect(page).to have_content 'runner-blue' + expect(page).not_to have_content 'runner-red' + end + + it 'shows no runner when tag does not match' do + create :ci_runner, description: 'runner-blue', tag_list: ['blue'] + create :ci_runner, description: 'runner-red', tag_list: ['blue'] + + visit admin_runners_path + + input_filtered_search_keys('tag:red') + + expect(page).not_to have_content 'runner-blue' + expect(page).not_to have_content 'runner-blue' + expect(page).to have_text 'No runners found' + end + + it 'shows correct runner when tag is selected and search term is entered' do + create :ci_runner, description: 'runner-a-1', tag_list: ['blue'] + create :ci_runner, description: 'runner-a-2', tag_list: ['red'] + create :ci_runner, description: 'runner-b-1', tag_list: ['blue'] + + visit admin_runners_path + + input_filtered_search_keys('tag:blue') + + expect(page).to have_content 'runner-a-1' + expect(page).to have_content 'runner-b-1' + expect(page).not_to have_content 'runner-a-2' + + input_filtered_search_keys('tag:blue runner-a') + + expect(page).to have_content 'runner-a-1' + expect(page).not_to have_content 'runner-b-1' + expect(page).not_to have_content 'runner-a-2' + end + end + it 'sorts by last contact date', :js do create(:ci_runner, description: 'runner-1', created_at: '2018-07-12 15:37', contacted_at: '2018-07-12 15:37') create(:ci_runner, description: 'runner-2', created_at: '2018-07-12 16:37', contacted_at: '2018-07-12 16:37') diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb index bf91dc121d8..c55dc4523f7 100644 --- a/spec/features/dashboard/activity_spec.rb +++ b/spec/features/dashboard/activity_spec.rb @@ -39,6 +39,8 @@ describe 'Dashboard > Activity' do event end + let(:issue) { create(:issue, project: project) } + let!(:merged_event) do create(:event, :merged, project: project, target: merge_request, author: user) end @@ -59,6 +61,10 @@ describe 'Dashboard > Activity' do create(:event, :closed, project: project, target: milestone, author: user) end + let!(:issue_event) do + create(:event, :created, project: project, target: issue, author: user) + end + before do project.add_maintainer(user) @@ -74,6 +80,7 @@ describe 'Dashboard > Activity' do expect(page).to have_content('closed') expect(page).to have_content('commented on') expect(page).to have_content('closed milestone') + expect(page).to have_content('opened issue') end end @@ -87,6 +94,7 @@ describe 'Dashboard > Activity' do expect(page).not_to have_content('accepted') expect(page).not_to have_content('closed') expect(page).not_to have_content('commented on') + expect(page).not_to have_content('opened issue') end end @@ -100,6 +108,7 @@ describe 'Dashboard > Activity' do expect(page).to have_content('accepted') expect(page).not_to have_content('closed') expect(page).not_to have_content('commented on') + expect(page).not_to have_content('opened issue') end end @@ -111,9 +120,10 @@ describe 'Dashboard > Activity' do expect(page).not_to have_content('pushed new branch') expect(page).not_to have_content('joined') expect(page).not_to have_content('accepted') - expect(page).to have_content('closed') + expect(page).not_to have_content('closed') expect(page).not_to have_content('commented on') - expect(page).to have_content('closed milestone') + expect(page).not_to have_content('closed milestone') + expect(page).to have_content('opened issue') end end @@ -127,6 +137,7 @@ describe 'Dashboard > Activity' do expect(page).not_to have_content('accepted') expect(page).not_to have_content('closed') expect(page).to have_content('commented on') + expect(page).not_to have_content('opened issue') end end @@ -140,6 +151,7 @@ describe 'Dashboard > Activity' do expect(page).not_to have_content('accepted') expect(page).not_to have_content('closed') expect(page).not_to have_content('commented on') + expect(page).not_to have_content('opened issue') end end @@ -155,6 +167,7 @@ describe 'Dashboard > Activity' do expect(page).not_to have_content('accepted') expect(page).not_to have_content('closed') expect(page).not_to have_content('commented on') + expect(page).not_to have_content('opened issue') end end end diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb index 57e3ddfb39c..1a53e7c9512 100644 --- a/spec/features/group_variables_spec.rb +++ b/spec/features/group_variables_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'Group variables', :js do let(:user) { create(:user) } let(:group) { create(:group) } - let!(:variable) { create(:ci_group_variable, key: 'test_key', value: 'test value', group: group) } + let!(:variable) { create(:ci_group_variable, key: 'test_key', value: 'test_value', group: group) } let(:page_path) { group_settings_ci_cd_path(group) } before do diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 8eb413bdd8d..986f3823275 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -278,7 +278,12 @@ describe 'GFM autocomplete', :js do end end - context 'labels' do + # This context has just one example in each contexts in order to improve spec performance. + context 'labels', :quarantine do + let!(:backend) { create(:label, project: project, title: 'backend') } + let!(:bug) { create(:label, project: project, title: 'bug') } + let!(:feature_proposal) { create(:label, project: project, title: 'feature proposal') } + it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do create(:label, project: project, title: label_xss_title) @@ -293,6 +298,83 @@ describe 'GFM autocomplete', :js do expect(find('.atwho-view-ul').text).to have_content('alert label') end end + + context 'when no labels are assigned' do + it 'shows labels' do + note = find('#note-body') + + # It should show all the labels on "~". + type(note, '~') + wait_for_requests + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show all the labels on "/label ~". + type(note, '/label ~') + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show all the labels on "/relabel ~". + type(note, '/relabel ~') + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show no labels on "/unlabel ~". + type(note, '/unlabel ~') + expect_labels(not_shown: [backend, bug, feature_proposal]) + end + end + + context 'when some labels are assigned' do + before do + issue.labels << [backend] + end + + it 'shows labels' do + note = find('#note-body') + + # It should show all the labels on "~". + type(note, '~') + wait_for_requests + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show only unset labels on "/label ~". + type(note, '/label ~') + expect_labels(shown: [bug, feature_proposal], not_shown: [backend]) + + # It should show all the labels on "/relabel ~". + type(note, '/relabel ~') + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show only set labels on "/unlabel ~". + type(note, '/unlabel ~') + expect_labels(shown: [backend], not_shown: [bug, feature_proposal]) + end + end + + context 'when all labels are assigned' do + before do + issue.labels << [backend, bug, feature_proposal] + end + + it 'shows labels' do + note = find('#note-body') + + # It should show all the labels on "~". + type(note, '~') + wait_for_requests + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show no labels on "/label ~". + type(note, '/label ~') + expect_labels(not_shown: [backend, bug, feature_proposal]) + + # It should show all the labels on "/relabel ~". + type(note, '/relabel ~') + expect_labels(shown: [backend, bug, feature_proposal]) + + # It should show all the labels on "/unlabel ~". + type(note, '/unlabel ~') + expect_labels(shown: [backend, bug, feature_proposal]) + end + end end shared_examples 'autocomplete suggestions' do diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index e60486f6dcb..0f604db870f 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -93,4 +93,22 @@ describe "User creates issue" do end end end + + context "when signed in as user with special characters in their name" do + let(:user_special) { create(:user, name: "Jon O'Shea") } + + before do + project.add_developer(user_special) + sign_in(user_special) + + visit(new_project_issue_path(project)) + end + + it "will correctly escape user names with an apostrophe when clicking 'Assign to me'", :js do + first('.assign-to-me-link').click + + expect(page).to have_content(user_special.name) + expect(page.find('input[name="issue[assignee_ids][]"]', visible: false)['data-meta']).to eq(user_special.name) + end + end end diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb index 27cffdc5f8b..b5e7c3954e2 100644 --- a/spec/features/issues/user_uses_quick_actions_spec.rb +++ b/spec/features/issues/user_uses_quick_actions_spec.rb @@ -243,7 +243,9 @@ describe 'Issues > User uses quick actions', :js do it 'does not move the issue' do add_note("/move not/valid") - expect(page).not_to have_content 'Commands applied' + wait_for_requests + + expect(page).to have_content 'Commands applied' expect(issue.reload).to be_open end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 406e80e91aa..9bc340ed4bb 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -233,8 +233,8 @@ describe 'Issues' do created_at: Time.now - (index * 60)) end end - let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') } - let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') } + let(:newer_due_milestone) { create(:milestone, project: project, due_date: '2013-12-11') } + let(:later_due_milestone) { create(:milestone, project: project, due_date: '2013-12-12') } it 'sorts by newest' do visit project_issues_path(project, sort: sort_value_created_date) diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb index 60ddb02da2c..c30ac9c4ae2 100644 --- a/spec/features/markdown/copy_as_gfm_spec.rb +++ b/spec/features/markdown/copy_as_gfm_spec.rb @@ -55,15 +55,10 @@ describe 'Copy as GFM', :js do To see how GitLab looks please see the [features page on our website](https://about.gitlab.com/features/). * Manage Git repositories with fine grained access controls that keep your code secure - * Perform code reviews and enhance collaboration with merge requests - * Complete continuous integration (CI) and CD pipelines to builds, test, and deploy your applications - * Each project can also have an issue tracker, issue board, and a wiki - * Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises - * Completely free and open source (MIT Expat license) GFM ) @@ -116,13 +111,11 @@ describe 'Copy as GFM', :js do <<~GFM, * [ ] Unchecked task - * [x] Checked task GFM <<~GFM 1. [ ] Unchecked ordered task - 1. [x] Checked ordered task GFM ) @@ -551,7 +544,6 @@ describe 'Copy as GFM', :js do <<~GFM, * List item - * List item 2 GFM @@ -565,7 +557,6 @@ describe 'Copy as GFM', :js do # nested lists <<~GFM, * Nested - * Lists GFM @@ -578,7 +569,6 @@ describe 'Copy as GFM', :js do <<~GFM, 1. Ordered list item - 1. Ordered list item 2 GFM @@ -592,7 +582,6 @@ describe 'Copy as GFM', :js do # nested ordered list <<~GFM, 1. Nested - 1. Ordered lists GFM diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb index 7839b97122c..b35f985126c 100644 --- a/spec/features/merge_request/maintainer_edits_fork_spec.rb +++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb @@ -18,13 +18,15 @@ describe 'a maintainer edits files on a source-branch of an MR from a fork', :js end before do + stub_feature_flags(web_ide_default: false) + target_project.add_maintainer(user) sign_in(user) visit project_merge_request_path(target_project, merge_request) click_link 'Changes' wait_for_requests - first('.js-file-title').click_link 'Edit' + first('.js-file-title').find('.js-edit-blob').click wait_for_requests end diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb index 51b78d3e7d1..19edce1b562 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -178,7 +178,7 @@ describe 'Merge request > User posts diff notes', :js do end end - describe 'with muliple note forms' do + describe 'with multiple note forms' do before do visit diffs_project_merge_request_path(project, merge_request, view: 'inline') click_diff_line(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]')) diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb index 1bbcf455ac7..dc0862be6fc 100644 --- a/spec/features/merge_request/user_posts_notes_spec.rb +++ b/spec/features/merge_request/user_posts_notes_spec.rb @@ -67,7 +67,7 @@ describe 'Merge request > User posts notes', :js do end end - describe 'when reply_to_individual_notes feature flag is not set' do + describe 'when reply_to_individual_notes feature flag is disabled' do before do stub_feature_flags(reply_to_individual_notes: false) visit project_merge_request_path(project, merge_request) @@ -78,9 +78,8 @@ describe 'Merge request > User posts notes', :js do end end - describe 'when reply_to_individual_notes feature flag is set' do + describe 'when reply_to_individual_notes feature flag is not set' do before do - stub_feature_flags(reply_to_individual_notes: true) visit project_merge_request_path(project, merge_request) end diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb index 7b473faa884..97b2aa82fce 100644 --- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb @@ -49,7 +49,7 @@ describe 'Merge request > User sees merge request pipelines', :js do let!(:merge_request_pipeline) do Ci::CreatePipelineService.new(project, user, ref: 'feature') - .execute(:merge_request, merge_request: merge_request) + .execute(:merge_request_event, merge_request: merge_request) end before do @@ -81,7 +81,7 @@ describe 'Merge request > User sees merge request pipelines', :js do let!(:merge_request_pipeline_2) do Ci::CreatePipelineService.new(project, user, ref: 'feature') - .execute(:merge_request, merge_request: merge_request) + .execute(:merge_request_event, merge_request: merge_request) end before do @@ -220,7 +220,7 @@ describe 'Merge request > User sees merge request pipelines', :js do let!(:merge_request_pipeline) do Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature') - .execute(:merge_request, merge_request: merge_request) + .execute(:merge_request_event, merge_request: merge_request) end let(:forked_project) { fork_project(project, user2, repository: true) } @@ -263,7 +263,7 @@ describe 'Merge request > User sees merge request pipelines', :js do let!(:merge_request_pipeline_2) do Ci::CreatePipelineService.new(forked_project, user2, ref: 'feature') - .execute(:merge_request, merge_request: merge_request) + .execute(:merge_request_event, merge_request: merge_request) end before do diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb index aa91ade46ca..5c45e363997 100644 --- a/spec/features/merge_request/user_sees_versions_spec.rb +++ b/spec/features/merge_request/user_sees_versions_spec.rb @@ -1,7 +1,11 @@ require 'rails_helper' describe 'Merge request > User sees versions', :js do - let(:merge_request) { create(:merge_request, importing: true) } + let(:merge_request) do + create(:merge_request).tap do |mr| + mr.merge_request_diff.destroy + end + end let(:project) { merge_request.source_project } let(:user) { project.creator } let!(:merge_request_diff1) { merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb index ef7ae490b0f..c691011b9ca 100644 --- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb @@ -13,7 +13,7 @@ describe 'Merge requests > User lists merge requests' do source_project: project, source_branch: 'fix', assignee: user, - milestone: create(:milestone, due_date: '2013-12-11'), + milestone: create(:milestone, project: project, due_date: '2013-12-11'), created_at: 1.minute.ago, updated_at: 1.minute.ago) create(:merge_request, @@ -21,7 +21,7 @@ describe 'Merge requests > User lists merge requests' do source_project: project, source_branch: 'markdown', assignee: user, - milestone: create(:milestone, due_date: '2013-12-12'), + milestone: create(:milestone, project: project, due_date: '2013-12-12'), created_at: 2.minutes.ago, updated_at: 2.minutes.ago) create(:merge_request, diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb index d3050760c06..2aa0177af5d 100644 --- a/spec/features/profiles/active_sessions_spec.rb +++ b/spec/features/profiles/active_sessions_spec.rb @@ -7,6 +7,8 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do end end + let(:admin) { create(:admin) } + around do |example| Timecop.freeze(Time.zone.parse('2018-03-12 09:06')) do example.run @@ -16,6 +18,7 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do it 'User sees their active sessions' do Capybara::Session.new(:session1) Capybara::Session.new(:session2) + Capybara::Session.new(:session3) # note: headers can only be set on the non-js (aka. rack-test) driver using_session :session1 do @@ -37,9 +40,27 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do gitlab_sign_in(user) end + # set an admin session impersonating the user + using_session :session3 do + Capybara.page.driver.header( + 'User-Agent', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36' + ) + + gitlab_sign_in(admin) + + visit admin_user_path(user) + + click_link 'Impersonate' + end + using_session :session1 do visit profile_active_sessions_path + expect(page).to( + have_selector('ul.list-group li.list-group-item', { text: 'Signed in on', + count: 2 })) + expect(page).to have_content( '127.0.0.1 ' \ 'This is your current session ' \ @@ -57,33 +78,8 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do ) expect(page).to have_selector '[title="Smartphone"]', count: 1 - end - end - - it 'User can revoke a session', :js, :redis_session_store do - Capybara::Session.new(:session1) - Capybara::Session.new(:session2) - - # set an additional session in another browser - using_session :session2 do - gitlab_sign_in(user) - end - - using_session :session1 do - gitlab_sign_in(user) - visit profile_active_sessions_path - - expect(page).to have_link('Revoke', count: 1) - - accept_confirm { click_on 'Revoke' } - - expect(page).not_to have_link('Revoke') - end - - using_session :session2 do - visit profile_active_sessions_path - expect(page).to have_content('You need to sign in or sign up before continuing.') + expect(page).not_to have_content('Chrome on Windows') end end end diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb index a93df3696d2..6bdf5df1036 100644 --- a/spec/features/project_variables_spec.rb +++ b/spec/features/project_variables_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'Project variables', :js do let(:user) { create(:user) } let(:project) { create(:project) } - let(:variable) { create(:ci_variable, key: 'test_key', value: 'test value') } + let(:variable) { create(:ci_variable, key: 'test_key', value: 'test_value') } let(:page_path) { project_settings_ci_cd_path(project) } before do diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 3edcc7ac2cd..a7aa63018fd 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -548,10 +548,7 @@ describe 'File blob', :js do it 'displays an auxiliary viewer' do aggregate_failures do # shows names of dependency manager and package - expect(page).to have_content('This project manages its dependencies using RubyGems and defines a gem named activerecord.') - - # shows a link to the gem - expect(page).to have_link('activerecord', href: 'https://rubygems.org/gems/activerecord') + expect(page).to have_content('This project manages its dependencies using RubyGems.') # shows a learn more link expect(page).to have_link('Learn more', href: 'https://rubygems.org/') diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index 828f6f9921e..57d21f3e182 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -49,6 +49,15 @@ describe 'Editing file blob', :js do end end + it 'updates the content of file with a number as file path' do + project.repository.create_file(user, '1', 'test', message: 'testing', branch_name: branch) + visit project_blob_path(project, tree_join(branch, '1')) + + edit_and_commit + + expect(page).to have_content 'NextFeature' + end + context 'from blob file path' do before do visit project_blob_path(project, tree_join(branch, file_path)) diff --git a/spec/features/projects/clusters/applications_spec.rb b/spec/features/projects/clusters/applications_spec.rb index 2c8d014c36d..713e25cdcb2 100644 --- a/spec/features/projects/clusters/applications_spec.rb +++ b/spec/features/projects/clusters/applications_spec.rb @@ -17,7 +17,7 @@ describe 'Clusters Applications', :js do end context 'when cluster is being created' do - let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project])} + let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) } it 'user is unable to install applications' do page.within('.js-cluster-application-row-helm') do @@ -28,9 +28,11 @@ describe 'Clusters Applications', :js do end context 'when cluster is created' do - let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project])} + let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } it 'user can install applications' do + wait_for_requests + page.within('.js-cluster-application-row-helm') do expect(page.find(:css, '.js-cluster-application-install-button')['disabled']).to be_nil expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Install') @@ -44,6 +46,8 @@ describe 'Clusters Applications', :js do page.within('.js-cluster-application-row-helm') do page.find(:css, '.js-cluster-application-install-button').click end + + wait_for_requests end it 'they see status transition' do @@ -52,8 +56,6 @@ describe 'Clusters Applications', :js do expect(page.find(:css, '.js-cluster-application-install-button')['disabled']).to eq('true') expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing') - wait_until_helm_created! - Clusters::Cluster.last.application_helm.make_installing! # FE starts polling and update the buttons to "Installing" @@ -76,7 +78,7 @@ describe 'Clusters Applications', :js do end context 'on an abac cluster' do - let(:cluster) { create(:cluster, :provided_by_gcp, :rbac_disabled, projects: [project])} + let(:cluster) { create(:cluster, :provided_by_gcp, :rbac_disabled, projects: [project]) } it 'should show info block and not be installable' do page.within('.js-cluster-application-row-knative') do @@ -87,7 +89,7 @@ describe 'Clusters Applications', :js do end context 'on an rbac cluster' do - let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project])} + let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } it 'should not show callout block and be installable' do page.within('.js-cluster-application-row-knative') do @@ -95,6 +97,60 @@ describe 'Clusters Applications', :js do expect(page).to have_css('.js-cluster-application-install-button:not([disabled])') end end + + describe 'when user clicks install button' do + def domainname_form_value + page.find('.js-knative-domainname').value + end + + before do + allow(ClusterInstallAppWorker).to receive(:perform_async) + allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in) + allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async) + + page.within('.js-cluster-application-row-knative') do + expect(page).to have_css('.js-cluster-application-install-button:not([disabled])') + + page.find('.js-knative-domainname').set("domain.example.org") + + click_button 'Install' + + wait_for_requests + + expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installing') + + Clusters::Cluster.last.application_knative.make_installing! + Clusters::Cluster.last.application_knative.make_installed! + Clusters::Cluster.last.application_knative.update_attribute(:external_ip, '127.0.0.1') + end + end + + it 'shows status transition' do + page.within('.js-cluster-application-row-knative') do + expect(domainname_form_value).to eq('domain.example.org') + expect(page).to have_css('.js-cluster-application-install-button', exact_text: 'Installed') + end + + expect(page).to have_content('Knative was successfully installed on your Kubernetes cluster') + expect(page).to have_css('.js-knative-save-domain-button'), exact_text: 'Save changes' + end + + it 'can then update the domain' do + page.within('.js-cluster-application-row-knative') do + expect(ClusterPatchAppWorker).to receive(:perform_async) + + expect(domainname_form_value).to eq('domain.example.org') + + page.find('.js-knative-domainname').set("new.domain.example.org") + + click_button 'Save changes' + + wait_for_requests + + expect(domainname_form_value).to eq('new.domain.example.org') + end + end + end end end @@ -148,6 +204,8 @@ describe 'Clusters Applications', :js do page.within('.js-cluster-application-row-ingress') do expect(page).to have_css('.js-cluster-application-install-button:not([disabled])') page.find(:css, '.js-cluster-application-install-button').click + + wait_for_requests end end @@ -184,14 +242,4 @@ describe 'Clusters Applications', :js do end end end - - def wait_until_helm_created! - retries = 0 - - while Clusters::Cluster.last.application_helm.nil? - raise "Timed out waiting for helm application to be created in DB" if (retries += 1) > 3 - - sleep(1) - end - end end diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index a8a3b6910fb..3090f1a2131 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -120,7 +120,7 @@ describe 'Environment' do end it 'does show a play button' do - expect(page).to have_link(action.name.humanize) + expect(page).to have_link(action.name) end it 'does allow to play manual action', :js do @@ -128,7 +128,7 @@ describe 'Environment' do find('button.dropdown').click - expect { click_link(action.name.humanize) } + expect { click_link(action.name) } .not_to change { Ci::Pipeline.count } wait_for_all_requests @@ -140,7 +140,7 @@ describe 'Environment' do context 'when user has no ability to trigger a deployment' do it 'does not show a play button' do - expect(page).not_to have_link(action.name.humanize) + expect(page).not_to have_link(action.name) end end diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 66c6545204b..b2a435e554d 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -183,14 +183,14 @@ describe 'Environments page', :js do it 'shows a play button' do find('.js-environment-actions-dropdown').click - expect(page).to have_content(action.name.humanize) + expect(page).to have_content(action.name) end it 'allows to play a manual action', :js do expect(action).to be_manual find('.js-environment-actions-dropdown').click - expect(page).to have_content(action.name.humanize) + expect(page).to have_content(action.name) expect { find('.js-manual-action-link').click } .not_to change { Ci::Pipeline.count } @@ -311,7 +311,7 @@ describe 'Environments page', :js do it "has link to the delayed job's action" do find('.js-environment-actions-dropdown').click - expect(page).to have_button('Delayed job') + expect(page).to have_button('delayed job') expect(page).to have_content(/\d{2}:\d{2}:\d{2}/) end @@ -333,7 +333,7 @@ describe 'Environments page', :js do context 'when user played a delayed job immediately' do before do find('.js-environment-actions-dropdown').click - page.accept_confirm { click_button('Delayed job') } + page.accept_confirm { click_button('delayed job') } wait_for_requests end diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb index fceead0b45e..b2d2dba55f1 100644 --- a/spec/features/projects/members/invite_group_spec.rb +++ b/spec/features/projects/members/invite_group_spec.rb @@ -27,6 +27,7 @@ describe 'Project > Members > Invite group', :js do before do project.add_maintainer(maintainer) + group_to_share_with.add_guest(maintainer) sign_in(maintainer) end @@ -112,6 +113,7 @@ describe 'Project > Members > Invite group', :js do before do project.add_maintainer(maintainer) + group.add_guest(maintainer) sign_in(maintainer) visit project_settings_members_path(project) diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 72ef460d315..36b8c15b8b6 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -666,7 +666,7 @@ describe 'Pipeline', :js do let(:pipeline) do create(:ci_pipeline, - source: :merge_request, + source: :merge_request_event, project: merge_request.source_project, ref: 'feature', sha: merge_request.diff_head_sha, diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb index 06290c67c70..af56cb0d4ee 100644 --- a/spec/features/projects/settings/operations_settings_spec.rb +++ b/spec/features/projects/settings/operations_settings_spec.rb @@ -20,4 +20,81 @@ describe 'Projects > Settings > For a forked project', :js do expect(page).to have_selector('a[title="Operations"]', visible: false) end end + + describe 'Settings > Operations' do + context 'error tracking settings form' do + let(:sentry_list_projects_url) { 'http://sentry.example.com/api/0/projects/' } + + context 'success path' do + let(:projects_sample_response) do + Gitlab::Utils.deep_indifferent_access( + JSON.parse(fixture_file('sentry/list_projects_sample_response.json')) + ) + end + + before do + WebMock.stub_request(:get, sentry_list_projects_url) + .to_return( + status: 200, + headers: { 'Content-Type' => 'application/json' }, + body: projects_sample_response.to_json + ) + end + + it 'successfully fills and submits the form' do + visit project_settings_operations_path(project) + + wait_for_requests + + expect(page).to have_content('Sentry API URL') + expect(page.body).to include('Error Tracking') + expect(page).to have_button('Connect') + + check('Active') + fill_in('error-tracking-api-host', with: 'http://sentry.example.com') + fill_in('error-tracking-token', with: 'token') + + click_button('Connect') + + within('div#project-dropdown') do + click_button('Select project') + click_button('Sentry | Internal') + end + + click_button('Save changes') + + wait_for_requests + + assert_text('Your changes have been saved') + end + end + + context 'project dropdown fails to load' do + before do + WebMock.stub_request(:get, sentry_list_projects_url) + .to_return( + status: 400, + headers: { 'Content-Type' => 'application/json' }, + body: { + message: 'Sentry response code: 401' + }.to_json + ) + end + + it 'displays error message' do + visit project_settings_operations_path(project) + + wait_for_requests + + check('Active') + fill_in('error-tracking-api-host', with: 'http://sentry.example.com') + fill_in('error-tracking-token', with: 'token') + + click_button('Connect') + + assert_text('Connection has failed. Re-check Auth Token and try again.') + end + end + end + end end diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb new file mode 100644 index 00000000000..7afddc0e712 --- /dev/null +++ b/spec/features/projects/settings/project_settings_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Projects settings' do + set(:project) { create(:project) } + let(:user) { project.owner } + let(:panel) { find('.general-settings', match: :first) } + let(:button) { panel.find('.btn.js-settings-toggle') } + let(:title) { panel.find('.settings-title') } + + before do + sign_in(user) + visit edit_project_path(project) + end + + it 'can toggle sections by clicking the title or button', :js do + expect_toggle_state(:expanded) + + button.click + + expect_toggle_state(:collapsed) + + button.click + + expect_toggle_state(:expanded) + + title.click + + expect_toggle_state(:collapsed) + + title.click + + expect_toggle_state(:expanded) + end + + def expect_toggle_state(state) + is_collapsed = state == :collapsed + + expect(button).to have_content(is_collapsed ? 'Expand' : 'Collapse') + expect(panel[:class]).send(is_collapsed ? 'not_to' : 'to', include('expanded')) + end +end diff --git a/spec/features/projects/settings/user_manages_group_links_spec.rb b/spec/features/projects/settings/user_manages_group_links_spec.rb index 676659b90c3..e5a58c44e41 100644 --- a/spec/features/projects/settings/user_manages_group_links_spec.rb +++ b/spec/features/projects/settings/user_manages_group_links_spec.rb @@ -10,6 +10,7 @@ describe 'Projects > Settings > User manages group links' do before do project.add_maintainer(user) + group_market.add_guest(user) sign_in(user) share_link = project.project_group_links.new(group_access: Gitlab::Access::MAINTAINER) diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb index ee5734a9bf1..383e8824b7b 100644 --- a/spec/features/projects/user_sees_sidebar_spec.rb +++ b/spec/features/projects/user_sees_sidebar_spec.rb @@ -4,6 +4,108 @@ describe 'Projects > User sees sidebar' do let(:user) { create(:user) } let(:project) { create(:project, :private, public_builds: false, namespace: user.namespace) } + # NOTE: See documented behaviour https://design.gitlab.com/regions/navigation#contextual-navigation + context 'on different viewports', :js do + include MobileHelpers + + before do + sign_in(user) + end + + shared_examples 'has a expanded nav sidebar' do + it 'has a expanded desktop nav-sidebar on load' do + expect(page).to have_content('Collapse sidebar') + expect(page).not_to have_selector('.sidebar-collapsed-desktop') + expect(page).not_to have_selector('.sidebar-expanded-mobile') + end + + it 'can collapse the nav-sidebar' do + page.find('.nav-sidebar .js-toggle-sidebar').click + expect(page).to have_selector('.sidebar-collapsed-desktop') + expect(page).not_to have_content('Collapse sidebar') + expect(page).not_to have_selector('.sidebar-expanded-mobile') + end + end + + shared_examples 'has a collapsed nav sidebar' do + it 'has a collapsed desktop nav-sidebar on load' do + expect(page).not_to have_content('Collapse sidebar') + expect(page).not_to have_selector('.sidebar-expanded-mobile') + end + + it 'can expand the nav-sidebar' do + page.find('.nav-sidebar .js-toggle-sidebar').click + expect(page).to have_selector('.sidebar-expanded-mobile') + expect(page).to have_content('Collapse sidebar') + end + end + + shared_examples 'has a mobile nav-sidebar' do + it 'has a hidden nav-sidebar on load' do + expect(page).not_to have_content('.mobile-nav-open') + expect(page).not_to have_selector('.sidebar-expanded-mobile') + end + + it 'can expand the nav-sidebar' do + page.find('.toggle-mobile-nav').click + expect(page).to have_selector('.mobile-nav-open') + expect(page).to have_selector('.sidebar-expanded-mobile') + end + end + + context 'with a extra small viewport' do + before do + resize_screen_xs + visit project_path(project) + expect(page).to have_selector('.nav-sidebar') + expect(page).to have_selector('.toggle-mobile-nav') + end + + it_behaves_like 'has a mobile nav-sidebar' + end + + context 'with a small size viewport' do + before do + resize_screen_sm + visit project_path(project) + expect(page).to have_selector('.nav-sidebar') + expect(page).to have_selector('.toggle-mobile-nav') + end + + it_behaves_like 'has a mobile nav-sidebar' + end + + context 'with medium size viewport' do + before do + resize_window(768, 800) + visit project_path(project) + expect(page).to have_selector('.nav-sidebar') + end + + it_behaves_like 'has a collapsed nav sidebar' + end + + context 'with viewport size 1199px' do + before do + resize_window(1199, 800) + visit project_path(project) + expect(page).to have_selector('.nav-sidebar') + end + + it_behaves_like 'has a collapsed nav sidebar' + end + + context 'with a extra large viewport' do + before do + resize_window(1200, 800) + visit project_path(project) + expect(page).to have_selector('.nav-sidebar') + end + + it_behaves_like 'has a expanded nav sidebar' + end + end + context 'as owner' do before do sign_in(user) diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb index 4705cd12d23..3238e07fe15 100644 --- a/spec/features/security/group/private_access_spec.rb +++ b/spec/features/security/group/private_access_spec.rb @@ -27,7 +27,7 @@ describe 'Private Group access' do it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:reporter).of(group) } it { is_expected.to be_allowed_for(:guest).of(group) } - it { is_expected.to be_allowed_for(project_guest) } + it { is_expected.to be_denied_for(project_guest) } it { is_expected.to be_denied_for(:user) } it { is_expected.to be_denied_for(:external) } it { is_expected.to be_denied_for(:visitor) } @@ -42,7 +42,7 @@ describe 'Private Group access' do it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:reporter).of(group) } it { is_expected.to be_allowed_for(:guest).of(group) } - it { is_expected.to be_allowed_for(project_guest) } + it { is_expected.to be_denied_for(project_guest) } it { is_expected.to be_denied_for(:user) } it { is_expected.to be_denied_for(:external) } it { is_expected.to be_denied_for(:visitor) } @@ -58,7 +58,7 @@ describe 'Private Group access' do it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:reporter).of(group) } it { is_expected.to be_allowed_for(:guest).of(group) } - it { is_expected.to be_allowed_for(project_guest) } + it { is_expected.to be_denied_for(project_guest) } it { is_expected.to be_denied_for(:user) } it { is_expected.to be_denied_for(:external) } it { is_expected.to be_denied_for(:visitor) } @@ -73,7 +73,7 @@ describe 'Private Group access' do it { is_expected.to be_allowed_for(:developer).of(group) } it { is_expected.to be_allowed_for(:reporter).of(group) } it { is_expected.to be_allowed_for(:guest).of(group) } - it { is_expected.to be_allowed_for(project_guest) } + it { is_expected.to be_denied_for(project_guest) } it { is_expected.to be_denied_for(:user) } it { is_expected.to be_denied_for(:external) } it { is_expected.to be_denied_for(:visitor) } @@ -93,4 +93,28 @@ describe 'Private Group access' do it { is_expected.to be_denied_for(:visitor) } it { is_expected.to be_denied_for(:external) } end + + describe 'GET /groups/:path for shared projects' do + let(:project) { create(:project, :public) } + before do + Projects::GroupLinks::CreateService.new( + project, + create(:user), + link_group_access: ProjectGroupLink::DEVELOPER + ).execute(group) + end + + subject { group_path(group) } + + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(group) } + it { is_expected.to be_allowed_for(:maintainer).of(group) } + it { is_expected.to be_allowed_for(:developer).of(group) } + it { is_expected.to be_allowed_for(:reporter).of(group) } + it { is_expected.to be_allowed_for(:guest).of(group) } + it { is_expected.to be_denied_for(project_guest) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } + end end |