diff options
Diffstat (limited to 'spec/features/projects')
30 files changed, 695 insertions, 628 deletions
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb index 9fe3f4cd63e..489a90cc8fc 100644 --- a/spec/features/projects/commit/cherry_pick_spec.rb +++ b/spec/features/projects/commit/cherry_pick_spec.rb @@ -2,108 +2,126 @@ require 'spec_helper' -RSpec.describe 'Cherry-pick Commits' do - let(:user) { create(:user) } - let(:group) { create(:group) } - let(:project) { create(:project, :repository, namespace: group) } - let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') } - let(:master_pickable_merge) { project.commit('e56497bb5f03a90a51293fc6d516788730953899') } +RSpec.describe 'Cherry-pick Commits', :js do + let_it_be(:user) { create(:user) } + let_it_be(:sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' } + let!(:project) { create_default(:project, :repository, namespace: user.namespace) } + let(:master_pickable_commit) { project.commit(sha) } before do sign_in(user) - project.add_maintainer(user) - visit project_commit_path(project, master_pickable_commit.id) end - context "I cherry-pick a commit" do - it do - find("a[href='#modal-cherry-pick-commit']").click - expect(page).not_to have_content('v1.0.0') # Only branches, not tags - page.within('#modal-cherry-pick-commit') do - uncheck 'create_merge_request' - click_button 'Cherry-pick' - end - expect(page).to have_content('The commit has been successfully cherry-picked into master.') - end - end + context 'when clicking cherry-pick from the dropdown for a commit on pipelines tab' do + it 'launches the modal form' do + create(:ci_empty_pipeline, sha: sha) + visit project_commit_path(project, master_pickable_commit.id) + click_link 'Pipelines' - context "I cherry-pick a merge commit" do - it do - find("a[href='#modal-cherry-pick-commit']").click - page.within('#modal-cherry-pick-commit') do - uncheck 'create_merge_request' - click_button 'Cherry-pick' + open_modal + + page.within(modal_selector) do + expect(page).to have_content('Cherry-pick this commit') end - expect(page).to have_content('The commit has been successfully cherry-picked into master.') end end - context "I cherry-pick a commit that was previously cherry-picked" do - it do - find("a[href='#modal-cherry-pick-commit']").click - page.within('#modal-cherry-pick-commit') do - uncheck 'create_merge_request' - click_button 'Cherry-pick' - end + context 'when starting from the commit tab' do + before do visit project_commit_path(project, master_pickable_commit.id) - find("a[href='#modal-cherry-pick-commit']").click - page.within('#modal-cherry-pick-commit') do - uncheck 'create_merge_request' - click_button 'Cherry-pick' - end - expect(page).to have_content('Sorry, we cannot cherry-pick this commit automatically.') end - end - context "I cherry-pick a commit in a new merge request", :js do - it do - find('.header-action-buttons a.dropdown-toggle').click - find("a[href='#modal-cherry-pick-commit']").click - page.within('#modal-cherry-pick-commit') do - click_button 'Cherry-pick' + context 'when cherry-picking a commit' do + specify do + cherry_pick_commit + + expect(page).to have_content('The commit has been successfully cherry-picked into master.') end + end - wait_for_requests + context 'when cherry-picking a merge commit' do + specify do + cherry_pick_commit - expect(page).to have_content("The commit has been successfully cherry-picked into cherry-pick-#{master_pickable_commit.short_id}. You can now submit a merge request to get this change into the original branch.") - expect(page).to have_content("From cherry-pick-#{master_pickable_commit.short_id} into master") + expect(page).to have_content('The commit has been successfully cherry-picked into master.') + end end - end - context "I cherry-pick a commit from a different branch", :js do - it do - find('.header-action-buttons a.dropdown-toggle').click - find(:css, "a[href='#modal-cherry-pick-commit']").click + context 'when cherry-picking a commit that was previously cherry-picked' do + specify do + cherry_pick_commit - page.within('#modal-cherry-pick-commit') do - click_button 'master' + visit project_commit_path(project, master_pickable_commit.id) + + cherry_pick_commit + + expect(page).to have_content('Sorry, we cannot cherry-pick this commit automatically.') end + end - wait_for_requests + context 'when cherry-picking a commit in a new merge request' do + specify do + cherry_pick_commit(create_merge_request: true) - page.within('#modal-cherry-pick-commit .dropdown-menu') do - find('.dropdown-input input').set('feature') - wait_for_requests - click_link "feature" + expect(page).to have_content("The commit has been successfully cherry-picked into cherry-pick-#{master_pickable_commit.short_id}. You can now submit a merge request to get this change into the original branch.") + expect(page).to have_content("From cherry-pick-#{master_pickable_commit.short_id} into master") end + end - page.within('#modal-cherry-pick-commit') do - uncheck 'create_merge_request' - click_button 'Cherry-pick' + context 'when I cherry-picking a commit from a different branch' do + specify do + open_modal + + page.within(modal_selector) do + click_button 'master' + end + + page.within("#{modal_selector} .dropdown-menu") do + find('[data-testid="dropdown-search-box"]').set('feature') + wait_for_requests + click_button 'feature' + end + + submit_cherry_pick + + expect(page).to have_content('The commit has been successfully cherry-picked into feature.') end + end + + context 'when the project is archived' do + let(:project) { create(:project, :repository, :archived, namespace: user.namespace) } - expect(page).to have_content('The commit has been successfully cherry-picked into feature.') + it 'does not show the cherry-pick link' do + open_dropdown + + expect(page).not_to have_text("Cherry-pick") + end end end - context 'when the project is archived' do - let(:project) { create(:project, :repository, :archived, namespace: group) } + def cherry_pick_commit(create_merge_request: false) + open_modal - it 'does not show the cherry-pick link' do - find('.header-action-buttons a.dropdown-toggle').click + submit_cherry_pick(create_merge_request: create_merge_request) + end + + def open_dropdown + find('.header-action-buttons .dropdown').click + end - expect(page).not_to have_text("Cherry-pick") - expect(page).not_to have_css("a[href='#modal-cherry-pick-commit']") + def open_modal + open_dropdown + find('[data-testid="cherry-pick-commit-link"]').click + end + + def submit_cherry_pick(create_merge_request: false) + page.within(modal_selector) do + uncheck('create_merge_request') unless create_merge_request + click_button('Cherry-pick') end end + + def modal_selector + '[data-testid="modal-commit"]' + end end diff --git a/spec/features/projects/commit/user_reverts_commit_spec.rb b/spec/features/projects/commit/user_reverts_commit_spec.rb index f3c364dab97..72c639a027e 100644 --- a/spec/features/projects/commit/user_reverts_commit_spec.rb +++ b/spec/features/projects/commit/user_reverts_commit_spec.rb @@ -6,58 +6,89 @@ RSpec.describe 'User reverts a commit', :js do include RepoHelpers let_it_be(:user) { create(:user) } - let(:project) { create(:project, :repository, namespace: user.namespace) } + let!(:project) { create_default(:project, :repository, namespace: user.namespace) } before do sign_in(user) - - visit(project_commit_path(project, sample_commit.id)) end - def revert_commit(create_merge_request: false) - find('.header-action-buttons .dropdown').click - find('[data-testid="revert-commit-link"]').click + context 'when clicking revert from the dropdown for a commit on pipelines tab' do + it 'launches the modal and is able to submit the revert' do + sha = '7d3b0f7cff5f37573aea97cebfd5692ea1689924' + create(:ci_empty_pipeline, sha: sha) + visit project_commit_path(project, project.commit(sha).id) + click_link 'Pipelines' - page.within('[data-testid="modal-commit"]') do - uncheck('create_merge_request') unless create_merge_request - click_button('Revert') + open_modal + + page.within(modal_selector) do + expect(page).to have_content('Revert this commit') + end end end - context 'without creating a new merge request' do - it 'reverts a commit' do - revert_commit + context 'when starting from the commit tab' do + before do + visit project_commit_path(project, sample_commit.id) + end + + context 'without creating a new merge request' do + it 'reverts a commit' do + revert_commit + + expect(page).to have_content('The commit has been successfully reverted.') + end + + it 'does not revert a previously reverted commit' do + revert_commit + # Visit the comment again once it was reverted. + visit project_commit_path(project, sample_commit.id) + + revert_commit - expect(page).to have_content('The commit has been successfully reverted.') + expect(page).to have_content('Sorry, we cannot revert this commit automatically.') + end end - it 'does not revert a previously reverted commit' do - revert_commit - # Visit the comment again once it was reverted. - visit project_commit_path(project, sample_commit.id) + context 'with creating a new merge request' do + it 'reverts a commit' do + revert_commit(create_merge_request: true) + + expect(page).to have_content('The commit has been successfully reverted. You can now submit a merge request to get this change into the original branch.') + expect(page).to have_content("From revert-#{Commit.truncate_sha(sample_commit.id)} into master") + end + end - revert_commit + context 'when the project is archived' do + let(:project) { create(:project, :repository, :archived, namespace: user.namespace) } - expect(page).to have_content('Sorry, we cannot revert this commit automatically.') + it 'does not show the revert link' do + open_dropdown + + expect(page).not_to have_link('Revert') + end end end - context 'with creating a new merge request' do - it 'reverts a commit' do - revert_commit(create_merge_request: true) + def revert_commit(create_merge_request: false) + open_modal - expect(page).to have_content('The commit has been successfully reverted. You can now submit a merge request to get this change into the original branch.') - expect(page).to have_content("From revert-#{Commit.truncate_sha(sample_commit.id)} into master") + page.within(modal_selector) do + uncheck('create_merge_request') unless create_merge_request + click_button('Revert') end end - context 'when the project is archived' do - let(:project) { create(:project, :repository, :archived, namespace: user.namespace) } + def open_dropdown + find('.header-action-buttons .dropdown').click + end - it 'does not show the revert link' do - find('.header-action-buttons .dropdown').click + def open_modal + open_dropdown + find('[data-testid="revert-commit-link"]').click + end - expect(page).not_to have_link('Revert') - end + def modal_selector + '[data-testid="modal-commit"]' end end diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb index 596b4773716..4894e2b7f3e 100644 --- a/spec/features/projects/commits/user_browses_commits_spec.rb +++ b/spec/features/projects/commits/user_browses_commits_spec.rb @@ -203,10 +203,11 @@ RSpec.describe 'User browses commits' do context 'when click the compare tab' do before do + wait_for_requests click_link('Compare') end - it 'does not render create merge request button' do + it 'does not render create merge request button', :js do expect(page).not_to have_link 'Create merge request' end end @@ -236,10 +237,11 @@ RSpec.describe 'User browses commits' do context 'when click the compare tab' do before do + wait_for_requests click_link('Compare') end - it 'renders create merge request button' do + it 'renders create merge request button', :js do expect(page).to have_link 'Create merge request' end end @@ -276,10 +278,11 @@ RSpec.describe 'User browses commits' do context 'when click the compare tab' do before do + wait_for_requests click_link('Compare') end - it 'renders button to the merge request' do + it 'renders button to the merge request', :js do expect(page).not_to have_link 'Create merge request' expect(page).to have_link 'View open merge request', href: project_merge_request_path(project, merge_request) end diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb index e387ea4d473..64e9968061c 100644 --- a/spec/features/projects/compare_spec.rb +++ b/spec/features/projects/compare_spec.rb @@ -17,10 +17,10 @@ RSpec.describe "Compare", :js do visit project_compare_index_path(project, from: 'master', to: 'master') select_using_dropdown 'from', 'feature' - expect(find('.js-compare-from-dropdown .dropdown-toggle-text')).to have_content('feature') + expect(find('.js-compare-from-dropdown .gl-new-dropdown-button-text')).to have_content('feature') select_using_dropdown 'to', 'binary-encoding' - expect(find('.js-compare-to-dropdown .dropdown-toggle-text')).to have_content('binary-encoding') + expect(find('.js-compare-to-dropdown .gl-new-dropdown-button-text')).to have_content('binary-encoding') click_button 'Compare' @@ -32,8 +32,8 @@ RSpec.describe "Compare", :js do it "pre-populates fields" do visit project_compare_index_path(project, from: "master", to: "master") - expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("master") - expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("master") + expect(find(".js-compare-from-dropdown .gl-new-dropdown-button-text")).to have_content("master") + expect(find(".js-compare-to-dropdown .gl-new-dropdown-button-text")).to have_content("master") end it_behaves_like 'compares branches' @@ -99,7 +99,7 @@ RSpec.describe "Compare", :js do find(".js-compare-from-dropdown .compare-dropdown-toggle").click - expect(find(".js-compare-from-dropdown .dropdown-content")).to have_selector("li", count: 3) + expect(find(".js-compare-from-dropdown .gl-new-dropdown-contents")).to have_selector('li.gl-new-dropdown-item', count: 1) end context 'when commit has overflow', :js do @@ -125,10 +125,10 @@ RSpec.describe "Compare", :js do visit project_compare_index_path(project, from: "master", to: "master") select_using_dropdown "from", "v1.0.0" - expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("v1.0.0") + expect(find(".js-compare-from-dropdown .gl-new-dropdown-button-text")).to have_content("v1.0.0") select_using_dropdown "to", "v1.1.0" - expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("v1.1.0") + expect(find(".js-compare-to-dropdown .gl-new-dropdown-button-text")).to have_content("v1.1.0") click_button "Compare" expect(page).to have_content "Commits" @@ -136,19 +136,22 @@ RSpec.describe "Compare", :js do end def select_using_dropdown(dropdown_type, selection, commit: false) + wait_for_requests + dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click # find input before using to wait for the inputs visibility dropdown.find('.dropdown-menu') dropdown.fill_in("Filter by Git revision", with: selection) + wait_for_requests if commit - dropdown.find('input[type="search"]').send_keys(:return) + dropdown.find('.gl-search-box-by-type-input').send_keys(:return) else # find before all to wait for the items visibility - dropdown.find("a[data-ref=\"#{selection}\"]", match: :first) - dropdown.all("a[data-ref=\"#{selection}\"]").last.click + dropdown.find(".js-compare-#{dropdown_type}-dropdown .dropdown-item", text: selection, match: :first) + dropdown.all(".js-compare-#{dropdown_type}-dropdown .dropdown-item", text: selection).first.click end end end diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb index 17258f7042f..40d19a94b42 100644 --- a/spec/features/projects/files/dockerfile_dropdown_spec.rb +++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb @@ -2,14 +2,16 @@ require 'spec_helper' -RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297400' do +RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do + include Spec::Support::Helpers::Features::EditorLiteSpecHelpers + before do project = create(:project, :repository) sign_in project.owner visit project_new_blob_path(project, 'master', file_name: 'Dockerfile') end - it 'user can pick a Dockerfile file from the dropdown', :js do + it 'user can pick a Dockerfile file from the dropdown' do expect(page).to have_css('.dockerfile-selector') find('.js-dockerfile-selector').click @@ -24,6 +26,6 @@ RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', quarant wait_for_requests expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'Apply a template') - expect(page).to have_content('COPY ./ /usr/local/apache2/htdocs/') + expect(editor_get_value).to have_content('COPY ./ /usr/local/apache2/htdocs/') end end diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb index 5a39f2bcd98..a9f2463ecf6 100644 --- a/spec/features/projects/files/gitignore_dropdown_spec.rb +++ b/spec/features/projects/files/gitignore_dropdown_spec.rb @@ -2,14 +2,16 @@ require 'spec_helper' -RSpec.describe 'Projects > Files > User wants to add a .gitignore file' do +RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do + include Spec::Support::Helpers::Features::EditorLiteSpecHelpers + before do project = create(:project, :repository) sign_in project.owner visit project_new_blob_path(project, 'master', file_name: '.gitignore') end - it 'user can pick a .gitignore file from the dropdown', :js do + it 'user can pick a .gitignore file from the dropdown' do expect(page).to have_css('.gitignore-selector') find('.js-gitignore-selector').click @@ -24,7 +26,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitignore file' do wait_for_requests expect(page).to have_css('.gitignore-selector .dropdown-toggle-text', text: 'Apply a template') - expect(page).to have_content('/.bundle') - expect(page).to have_content('config/initializers/secret_token.rb') + expect(editor_get_value).to have_content('/.bundle') + expect(editor_get_value).to have_content('config/initializers/secret_token.rb') end end diff --git a/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb index 6308acb41f5..ca6f03472dd 100644 --- a/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb +++ b/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do + include Spec::Support::Helpers::Features::EditorLiteSpecHelpers + before do project = create(:project, :repository) sign_in project.owner @@ -34,8 +36,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do let(:experiment_active) { true } let(:in_experiment_group) { true } - it 'allows the user to pick a "Learn CI/CD syntax" template from the dropdown', :js, - { quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297347' } } do + it 'allows the user to pick a "Learn CI/CD syntax" template from the dropdown', :js do expect(page).to have_css('.gitlab-ci-syntax-yml-selector') find('.js-gitlab-ci-syntax-yml-selector').click @@ -50,7 +51,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do wait_for_requests expect(page).to have_css('.gitlab-ci-syntax-yml-selector .dropdown-toggle-text', text: 'Learn CI/CD syntax') - expect(page).to have_content('You can use artifacts to pass data to jobs in later stages.') + expect(editor_get_value).to have_content('You can use artifacts to pass data to jobs in later stages.') end end end diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb index 879cb6a65c8..55b9f38d8e7 100644 --- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb +++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb @@ -2,14 +2,16 @@ require 'spec_helper' -RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do +RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js do + include Spec::Support::Helpers::Features::EditorLiteSpecHelpers + before do project = create(:project, :repository) sign_in project.owner visit project_new_blob_path(project, 'master', file_name: '.gitlab-ci.yml') end - it 'user can pick a template from the dropdown', :js do + it 'user can pick a template from the dropdown' do expect(page).to have_css('.gitlab-ci-yml-selector') find('.js-gitlab-ci-yml-selector').click @@ -24,7 +26,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do wait_for_requests expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template') - expect(page).to have_content('This file is a template, and might need editing before it works on your project') - expect(page).to have_content('jekyll build -d test') + expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project') + expect(editor_get_value).to have_content('jekyll build -d test') end end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 1557a8a2d72..adf664f26af 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -533,10 +533,10 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do expect(page).to have_content('Trigger token') expect(page).to have_content('Trigger variables') - expect(page).not_to have_css('.js-reveal-variables') + expect(page).not_to have_selector('[data-testid="trigger-reveal-values-button"]') - expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1') - expect(page).to have_selector('.js-build-value', text: '••••••') + expect(page).to have_selector('[data-testid="trigger-build-key"]', text: 'TRIGGER_KEY_1') + expect(page).to have_selector('[data-testid="trigger-build-value"]', text: '••••••') end end @@ -571,17 +571,17 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do expect(page).to have_content('Trigger token') expect(page).to have_content('Trigger variables') - expect(page).to have_css('.js-reveal-variables') + expect(page).to have_selector('[data-testid="trigger-reveal-values-button"]') - expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1') - expect(page).to have_selector('.js-build-value', text: '••••••') + expect(page).to have_selector('[data-testid="trigger-build-key"]', text: 'TRIGGER_KEY_1') + expect(page).to have_selector('[data-testid="trigger-build-value"]', text: '••••••') end it 'reveals values on button click', :js do click_button 'Reveal values' - expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1') - expect(page).to have_selector('.js-build-value', text: 'TRIGGER_VALUE_1') + expect(page).to have_selector('[data-testid="trigger-build-key"]', text: 'TRIGGER_KEY_1') + expect(page).to have_selector('[data-testid="trigger-build-value"]', text: 'TRIGGER_VALUE_1') end end diff --git a/spec/features/projects/members/anonymous_user_sees_members_spec.rb b/spec/features/projects/members/anonymous_user_sees_members_spec.rb index 3b0f00c5494..c0849cc7330 100644 --- a/spec/features/projects/members/anonymous_user_sees_members_spec.rb +++ b/spec/features/projects/members/anonymous_user_sees_members_spec.rb @@ -8,6 +8,8 @@ RSpec.describe 'Projects > Members > Anonymous user sees members' do let(:project) { create(:project, :public) } before do + stub_feature_flags(vue_project_members_list: false) + project.add_maintainer(user) create(:project_group_link, project: project, group: group) end diff --git a/spec/features/projects/members/group_members_spec.rb b/spec/features/projects/members/group_members_spec.rb index aa15f04bf24..b6a5fbf5584 100644 --- a/spec/features/projects/members/group_members_spec.rb +++ b/spec/features/projects/members/group_members_spec.rb @@ -13,6 +13,8 @@ RSpec.describe 'Projects members', :js do let(:group_requester) { create(:user) } before do + stub_feature_flags(vue_project_members_list: false) + project.add_developer(developer) group.add_owner(user) sign_in(user) diff --git a/spec/features/projects/members/groups_with_access_list_spec.rb b/spec/features/projects/members/groups_with_access_list_spec.rb index 686d86b1783..de27692b535 100644 --- a/spec/features/projects/members/groups_with_access_list_spec.rb +++ b/spec/features/projects/members/groups_with_access_list_spec.rb @@ -11,6 +11,8 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do let!(:group_link) { create(:project_group_link, project: project, group: group, **additional_link_attrs) } before do + stub_feature_flags(vue_project_members_list: false) + travel_to Time.now.utc.beginning_of_day project.add_maintainer(user) diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb index bb56ae348fb..8e956c4a7cd 100644 --- a/spec/features/projects/members/invite_group_spec.rb +++ b/spec/features/projects/members/invite_group_spec.rb @@ -8,6 +8,11 @@ RSpec.describe 'Project > Members > Invite group', :js do let(:maintainer) { create(:user) } + before do + stub_feature_flags(invite_members_group_modal: false) + stub_feature_flags(vue_project_members_list: false) + end + describe 'Share with group lock' do shared_examples 'the project can be shared with groups' do it 'the "Invite group" tab exists' do diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb index 62115f2dce6..a62ccfab244 100644 --- a/spec/features/projects/members/list_spec.rb +++ b/spec/features/projects/members/list_spec.rb @@ -13,10 +13,18 @@ RSpec.describe 'Project members list' do before do stub_feature_flags(invite_members_group_modal: false) + stub_feature_flags(vue_project_members_list: false) + sign_in(user1) group.add_owner(user1) end + it 'pushes `vue_project_members_list` feature flag to the frontend' do + visit_members_page + + expect(page).to have_pushed_frontend_feature_flags(vueProjectMembersList: false) + end + it 'show members from project and group' do project.add_developer(user2) diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb index d69c3f2652c..e7970b28e37 100644 --- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb +++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb @@ -11,6 +11,8 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date let(:new_member) { create(:user) } before do + stub_feature_flags(vue_project_members_list: false) + travel_to Time.now.utc.beginning_of_day project.add_maintainer(maintainer) @@ -18,6 +20,8 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date end it 'expiration date is displayed in the members list' do + stub_feature_flags(invite_members_group_modal: false) + visit project_project_members_path(project) page.within '.invite-users-form' do diff --git a/spec/features/projects/members/sorting_spec.rb b/spec/features/projects/members/sorting_spec.rb index be27cbc0d66..9b9f1f26d66 100644 --- a/spec/features/projects/members/sorting_spec.rb +++ b/spec/features/projects/members/sorting_spec.rb @@ -8,6 +8,8 @@ RSpec.describe 'Projects > Members > Sorting' do let(:project) { create(:project, namespace: maintainer.namespace, creator: maintainer) } before do + stub_feature_flags(vue_project_members_list: false) + create(:project_member, :developer, user: developer, project: project, created_at: 3.days.ago) sign_in(maintainer) diff --git a/spec/features/projects/members/tabs_spec.rb b/spec/features/projects/members/tabs_spec.rb index bdcf02c82a4..7c72ba31029 100644 --- a/spec/features/projects/members/tabs_spec.rb +++ b/spec/features/projects/members/tabs_spec.rb @@ -20,6 +20,7 @@ RSpec.describe 'Projects > Members > Tabs' do end before do + stub_feature_flags(vue_project_members_list: false) allow(Kaminari.config).to receive(:default_per_page).and_return(1) sign_in(user) diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index 25791b393bc..4ff3827b240 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -67,23 +67,4 @@ RSpec.describe 'Project navbar' do it_behaves_like 'verified navigation bar' end - - context 'when invite team members is not available' do - it 'does not display the js-invite-members-trigger' do - visit project_path(project) - - expect(page).not_to have_selector('.js-invite-members-trigger') - end - end - - context 'when invite team members is available' do - it 'includes the div for js-invite-members-trigger' do - stub_feature_flags(invite_members_group_modal: true) - allow_any_instance_of(InviteMembersHelper).to receive(:invite_members_allowed?).and_return(true) - - visit project_path(project) - - expect(page).to have_selector('.js-invite-members-trigger') - end - end end diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb new file mode 100644 index 00000000000..24c9edb79e5 --- /dev/null +++ b/spec/features/projects/pages/user_adds_domain_spec.rb @@ -0,0 +1,185 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe 'User adds pages domain', :js do + include LetsEncryptHelpers + + let_it_be(:project) { create(:project, pages_https_only: false) } + let(:user) { create(:user) } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + + project.add_maintainer(user) + + sign_in(user) + end + + context 'when pages are exposed on external HTTP address', :http_pages_enabled do + let(:project) { create(:project, pages_https_only: false) } + + shared_examples 'adds new domain' do + it 'adds new domain' do + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + end + end + + it 'allows to add new domain' do + visit project_pages_path(project) + + expect(page).to have_content('New Domain') + end + + it_behaves_like 'adds new domain' + + context 'when project in group namespace' do + it_behaves_like 'adds new domain' do + let(:group) { create :group } + let(:project) { create(:project, namespace: group, pages_https_only: false) } + end + end + + context 'when pages domain is added' do + before do + create(:pages_domain, project: project, domain: 'my.test.domain.com') + + visit new_project_pages_domain_path(project) + end + + it 'renders certificates is disabled' do + expect(page).to have_content('Support for custom certificates is disabled') + end + + it 'does not adds new domain and renders error message' do + fill_in 'Domain', with: 'my.test.domain.com' + click_button 'Create New Domain' + + expect(page).to have_content('Domain has already been taken') + end + end + end + + context 'when pages are exposed on external HTTPS address', :https_pages_enabled, :js do + let(:certificate_pem) do + attributes_for(:pages_domain)[:certificate] + end + + let(:certificate_key) do + attributes_for(:pages_domain)[:key] + end + + it 'adds new domain with certificate' do + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + + fill_in 'Certificate (PEM)', with: certificate_pem + fill_in 'Key (PEM)', with: certificate_key + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + end + + it "adds new domain with certificate if Let's Encrypt is enabled" do + stub_lets_encrypt_settings + + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + + find('.js-auto-ssl-toggle-container .project-feature-toggle').click + + fill_in 'Certificate (PEM)', with: certificate_pem + fill_in 'Key (PEM)', with: certificate_key + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + end + + it 'shows validation error if domain is duplicated' do + project.pages_domains.create!(domain: 'my.test.domain.com') + + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + click_button 'Create New Domain' + + expect(page).to have_content('Domain has already been taken') + end + + describe 'with dns verification enabled' do + before do + stub_application_setting(pages_domain_verification_enabled: true) + end + + it 'shows the DNS verification record' do + domain = create(:pages_domain, project: project) + + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + expect(page).to have_field :domain_verification, with: "#{domain.verification_domain} TXT #{domain.keyed_verification_code}" + end + end + + describe 'updating the certificate for an existing domain' do + let!(:domain) do + create(:pages_domain, project: project, auto_ssl_enabled: false) + end + + it 'allows the certificate to be updated' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + click_button 'Save Changes' + + expect(page).to have_content('Domain was updated') + end + + context 'when the certificate is invalid' do + let!(:domain) do + create(:pages_domain, :without_certificate, :without_key, project: project) + end + + it 'tells the user what the problem is' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + + fill_in 'Certificate (PEM)', with: 'invalid data' + click_button 'Save Changes' + + expect(page).to have_content('Certificate must be a valid PEM certificate') + expect(page).to have_content('Certificate misses intermediates') + expect(page).to have_content("Key doesn't match the certificate") + end + end + + it 'allows the certificate to be removed', :js do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + + accept_confirm { click_link 'Remove' } + + expect(page).to have_field('Certificate (PEM)', with: '') + expect(page).to have_field('Key (PEM)', with: '') + domain.reload + expect(domain.certificate).to be_nil + expect(domain.key).to be_nil + end + + it 'shows the DNS CNAME record' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}." + end + end + end +end diff --git a/spec/features/projects/pages_lets_encrypt_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb index 302e9f5e533..cf8438d5e6f 100644 --- a/spec/features/projects/pages_lets_encrypt_spec.rb +++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb @@ -17,7 +17,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do project.add_role(user, role) sign_in(user) - project.namespace.update(owner: user) + project.namespace.update!(owner: user) allow_next_instance_of(Project) do |instance| allow(instance).to receive(:pages_deployed?) { true } end diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb new file mode 100644 index 00000000000..3649fae17ce --- /dev/null +++ b/spec/features/projects/pages/user_edits_settings_spec.rb @@ -0,0 +1,201 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe 'Pages edits pages settings', :js do + let(:project) { create(:project, pages_https_only: false) } + let(:user) { create(:user) } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + + project.add_maintainer(user) + + sign_in(user) + end + + context 'when user is the owner' do + before do + project.namespace.update!(owner: user) + end + + context 'when pages deployed' do + before do + project.mark_pages_as_deployed + end + + it 'renders Access pages' do + visit project_pages_path(project) + + expect(page).to have_content('Access pages') + end + + context 'when pages are disabled in the project settings' do + it 'renders disabled warning' do + project.project_feature.update!(pages_access_level: ProjectFeature::DISABLED) + + visit project_pages_path(project) + + expect(page).to have_content('GitLab Pages are disabled for this project') + end + end + + it 'renders first deployment warning' do + visit project_pages_path(project) + + expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.') + end + + shared_examples 'does not render access control warning' do + it 'does not render access control warning' do + visit project_pages_path(project) + + expect(page).not_to have_content('Access Control is enabled for this Pages website') + end + end + + include_examples 'does not render access control warning' + + context 'when access control is enabled in gitlab settings' do + before do + stub_pages_setting(access_control: true) + end + + it 'renders access control warning' do + visit project_pages_path(project) + + expect(page).to have_content('Access Control is enabled for this Pages website') + end + + context 'when pages are public' do + before do + project.project_feature.update!(pages_access_level: ProjectFeature::PUBLIC) + end + + include_examples 'does not render access control warning' + end + end + + context 'when support for external domains is disabled' do + it 'renders message that support is disabled' do + visit project_pages_path(project) + + expect(page).to have_content('Support for domains and certificates is disabled') + end + end + end + + it 'does not see anything to destroy' do + visit project_pages_path(project) + + expect(page).to have_content('Configure pages') + expect(page).not_to have_link('Remove pages') + end + + describe 'project settings page' do + it 'renders "Pages" tab' do + visit edit_project_path(project) + + page.within '.nav-sidebar' do + expect(page).to have_link('Pages') + end + end + + context 'when pages are disabled' do + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(false) + end + + it 'does not render "Pages" tab' do + visit edit_project_path(project) + + page.within '.nav-sidebar' do + expect(page).not_to have_link('Pages') + end + end + end + end + end + + describe 'HTTPS settings', :https_pages_enabled do + before do + project.namespace.update!(owner: user) + + project.mark_pages_as_deployed + end + + it 'tries to change the setting' do + visit project_pages_path(project) + expect(page).to have_content("Force HTTPS (requires valid certificates)") + + uncheck :project_pages_https_only + + click_button 'Save' + + expect(page).to have_text('Your changes have been saved') + expect(page).not_to have_checked_field('project_pages_https_only') + end + + context 'setting could not be updated' do + let(:service) { instance_double('Projects::UpdateService') } + + before do + allow(Projects::UpdateService).to receive(:new).and_return(service) + allow(service).to receive(:execute).and_return(status: :error, message: 'Some error has occured') + end + + it 'tries to change the setting' do + visit project_pages_path(project) + + uncheck :project_pages_https_only + + click_button 'Save' + + expect(page).to have_text('Some error has occured') + end + end + + context 'non-HTTPS domain exists' do + let(:project) { create(:project, pages_https_only: false) } + + before do + create(:pages_domain, :without_key, :without_certificate, project: project) + end + + it 'the setting is disabled' do + visit project_pages_path(project) + + expect(page).to have_field(:project_pages_https_only, disabled: true) + expect(page).to have_button('Save') + end + end + + context 'HTTPS pages are disabled', :https_pages_disabled do + it 'the setting is unavailable' do + visit project_pages_path(project) + + expect(page).not_to have_field(:project_pages_https_only) + expect(page).not_to have_content('Force HTTPS (requires valid certificates)') + expect(page).to have_button('Save') + end + end + end + + describe 'Remove page' do + context 'when pages are deployed' do + before do + project.mark_pages_as_deployed + end + + 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 scheduled for removal') + expect(project.reload.pages_deployed?).to be_falsey + end + end + end +end diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb deleted file mode 100644 index 11f712fde81..00000000000 --- a/spec/features/projects/pages_spec.rb +++ /dev/null @@ -1,411 +0,0 @@ -# frozen_string_literal: true -require 'spec_helper' - -RSpec.shared_examples 'pages settings editing' do - let_it_be(:project) { create(:project, pages_https_only: false) } - let(:user) { create(:user) } - let(:role) { :maintainer } - - before do - allow(Gitlab.config.pages).to receive(:enabled).and_return(true) - - project.add_role(user, role) - - sign_in(user) - end - - context 'when user is the owner' do - before do - project.namespace.update(owner: user) - end - - context 'when pages deployed' do - before do - allow_any_instance_of(Project).to receive(:pages_deployed?) { true } - end - - it 'renders Access pages' do - visit project_pages_path(project) - - expect(page).to have_content('Access pages') - end - - context 'when pages are disabled in the project settings' do - it 'renders disabled warning' do - project.project_feature.update!(pages_access_level: ProjectFeature::DISABLED) - - visit project_pages_path(project) - - expect(page).to have_content('GitLab Pages are disabled for this project') - end - end - - it 'renders first deployment warning' do - visit project_pages_path(project) - - expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.') - end - - shared_examples 'does not render access control warning' do - it 'does not render access control warning' do - visit project_pages_path(project) - - expect(page).not_to have_content('Access Control is enabled for this Pages website') - end - end - - include_examples 'does not render access control warning' - - context 'when access control is enabled in gitlab settings' do - before do - stub_pages_setting(access_control: true) - end - - it 'renders access control warning' do - visit project_pages_path(project) - - expect(page).to have_content('Access Control is enabled for this Pages website') - end - - context 'when pages are public' do - before do - project.project_feature.update!(pages_access_level: ProjectFeature::PUBLIC) - end - - include_examples 'does not render access control warning' - end - end - - context 'when support for external domains is disabled' do - it 'renders message that support is disabled' do - visit project_pages_path(project) - - expect(page).to have_content('Support for domains and certificates is disabled') - end - end - - context 'when pages are exposed on external HTTP address', :http_pages_enabled do - let(:project) { create(:project, pages_https_only: false) } - - shared_examples 'adds new domain' do - it 'adds new domain' do - visit new_project_pages_domain_path(project) - - fill_in 'Domain', with: 'my.test.domain.com' - click_button 'Create New Domain' - - expect(page).to have_content('my.test.domain.com') - end - end - - it 'allows to add new domain' do - visit project_pages_path(project) - - expect(page).to have_content('New Domain') - end - - it_behaves_like 'adds new domain' - - context 'when project in group namespace' do - it_behaves_like 'adds new domain' do - let(:group) { create :group } - let(:project) { create(:project, namespace: group, pages_https_only: false) } - end - end - - context 'when pages domain is added' do - before do - create(:pages_domain, project: project, domain: 'my.test.domain.com') - - visit new_project_pages_domain_path(project) - end - - it 'renders certificates is disabled' do - expect(page).to have_content('Support for custom certificates is disabled') - end - - it 'does not adds new domain and renders error message' do - fill_in 'Domain', with: 'my.test.domain.com' - click_button 'Create New Domain' - - expect(page).to have_content('Domain has already been taken') - end - end - end - - context 'when pages are exposed on external HTTPS address', :https_pages_enabled, :js do - let(:certificate_pem) do - attributes_for(:pages_domain)[:certificate] - end - - let(:certificate_key) do - attributes_for(:pages_domain)[:key] - end - - it 'adds new domain with certificate' do - visit new_project_pages_domain_path(project) - - fill_in 'Domain', with: 'my.test.domain.com' - - if ::Gitlab::LetsEncrypt.enabled? - find('.js-auto-ssl-toggle-container .project-feature-toggle').click - end - - fill_in 'Certificate (PEM)', with: certificate_pem - fill_in 'Key (PEM)', with: certificate_key - click_button 'Create New Domain' - - expect(page).to have_content('my.test.domain.com') - end - - it 'shows validation error if domain is duplicated' do - project.pages_domains.create!(domain: 'my.test.domain.com') - - visit new_project_pages_domain_path(project) - - fill_in 'Domain', with: 'my.test.domain.com' - click_button 'Create New Domain' - - expect(page).to have_content('Domain has already been taken') - end - - describe 'with dns verification enabled' do - before do - stub_application_setting(pages_domain_verification_enabled: true) - end - - it 'shows the DNS verification record' do - domain = create(:pages_domain, project: project) - - visit project_pages_path(project) - - within('#content-body') { click_link 'Edit' } - expect(page).to have_field :domain_verification, with: "#{domain.verification_domain} TXT #{domain.keyed_verification_code}" - end - end - - describe 'updating the certificate for an existing domain' do - let!(:domain) do - create(:pages_domain, project: project, auto_ssl_enabled: false) - end - - it 'allows the certificate to be updated' do - visit project_pages_path(project) - - within('#content-body') { click_link 'Edit' } - click_button 'Save Changes' - - expect(page).to have_content('Domain was updated') - end - - context 'when the certificate is invalid' do - let!(:domain) do - create(:pages_domain, :without_certificate, :without_key, project: project) - end - - it 'tells the user what the problem is' do - visit project_pages_path(project) - - within('#content-body') { click_link 'Edit' } - - if ::Gitlab::LetsEncrypt.enabled? - find('.js-auto-ssl-toggle-container .project-feature-toggle').click - end - - fill_in 'Certificate (PEM)', with: 'invalid data' - click_button 'Save Changes' - - expect(page).to have_content('Certificate must be a valid PEM certificate') - expect(page).to have_content('Certificate misses intermediates') - expect(page).to have_content("Key doesn't match the certificate") - end - end - - it 'allows the certificate to be removed', :js do - visit project_pages_path(project) - - within('#content-body') { click_link 'Edit' } - - accept_confirm { click_link 'Remove' } - - expect(page).to have_field('Certificate (PEM)', with: '') - expect(page).to have_field('Key (PEM)', with: '') - domain.reload - expect(domain.certificate).to be_nil - expect(domain.key).to be_nil - end - - it 'shows the DNS CNAME record' do - visit project_pages_path(project) - - within('#content-body') { click_link 'Edit' } - expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}." - end - end - end - end - - it 'does not see anything to destroy' do - visit project_pages_path(project) - - expect(page).to have_content('Configure pages') - expect(page).not_to have_link('Remove pages') - end - - describe 'project settings page' do - it 'renders "Pages" tab' do - visit edit_project_path(project) - - page.within '.nav-sidebar' do - expect(page).to have_link('Pages') - end - end - - context 'when pages are disabled' do - before do - allow(Gitlab.config.pages).to receive(:enabled).and_return(false) - end - - it 'does not render "Pages" tab' do - visit edit_project_path(project) - - page.within '.nav-sidebar' do - expect(page).not_to have_link('Pages') - end - end - end - end - end - - describe 'HTTPS settings', :https_pages_enabled do - before do - project.namespace.update(owner: user) - - allow_any_instance_of(Project).to receive(:pages_deployed?) { true } - end - - it 'tries to change the setting' do - visit project_pages_path(project) - expect(page).to have_content("Force HTTPS (requires valid certificates)") - - uncheck :project_pages_https_only - - click_button 'Save' - - expect(page).to have_text('Your changes have been saved') - expect(page).not_to have_checked_field('project_pages_https_only') - end - - context 'setting could not be updated' do - let(:service) { instance_double('Projects::UpdateService') } - - before do - allow(Projects::UpdateService).to receive(:new).and_return(service) - allow(service).to receive(:execute).and_return(status: :error, message: 'Some error has occured') - end - - it 'tries to change the setting' do - visit project_pages_path(project) - - uncheck :project_pages_https_only - - click_button 'Save' - - expect(page).to have_text('Some error has occured') - end - end - - context 'non-HTTPS domain exists' do - let(:project) { create(:project, pages_https_only: false) } - - before do - create(:pages_domain, :without_key, :without_certificate, project: project) - end - - it 'the setting is disabled' do - visit project_pages_path(project) - - expect(page).to have_field(:project_pages_https_only, disabled: true) - expect(page).to have_button('Save') - end - end - - context 'HTTPS pages are disabled', :https_pages_disabled do - it 'the setting is unavailable' do - visit project_pages_path(project) - - expect(page).not_to have_field(:project_pages_https_only) - expect(page).not_to have_content('Force HTTPS (requires valid certificates)') - expect(page).to have_button('Save') - end - end - end - - describe 'Remove page' do - let(:project) { create :project, :repository } - - context 'when pages are deployed' do - let(:pipeline) do - commit_sha = project.commit('HEAD').sha - - project.ci_pipelines.create( - ref: 'HEAD', - sha: commit_sha, - source: :push, - protected: false - ) - end - - let(:ci_build) do - create( - :ci_build, - project: project, - pipeline: pipeline, - ref: 'HEAD') - end - - let!(:artifact) do - create(:ci_job_artifact, :archive, :correct_checksum, - file: fixture_file_upload(File.join('spec/fixtures/pages.zip')), job: ci_build) - end - - let!(:metadata) do - create(:ci_job_artifact, :metadata, - file: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta')), job: ci_build) - end - - before do - result = Projects::UpdatePagesService.new(project, ci_build).execute - expect(result[:status]).to eq(:success) - expect(project).to be_pages_deployed - end - - 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 scheduled for removal') - expect(project.reload.pages_deployed?).to be_falsey - end - end - end -end - -RSpec.describe 'Pages', :js do - include LetsEncryptHelpers - - context 'when editing normally' do - include_examples 'pages settings editing' - end - - context 'when letsencrypt support is enabled' do - before do - stub_lets_encrypt_settings - end - - include_examples 'pages settings editing' - end -end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index ac3566fbbdd..e1d68a3f12e 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -15,6 +15,7 @@ RSpec.describe 'Pipeline', :js do sign_in(user) project.add_role(user, role) stub_feature_flags(graphql_pipeline_details: false) + stub_feature_flags(graphql_pipeline_details_users: false) end shared_context 'pipeline builds' do @@ -625,20 +626,6 @@ RSpec.describe 'Pipeline', :js do end end end - - context 'when FF dag_pipeline_tab is disabled' do - before do - stub_feature_flags(dag_pipeline_tab: false) - visit_pipeline - end - - it 'does not show DAG link' do - expect(page).to have_link('Pipeline') - expect(page).to have_link('Jobs') - expect(page).not_to have_link('DAG') - expect(page).to have_link('Failed Jobs') - end - end end context 'when user does not have access to read jobs' do diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 450524b8d70..e0a0591fe6b 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -13,6 +13,7 @@ RSpec.describe 'Pipelines', :js do before do sign_in(user) stub_feature_flags(graphql_pipeline_details: false) + stub_feature_flags(graphql_pipeline_details_users: false) project.add_developer(user) project.update!(auto_devops_attributes: { enabled: false }) end @@ -287,23 +288,23 @@ RSpec.describe 'Pipelines', :js do end it 'has a dropdown with play button' do - expect(page).to have_selector('.dropdown-new.btn.btn-default .icon-play') + expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] [data-testid="play-icon"]') end it 'has link to the manual action' do - find('.js-pipeline-dropdown-manual-actions').click + find('[data-testid="pipelines-manual-actions-dropdown"]').click expect(page).to have_button('manual build') end context 'when manual action was played' do before do - find('.js-pipeline-dropdown-manual-actions').click + find('[data-testid="pipelines-manual-actions-dropdown"]').click click_button('manual build') end it 'enqueues manual action job' do - expect(page).to have_selector('.js-pipeline-dropdown-manual-actions:disabled') + expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] .gl-dropdown-toggle:disabled') end end end @@ -321,11 +322,11 @@ RSpec.describe 'Pipelines', :js do end it 'has a dropdown for actionable jobs' do - expect(page).to have_selector('.dropdown-new.btn.btn-default .icon-play') + expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] [data-testid="play-icon"]') end it "has link to the delayed job's action" do - find('.js-pipeline-dropdown-manual-actions').click + find('[data-testid="pipelines-manual-actions-dropdown"]').click time_diff = [0, delayed_job.scheduled_at - Time.now].max expect(page).to have_button('delayed job 1') @@ -341,7 +342,7 @@ RSpec.describe 'Pipelines', :js do end it "shows 00:00:00 as the remaining time" do - find('.js-pipeline-dropdown-manual-actions').click + find('[data-testid="pipelines-manual-actions-dropdown"]').click expect(page).to have_content("00:00:00") end @@ -349,7 +350,7 @@ RSpec.describe 'Pipelines', :js do context 'when user played a delayed job immediately' do before do - find('.js-pipeline-dropdown-manual-actions').click + find('[data-testid="pipelines-manual-actions-dropdown"]').click page.accept_confirm { click_button('delayed job 1') } wait_for_requests end @@ -517,56 +518,75 @@ RSpec.describe 'Pipelines', :js do end end - context 'mini pipeline graph' do - let!(:build) do - create(:ci_build, :pending, pipeline: pipeline, - stage: 'build', - name: 'build') - end - - before do - visit_project_pipelines - end + shared_examples 'mini pipeline renders' do |ci_mini_pipeline_gl_dropdown_enabled| + context 'mini pipeline graph' do + let!(:build) do + create(:ci_build, :pending, pipeline: pipeline, + stage: 'build', + name: 'build') + end - it 'renders a mini pipeline graph' do - expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]') - expect(page).to have_selector('.js-builds-dropdown-button') - end + before do + stub_feature_flags(ci_mini_pipeline_gl_dropdown: ci_mini_pipeline_gl_dropdown_enabled) + visit_project_pipelines + end - context 'when clicking a stage badge' do - it 'opens a dropdown' do - find('.js-builds-dropdown-button').click + let_it_be(:dropdown_toggle_selector) do + if ci_mini_pipeline_gl_dropdown_enabled + '[data-testid="mini-pipeline-graph-dropdown"] .dropdown-toggle' + else + '[data-testid="mini-pipeline-graph-dropdown-toggle"]' + end + end - expect(page).to have_link build.name + it 'renders a mini pipeline graph' do + expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]') + expect(page).to have_selector(dropdown_toggle_selector) end - it 'is possible to cancel pending build' do - find('.js-builds-dropdown-button').click - find('.js-ci-action').click - wait_for_requests + context 'when clicking a stage badge' do + it 'opens a dropdown' do + find(dropdown_toggle_selector).click - expect(build.reload).to be_canceled - end - end + expect(page).to have_link build.name + end - context 'for a failed pipeline' do - let!(:build) do - create(:ci_build, :failed, pipeline: pipeline, - stage: 'build', - name: 'build') + it 'is possible to cancel pending build' do + find(dropdown_toggle_selector).click + find('.js-ci-action').click + wait_for_requests + + expect(build.reload).to be_canceled + end end - it 'displays the failure reason' do - find('.js-builds-dropdown-button').click + context 'for a failed pipeline' do + let!(:build) do + create(:ci_build, :failed, pipeline: pipeline, + stage: 'build', + name: 'build') + end + + it 'displays the failure reason' do + find(dropdown_toggle_selector).click - within('.js-builds-dropdown-list') do - build_element = page.find('.mini-pipeline-graph-dropdown-item') - expect(build_element['title']).to eq('build - failed - (unknown failure)') + within('.js-builds-dropdown-list') do + build_element = page.find('.mini-pipeline-graph-dropdown-item') + expect(build_element['title']).to eq('build - failed - (unknown failure)') + end end end end end + context 'with ci_mini_pipeline_gl_dropdown disabled' do + it_behaves_like "mini pipeline renders", false + end + + context 'with ci_mini_pipeline_gl_dropdown enabled' do + it_behaves_like "mini pipeline renders", true + end + context 'with pagination' do before do allow(Ci::Pipeline).to receive(:default_per_page).and_return(1) 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 3994f55caee..4dfd4416eeb 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 @@ -40,4 +40,8 @@ RSpec.describe 'Slack slash commands', :js do value = find_field('url').value expect(value).to match("api/v4/projects/#{project.id}/services/slack_slash_commands/trigger") end + + it 'shows help content' do + expect(page).to have_content('This service allows users to perform common operations on this project by entering slash commands in Slack.') + end end diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb index c087237fd7c..39c4315bf0f 100644 --- a/spec/features/projects/settings/pipelines_settings_spec.rb +++ b/spec/features/projects/settings/pipelines_settings_spec.rb @@ -46,7 +46,7 @@ RSpec.describe "Projects > Settings > Pipelines settings" do it 'updates auto_cancel_pending_pipelines' do visit project_settings_ci_cd_path(project) - page.check('Auto-cancel redundant, pending pipelines') + page.check('Auto-cancel redundant pipelines') page.within '#js-general-pipeline-settings' do click_on 'Save changes' end diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb index 3e520142117..2f257d299d8 100644 --- a/spec/features/projects/settings/repository_settings_spec.rb +++ b/spec/features/projects/settings/repository_settings_spec.rb @@ -63,7 +63,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do click_button 'Add key' expect(page).to have_content('new_deploy_key') - expect(page).to have_content('Write access allowed') + expect(page).to have_content('Grant write permissions to this key') end it 'edit an existing deploy key' do @@ -77,7 +77,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do click_button 'Save changes' expect(page).to have_content('updated_deploy_key') - expect(page).to have_content('Write access allowed') + expect(page).to have_content('Grant write permissions to this key') end it 'edit an existing public deploy key to be writable' do @@ -90,7 +90,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do click_button 'Save changes' expect(page).to have_content('public_deploy_key') - expect(page).to have_content('Write access allowed') + expect(page).to have_content('Grant write permissions to this key') end it 'edit a deploy key from projects user has access to' do diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/settings/user_manages_project_members_spec.rb index 726b8fb6840..a4abdf9f571 100644 --- a/spec/features/projects/settings/user_manages_project_members_spec.rb +++ b/spec/features/projects/settings/user_manages_project_members_spec.rb @@ -11,6 +11,8 @@ RSpec.describe 'Projects > Settings > User manages project members' do let(:user_mike) { create(:user, name: 'Mike') } before do + stub_feature_flags(vue_project_members_list: false) + project.add_maintainer(user) project.add_developer(user_dmitriy) sign_in(user) @@ -37,6 +39,8 @@ RSpec.describe 'Projects > Settings > User manages project members' do end it 'imports a team from another project' do + stub_feature_flags(invite_members_group_modal: false) + project2.add_maintainer(user) project2.add_reporter(user_mike) diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb index d444ea27d35..5f7d9b0963b 100644 --- a/spec/features/projects/show/user_manages_notifications_spec.rb +++ b/spec/features/projects/show/user_manages_notifications_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do let(:project) { create(:project, :public, :repository) } before do + stub_feature_flags(vue_notification_dropdown: false) sign_in(project.owner) end diff --git a/spec/features/projects/show/user_sees_git_instructions_spec.rb b/spec/features/projects/show/user_sees_git_instructions_spec.rb index febdb70de86..e6157887c12 100644 --- a/spec/features/projects/show/user_sees_git_instructions_spec.rb +++ b/spec/features/projects/show/user_sees_git_instructions_spec.rb @@ -5,6 +5,13 @@ require 'spec_helper' RSpec.describe 'Projects > Show > User sees Git instructions' do let_it_be(:user) { create(:user) } + before do + # Reset user notification settings between examples to prevent + # validation failure on NotificationSetting. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/299822#note_492817174 + user.notification_settings.reset + end + shared_examples_for 'redirects to the sign in page' do it 'redirects to the sign in page' do expect(current_path).to eq(new_user_session_path) |