diff options
Diffstat (limited to 'qa/qa/specs/features/browser_ui')
42 files changed, 1301 insertions, 197 deletions
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb index 23de213012e..163469e1e88 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - context 'Manage', :requires_admin, :skip_live_env do + RSpec.describe 'Manage', :requires_admin, :skip_live_env do describe '2FA' do let(:owner_user) do Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_2fa_owner_username_1, Runtime::Env.gitlab_qa_2fa_owner_password_1) diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb index e81ebd5fa9d..7f3c3049499 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb @@ -22,7 +22,7 @@ module QA it 'allows 2FA code recovery via ssh' do recovery_code = Support::SSH.perform do |ssh| ssh.key = ssh_key - ssh.uri = address.gsub(uri.port.to_s, ssh_port) + ssh.uri = address.gsub(/(?<=:)(#{uri.port})/, ssh_port) ssh.setup output = ssh.reset_2fa_codes output.scan(/([A-Za-z0-9]{16})\n/).flatten.first diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb index e514507fcb6..12a1b419f8b 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - context 'Manage', :requires_admin, :skip_live_env do + RSpec.describe 'Manage', :requires_admin, :skip_live_env do describe '2FA' do let(:owner_user) do Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_2fa_owner_username_1, Runtime::Env.gitlab_qa_2fa_owner_password_1) diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb index f6aecff9f26..e4ac59cf5e0 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb @@ -12,7 +12,9 @@ module QA login_page.login('user1', 'user1pass') end - expect(page).to have_content('Welcome to GitLab') + Page::Dashboard::Welcome.perform do |welcome| + expect(welcome).to have_content('Welcome to GitLab') + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb index 11a6bf6fdfa..2bb03b6154f 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb @@ -13,11 +13,39 @@ module QA end end - RSpec.describe 'Manage', :skip_signup_disabled do + RSpec.describe 'Manage', :skip_signup_disabled, :requires_admin do + describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/935' do + before do + # When LDAP is enabled, a previous test might have created a token for the LDAP 'tanuki' user who is not an admin + # So we need to set it to nil in order to create a new token for admin user so that we are able to set_application_settings + # Also, when GITLAB_LDAP_USERNAME is provided, it is used to create a token. This also needs to be set to nil temporarily + # for the same reason as above. + + @personal_access_token = Runtime::Env.personal_access_token + Runtime::Env.personal_access_token = nil + ldap_username = Runtime::Env.ldap_username + Runtime::Env.ldap_username = nil + + disable_require_admin_approval_after_user_signup + + Runtime::Env.ldap_username = ldap_username + end + + it_behaves_like 'registration and login' + + after do + Runtime::Env.personal_access_token = @personal_access_token + end + end + describe 'standard', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/936' do + before(:all) do + disable_require_admin_approval_after_user_signup + end + it_behaves_like 'registration and login' - context 'when user account is deleted', :requires_admin do + context 'when user account is deleted' do let(:user) do Resource::User.fabricate_via_api! do |resource| resource.api_client = admin_api_client @@ -61,11 +89,10 @@ module QA end end end - end - RSpec.describe 'Manage', :orchestrated, :ldap_no_tls, :skip_signup_disabled do - describe 'while LDAP is enabled', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/935' do - it_behaves_like 'registration and login' + def disable_require_admin_approval_after_user_signup + Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: false) + sleep 10 # It takes a moment for the setting to come into effect end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb index 27350176a1e..e71cbeb9837 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb @@ -15,9 +15,9 @@ module QA Page::Project::Menu.perform(&:click_members) Page::Project::Members.perform do |members| members.add_member(user.username) - end - expect(page).to have_content(/@#{user.username}(\n| )?Given access/) + expect(members).to have_content(/@#{user.username}( Is using seat)?(\n| )?Given access/) + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb index 6d07f72a044..2f2f40cba3b 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb @@ -11,12 +11,14 @@ module QA project.description = 'create awesome project test' end - expect(page).to have_content(created_project.name) - expect(page).to have_content( - /Project \S?awesome-project\S+ was successfully created/ - ) - expect(page).to have_content('create awesome project test') - expect(page).to have_content('The repository for this project is empty') + Page::Project::Show.perform do |project| + expect(project).to have_content(created_project.name) + expect(project).to have_content( + /Project \S?awesome-project\S+ was successfully created/ + ) + expect(project).to have_content('create awesome project test') + expect(project).to have_content('The repository for this project is empty') + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb index 83dfb2d9639..d54ce0ac0fc 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -1,30 +1,35 @@ # frozen_string_literal: true module QA - RSpec.describe 'Manage', :github, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/26952', type: :bug } do - describe 'Project import from GitHub' do + RSpec.describe 'Manage', :github, :requires_admin do + describe 'Project import' do + let!(:user) do + Resource::User.fabricate_via_api! do |resource| + resource.api_client = Runtime::API::Client.as_admin + end + end + + let(:group) { Resource::Group.fabricate_via_api! } + let(:imported_project) do - Resource::ProjectImportedFromGithub.fabricate! do |project| + Resource::ProjectImportedFromGithub.fabricate_via_browser_ui! do |project| project.name = 'imported-project' - project.personal_access_token = Runtime::Env.github_access_token - project.github_repository_path = 'gitlab-qa/test-project' + project.group = group + project.github_personal_access_token = Runtime::Env.github_access_token + project.github_repository_path = 'gitlab-qa-github/test-project' end end - after do - # We need to delete the imported project because it's impossible to import - # the same GitHub project twice for a given user. - api_client = Runtime::API::Client.new(:gitlab) - delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") - delete delete_project_request.url - - expect_status(202) + before do + group.add_member(user, Resource::Members::AccessLevel::MAINTAINER) + end - Page::Main::Menu.perform(&:sign_out_if_signed_in) + after do + user.remove_via_api! end - it 'user imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do - Flow::Login.sign_in + it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do + Flow::Login.sign_in(as: user) imported_project # import the project @@ -44,25 +49,28 @@ module QA end def verify_repository_import - expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') - expect(page).to have_content(imported_project.name) + Page::Project::Show.perform do |project| + expect(project).to have_content('This test project is used for automated GitHub import by GitLab QA.') + expect(project).to have_content(imported_project.name) + end end def verify_issues_import QA::Support::Retrier.retry_on_exception do Page::Project::Menu.perform(&:click_issues) - expect(page).to have_content('This is a sample issue') - click_link 'This is a sample issue' + Page::Project::Issue::Show.perform do |issue_page| + expect(issue_page).to have_content('This is a sample issue') - expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') + click_link 'This is a sample issue' - # Comments - comment_text = 'This is a comment from @rymai.' + expect(issue_page).to have_content('This is a sample first comment') + + # Comments + comment_text = 'This is a comment from @sliaquat' - Page::Project::Issue::Show.perform do |issue_page| expect(issue_page).to have_comment(comment_text) - expect(issue_page).to have_label('enhancement') + expect(issue_page).to have_label('custom new label') expect(issue_page).to have_label('help wanted') expect(issue_page).to have_label('good first issue') end @@ -71,26 +79,23 @@ module QA def verify_merge_requests_import Page::Project::Menu.perform(&:click_merge_requests) - expect(page).to have_content('Improve README.md') - click_link 'Improve README.md' + Page::MergeRequest::Show.perform do |merge_request| + expect(merge_request).to have_content('Improve readme') - expect(page).to have_content('This improves the README file a bit.') + click_link 'Improve readme' - # Review comment are not supported yet - expect(page).not_to have_content('Really nice change.') + expect(merge_request).to have_content('This improves the README file a bit.') - # Comments - expect(page).to have_content('Nice work! This is a comment from @rymai.') + # Comments + expect(merge_request).to have_content('[PR comment by @sliaquat] Nice work!') - # Diff comments - expect(page).to have_content('[Review comment] I like that!') - expect(page).to have_content('[Review comment] Nice blank line.') - expect(page).to have_content('[Single diff comment] Much better without this line!') + # Diff comments + expect(merge_request).to have_content('[Single diff comment] Good riddance') + expect(merge_request).to have_content('[Single diff comment] Nice addition') - Page::MergeRequest::Show.perform do |merge_request| expect(merge_request).to have_label('bug') - expect(merge_request).to have_label('enhancement') + expect(merge_request).to have_label('documentation') end end @@ -107,7 +112,9 @@ module QA def verify_wiki_import Page::Project::Menu.perform(&:click_wiki) - expect(page).to have_content('Welcome to the test-project wiki!') + Page::Project::Wiki::Show.perform do |wiki| + expect(wiki).to have_content('Welcome to the test-project wiki!') + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb index fd6d26153ea..3609d083fde 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb @@ -13,9 +13,11 @@ module QA end.project.visit! Page::Project::Menu.perform(&:click_activity) - Page::Project::Activity.perform(&:click_push_events) + Page::Project::Activity.perform do |activity| + activity.click_push_events - expect(page).to have_content('pushed new branch master') + expect(activity).to have_content('pushed new branch master') + end end end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb index 6b309716f55..22157d648ca 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb @@ -26,7 +26,7 @@ module QA expect(show).not_to have_content(my_first_reply) show.expand_replies - expect(show).to have_content(my_first_reply) + expect(show).to have_comment(my_first_reply) expect(show).not_to have_content(one_reply) end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb index c9ae47459c4..d3780186f36 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb @@ -16,11 +16,11 @@ module QA show.comment(first_version_of_comment) - expect(show).to have_content(first_version_of_comment) + expect(show).to have_comment(first_version_of_comment) show.edit_comment(second_version_of_comment) - expect(show).to have_content(second_version_of_comment) + expect(show).to have_comment(second_version_of_comment) expect(show).not_to have_content(first_version_of_comment) end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb index 863c394a9f9..9550572bd5c 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb @@ -19,7 +19,7 @@ module QA end end - it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/852' do + it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1085' do closed_issue.visit! Page::Project::Issue::Show.perform do |issue_page| diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb index 9a054e7d1c8..e275c3decd3 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Plan', :reliable do + RSpec.describe 'Plan' do describe 'filter issue comments activities' do before do Flow::Login.sign_in @@ -18,16 +18,16 @@ module QA show.comment(my_own_comment, filter: :comments_only) expect(show).not_to have_content(made_the_issue_confidential) - expect(show).to have_content(my_own_comment) + expect(show).to have_comment(my_own_comment) show.select_all_activities_filter - expect(show).to have_content(made_the_issue_confidential) - expect(show).to have_content(my_own_comment) + expect(show).to have_system_note(made_the_issue_confidential) + expect(show).to have_comment(my_own_comment) show.select_history_only_filter - expect(show).to have_content(made_the_issue_confidential) + expect(show).to have_system_note(made_the_issue_confidential) expect(show).not_to have_content(my_own_comment) end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb new file mode 100644 index 00000000000..26a83fc3caa --- /dev/null +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Plan', :requires_admin, :actioncable, :orchestrated do + describe 'Assignees' do + let(:user1) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) } + let(:user2) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) } + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-to-test-assignees' + end + end + + before do + Runtime::Feature.enable('real_time_issue_sidebar', project: project) + Runtime::Feature.enable('broadcast_issue_updates', project: project) + + Flow::Login.sign_in + + project.add_member(user1) + project.add_member(user2) + end + + after do + Runtime::Feature.disable('real_time_issue_sidebar', project: project) + Runtime::Feature.disable('broadcast_issue_updates', project: project) + end + + it 'update without refresh', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1048' do + issue = Resource::Issue.fabricate_via_api! do |issue| + issue.project = project + issue.assignee_ids = [user1.id] + end + + issue.visit! + + Page::Project::Issue::Show.perform do |show| + expect(show).to have_assignee(user1.name) + + issue.set_issue_assignees(assignee_ids: [user2.id]) + + expect(show).to have_assignee(user2.name) + expect(show).to have_no_assignee_named(user1.name) + + issue.set_issue_assignees(assignee_ids: []) + + expect(show).to have_no_assignee_named(user1.name) + expect(show).to have_no_assignee_named(user2.name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb index 7844d0d7ccb..970615e8b90 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb @@ -3,8 +3,15 @@ module QA RSpec.describe 'Create', :requires_admin do describe 'View merge request merge-ref diff' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'merge-ref-diff' + end + end + let(:merge_request) do Resource::MergeRequest.fabricate_via_api! do |merge_request| + merge_request.project = project merge_request.title = 'This is a merge request' merge_request.description = '... for viewing merge-ref and merge-base diffs' merge_request.file_content = 'This exists on the source branch only' @@ -13,16 +20,14 @@ module QA let(:new_file_name) { "added_file-#{SecureRandom.hex(8)}.txt" } - before do - commit_to_branch(merge_request.target_branch, new_file_name) - commit_to_branch(merge_request.source_branch, new_file_name) - - Flow::Login.sign_in - end - context 'when the feature flag default_merge_ref_for_diffs is enabled' do before do - Runtime::Feature.enable('default_merge_ref_for_diffs', project: merge_request.project) + Runtime::Feature.enable('default_merge_ref_for_diffs', project: project) + + commit_to_branch(merge_request.target_branch, new_file_name) + commit_to_branch(merge_request.source_branch, new_file_name) + + Flow::Login.sign_in merge_request.visit! end @@ -42,7 +47,12 @@ module QA context 'when the feature flag default_merge_ref_for_diffs is disabled' do before do - Runtime::Feature.disable('default_merge_ref_for_diffs', project: merge_request.project) + Runtime::Feature.disable('default_merge_ref_for_diffs', project: project) + + commit_to_branch(merge_request.target_branch, new_file_name) + commit_to_branch(merge_request.source_branch, new_file_name) + + Flow::Login.sign_in merge_request.visit! end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb deleted file mode 100644 index 5aa5f0fc0a3..00000000000 --- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.describe 'Create' do - describe 'Files management' do - it 'user creates, edits and deletes a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/451' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) - - # Create - file_name = 'QA Test - File name' - file_content = 'QA Test - File content' - commit_message_for_create = 'QA Test - Create new file' - - Resource::File.fabricate_via_browser_ui! do |file| - file.name = file_name - file.content = file_content - file.commit_message = commit_message_for_create - end - - expect(page).to have_content(file_name) - expect(page).to have_content(file_content) - expect(page).to have_content(commit_message_for_create) - - # Edit - updated_file_content = 'QA Test - Updated file content' - commit_message_for_update = 'QA Test - Update file' - - Page::File::Show.perform(&:click_edit) - - Page::File::Form.act do - remove_content - add_content(updated_file_content) - add_commit_message(commit_message_for_update) - commit_changes - end - - expect(page).to have_content('Your changes have been successfully committed.') - expect(page).to have_content(updated_file_content) - expect(page).to have_content(commit_message_for_update) - - # Delete - commit_message_for_delete = 'QA Test - Delete file' - - Page::File::Show.act do - click_delete - add_commit_message(commit_message_for_delete) - click_delete_file - end - - expect(page).to have_content('The file has been successfully deleted.') - expect(page).to have_content(commit_message_for_delete) - expect(page).to have_no_content(file_name) - end - end - end -end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb new file mode 100644 index 00000000000..cd333b3cea2 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + context 'File management' do + file_name = 'QA Test - File name' + file_content = 'QA Test - File content' + commit_message_for_create = 'QA Test - Create new file' + + before do + Flow::Login.sign_in + end + + it 'user creates a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1093' do + Resource::File.fabricate_via_browser_ui! do |file| + file.name = file_name + file.content = file_content + file.commit_message = commit_message_for_create + end + + Page::File::Show.perform do |file| + aggregate_failures 'file details' do + expect(file).to have_file(file_name) + expect(file).to have_file_content(file_content) + expect(file).to have_commit_message(commit_message_for_create) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb new file mode 100644 index 00000000000..903001aa4f0 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + context 'File management' do + let(:file) { Resource::File.fabricate_via_api! } + + commit_message_for_delete = 'QA Test - Delete file' + + before do + Flow::Login.sign_in + file.visit! + end + + it 'user deletes a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1095' do + Page::File::Show.perform do |file| + file.click_delete + file.add_commit_message(commit_message_for_delete) + file.click_delete_file + end + + Page::Project::Show.perform do |project| + aggregate_failures 'file details' do + expect(project).to have_notice('The file has been successfully deleted.') + expect(project).to have_commit_message(commit_message_for_delete) + expect(project).not_to have_file(file.name) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb new file mode 100644 index 00000000000..0da774b557f --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + context 'File management' do + let(:file) { Resource::File.fabricate_via_api! } + + updated_file_content = 'QA Test - Updated file content' + commit_message_for_update = 'QA Test - Update file' + + before do + Flow::Login.sign_in + file.visit! + end + + it 'user edits a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1094' do + Page::File::Show.perform(&:click_edit) + + Page::File::Form.perform do |file| + file.remove_content + file.add_content(updated_file_content) + file.add_commit_message(commit_message_for_update) + file.commit_changes + end + + Page::File::Show.perform do |file| + aggregate_failures 'file details' do + expect(file).to have_notice('Your changes have been successfully committed.') + expect(file).to have_file_content(updated_file_content) + expect(file).to have_commit_message(commit_message_for_update) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb index 45afa252305..e4a492d3487 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb @@ -3,7 +3,7 @@ module QA RSpec.describe 'Create' do describe 'Push mirror a repository over HTTP' do - it 'configures and syncs LFS objects for a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/414' do + it 'configures and syncs LFS objects for a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1075' do Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.perform(&:sign_in_using_credentials) diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb index 00d4acbd1e1..f01a3b21eee 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb @@ -35,8 +35,11 @@ module QA # Check that the target project has the commit from the source target_project.visit! - expect(page).to have_content('README.md') - expect(page).to have_content('This is a test project') + + Page::Project::Show.perform do |project| + expect(project).to have_content('README.md') + expect(project).to have_content('This is a test project') + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb new file mode 100644 index 00000000000..469335db5ab --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Multiple file snippet' do + let(:personal_snippet) do + Resource::Snippet.fabricate_via_api! do |snippet| + snippet.title = 'Personal snippet to add file to' + snippet.file_name = 'Original file name' + snippet.file_content = 'Original file content' + end + end + + let(:project_snippet) do + Resource::ProjectSnippet.fabricate_via_api! do |snippet| + snippet.title = 'Project snippet to add file to' + snippet.file_name = 'Original file name' + snippet.file_content = 'Original file content' + end + end + + before do + Flow::Login.sign_in + end + + shared_examples 'adding file to snippet' do |snippet_type| + it "adds second file to an existing #{snippet_type} to make it multi-file" do + send(snippet_type).visit! + + Page::Dashboard::Snippet::Show.perform(&:click_edit_button) + + Page::Dashboard::Snippet::Edit.perform do |snippet| + snippet.click_add_file + snippet.fill_file_name('Second file name', 2) + snippet.fill_file_content('Second file content', 2) + snippet.save_changes + end + + Page::Dashboard::Snippet::Show.perform do |snippet| + aggregate_failures 'file names and contents' do + expect(snippet).to have_file_name('Original file name', 1) + expect(snippet).to have_file_content('Original file content', 1) + expect(snippet).to have_file_name('Second file name', 2) + expect(snippet).to have_file_content('Second file content', 2) + end + end + end + end + + it_behaves_like 'adding file to snippet', :personal_snippet + it_behaves_like 'adding file to snippet', :project_snippet + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb index a3f6d521766..efd61a2e63a 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do + RSpec.describe 'Create' do describe 'Version control for personal snippets' do let(:new_file) { 'new_snippet_file' } let(:changed_content) { 'changes' } @@ -22,13 +22,13 @@ module QA end let(:repository_uri_http) do - snippet + snippet.visit! Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_http) end let(:repository_uri_ssh) do ssh_key - snippet + snippet.visit! Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_ssh) end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb index be56b870490..79e2677da66 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do + RSpec.describe 'Create' do describe 'Version control for project snippets' do let(:new_file) { 'new_snippet_file' } let(:changed_content) { 'changes' } @@ -22,13 +22,13 @@ module QA end let(:repository_uri_http) do - snippet + snippet.visit! Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_http) end let(:repository_uri_ssh) do ssh_key - snippet + snippet.visit! Page::Dashboard::Snippet::Show.perform(&:get_repository_uri_ssh) end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb new file mode 100644 index 00000000000..ca6ea5db65d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Multiple file snippet' do + let(:personal_snippet) do + Resource::Snippet.fabricate_via_api! do |snippet| + snippet.title = 'Personal snippet to delete file from' + snippet.file_name = 'Original file name' + snippet.file_content = 'Original file content' + + snippet.add_files do |files| + files.append(name: 'Second file name', content: 'Second file content') + end + end + end + + let(:project_snippet) do + Resource::ProjectSnippet.fabricate_via_api! do |snippet| + snippet.title = 'Project snippet to delete file from' + snippet.file_name = 'Original file name' + snippet.file_content = 'Original file content' + + snippet.add_files do |files| + files.append(name: 'Second file name', content: 'Second file content') + end + end + end + + before do + Flow::Login.sign_in + end + + shared_examples 'deleting file from snippet' do |snippet_type| + it "deletes second file from an existing #{snippet_type} to make it single-file" do + send(snippet_type).visit! + + Page::Dashboard::Snippet::Show.perform(&:click_edit_button) + + Page::Dashboard::Snippet::Edit.perform do |snippet| + snippet.click_delete_file(2) + snippet.save_changes + end + + Page::Dashboard::Snippet::Show.perform do |snippet| + aggregate_failures 'file names and contents' do + expect(snippet).to have_file_name('Original file name') + expect(snippet).to have_file_content('Original file content') + expect(snippet).to have_no_file_name('Second file name') + expect(snippet).to have_no_file_content('Second file content') + end + end + end + end + + it_behaves_like 'deleting file from snippet', :personal_snippet + it_behaves_like 'deleting file from snippet', :project_snippet + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb index 6b21d84cb13..971c5371d44 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb @@ -18,7 +18,7 @@ module QA context 'when the snippet is public' do it 'can be shared with not signed-in users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1016' do - snippet + snippet.visit! sharing_link = Page::Dashboard::Snippet::Show.perform do |snippet| expect(snippet).to have_embed_dropdown @@ -40,7 +40,7 @@ module QA context 'when the snippet is changed to private' do it 'does not display Embed/Share dropdown', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1015' do - snippet + snippet.visit! Page::Dashboard::Snippet::Show.perform do |snippet| expect(snippet).to have_embed_dropdown diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb index 8de739f1559..1e6cb4047f9 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb @@ -65,8 +65,7 @@ module QA ) end.project.visit! - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + Flow::Pipeline.visit_latest_pipeline { 'test-success': :passed, diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb new file mode 100644 index 00000000000..cedc2db2a1a --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require 'faker' + +module QA + RSpec.describe 'Verify', :runner, :requires_admin, :skip_live_env do + describe "Include multiple files from a project" do + let(:feature_flag) { :ci_include_multiple_files_from_project } + let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + let(:expected_text) { Faker::Lorem.sentence } + let(:unexpected_text) { Faker::Lorem.sentence } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-pipeline-1' + end + end + + let(:other_project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-pipeline-2' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = [executor] + end + end + + before do + Runtime::Feature.enable(feature_flag) + Flow::Login.sign_in + add_included_files + add_main_ci_file + project.visit! + view_the_last_pipeline + end + + after do + Runtime::Feature.disable(feature_flag) + runner.remove_via_api! + end + + it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1082' do + Page::Project::Pipeline::Show.perform do |pipeline| + aggregate_failures 'pipeline has all expected jobs' do + expect(pipeline).to have_job('build') + expect(pipeline).to have_job('test') + expect(pipeline).to have_job('deploy') + end + + pipeline.click_job('test') + end + + Page::Project::Job::Show.perform do |job| + aggregate_failures 'main CI is not overridden' do + expect(job.output).to have_no_content("#{unexpected_text}") + expect(job.output).to have_content("#{expected_text}") + end + end + end + + private + + def add_main_ci_file + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add config file' + commit.add_files([main_ci_file]) + end + end + + def add_included_files + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = other_project + commit.commit_message = 'Add files' + commit.add_files([included_file_1, included_file_2]) + end + end + + def view_the_last_pipeline + Page::Project::Menu.perform(&:click_ci_cd_pipelines) + Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_success) + Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + end + + def main_ci_file + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + include: + - project: #{other_project.full_path} + file: + - file1.yml + - file2.yml + + build: + stage: build + tags: ["#{executor}"] + script: echo 'build' + + test: + stage: test + tags: ["#{executor}"] + script: echo "#{expected_text}" + YAML + } + end + + def included_file_1 + { + file_path: 'file1.yml', + content: <<~YAML + test: + stage: test + tags: ["#{executor}"] + script: echo "#{unexpected_text}" + YAML + } + end + + def included_file_2 + { + file_path: 'file2.yml', + content: <<~YAML + deploy: + stage: deploy + tags: ["#{executor}"] + script: echo 'deploy' + YAML + } + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb new file mode 100644 index 00000000000..c5d73d2fd7d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'faker' + +module QA + RSpec.describe 'Verify', :runner do + context 'When pipeline is blocked' do + let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-blocked-pipeline' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = [executor] + end + end + + let!(:ci_file) do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files( + [ + file_path: '.gitlab-ci.yml', + content: <<~YAML + test_blocked_pipeline: + stage: build + tags: [#{executor}] + script: echo 'OK!' + + manual_job: + stage: test + needs: [test_blocked_pipeline] + script: echo do not click me + when: manual + + dummy_job: + stage: deploy + needs: [manual_job] + script: echo nothing + YAML + ] + ) + end + end + + let(:merge_request) do + Resource::MergeRequest.fabricate_via_api! do |merge_request| + merge_request.project = project + merge_request.description = Faker::Lorem.sentence + merge_request.target_new_branch = false + merge_request.file_name = 'custom_file.txt' + merge_request.file_content = Faker::Lorem.sentence + end + end + + before do + Flow::Login.sign_in + merge_request.visit! + end + + after do + runner.remove_via_api! + end + + it 'can still merge MR successfully', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/971' do + Page::MergeRequest::Show.perform do |show| + show.wait_until(reload: false) { show.has_pipeline_status?('running') } + show.merge_immediately! + + expect(show).to be_merged + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb new file mode 100644 index 00000000000..eafe28c1ee6 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +require 'faker' + +module QA + RSpec.describe 'Verify', :runner, :requires_admin do + describe "Pass dotenv variables to downstream via bridge" do + let(:feature_flag) { :ci_bridge_dependency_variables } + let(:executor_1) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + let(:executor_2) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + + let(:upstream_project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-pipeline-1' + end + end + + let(:downstream_project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-pipeline-2' + end + end + + let!(:runner_1) do + Resource::Runner.fabricate! do |runner| + runner.project = upstream_project + runner.name = executor_1 + runner.tags = [executor_1] + end + end + + let!(:runner_2) do + Resource::Runner.fabricate! do |runner| + runner.project = downstream_project + runner.name = executor_2 + runner.tags = [executor_2] + end + end + + before do + Runtime::Feature.enable(feature_flag) + Flow::Login.sign_in + add_ci_file(downstream_project, downstream_ci_file) + add_ci_file(upstream_project, upstream_ci_file) + upstream_project.visit! + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'success') + end + + after do + Runtime::Feature.disable(feature_flag) + runner_1.remove_via_api! + runner_2.remove_via_api! + end + + it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1086' do + Page::Project::Pipeline::Show.perform do |parent_pipeline| + Support::Waiter.wait_until { parent_pipeline.has_child_pipeline? } + parent_pipeline.expand_child_pipeline + parent_pipeline.click_job('downstream_test') + end + + Page::Project::Job::Show.perform do |show| + expect(show).to have_passed(timeout: 360) + end + end + + private + + def add_ci_file(project, file) + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add config file' + commit.add_files([file]) + end + end + + def upstream_ci_file + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + build: + stage: build + tags: ["#{executor_1}"] + script: echo "MY_VAR=hello" >> variables.env + artifacts: + reports: + dotenv: variables.env + + trigger: + stage: deploy + variables: + PASSED_MY_VAR: $MY_VAR + trigger: #{downstream_project.full_path} + YAML + } + end + + def downstream_ci_file + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + downstream_test: + stage: test + tags: ["#{executor_2}"] + script: '[ "$PASSED_MY_VAR" = hello ]; exit "$?"' + YAML + } + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb index 153ccafaa20..b79bda108af 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb @@ -2,11 +2,8 @@ module QA RSpec.describe 'Verify' do - describe 'Run pipeline', :requires_admin, :skip_live_env do - # [TODO]: Developer to remove :requires_admin and :skip_live_env once FF is removed in https://gitlab.com/gitlab-org/gitlab/-/issues/229632 - + describe 'Run pipeline', only: { subdomain: :staging } do context 'with web only rule' do - let(:feature_flag) { :new_pipeline_form } let(:job_name) { 'test_job' } let(:project) do Resource::Project.fabricate_via_api! do |project| @@ -20,33 +17,29 @@ module QA commit.commit_message = 'Add .gitlab-ci.yml' commit.add_files( [ - { - file_path: '.gitlab-ci.yml', - content: <<~YAML - #{job_name}: - tags: - - #{project.name} - script: echo 'OK' - only: - - web - YAML - } + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + #{job_name}: + tags: + - #{project.name} + script: echo 'OK' + only: + - web + + YAML + } ] ) end end before do - Runtime::Feature.enable(feature_flag) # [TODO]: Developer to remove when feature flag is removed Flow::Login.sign_in project.visit! Page::Project::Menu.perform(&:click_ci_cd_pipelines) end - after do - Runtime::Feature.disable(feature_flag) # [TODO]: Developer to remove when feature flag is removed - end - it 'can trigger pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/946' do Page::Project::Pipeline::Index.perform do |index| expect(index).not_to have_pipeline # should not auto trigger pipeline diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb index 39d5fbaba6b..2f66ed697a3 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb @@ -29,7 +29,7 @@ module QA Flow::Login.sign_in add_ci_files project.visit! - view_the_last_pipeline + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'success') end after do @@ -64,12 +64,6 @@ module QA end end - def view_the_last_pipeline - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_success) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) - end - def parent_ci_file { file_path: '.gitlab-ci.yml', diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb new file mode 100644 index 00000000000..7783dba3fa7 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :packages do + describe 'Composer Repository' do + include Runtime::Fixtures + + let(:package_name) { 'my_package' } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'composer-package-project' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + let!(:gitlab_address_with_port) do + uri = URI.parse(Runtime::Scenario.gitlab_address) + "#{uri.scheme}://#{uri.host}:#{uri.port}" + end + + let(:composer_json_file) do + <<~EOF + { + "name": "#{project.path_with_namespace}/#{package_name}", + "description": "Library XY", + "type": "library", + "license": "GPL-3.0-only", + "authors": [ + { + "name": "John Doe", + "email": "john@example.com" + } + ], + "require": {} + } + EOF + end + + let(:gitlab_ci_yaml) do + <<~YAML + publish: + image: curlimages/curl:latest + stage: build + variables: + URL: "$CI_SERVER_PROTOCOL://$CI_SERVER_HOST:$CI_SERVER_PORT/api/v4/projects/$CI_PROJECT_ID/packages/composer?job_token=$CI_JOB_TOKEN" + script: + - version=$([[ -z "$CI_COMMIT_TAG" ]] && echo "branch=$CI_COMMIT_REF_NAME" || echo "tag=$CI_COMMIT_TAG") + - insecure=$([ "$CI_SERVER_PROTOCOL" = "http" ] && echo "--insecure" || echo "") + - response=$(curl -s -w "%{http_code}" $insecure --data $version $URL) + - code=$(echo "$response" | tail -n 1) + - body=$(echo "$response" | head -n 1) + tags: + - "runner-for-#{project.name}" + YAML + end + + before do + Flow::Login.sign_in + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([{ + file_path: '.gitlab-ci.yml', + content: gitlab_ci_yaml + }, + { + file_path: 'composer.json', + content: composer_json_file + }] + ) + end + + project.visit! + Page::Project::Menu.perform(&:click_ci_cd_pipelines) + Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('publish') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + end + + after do + runner.remove_via_api! + end + + it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1088' do + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_package(package_name) + index.click_package(package_name) + end + + Page::Project::Packages::Show.perform do |package| + package.click_delete + end + + Page::Project::Packages::Index.perform do |index| + aggregate_failures 'package deletion' do + expect(index).to have_content("Package deleted successfully") + expect(index).to have_no_package(package_name) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb new file mode 100644 index 00000000000..2b06ba8646f --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :packages do + describe 'Conan Repository' do + include Runtime::Fixtures + + let(:package_name) { 'conantest' } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'conan-package-project' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + let(:gitlab_address_with_port) do + uri = URI.parse(Runtime::Scenario.gitlab_address) + "#{uri.scheme}://#{uri.host}:#{uri.port}" + end + + after do + runner.remove_via_api! + end + + it 'publishes a conan package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do + Flow::Login.sign_in + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([{ + file_path: '.gitlab-ci.yml', + content: + <<~YAML + image: conanio/gcc7 + + create_package: + stage: deploy + script: + - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan" + - "conan new #{package_name}/0.1 -t" + - "conan create . mycompany/stable" + - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package_name}/0.1@mycompany/stable --all --remote=gitlab" + tags: + - "runner-for-#{project.name}" + YAML + }]) + end + + project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('create_package') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_package(package_name) + index.click_package(package_name) + end + + Page::Project::Packages::Show.perform do |package| + package.click_delete + end + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_content("Package deleted successfully") + expect(index).to have_no_package(package_name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb new file mode 100644 index 00000000000..e163fcbe574 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :packages do + describe 'Maven Repository with Gradle' do + include Runtime::Fixtures + + let(:group_id) { 'com.gitlab.qa' } + let(:artifact_id) { 'maven_gradle' } + let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') } + let(:auth_token) do + unless Page::Main::Menu.perform(&:signed_in?) + Flow::Login.sign_in + end + + Resource::PersonalAccessToken.fabricate!.access_token + end + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'maven-with-gradle-project' + project.initialize_with_readme = true + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + let(:gitlab_address_with_port) do + uri = URI.parse(Runtime::Scenario.gitlab_address) + "#{uri.scheme}://#{uri.host}:#{uri.port}" + end + + after do + runner.remove_via_api! + end + + it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([{ + file_path: '.gitlab-ci.yml', + content: + <<~YAML + deploy: + image: gradle:6.5-jdk11 + script: + - 'gradle publish' + only: + - master + tags: + - "runner-for-#{project.name}" + YAML + }, + { + file_path: 'build.gradle', + content: + <<~EOF + plugins { + id 'java' + id 'maven-publish' + } + + publishing { + publications { + library(MavenPublication) { + groupId '#{group_id}' + artifactId '#{artifact_id}' + from components.java + } + } + repositories { + maven { + url "#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/maven" + credentials(HttpHeaderCredentials) { + name = "Private-Token" + value = "#{auth_token}" + } + authentication { + header(HttpHeaderAuthentication) + } + } + } + } + EOF + }]) + end + + project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('deploy') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_package(package_name) + + index.click_package(package_name) + end + + Page::Project::Packages::Show.perform do |show| + show.click_delete + end + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_content("Package deleted successfully") + expect(index).to have_no_package(package_name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb new file mode 100644 index 00000000000..0b70adf9ff6 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :packages do + describe 'NuGet Repository' do + include Runtime::Fixtures + + let(:package_name) { 'dotnetcore' } + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'nuget-package-project' + project.template_name = 'dotnetcore' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + after do + runner.remove_via_api! + end + + it 'publishes a nuget package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do + Flow::Login.sign_in + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.update_files( + [ + { + file_path: '.gitlab-ci.yml', + content: <<~YAML + image: mcr.microsoft.com/dotnet/core/sdk:3.1 + + stages: + - deploy + + deploy: + stage: deploy + script: + - dotnet restore -p:Configuration=Release + - dotnet build -c Release + - dotnet pack -c Release + - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text + - dotnet nuget push "bin/Release/*.nupkg" --source gitlab + only: + - master + tags: + - "runner-for-#{project.name}" + YAML + } + ] + ) + end + + project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('deploy') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_package(package_name) + index.click_package(package_name) + end + + Page::Project::Packages::Show.perform do |package| + package.click_delete + end + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_content("Package deleted successfully") + expect(index).to have_no_package(package_name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb new file mode 100644 index 00000000000..35c41bbb2b0 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb @@ -0,0 +1,113 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :packages do + describe 'PyPI Repository' do + include Runtime::Fixtures + + let(:package_name) { 'mypypipackage' } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'pypi-package-project' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + let(:gitlab_address_with_port) do + uri = URI.parse(Runtime::Scenario.gitlab_address) + "#{uri.scheme}://#{uri.host}:#{uri.port}" + end + + before do + Flow::Login.sign_in + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([{ + file_path: '.gitlab-ci.yml', + content: + <<~YAML + image: python:latest + + run: + script: + - pip install twine + - python setup.py sdist bdist_wheel + - "TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*" + tags: + - "runner-for-#{project.name}" + YAML + }, + { + file_path: 'setup.py', + content: + <<~EOF + import setuptools + + setuptools.setup( + name="mypypipackage", + version="0.0.1", + author="Example Author", + author_email="author@example.com", + description="A small example package", + packages=setuptools.find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + python_requires='>=3.6', + ) + EOF + + }]) + end + + project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('run') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + end + + after do + runner.remove_via_api! + end + + it 'publishes a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1087' do + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_package(package_name) + index.click_package(package_name) + end + + Page::Project::Packages::Show.perform do |package| + package.click_delete + end + + Page::Project::Packages::Index.perform do |index| + aggregate_failures do + expect(index).to have_content("Package deleted successfully") + expect(index).to have_no_package(package_name) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb index abac4f2b91d..8e61ec4d2d7 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb @@ -77,8 +77,7 @@ module QA sha1sum = Digest::SHA1.hexdigest(gitlab_ci) - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform(&:click_on_first_job) Page::Project::Job::Show.perform do |job| diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb index de035e3278a..10795654617 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Release', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/213222', type: :flaky } do + RSpec.describe 'Release' do describe 'Deploy token creation' do it 'user adds a deploy token', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/419' do Flow::Login.sign_in diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb index ece45d093a7..ec26e338b28 100644 --- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb @@ -27,7 +27,7 @@ module QA it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/751' do add_ci_files(success_child_ci_file) - view_pipelines + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline @@ -37,7 +37,7 @@ module QA it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/752' do add_ci_files(fail_child_ci_file) - view_pipelines + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline @@ -47,12 +47,6 @@ module QA private - def view_pipelines - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_completion) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) - end - def success_child_ci_file { file_path: '.child-ci.yml', diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb index 38cee0e62ca..d7f5a326b0e 100644 --- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb @@ -27,7 +27,7 @@ module QA it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/754' do add_ci_files(success_child_ci_file) - view_pipelines + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline @@ -37,7 +37,7 @@ module QA it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/753' do add_ci_files(fail_child_ci_file) - view_pipelines + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline @@ -47,12 +47,6 @@ module QA private - def view_pipelines - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_completion) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) - end - def success_child_ci_file { file_path: '.child-ci.yml', diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb index 6d31780f196..a619ccfad19 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb @@ -54,8 +54,7 @@ module QA push.commit_message = 'Create Auto DevOps compatible rack application' end - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| pipeline.click_job('build') @@ -119,8 +118,7 @@ module QA end it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/444' do - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| expect(pipeline).to have_tag('Auto DevOps') |