diff options
Diffstat (limited to 'spec/features/projects')
49 files changed, 723 insertions, 537 deletions
diff --git a/spec/features/projects/artifacts/raw_spec.rb b/spec/features/projects/artifacts/raw_spec.rb index d72a35fddf8..d580262d48b 100644 --- a/spec/features/projects/artifacts/raw_spec.rb +++ b/spec/features/projects/artifacts/raw_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Raw artifact', :js do +RSpec.describe 'Raw artifact' do let(:project) { create(:project, :public) } let(:pipeline) { create(:ci_empty_pipeline, project: project) } let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 3032d115a00..7c564d76f70 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -564,35 +564,76 @@ RSpec.describe 'File blob', :js do file_path: '.gitlab/dashboards/custom-dashboard.yml', file_content: file_content ).execute - - visit_blob('.gitlab/dashboards/custom-dashboard.yml') end - context 'valid dashboard file' do - let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } + context 'with metrics_dashboard_exhaustive_validations feature flag off' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: false) + visit_blob('.gitlab/dashboards/custom-dashboard.yml') + end - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that dashboard yaml is valid - expect(page).to have_content('Metrics Dashboard YAML definition is valid.') + context 'valid dashboard file' do + let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } + + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is valid + expect(page).to have_content('Metrics Dashboard YAML definition is valid.') + + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end + + context 'invalid dashboard file' do + let(:file_content) { "dashboard: 'invalid'" } - # shows a learn more link - expect(page).to have_link('Learn more') + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is invalid + expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') + expect(page).to have_content("panel_groups: should be an array of panel_groups objects") + + # shows a learn more link + expect(page).to have_link('Learn more') + end end end end - context 'invalid dashboard file' do - let(:file_content) { "dashboard: 'invalid'" } + context 'with metrics_dashboard_exhaustive_validations feature flag on' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: true) + visit_blob('.gitlab/dashboards/custom-dashboard.yml') + end - it 'displays an auxiliary viewer' do - aggregate_failures do - # shows that dashboard yaml is invalid - expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') - expect(page).to have_content("panel_groups: should be an array of panel_groups objects") + context 'valid dashboard file' do + let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } - # shows a learn more link - expect(page).to have_link('Learn more') + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is valid + expect(page).to have_content('Metrics Dashboard YAML definition is valid.') + + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end + + context 'invalid dashboard file' do + let(:file_content) { "dashboard: 'invalid'" } + + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that dashboard yaml is invalid + expect(page).to have_content('Metrics Dashboard YAML definition is invalid:') + expect(page).to have_content("root is missing required keys: panel_groups") + + # shows a learn more link + expect(page).to have_link('Learn more') + end end end end diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index dbd1cebd515..0e2444c5434 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -97,7 +97,7 @@ RSpec.describe 'Branches' do end describe 'Delete unprotected branch on Overview' do - it 'removes branch after confirmation', :js do + it 'removes branch after confirmation', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/239019' do visit project_branches_filtered_path(project, state: 'all') expect(all('.all-branches').last).to have_selector('li', count: 20) diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb index ba063acbe70..ce435151b84 100644 --- a/spec/features/projects/ci/lint_spec.rb +++ b/spec/features/projects/ci/lint_spec.rb @@ -3,89 +3,122 @@ require 'spec_helper' RSpec.describe 'CI Lint', :js do + include Spec::Support::Helpers::Features::EditorLiteSpecHelpers + let(:project) { create(:project, :repository) } let(:user) { create(:user) } - before do - project.add_developer(user) - sign_in(user) - - visit project_ci_lint_path(project) - find('#ci-editor') - execute_script("ace.edit('ci-editor').setValue(#{yaml_content.to_json});") + shared_examples 'correct ci linting process' do + describe 'YAML parsing' do + shared_examples 'validates the YAML' do + before do + stub_feature_flags(ci_lint_vue: false) + click_on 'Validate' + end - # Ace editor updates a hidden textarea and it happens asynchronously - wait_for('YAML content') do - find('.ace_content').text.present? - end - end + context 'YAML is correct' do + let(:yaml_content) do + File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + end - describe 'YAML parsing' do - shared_examples 'validates the YAML' do - before do - click_on 'Validate' - end + it 'parses Yaml and displays the jobs' do + expect(page).to have_content('Status: syntax is correct') - context 'YAML is correct' do - let(:yaml_content) do - File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + within "table" do + aggregate_failures do + expect(page).to have_content('Job - rspec') + expect(page).to have_content('Job - spinach') + expect(page).to have_content('Deploy Job - staging') + expect(page).to have_content('Deploy Job - production') + end + end + end end - it 'parses Yaml and displays the jobs' do - expect(page).to have_content('Status: syntax is correct') + context 'YAML is incorrect' do + let(:yaml_content) { 'value: cannot have :' } - within "table" do - aggregate_failures do - expect(page).to have_content('Job - rspec') - expect(page).to have_content('Job - spinach') - expect(page).to have_content('Deploy Job - staging') - expect(page).to have_content('Deploy Job - production') - end + it 'displays information about an error' do + expect(page).to have_content('Status: syntax is incorrect') + expect(page).to have_selector(content_selector, text: yaml_content) end end end - context 'YAML is incorrect' do - let(:yaml_content) { 'value: cannot have :' } + it_behaves_like 'validates the YAML' - it 'displays information about an error' do - expect(page).to have_content('Status: syntax is incorrect') - expect(page).to have_selector('.ace_content', text: yaml_content) + context 'when Dry Run is checked' do + before do + check 'Simulate a pipeline created for the default branch' end + + it_behaves_like 'validates the YAML' end - end - it_behaves_like 'validates the YAML' + describe 'YAML revalidate' do + let(:yaml_content) { 'my yaml content' } - context 'when Dry Run is checked' do + it 'loads previous YAML content after validation' do + expect(page).to have_field('content', with: 'my yaml content', visible: false, type: 'textarea') + end + end + end + + describe 'YAML clearing' do before do - check 'Simulate a pipeline created for the default branch' + click_on 'Clear' end - it_behaves_like 'validates the YAML' + context 'YAML is present' do + let(:yaml_content) do + File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + end + + it 'YAML content is cleared' do + expect(page).to have_field('content', with: '', visible: false, type: 'textarea') + end + end end + end - describe 'YAML revalidate' do - let(:yaml_content) { 'my yaml content' } + context 'with ACE editor' do + it_behaves_like 'correct ci linting process' do + let(:content_selector) { '.ace_content' } - it 'loads previous YAML content after validation' do - expect(page).to have_field('content', with: 'my yaml content', visible: false, type: 'textarea') + before do + stub_feature_flags(monaco_ci: false) + stub_feature_flags(ci_lint_vue: false) + project.add_developer(user) + sign_in(user) + + visit project_ci_lint_path(project) + find('#ci-editor') + execute_script("ace.edit('ci-editor').setValue(#{yaml_content.to_json});") + + # Ace editor updates a hidden textarea and it happens asynchronously + wait_for('YAML content') do + find(content_selector).text.present? + end end end end - describe 'YAML clearing' do - before do - click_on 'Clear' - end + context 'with Editor Lite' do + it_behaves_like 'correct ci linting process' do + let(:content_selector) { '.content .view-lines' } - context 'YAML is present' do - let(:yaml_content) do - File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) - end + before do + stub_feature_flags(monaco_ci: true) + stub_feature_flags(ci_lint_vue: false) + project.add_developer(user) + sign_in(user) - it 'YAML content is cleared' do - expect(page).to have_field('content', with: '', visible: false, type: 'textarea') + visit project_ci_lint_path(project) + editor_set_value(yaml_content) + + wait_for('YAML content') do + find(content_selector).text.present? + end end end end diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index 63e5546b43c..04339d20d77 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -144,7 +144,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do visit project_clusters_path(project) click_link 'Add Kubernetes cluster' - click_link 'Add existing cluster' + click_link 'Connect existing cluster' end it 'user sees the "Environment scope" field' do diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index 450eaa7f004..9d0dc65093e 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -26,7 +26,7 @@ RSpec.describe 'User Cluster', :js do visit project_clusters_path(project) click_link 'Add Kubernetes cluster' - click_link 'Add existing cluster' + click_link 'Connect existing cluster' end context 'when user filled form with valid parameters' do diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb index c56a1ed1711..d674fbc457e 100644 --- a/spec/features/projects/clusters_spec.rb +++ b/spec/features/projects/clusters_spec.rb @@ -43,7 +43,7 @@ RSpec.describe 'Clusters', :js do context 'when user filled form with environment scope' do before do click_link 'Add Kubernetes cluster' - click_link 'Add existing cluster' + click_link 'Connect existing cluster' fill_in 'cluster_name', with: 'staging-cluster' fill_in 'cluster_environment_scope', with: 'staging/*' click_button 'Add Kubernetes cluster' @@ -72,7 +72,7 @@ RSpec.describe 'Clusters', :js do context 'when user updates duplicated environment scope' do before do click_link 'Add Kubernetes cluster' - click_link 'Add existing cluster' + click_link 'Connect existing cluster' fill_in 'cluster_name', with: 'staging-cluster' fill_in 'cluster_environment_scope', with: '*' fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'https://0.0.0.0' diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb index 7bd3bce85d5..cf9b86f16bb 100644 --- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb +++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb @@ -26,8 +26,6 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do build.run visit project_commit_path(project, project.commit.id) - wait_for_all_requests - expect(page).to have_selector('.mr-widget-pipeline-graph') first('.mini-pipeline-graph-dropdown-toggle').click diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb index 70d47516246..6218578cac6 100644 --- a/spec/features/projects/deploy_keys_spec.rb +++ b/spec/features/projects/deploy_keys_spec.rb @@ -22,7 +22,7 @@ RSpec.describe 'Project deploy keys', :js do page.within(find('.qa-deploy-keys-settings')) do expect(page).to have_selector('.deploy-key', count: 1) - accept_confirm { find('.ic-remove').click } + accept_confirm { find('[data-testid="remove-icon"]').click } wait_for_requests diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index a05910cd892..7f2ef61bcbe 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -106,7 +106,7 @@ RSpec.describe 'Environments page', :js do expect(page).to have_css('.environments-container') expect(page.all('.environment-name').length).to eq(1) - expect(page.all('.ic-stop').length).to eq(0) + expect(page.all('[data-testid="stop-icon"]').length).to eq(0) end end end @@ -301,7 +301,7 @@ RSpec.describe 'Environments page', :js do end it 'has a dropdown for actionable jobs' do - expect(page).to have_selector('.dropdown-new.btn.btn-default .ic-play') + expect(page).to have_selector('.dropdown-new.btn.btn-default [data-testid="play-icon"]') end it "has link to the delayed job's action" do diff --git a/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb b/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb index aff8951d9de..908e30478b2 100644 --- a/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb +++ b/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb @@ -8,57 +8,26 @@ RSpec.describe 'User paginates issue designs', :js do let(:project) { create(:project_empty_repo, :public) } let(:issue) { create(:issue, project: project) } - context 'design_management_moved flag disabled' do - before do - stub_feature_flags(design_management_moved: false) - enable_design_management - - create_list(:design, 2, :with_file, issue: issue) - visit project_issue_path(project, issue) - click_link 'Designs' - wait_for_requests - find('.js-design-list-item', match: :first).click - end - - it 'paginates to next design' do - expect(find('.js-previous-design')[:disabled]).to eq('true') - - page.within(find('.js-design-header')) do - expect(page).to have_content('1 of 2') - end - - find('.js-next-design').click - - expect(find('.js-previous-design')[:disabled]).not_to eq('true') - - page.within(find('.js-design-header')) do - expect(page).to have_content('2 of 2') - end - end + before do + enable_design_management + create_list(:design, 2, :with_file, issue: issue) + visit project_issue_path(project, issue) + find('.js-design-list-item', match: :first).click end - context 'design_management_moved flag enabled' do - before do - enable_design_management - create_list(:design, 2, :with_file, issue: issue) - visit project_issue_path(project, issue) - find('.js-design-list-item', match: :first).click - end + it 'paginates to next design' do + expect(find('.js-previous-design')[:disabled]).to eq('true') - it 'paginates to next design' do - expect(find('.js-previous-design')[:disabled]).to eq('true') - - page.within(find('.js-design-header')) do - expect(page).to have_content('1 of 2') - end + page.within(find('.js-design-header')) do + expect(page).to have_content('1 of 2') + end - find('.js-next-design').click + find('.js-next-design').click - expect(find('.js-previous-design')[:disabled]).not_to eq('true') + expect(find('.js-previous-design')[:disabled]).not_to eq('true') - page.within(find('.js-design-header')) do - expect(page).to have_content('2 of 2') - end + page.within(find('.js-design-header')) do + expect(page).to have_content('2 of 2') end end end diff --git a/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb b/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb index 4e45312eac3..cfd8a4540ee 100644 --- a/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb +++ b/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb @@ -8,32 +8,13 @@ RSpec.describe 'User design permissions', :js do let(:project) { create(:project_empty_repo, :public) } let(:issue) { create(:issue, project: project) } - context 'design_management_moved flag disabled' do - before do - enable_design_management - stub_feature_flags(design_management_moved: false) + before do + enable_design_management - visit project_issue_path(project, issue) - - click_link 'Designs' - - wait_for_requests - end - - it 'user does not have permissions to upload design' do - expect(page).not_to have_field('design_file') - end + visit project_issue_path(project, issue) end - context 'design_management_moved flag enabled' do - before do - enable_design_management - - visit project_issue_path(project, issue) - end - - it 'user does not have permissions to upload design' do - expect(page).not_to have_field('design_file') - end + it 'user does not have permissions to upload design' do + expect(page).not_to have_field('design_file') end end diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb index 29a27992a0d..de1fcc9d787 100644 --- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb +++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb @@ -11,81 +11,34 @@ RSpec.describe 'User uploads new design', :js do before do sign_in(user) + enable_design_management(feature_enabled) + visit project_issue_path(project, issue) end - context 'design_management_moved flag disabled' do - before do - enable_design_management(feature_enabled) - stub_feature_flags(design_management_moved: false) - visit project_issue_path(project, issue) + context "when the feature is available" do + let(:feature_enabled) { true } - click_link 'Designs' + it 'uploads designs' do + upload_design(logo_fixture, count: 1) - wait_for_requests - end - - context "when the feature is available" do - let(:feature_enabled) { true } - - it 'uploads designs' do - upload_design(logo_fixture, count: 1) - - expect(page).to have_selector('.js-design-list-item', count: 1) - - within first('#designs-tab .js-design-list-item') do - expect(page).to have_content('dk.png') - end + expect(page).to have_selector('.js-design-list-item', count: 1) - upload_design(gif_fixture, count: 2) - - # Known bug in the legacy implementation: new designs are inserted - # in the beginning on the frontend. - expect(page).to have_selector('.js-design-list-item', count: 2) - expect(page.all('.js-design-list-item').map(&:text)).to eq(['banana_sample.gif', 'dk.png']) + within first('[data-testid="designs-root"] .js-design-list-item') do + expect(page).to have_content('dk.png') end - end - context 'when the feature is not available' do - let(:feature_enabled) { false } + upload_design(gif_fixture, count: 2) - it 'shows the message about requirements' do - expect(page).to have_content("To upload designs, you'll need to enable LFS.") - end + expect(page).to have_selector('.js-design-list-item', count: 2) + expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif']) end end - context 'design_management_moved flag enabled' do - before do - enable_design_management(feature_enabled) - stub_feature_flags(design_management_moved: true) - visit project_issue_path(project, issue) - end - - context "when the feature is available" do - let(:feature_enabled) { true } + context 'when the feature is not available' do + let(:feature_enabled) { false } - it 'uploads designs' do - upload_design(logo_fixture, count: 1) - - expect(page).to have_selector('.js-design-list-item', count: 1) - - within first('[data-testid="designs-root"] .js-design-list-item') do - expect(page).to have_content('dk.png') - end - - upload_design(gif_fixture, count: 2) - - expect(page).to have_selector('.js-design-list-item', count: 2) - expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif']) - end - end - - context 'when the feature is not available' do - let(:feature_enabled) { false } - - it 'shows the message about requirements' do - expect(page).to have_content("To upload designs, you'll need to enable LFS.") - end + it 'shows the message about requirements' do + expect(page).to have_content("To upload designs, you'll need to enable LFS and have admin enable hashed storage.") end end diff --git a/spec/features/projects/issues/design_management/user_views_design_spec.rb b/spec/features/projects/issues/design_management/user_views_design_spec.rb index 49245218e81..b513a4fe3fa 100644 --- a/spec/features/projects/issues/design_management/user_views_design_spec.rb +++ b/spec/features/projects/issues/design_management/user_views_design_spec.rb @@ -9,42 +9,19 @@ RSpec.describe 'User views issue designs', :js do let_it_be(:issue) { create(:issue, project: project) } let_it_be(:design) { create(:design, :with_file, issue: issue) } - context 'design_management_moved flag disabled' do - before do - enable_design_management - stub_feature_flags(design_management_moved: false) + before do + enable_design_management - visit project_issue_path(project, issue) - - click_link 'Designs' - end - - it 'opens design detail' do - click_link design.filename - - page.within(find('.js-design-header')) do - expect(page).to have_content(design.filename) - end - - expect(page).to have_selector('.js-design-image') - end + visit project_issue_path(project, issue) end - context 'design_management_moved flag enabled' do - before do - enable_design_management + it 'opens design detail' do + click_link design.filename - visit project_issue_path(project, issue) + page.within(find('.js-design-header')) do + expect(page).to have_content(design.filename) end - it 'opens design detail' do - click_link design.filename - - page.within(find('.js-design-header')) do - expect(page).to have_content(design.filename) - end - - expect(page).to have_selector('.js-design-image') - end + expect(page).to have_selector('.js-design-image') end end diff --git a/spec/features/projects/issues/design_management/user_views_designs_spec.rb b/spec/features/projects/issues/design_management/user_views_designs_spec.rb index 772a9ffbe6f..46c772027ad 100644 --- a/spec/features/projects/issues/design_management/user_views_designs_spec.rb +++ b/spec/features/projects/issues/design_management/user_views_designs_spec.rb @@ -9,78 +9,37 @@ RSpec.describe 'User views issue designs', :js do let_it_be(:issue) { create(:issue, project: project) } let_it_be(:design) { create(:design, :with_file, issue: issue) } - context 'design_management_moved flag disabled' do - before do - enable_design_management - stub_feature_flags(design_management_moved: false) - end - - context 'navigates from the issue view' do - before do - visit project_issue_path(project, issue) - click_link 'Designs' - wait_for_requests - end - - it 'fetches list of designs' do - expect(page).to have_selector('.js-design-list-item', count: 1) - end - end - - context 'navigates directly to the design collection view' do - before do - visit designs_project_issue_path(project, issue) - end + before do + enable_design_management + end - it 'expands the sidebar' do - expect(page).to have_selector('.layout-page.right-sidebar-expanded') - end + context 'navigates from the issue view' do + before do + visit project_issue_path(project, issue) end - context 'navigates directly to the individual design view' do - before do - visit designs_project_issue_path(project, issue, vueroute: design.filename) - end - - it 'sees the design' do - expect(page).to have_selector('.js-design-detail') - end + it 'fetches list of designs' do + expect(page).to have_selector('.js-design-list-item', count: 1) end end - context 'design_management_moved flag enabled' do + context 'navigates directly to the design collection view' do before do - enable_design_management + visit designs_project_issue_path(project, issue) end - context 'navigates from the issue view' do - before do - visit project_issue_path(project, issue) - end - - it 'fetches list of designs' do - expect(page).to have_selector('.js-design-list-item', count: 1) - end + it 'expands the sidebar' do + expect(page).to have_selector('.layout-page.right-sidebar-expanded') end + end - context 'navigates directly to the design collection view' do - before do - visit designs_project_issue_path(project, issue) - end - - it 'expands the sidebar' do - expect(page).to have_selector('.layout-page.right-sidebar-expanded') - end + context 'navigates directly to the individual design view' do + before do + visit designs_project_issue_path(project, issue, vueroute: design.filename) end - context 'navigates directly to the individual design view' do - before do - visit designs_project_issue_path(project, issue, vueroute: design.filename) - end - - it 'sees the design' do - expect(page).to have_selector('.js-design-detail') - end + it 'sees the design' do + expect(page).to have_selector('.js-design-detail') end end end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 0a6f204454e..404c3e93586 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -373,13 +373,29 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do let(:expire_at) { Time.now + 7.days } context 'when user has ability to update job' do - it 'keeps artifacts when keep button is clicked' do - expect(page).to have_content 'The artifacts will be removed in' + context 'when artifacts are unlocked' do + before do + job.pipeline.unlocked! + end - click_link 'Keep' + it 'keeps artifacts when keep button is clicked' do + expect(page).to have_content 'The artifacts will be removed in' - expect(page).to have_no_link 'Keep' - expect(page).to have_no_content 'The artifacts will be removed in' + click_link 'Keep' + + expect(page).to have_no_link 'Keep' + expect(page).to have_no_content 'The artifacts will be removed in' + end + end + + context 'when artifacts are locked' do + before do + job.pipeline.artifacts_locked! + end + + it 'shows the keep button' do + expect(page).to have_link 'Keep' + end end end @@ -395,9 +411,26 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do context 'when artifacts expired' do let(:expire_at) { Time.now - 7.days } - it 'does not have the Keep button' do - expect(page).to have_content 'The artifacts were removed' - expect(page).not_to have_link 'Keep' + context 'when artifacts are unlocked' do + before do + job.pipeline.unlocked! + end + + it 'does not have the Keep button' do + expect(page).to have_content 'The artifacts were removed' + expect(page).not_to have_link 'Keep' + end + end + + context 'when artifacts are locked' do + before do + job.pipeline.artifacts_locked! + end + + it 'has the Keep button' do + expect(page).not_to have_content 'The artifacts were removed' + expect(page).to have_link 'Keep' + end end end end diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb index 058cbfff662..30e32ad1366 100644 --- a/spec/features/projects/members/invite_group_spec.rb +++ b/spec/features/projects/members/invite_group_spec.rb @@ -112,7 +112,7 @@ RSpec.describe 'Project > Members > Invite group', :js do let!(:group) { create(:group) } around do |example| - Timecop.freeze { example.run } + freeze_time { example.run } end before do diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index dcb901bcf11..07f65fe62df 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -18,6 +18,14 @@ RSpec.describe 'Project navbar' do project.add_maintainer(user) sign_in(user) + + if Gitlab.ee? + insert_after_sub_nav_item( + _('Kubernetes'), + within: _('Operations'), + new_sub_nav_item_name: _('Feature Flags') + ) + end end it_behaves_like 'verified navigation bar' do diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb index e1ace817c72..243579ee2f7 100644 --- a/spec/features/projects/pages_spec.rb +++ b/spec/features/projects/pages_spec.rb @@ -380,14 +380,14 @@ RSpec.shared_examples 'pages settings editing' do expect(project).to be_pages_deployed end - it 'removes the pages' do + it 'removes the pages', :sidekiq_inline do visit project_pages_path(project) expect(page).to have_link('Remove pages') accept_confirm { click_link 'Remove pages' } - expect(page).to have_content('Pages were removed') + expect(page).to have_content('Pages were scheduled for removal') expect(project.reload.pages_deployed?).to be_falsey end end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 26c46190e7d..f59dc5dd074 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -378,7 +378,7 @@ RSpec.describe 'Pipeline', :js do find('.js-tests-tab-link').click expect(page).to have_content('Jobs') - expect(page).to have_selector('.js-tests-detail', visible: :all) + expect(page).to have_selector('[data-testid="tests-detail"]', visible: :all) end end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 8747b3ab54c..a9c196bb84b 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -311,7 +311,7 @@ RSpec.describe 'Pipelines', :js do let!(:delayed_job) do create(:ci_build, :scheduled, pipeline: pipeline, - name: 'delayed job', + name: 'delayed job 1', stage: 'test') end @@ -327,7 +327,7 @@ RSpec.describe 'Pipelines', :js do find('.js-pipeline-dropdown-manual-actions').click time_diff = [0, delayed_job.scheduled_at - Time.now].max - expect(page).to have_button('delayed job') + expect(page).to have_button('delayed job 1') expect(page).to have_content(Time.at(time_diff).utc.strftime("%H:%M:%S")) end @@ -335,7 +335,7 @@ RSpec.describe 'Pipelines', :js do let!(:delayed_job) do create(:ci_build, :expired_scheduled, pipeline: pipeline, - name: 'delayed job', + name: 'delayed job 1', stage: 'test') end @@ -349,7 +349,7 @@ RSpec.describe 'Pipelines', :js do context 'when user played a delayed job immediately' do before do find('.js-pipeline-dropdown-manual-actions').click - page.accept_confirm { click_button('delayed job') } + page.accept_confirm { click_button('delayed job 1') } wait_for_requests end diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb new file mode 100644 index 00000000000..5d05a7e4c91 --- /dev/null +++ b/spec/features/projects/releases/user_creates_release_spec.rb @@ -0,0 +1,147 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'User creates release', :js do + include Spec::Support::Helpers::Features::ReleasesHelpers + + let_it_be(:project) { create(:project, :repository) } + let_it_be(:milestone_1) { create(:milestone, project: project, title: '1.1') } + let_it_be(:milestone_2) { create(:milestone, project: project, title: '1.2') } + let_it_be(:user) { create(:user) } + + let(:new_page_url) { new_project_release_path(project) } + let(:show_feature_flag) { true } + + before do + stub_feature_flags(release_show_page: show_feature_flag) + + project.add_developer(user) + + gitlab_sign_in(user) + + visit new_page_url + + wait_for_requests + end + + it 'renders the breadcrumbs', :aggregate_failures do + within('.breadcrumbs') do + expect(page).to have_content("#{project.creator.name} #{project.name} New Release") + + expect(page).to have_link(project.creator.name, href: user_path(project.creator)) + expect(page).to have_link(project.name, href: project_path(project)) + expect(page).to have_link('New Release', href: new_project_release_path(project)) + end + end + + it 'defaults the "Create from" dropdown to the project\'s default branch' do + expect(page.find('.ref-selector button')).to have_content(project.default_branch) + end + + context 'when the "Save release" button is clicked' do + let(:tag_name) { 'v1.0' } + let(:release_title) { 'A most magnificent release' } + let(:release_notes) { 'Best. Release. **Ever.** :rocket:' } + let(:link_1) { { url: 'https://gitlab.example.com/runbook', title: 'An example runbook', type: 'runbook' } } + let(:link_2) { { url: 'https://gitlab.example.com/other', title: 'An example link', type: 'other' } } + + before do + fill_out_form_and_submit + end + + it 'creates a new release when "Create release" is clicked', :aggregate_failures do + release = project.releases.last + + expect(release.tag).to eq(tag_name) + expect(release.sha).to eq(commit.id) + expect(release.name).to eq(release_title) + expect(release.milestones.first.title).to eq(milestone_1.title) + expect(release.milestones.second.title).to eq(milestone_2.title) + expect(release.description).to eq(release_notes) + expect(release.links.length).to eq(2) + + link = release.links.find { |l| l.link_type == link_1[:type] } + expect(link.url).to eq(link_1[:url]) + expect(link.name).to eq(link_1[:title]) + + link = release.links.find { |l| l.link_type == link_2[:type] } + expect(link.url).to eq(link_2[:url]) + expect(link.name).to eq(link_2[:title]) + end + + it 'redirects to the dedicated page for the newly created release' do + release = project.releases.last + + expect(page).to have_current_path(project_release_path(project, release)) + end + + context 'when the release_show_page feature flag is disabled' do + let(:show_feature_flag) { false } + + it 'redirects to the main "Releases" page' do + expect(page).to have_current_path(project_releases_path(project)) + end + end + end + + context 'when the "Cancel" button is clicked' do + before do + click_link_or_button 'Cancel' + + wait_for_all_requests + end + + it 'redirects to the main "Releases" page' do + expect(page).to have_current_path(project_releases_path(project)) + end + + context 'when the URL includes a back_url query parameter' do + let(:back_path) { project_releases_path(project, params: { page: 2 }) } + let(:new_page_url) do + new_project_release_path(project, params: { back_url: back_path }) + end + + it 'redirects to the page specified with back_url' do + expect(page).to have_current_path(back_path) + end + end + end + + def fill_out_form_and_submit + fill_tag_name(tag_name) + + select_create_from(branch.name) + + fill_release_title(release_title) + + select_milestone(milestone_1.title, and_tab: false) + select_milestone(milestone_2.title) + + # Focus the "Release notes" field by clicking instead of tabbing + # because tabbing to the field requires too many tabs + # (see https://gitlab.com/gitlab-org/gitlab/-/issues/238619) + find_field('Release notes').click + fill_release_notes(release_notes) + + # Tab past the "assets" documentation link + focused_element.send_keys(:tab) + + fill_asset_link(link_1) + add_another_asset_link + fill_asset_link(link_2) + + # Submit using the Control+Enter shortcut + focused_element.send_keys([:control, :enter]) + + wait_for_all_requests + end + + def branch + project.repository.branches.find { |b| b.name == 'feature' } + end + + def commit + branch.dereferenced_target + end +end diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb index 962d5551631..993d3371904 100644 --- a/spec/features/projects/releases/user_views_releases_spec.rb +++ b/spec/features/projects/releases/user_views_releases_spec.rb @@ -13,37 +13,25 @@ RSpec.describe 'User views releases', :js do project.add_guest(guest) end - context('when the user is a maintainer') do - before do - gitlab_sign_in(maintainer) - end - - it 'sees the release' do - visit project_releases_path(project) - - expect(page).to have_content(release.name) - expect(page).to have_content(release.tag) - expect(page).not_to have_content('Upcoming Release') - end - - shared_examples 'asset link tests' do - context 'when there is a link as an asset' do - let!(:release_link) { create(:release_link, release: release, url: url ) } - let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" } - let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release) << release_link.filepath } + shared_examples 'releases page' do + context('when the user is a maintainer') do + before do + gitlab_sign_in(maintainer) + end - it 'sees the link' do - visit project_releases_path(project) + it 'sees the release' do + visit project_releases_path(project) - page.within('.js-assets-list') do - expect(page).to have_link release_link.name, href: direct_asset_link - expect(page).not_to have_css('[data-testid="external-link-indicator"]') - end - end + expect(page).to have_content(release.name) + expect(page).to have_content(release.tag) + expect(page).not_to have_content('Upcoming Release') + end - context 'when there is a link redirect' do - let!(:release_link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) } + shared_examples 'asset link tests' do + context 'when there is a link as an asset' do + let!(:release_link) { create(:release_link, release: release, url: url ) } let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" } + let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release) << release_link.filepath } it 'sees the link' do visit project_releases_path(project) @@ -53,77 +41,103 @@ RSpec.describe 'User views releases', :js do expect(page).not_to have_css('[data-testid="external-link-indicator"]') end end - end - context 'when url points to external resource' do - let(:url) { 'http://google.com/download' } + context 'when there is a link redirect' do + let!(:release_link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) } + let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" } - it 'sees that the link is external resource' do - visit project_releases_path(project) + it 'sees the link' do + visit project_releases_path(project) - page.within('.js-assets-list') do - expect(page).to have_css('[data-testid="external-link-indicator"]') + page.within('.js-assets-list') do + expect(page).to have_link release_link.name, href: direct_asset_link + expect(page).not_to have_css('[data-testid="external-link-indicator"]') + end + end + end + + context 'when url points to external resource' do + let(:url) { 'http://google.com/download' } + + it 'sees that the link is external resource' do + visit project_releases_path(project) + + page.within('.js-assets-list') do + expect(page).to have_css('[data-testid="external-link-indicator"]') + end end end end end - end - context 'when the release_asset_link_type feature flag is enabled' do - before do - stub_feature_flags(release_asset_link_type: true) + context 'when the release_asset_link_type feature flag is enabled' do + before do + stub_feature_flags(release_asset_link_type: true) + end + + it_behaves_like 'asset link tests' end - it_behaves_like 'asset link tests' - end + context 'when the release_asset_link_type feature flag is disabled' do + before do + stub_feature_flags(release_asset_link_type: false) + end - context 'when the release_asset_link_type feature flag is disabled' do - before do - stub_feature_flags(release_asset_link_type: false) + it_behaves_like 'asset link tests' end - it_behaves_like 'asset link tests' - end + context 'with an upcoming release' do + let(:tomorrow) { Time.zone.now + 1.day } + let!(:release) { create(:release, project: project, released_at: tomorrow ) } - context 'with an upcoming release' do - let(:tomorrow) { Time.zone.now + 1.day } - let!(:release) { create(:release, project: project, released_at: tomorrow ) } + it 'sees the upcoming tag' do + visit project_releases_path(project) - it 'sees the upcoming tag' do - visit project_releases_path(project) + expect(page).to have_content('Upcoming Release') + end + end + + context 'with a tag containing a slash' do + it 'sees the release' do + release = create :release, project: project, tag: 'debian/2.4.0-1' + visit project_releases_path(project) - expect(page).to have_content('Upcoming Release') + expect(page).to have_content(release.name) + expect(page).to have_content(release.tag) + end end end - context 'with a tag containing a slash' do - it 'sees the release' do - release = create :release, project: project, tag: 'debian/2.4.0-1' + context('when the user is a guest') do + before do + gitlab_sign_in(guest) + end + + it 'renders release info except for Git-related data' do visit project_releases_path(project) - expect(page).to have_content(release.name) - expect(page).to have_content(release.tag) + within('.release-block') do + expect(page).to have_content(release.description) + + # The following properties (sometimes) include Git info, + # so they are not rendered for Guest users + expect(page).not_to have_content(release.name) + expect(page).not_to have_content(release.tag) + expect(page).not_to have_content(release.commit.short_id) + end end end end - context('when the user is a guest') do + context 'when the graphql_releases_page feature flag is enabled' do + it_behaves_like 'releases page' + end + + context 'when the graphql_releases_page feature flag is disabled' do before do - gitlab_sign_in(guest) + stub_feature_flags(graphql_releases_page: false) end - it 'renders release info except for Git-related data' do - visit project_releases_path(project) - - within('.release-block') do - expect(page).to have_content(release.description) - - # The following properties (sometimes) include Git info, - # so they are not rendered for Guest users - expect(page).not_to have_content(release.name) - expect(page).not_to have_content(release.tag) - expect(page).not_to have_content(release.commit.short_id) - end - end + it_behaves_like 'releases page' end end diff --git a/spec/features/projects/services/user_activates_asana_spec.rb b/spec/features/projects/services/user_activates_asana_spec.rb index 3e24d106be0..e95e7e89fc2 100644 --- a/spec/features/projects/services/user_activates_asana_spec.rb +++ b/spec/features/projects/services/user_activates_asana_spec.rb @@ -12,6 +12,6 @@ RSpec.describe 'User activates Asana' do click_test_then_save_integration - expect(page).to have_content('Asana activated.') + expect(page).to have_content('Asana settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_assembla_spec.rb b/spec/features/projects/services/user_activates_assembla_spec.rb index 2e49f4caa82..63cc424a641 100644 --- a/spec/features/projects/services/user_activates_assembla_spec.rb +++ b/spec/features/projects/services/user_activates_assembla_spec.rb @@ -13,8 +13,8 @@ RSpec.describe 'User activates Assembla' do visit_project_integration('Assembla') fill_in('Token', with: 'verySecret') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('Assembla activated.') + expect(page).to have_content('Assembla settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb index 7b89b9ac4a7..a9d91454670 100644 --- a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb +++ b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb @@ -16,9 +16,9 @@ RSpec.describe 'User activates Atlassian Bamboo CI' do fill_in('Username', with: 'user') fill_in('Password', with: 'verySecret') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('Atlassian Bamboo CI activated.') + expect(page).to have_content('Atlassian Bamboo CI settings saved and active.') # Password field should not be filled in. click_link('Atlassian Bamboo CI') diff --git a/spec/features/projects/services/user_activates_emails_on_push_spec.rb b/spec/features/projects/services/user_activates_emails_on_push_spec.rb index 40947027146..5a075fc61e8 100644 --- a/spec/features/projects/services/user_activates_emails_on_push_spec.rb +++ b/spec/features/projects/services/user_activates_emails_on_push_spec.rb @@ -9,8 +9,8 @@ RSpec.describe 'User activates Emails on push' do visit_project_integration('Emails on push') fill_in('Recipients', with: 'qa@company.name') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('Emails on push activated.') + expect(page).to have_content('Emails on push settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_flowdock_spec.rb b/spec/features/projects/services/user_activates_flowdock_spec.rb index 9581d718400..4a4d7bbecfd 100644 --- a/spec/features/projects/services/user_activates_flowdock_spec.rb +++ b/spec/features/projects/services/user_activates_flowdock_spec.rb @@ -15,8 +15,8 @@ RSpec.describe 'User activates Flowdock' do visit_project_integration('Flowdock') fill_in('Token', with: 'verySecret') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('Flowdock activated.') + expect(page).to have_content('Flowdock settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb index a2820c4bb0f..cffb780e05d 100644 --- a/spec/features/projects/services/user_activates_hipchat_spec.rb +++ b/spec/features/projects/services/user_activates_hipchat_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'User activates HipChat', :js do include_context 'project service activation' - context 'with standart settings' do + context 'with standard settings' do before do stub_request(:post, /.*api.hipchat.com.*/) end @@ -15,9 +15,9 @@ RSpec.describe 'User activates HipChat', :js do fill_in('Room', with: 'gitlab') fill_in('Token', with: 'verySecret') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('HipChat activated.') + expect(page).to have_content('HipChat settings saved and active.') end end @@ -32,9 +32,9 @@ RSpec.describe 'User activates HipChat', :js do fill_in('Token', with: 'secretCustom') fill_in('Server', with: 'https://chat.example.com') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('HipChat activated.') + expect(page).to have_content('HipChat settings saved and active.') end end end diff --git a/spec/features/projects/services/user_activates_irker_spec.rb b/spec/features/projects/services/user_activates_irker_spec.rb index fad40fa6085..e4d92dc30ff 100644 --- a/spec/features/projects/services/user_activates_irker_spec.rb +++ b/spec/features/projects/services/user_activates_irker_spec.rb @@ -10,8 +10,8 @@ RSpec.describe 'User activates Irker (IRC gateway)' do check('Colorize messages') fill_in('Recipients', with: 'irc://chat.freenode.net/#commits') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('Irker (IRC gateway) activated.') + expect(page).to have_content('Irker (IRC gateway) settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb index 4f25794d058..1aec8883395 100644 --- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb +++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'User activates issue tracker', :js do let(:url) { 'http://tracker.example.com' } def fill_form(disable: false, skip_new_issue_url: false) - click_active_toggle if disable + click_active_checkbox if disable fill_in 'service_project_url', with: url fill_in 'service_issues_url', with: "#{url}/:id" @@ -16,7 +16,7 @@ RSpec.describe 'User activates issue tracker', :js do fill_in 'service_new_issue_url', with: url unless skip_new_issue_url end - shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false| + shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false, skip_test: false| describe 'user sets and activates the Service' do context 'when the connection test succeeds' do before do @@ -25,11 +25,15 @@ RSpec.describe 'User activates issue tracker', :js do visit_project_integration(tracker) fill_form(skip_new_issue_url: skip_new_issue_url) - click_test_integration + if skip_test + click_save_integration + else + click_test_then_save_integration(expect_test_to_fail: false) + end end it 'activates the service' do - expect(page).to have_content("#{tracker} activated.") + expect(page).to have_content("#{tracker} settings saved and active.") expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_'))) end @@ -47,9 +51,13 @@ RSpec.describe 'User activates issue tracker', :js do visit_project_integration(tracker) fill_form(skip_new_issue_url: skip_new_issue_url) - click_test_then_save_integration + if skip_test + click_button('Save changes') + else + click_test_then_save_integration + end - expect(page).to have_content("#{tracker} activated.") + expect(page).to have_content("#{tracker} settings saved and active.") expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_'))) end end @@ -64,7 +72,7 @@ RSpec.describe 'User activates issue tracker', :js do end it 'saves but does not activate the service' do - expect(page).to have_content("#{tracker} settings saved, but not activated.") + expect(page).to have_content("#{tracker} settings saved, but not active.") expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_'))) end @@ -80,4 +88,5 @@ RSpec.describe 'User activates issue tracker', :js do it_behaves_like 'external issue tracker activation', tracker: 'YouTrack', skip_new_issue_url: true it_behaves_like 'external issue tracker activation', tracker: 'Bugzilla' it_behaves_like 'external issue tracker activation', tracker: 'Custom Issue Tracker' + it_behaves_like 'external issue tracker activation', tracker: 'EWM', skip_test: true end diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb index 8ee369eb6ec..72881054c6c 100644 --- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb +++ b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb @@ -18,8 +18,8 @@ RSpec.describe 'User activates JetBrains TeamCity CI' do fill_in('Username', with: 'user') fill_in('Password', with: 'verySecret') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('JetBrains TeamCity CI activated.') + expect(page).to have_content('JetBrains TeamCity CI settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_jira_spec.rb b/spec/features/projects/services/user_activates_jira_spec.rb index 483671c4b5b..85afc54be48 100644 --- a/spec/features/projects/services/user_activates_jira_spec.rb +++ b/spec/features/projects/services/user_activates_jira_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'User activates Jira', :js do include_context 'project service activation' include_context 'project service Jira context' - describe 'user sets and activates Jira Service' do + describe 'user tests Jira Service' do context 'when Jira connection test succeeds' do before do server_info = { key: 'value' }.to_json @@ -14,11 +14,11 @@ RSpec.describe 'User activates Jira', :js do visit_project_integration('Jira') fill_form - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) end it 'activates the Jira service' do - expect(page).to have_content('Jira activated.') + expect(page).to have_content('Jira settings saved and active.') expect(current_path).to eq(edit_project_service_path(project, :jira)) end @@ -54,21 +54,24 @@ RSpec.describe 'User activates Jira', :js do fill_form click_test_then_save_integration - expect(page).to have_content('Jira activated.') + expect(page).to have_content('Jira settings saved and active.') expect(current_path).to eq(edit_project_service_path(project, :jira)) end end end describe 'user disables the Jira Service' do + include JiraServiceHelper + before do + stub_jira_service_test visit_project_integration('Jira') fill_form(disable: true) - click_button('Save changes') + click_save_integration end it 'saves but does not activate the Jira service' do - expect(page).to have_content('Jira settings saved, but not activated.') + expect(page).to have_content('Jira settings saved, but not active.') expect(current_path).to eq(edit_project_service_path(project, :jira)) 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 6ddffb710a8..32519b14d4e 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 @@ -28,21 +28,21 @@ RSpec.describe 'Set up Mattermost slash commands', :js do token = ('a'..'z').to_a.join fill_in 'service_token', with: token - click_active_toggle - click_on 'Save changes' + click_active_checkbox + click_save_integration expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands)) - expect(page).to have_content('Mattermost slash commands settings saved, but not activated.') + expect(page).to have_content('Mattermost slash commands settings saved, but not active.') end it 'redirects to the integrations page after activating' do token = ('a'..'z').to_a.join fill_in 'service_token', with: token - click_on 'Save changes' + click_save_integration expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands)) - expect(page).to have_content('Mattermost slash commands activated.') + expect(page).to have_content('Mattermost slash commands settings saved and active.') end it 'shows the add to mattermost button' do diff --git a/spec/features/projects/services/user_activates_packagist_spec.rb b/spec/features/projects/services/user_activates_packagist_spec.rb index 70cf612bb2a..87303cf8fb4 100644 --- a/spec/features/projects/services/user_activates_packagist_spec.rb +++ b/spec/features/projects/services/user_activates_packagist_spec.rb @@ -16,6 +16,6 @@ RSpec.describe 'User activates Packagist' do click_test_then_save_integration - expect(page).to have_content('Packagist activated.') + expect(page).to have_content('Packagist settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb b/spec/features/projects/services/user_activates_pivotaltracker_spec.rb index 8e99c6e303b..83f66d4fa7b 100644 --- a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb +++ b/spec/features/projects/services/user_activates_pivotaltracker_spec.rb @@ -13,8 +13,8 @@ RSpec.describe 'User activates PivotalTracker' do visit_project_integration('PivotalTracker') fill_in('Token', with: 'verySecret') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('PivotalTracker activated.') + expect(page).to have_content('PivotalTracker settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_prometheus_spec.rb b/spec/features/projects/services/user_activates_prometheus_spec.rb index 89b1f447c32..b89e89d250f 100644 --- a/spec/features/projects/services/user_activates_prometheus_spec.rb +++ b/spec/features/projects/services/user_activates_prometheus_spec.rb @@ -16,7 +16,7 @@ RSpec.describe 'User activates Prometheus' do click_button('Save changes') - expect(page).not_to have_content('Prometheus activated.') + expect(page).not_to have_content('Prometheus settings saved and active.') expect(page).to have_content('Fields on this page has been deprecated.') end end diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/services/user_activates_pushover_spec.rb index 789cc30a42e..3cfd069032a 100644 --- a/spec/features/projects/services/user_activates_pushover_spec.rb +++ b/spec/features/projects/services/user_activates_pushover_spec.rb @@ -17,8 +17,8 @@ RSpec.describe 'User activates Pushover' do select('High Priority', from: 'Priority') select('Bike', from: 'Sound') - click_test_integration + click_test_then_save_integration(expect_test_to_fail: false) - expect(page).to have_content('Pushover activated.') + expect(page).to have_content('Pushover settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/services/user_activates_slack_notifications_spec.rb index 20e2bd3f085..2a880e05e0f 100644 --- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb +++ b/spec/features/projects/services/user_activates_slack_notifications_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'User activates Slack notifications', :js do click_test_then_save_integration - expect(page).to have_content('Slack notifications activated.') + expect(page).to have_content('Slack notifications settings saved and active.') end end diff --git a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb index afe6855d6ad..3994f55caee 100644 --- a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb +++ b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb @@ -21,11 +21,11 @@ RSpec.describe 'Slack slash commands', :js do it 'redirects to the integrations page after saving but not activating' do fill_in 'Token', with: 'token' - click_active_toggle + click_active_checkbox click_on 'Save' expect(current_path).to eq(edit_project_service_path(project, :slack_slash_commands)) - expect(page).to have_content('Slack slash commands settings saved, but not activated.') + expect(page).to have_content('Slack slash commands settings saved, but not active.') end it 'redirects to the integrations page after activating' do @@ -33,7 +33,7 @@ RSpec.describe 'Slack slash commands', :js do click_on 'Save' expect(current_path).to eq(edit_project_service_path(project, :slack_slash_commands)) - expect(page).to have_content('Slack slash commands activated.') + expect(page).to have_content('Slack slash commands settings saved and active.') end it 'shows the correct trigger url' do diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb index 8beecedf85f..8c7b7bc70a2 100644 --- a/spec/features/projects/settings/repository_settings_spec.rb +++ b/spec/features/projects/settings/repository_settings_spec.rb @@ -70,7 +70,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do project.deploy_keys << private_deploy_key visit project_settings_repository_path(project) - find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click + find('.deploy-key', text: private_deploy_key.title).find('[data-testid="pencil-icon"]').click fill_in 'deploy_key_title', with: 'updated_deploy_key' check 'deploy_key_deploy_keys_projects_attributes_0_can_push' @@ -84,7 +84,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do project.deploy_keys << public_deploy_key visit project_settings_repository_path(project) - find('.deploy-key', text: public_deploy_key.title).find('.ic-pencil').click + find('.deploy-key', text: public_deploy_key.title).find('[data-testid="pencil-icon"]').click check 'deploy_key_deploy_keys_projects_attributes_0_can_push' click_button 'Save changes' @@ -102,7 +102,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do find('.js-deployKeys-tab-available_project_keys').click - find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click + find('.deploy-key', text: private_deploy_key.title).find('[data-testid="pencil-icon"]').click fill_in 'deploy_key_title', with: 'updated_deploy_key' click_button 'Save changes' @@ -116,7 +116,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do project.deploy_keys << private_deploy_key visit project_settings_repository_path(project) - accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click } + accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('[data-testid="remove-icon"]').click } expect(page).not_to have_content(private_deploy_key.title) end diff --git a/spec/features/projects/settings/user_renames_a_project_spec.rb b/spec/features/projects/settings/user_renames_a_project_spec.rb index 6088ea31661..1ff976eb800 100644 --- a/spec/features/projects/settings/user_renames_a_project_spec.rb +++ b/spec/features/projects/settings/user_renames_a_project_spec.rb @@ -37,7 +37,7 @@ RSpec.describe 'Projects > Settings > User renames a project' do it 'shows errors for invalid project path' do change_path(project, 'foo&bar') - expect(page).to have_field 'Path', with: 'foo&bar' + expect(page).to have_field 'Path', with: 'gitlab' expect(page).to have_content "Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'" end end diff --git a/spec/features/projects/show/user_sees_readme_spec.rb b/spec/features/projects/show/user_sees_readme_spec.rb index 250f707948e..6a5b9472be8 100644 --- a/spec/features/projects/show/user_sees_readme_spec.rb +++ b/spec/features/projects/show/user_sees_readme_spec.rb @@ -14,4 +14,25 @@ RSpec.describe 'Projects > Show > User sees README' do expect(page).to have_content 'testme' end end + + context 'obeying robots.txt' do + before do + Gitlab::Testing::RobotsBlockerMiddleware.block_requests! + end + + after do + Gitlab::Testing::RobotsBlockerMiddleware.allow_requests! + end + + # For example, see this regression we had in + # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39520 + it 'does not block the requests necessary to load the project README', :js do + visit project_path(project) + wait_for_requests + + page.within('.readme-holder') do + expect(page).to have_content 'testme' + end + end + end end diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb index afa9de5ce86..81736fefae9 100644 --- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb +++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb @@ -226,7 +226,7 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do expect(project.repository.gitlab_ci_yml).to be_nil page.within('.project-buttons') do - expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_path) + expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_ide_path) end end diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb index 3db870f229a..503246bbdcf 100644 --- a/spec/features/projects/snippets/create_snippet_spec.rb +++ b/spec/features/projects/snippets/create_snippet_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Snippets > Create Snippet', :js do include DropzoneHelper + include Spec::Support::Helpers::Features::SnippetSpecHelpers let_it_be(:user) { create(:user) } let_it_be(:project) do @@ -16,96 +17,115 @@ RSpec.describe 'Projects > Snippets > Create Snippet', :js do let(:file_content) { 'Hello World!' } let(:md_description) { 'My Snippet **Description**' } let(:description) { 'My Snippet Description' } + let(:snippet_title_field) { 'project_snippet_title' } - before do - stub_feature_flags(snippets_vue: false) - stub_feature_flags(snippets_edit_vue: false) + shared_examples 'snippet creation' do + def fill_form + snippet_fill_in_form(title: title, content: file_content, description: md_description) + end - sign_in(user) + it 'shows collapsible description input' do + collapsed = description_field - visit new_project_snippet_path(project) - end + expect(page).not_to have_field(snippet_description_field) + expect(collapsed).to be_visible - def description_field - find('.js-description-input').find('input,textarea') - end + collapsed.click - def fill_form - fill_in 'project_snippet_title', with: title + expect(page).to have_field(snippet_description_field) + expect(collapsed).not_to be_visible + end - # Click placeholder first to expand full description field - description_field.click - fill_in 'project_snippet_description', with: md_description + it 'creates a new snippet' do + fill_form + click_button('Create snippet') + wait_for_requests - page.within('.file-editor') do - el = find('.inputarea') - el.send_keys file_content + expect(page).to have_content(title) + expect(page).to have_content(file_content) + page.within(snippet_description_view_selector) do + expect(page).to have_content(description) + expect(page).to have_selector('strong') + end end - end - it 'shows collapsible description input' do - collapsed = description_field + it 'uploads a file when dragging into textarea' do + fill_form + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') - expect(page).not_to have_field('project_snippet_description') - expect(collapsed).to be_visible + expect(snippet_description_value).to have_content('banana_sample') - collapsed.click + click_button('Create snippet') + wait_for_requests - expect(page).to have_field('project_snippet_description') - expect(collapsed).not_to be_visible - end + link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z}) + end + + context 'when the git operation fails' do + let(:error) { 'Error creating the snippet' } - it 'creates a new snippet' do - fill_form - click_button('Create snippet') - wait_for_requests + before do + allow_next_instance_of(Snippets::CreateService) do |instance| + allow(instance).to receive(:create_commit).and_raise(StandardError, error) + end - expect(page).to have_content(title) - expect(page).to have_content(file_content) - page.within('.snippet-header .description') do - expect(page).to have_content(description) - expect(page).to have_selector('strong') + fill_form + + click_button('Create snippet') + wait_for_requests + end + + it 'renders the new page and displays the error' do + expect(page).to have_content(error) + expect(page).to have_content('New Snippet') + end end end - it 'uploads a file when dragging into textarea' do - fill_form - dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + context 'Vue application' do + let(:snippet_description_field) { 'snippet-description' } + let(:snippet_description_view_selector) { '.snippet-header .snippet-description' } - expect(page.find_field('project_snippet_description').value).to have_content('banana_sample') + before do + sign_in(user) + + visit new_project_snippet_path(project) + end - click_button('Create snippet') - wait_for_requests + it_behaves_like 'snippet creation' - link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] - expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z}) - end + it 'does not allow submitting the form without title and content' do + fill_in snippet_title_field, with: title - it 'displays validation errors' do - fill_in 'project_snippet_title', with: title - click_button('Create snippet') - wait_for_requests + expect(page).not_to have_button('Create snippet') - expect(page).to have_selector('#error_explanation') + snippet_fill_in_form(title: title, content: file_content) + expect(page).to have_button('Create snippet') + end end - context 'when the git operation fails' do - let(:error) { 'Error creating the snippet' } + context 'non-Vue application' do + let(:snippet_description_field) { 'project_snippet_description' } + let(:snippet_description_view_selector) { '.snippet-header .description' } before do - allow_next_instance_of(Snippets::CreateService) do |instance| - allow(instance).to receive(:create_commit).and_raise(StandardError, error) - end + stub_feature_flags(snippets_vue: false) + stub_feature_flags(snippets_edit_vue: false) - fill_form + sign_in(user) + visit new_project_snippet_path(project) + end + + it_behaves_like 'snippet creation' + + it 'displays validation errors' do + fill_in snippet_title_field, with: title click_button('Create snippet') wait_for_requests - end - it 'renders the new page and displays the error' do - expect(page).to have_content(error) - expect(page).to have_content('New Snippet') + expect(page).to have_selector('#error_explanation') end end end diff --git a/spec/features/projects/snippets/user_updates_snippet_spec.rb b/spec/features/projects/snippets/user_updates_snippet_spec.rb index a40113bd93e..193eaa9576a 100644 --- a/spec/features/projects/snippets/user_updates_snippet_spec.rb +++ b/spec/features/projects/snippets/user_updates_snippet_spec.rb @@ -3,57 +3,81 @@ require 'spec_helper' RSpec.describe 'Projects > Snippets > User updates a snippet', :js do + include Spec::Support::Helpers::Features::SnippetSpecHelpers + let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, namespace: user.namespace) } let_it_be(:snippet, reload: true) { create(:project_snippet, :repository, project: project, author: user) } - before do - stub_feature_flags(snippets_vue: false) - stub_feature_flags(snippets_edit_vue: false) + let(:snippet_title_field) { 'project_snippet_title' } + def bootstrap_snippet project.add_maintainer(user) sign_in(user) - visit(project_snippet_path(project, snippet)) + page.visit(edit_project_snippet_path(project, snippet)) - page.within('.detail-page-header') do - first(:link, 'Edit').click - end wait_for_all_requests end - it 'displays the snippet blob path and content' do - blob = snippet.blobs.first + shared_examples 'snippet update' do + it 'displays the snippet blob path and content' do + blob = snippet.blobs.first - aggregate_failures do - expect(page.find_field('project_snippet_file_name').value).to eq blob.path - expect(page.find('.file-content')).to have_content(blob.data.strip) - expect(page.find('.snippet-file-content', visible: false).value).to eq blob.data + aggregate_failures do + expect(snippet_get_first_blob_path).to eq blob.path + expect(snippet_get_first_blob_value).to have_content(blob.data.strip) + end end - end - it 'updates a snippet' do - fill_in('project_snippet_title', with: 'Snippet new title') - click_button('Save') + it 'updates a snippet' do + fill_in('project_snippet_title', with: 'Snippet new title') + click_button('Save') + + expect(page).to have_content('Snippet new title') + end + + context 'when the git operation fails' do + before do + allow_next_instance_of(Snippets::UpdateService) do |instance| + allow(instance).to receive(:create_commit).and_raise(StandardError, 'Error Message') + end + + fill_in(snippet_title_field, with: 'Snippet new title') + fill_in(snippet_blob_path_field, match: :first, with: 'new_file_name') + + click_button('Save') + end - expect(page).to have_content('Snippet new title') + it 'renders edit page and displays the error' do + expect(page.find('.flash-container')).to have_content('Error updating the snippet - Error Message') + expect(page).to have_content('Edit Snippet') + end + end end - context 'when the git operation fails' do + context 'Vue application' do before do - allow_next_instance_of(Snippets::UpdateService) do |instance| - allow(instance).to receive(:create_commit).and_raise(StandardError, 'Error Message') - end + bootstrap_snippet + end - fill_in('project_snippet_title', with: 'Snippet new title') - fill_in('project_snippet_file_name', with: 'new_file_name') + it_behaves_like 'snippet update' do + let(:snippet_blob_path_field) { 'snippet_file_name' } + let(:snippet_blob_content_selector) { '.file-content' } + end + end - click_button('Save') + context 'non-Vue application' do + before do + stub_feature_flags(snippets_vue: false) + stub_feature_flags(snippets_edit_vue: false) + + bootstrap_snippet end - it 'renders edit page and displays the error' do - expect(page.find('.flash-container span').text).to eq('Error updating the snippet - Error Message') - expect(page).to have_content('Edit Snippet') + it_behaves_like 'snippet update' do + let(:snippet_blob_path_field) { 'project_snippet_file_name' } + let(:snippet_blob_content_selector) { '.file-content' } end end end diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb index 1d443e0b339..50d7b353c46 100644 --- a/spec/features/projects/user_sees_sidebar_spec.rb +++ b/spec/features/projects/user_sees_sidebar_spec.rb @@ -6,10 +6,6 @@ RSpec.describe 'Projects > User sees sidebar' do let(:user) { create(:user) } let(:project) { create(:project, :private, public_builds: false, namespace: user.namespace) } - before do - stub_feature_flags(vue_issuables_list: false) - end - # NOTE: See documented behaviour https://design.gitlab.com/regions/navigation#contextual-navigation context 'on different viewports', :js do include MobileHelpers @@ -134,6 +130,7 @@ RSpec.describe 'Projects > User sees sidebar' do context 'as guest' do let(:guest) { create(:user) } + let!(:issue) { create(:issue, :opened, project: project, author: guest) } before do project.add_guest(guest) diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb index 6f78f888c12..d220db01c24 100644 --- a/spec/features/projects/view_on_env_spec.rb +++ b/spec/features/projects/view_on_env_spec.rb @@ -9,8 +9,6 @@ RSpec.describe 'View on environment', :js do let(:user) { project.creator } before do - stub_feature_flags(diffs_batch_load: false) - project.add_maintainer(user) end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb index 8eba2c98595..8f2fb9e827c 100644 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Projects > Wiki > User previews markdown changes', :js do let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') } let(:wiki_content) do <<-HEREDOC +Some text so key event for [ does not trigger an incorrect replacement. [regular link](regular) [relative link 1](../relative) [relative link 2](./relative) |