diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 15:44:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 15:44:42 +0000 |
commit | 4555e1b21c365ed8303ffb7a3325d773c9b8bf31 (patch) | |
tree | 5423a1c7516cffe36384133ade12572cf709398d /qa | |
parent | e570267f2f6b326480d284e0164a6464ba4081bc (diff) | |
download | gitlab-ce-4555e1b21c365ed8303ffb7a3325d773c9b8bf31.tar.gz |
Add latest changes from gitlab-org/gitlab@13-12-stable-eev13.12.0-rc42
Diffstat (limited to 'qa')
111 files changed, 2015 insertions, 597 deletions
diff --git a/qa/Gemfile b/qa/Gemfile index 21ca945a500..8b3a9802000 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -23,6 +23,9 @@ gem 'parallel', '~> 1.19' gem 'rspec-parameterized', '~> 0.4.2' gem 'github_api', '~> 0.18.2' +gem 'chemlab', '~> 0.5' +gem 'chemlab-library-www-gitlab-com', '~> 0.1' + group :development do gem 'pry-byebug', '~> 3.5.1', platform: :mri gem "ruby-debug-ide", "~> 0.7.0" diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 4eeaca1f1a6..9bac86bad08 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -33,6 +33,12 @@ GEM capybara-screenshot (1.0.23) capybara (>= 1.0, < 4) launchy + chemlab (0.5.0) + rake (~> 12.3.0) + selenium-webdriver (~> 3.12) + watir (~> 6.17) + chemlab-library-www-gitlab-com (0.1.1) + chemlab (~> 0.4) childprocess (3.0.0) coderay (1.1.2) concord (0.1.5) @@ -163,6 +169,9 @@ GEM equalizer (~> 0.0.9) parser (>= 2.6.5) procto (~> 0.0.2) + watir (6.18.0) + regexp_parser (>= 1.2, < 3) + selenium-webdriver (>= 3.8) xpath (3.2.0) nokogiri (~> 1.8) zeitwerk (2.4.2) @@ -175,6 +184,8 @@ DEPENDENCIES airborne (~> 0.3.4) capybara (~> 3.29.0) capybara-screenshot (~> 1.0.23) + chemlab (~> 0.5) + chemlab-library-www-gitlab-com (~> 0.1) faker (~> 1.6, >= 1.6.6) github_api (~> 0.18.2) gitlab-qa diff --git a/qa/README.md b/qa/README.md index 02fa84f4488..dc4a64fb8a9 100644 --- a/qa/README.md +++ b/qa/README.md @@ -54,9 +54,7 @@ the browser to use. You will need to have Chrome (or Chromium) and ### Run the end-to-end tests in a local development environment -Follow the GDK instructions to [prepare](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/prepare.md) -and [install](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/set-up-gdk.md) -your local GitLab development environment. +Follow the GDK instructions to [install](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/index.md) your local GitLab development environment. Once you have GDK running, switch to the `qa` directory. E.g., if you setup GDK to develop in the main `gitlab-ce` repo, the GitLab source code will be diff --git a/qa/knapsack/master_report.json b/qa/knapsack/master_report.json index 467150e84c7..47c6099a36d 100644 --- a/qa/knapsack/master_report.json +++ b/qa/knapsack/master_report.json @@ -1,54 +1,195 @@ { "qa/specs/features/ee/api/2_plan/epics_milestone_dates_spec.rb": 4.835599899291992, - "qa/specs/features/ee/browser_ui/2_plan/epic/epics_management_spec.rb": 69.85551619529724, - "qa/specs/features/ee/browser_ui/2_plan/epic/promote_issue_to_epic_spec.rb": 14.649160623550415, - "qa/specs/features/ee/browser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb": 12.790381908416748, - "qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb": 0.00018262863159179688, - "qa/specs/features/ee/browser_ui/3_create/repository/assign_code_owners_spec.rb": 59.73394823074341, "qa/specs/features/ee/browser_ui/3_create/repository/code_owners_spec.rb": 26.39240026473999, "qa/specs/features/ee/browser_ui/secure/create_project_with_secure_spec.rb": 46.76790499687195, "qa/specs/features/api/1_manage/users_spec.rb": 0.6089541912078857, - "qa/specs/features/api/3_create/repository/files_spec.rb": 5.015859127044678, - "qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb": 1.0199065208435059, - "qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb": 33.54091453552246, - "qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb": 3.438166856765747, "qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb": 20.58603596687317, - "qa/specs/features/browser_ui/1_manage/login/register_spec.rb": 22.320587396621704, - "qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb": 8.490083694458008, - "qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb": 10.214765310287476, - "qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb": 100.28881478309631, - "qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb": 7.882027864456177, - "qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb": 13.739388942718506, - "qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb": 13.403101205825806, - "qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb": 10.989444971084595, - "qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb": 10.811973810195923, - "qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb": 12.63524317741394, - "qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb": 11.280649185180664, - "qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb": 41.76726770401001, - "qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb": 32.5517954826355, - "qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb": 46.54227638244629, - "qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb": 27.943300485610962, - "qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb": 3.705310821533203, - "qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb": 40.09336972236633, "qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb": 31.49540114402771, "qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb": 16.18057894706726, - "qa/specs/features/browser_ui/3_create/repository/clone_spec.rb": 0.7397980690002441, "qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb": 18.047621726989746, - "qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb": 9.48607873916626, - "qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb": 23.710937023162842, "qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb": 19.459370374679565, - "qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb": 7.730542182922363, - "qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb": 29.76174831390381, "qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb": 22.800872802734375, - "qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb": 6.731764793395996, "qa/specs/features/browser_ui/3_create/snippet/create_snippet_spec.rb": 5.812374591827393, - "qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb": 25.460349321365356, "qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb": 17.273863554000854, "qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb": 8.31815505027771, - "qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb": 18.679633855819702, - "qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb": 15.342933893203735, - "qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb": 92.46774697303772, - "qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb": 20.252174615859985, - "qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb": 8.281434059143066, - "qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb": 8.810423135757446 -}
\ No newline at end of file + "qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb": 8.810423135757446, + "qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb": 51.81568956375122, + "qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb": 30.373554468154907, + "qa/specs/features/sanity/version_spec.rb": 0.0004665851593017578, + "qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb": 22.993898630142212, + "qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb": 58.383920192718506, + "qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb": 58.99856781959534, + "qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb": 36.358747243881226, + "qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb": 9.079580068588257, + "qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb": 39.412545919418335, + "qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb": 27.905837297439575, + "qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb": 130.09448766708374, + "qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb": 36.39329433441162, + "qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb": 99.71209812164307, + "qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb": 34.64759969711304, + "qa/specs/features/ee/browser_ui/2_plan/epic/promote_issue_to_epic_spec.rb": 25.72262978553772, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/project_issue_boards_spec.rb": 44.536749839782715, + "qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb": 18.482256174087524, + "qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb": 107.76105904579163, + "qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb": 16.314701795578003, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/read_only_board_configuration_spec.rb": 36.934654235839844, + "qa/specs/features/ee/browser_ui/2_plan/iterations/create_group_iteration_spec.rb": 17.103047847747803, + "qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb": 43.9788339138031, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/configurable_issue_board_spec.rb": 27.46922779083252, + "qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb": 28.352823495864868, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/configure_issue_board_by_label_spec.rb": 20.208287954330444, + "qa/specs/features/ee/browser_ui/2_plan/burndown_chart/burndown_chart_spec.rb": 13.733941793441772, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/sum_of_issues_weights_spec.rb": 21.879905223846436, + "qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb": 16.376311540603638, + "qa/specs/features/ee/browser_ui/2_plan/epic/epics_management_spec.rb": 98.71593880653381, + "qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/four_assignees_spec.rb": 39.15917229652405, + "qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb": 21.307689666748047, + "qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/more_than_four_assignees_spec.rb": 39.39231467247009, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/create_group_issue_board_spec.rb": 18.50350284576416, + "qa/specs/features/ee/browser_ui/2_plan/issues_analytics/issues_analytics_spec.rb": 30.67392325401306, + "qa/specs/features/ee/browser_ui/2_plan/custom_email/custom_email_spec.rb": 16.17888569831848, + "qa/specs/features/ee/browser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb": 45.47245216369629, + "qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb": 38.93913507461548, + "qa/specs/features/ee/browser_ui/2_plan/epic/roadmap_spec.rb": 12.087258100509644, + "qa/specs/features/ee/browser_ui/2_plan/issue_boards/group_issue_boards_spec.rb": 17.309232473373413, + "qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb": 67.43084001541138, + "qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb": 70.75156497955322, + "qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb": 22.20275855064392, + "qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb": 24.21539831161499, + "qa/specs/features/ee/browser_ui/2_plan/issues_weight/issue_weight_visualization_spec.rb": 20.22646951675415, + "qa/specs/features/ee/browser_ui/2_plan/iterations/assign_group_iteration_spec.rb": 31.00749373435974, + "qa/specs/features/ee/browser_ui/2_plan/issue/default_issue_template_spec.rb": 18.430193424224854, + "qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb": 13.615312337875366, + "qa/specs/features/ee/browser_ui/1_manage/project/project_templates_spec.rb": 54.21430277824402, + "qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_subgroup_spec.rb": 189.6901969909668, + "qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb": 94.04865074157715, + "qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb": 59.575963258743286, + "qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb": 12.545408725738525, + "qa/specs/features/ee/browser_ui/1_manage/group/share_group_with_group_spec.rb": 25.6483793258667, + "qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb": 48.9726402759552, + "qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb": 26.07162046432495, + "qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb": 8.41316819190979, + "qa/specs/features/ee/browser_ui/secure/merge_request_license_widget_spec.rb": 73.56247329711914, + "qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb": 70.19135999679565, + "qa/specs/features/api/3_create/repository/files_spec.rb": 6.235261917114258, + "qa/specs/features/browser_ui/5_package/container_registry_spec.rb": 7.263134717941284, + "qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb": 10.079012870788574, + "qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb": 16.52791404724121, + "qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb": 10.684799909591675, + "qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb": 72.14465713500977, + "qa/specs/features/api/1_manage/project_access_token_spec.rb": 1.7818918228149414, + "qa/specs/features/ee/browser_ui/4_verify/pipeline_subscription_with_group_owned_project_spec.rb": 46.62651777267456, + "qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb": 41.63330125808716, + "qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb": 15.664107322692871, + "qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb": 34.32576060295105, + "qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb": 31.586787939071655, + "qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb": 27.983626127243042, + "qa/specs/features/ee/browser_ui/secure/project_security_dashboard_spec.rb": 27.6742160320282, + "qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb": 33.06922268867493, + "qa/specs/features/ee/browser_ui/3_create/wiki/create_group_wiki_page_spec.rb": 22.77417540550232, + "qa/specs/features/api/1_manage/rate_limits_spec.rb": 11.836639165878296, + "qa/specs/features/ee/browser_ui/1_manage/user/minimal_access_user_spec.rb": 15.691015005111694, + "qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb": 26.72679090499878, + "qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb": 38.80854368209839, + "qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb": 15.07186245918274, + "qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb": 41.58929800987244, + "qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb": 101.82257866859436, + "qa/specs/features/ee/browser_ui/4_verify/pipelines_for_merged_results_and_merge_trains_spec.rb": 114.47506761550903, + "qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb": 13.438591957092285, + "qa/specs/features/ee/browser_ui/3_create/merge_request/default_merge_request_template_spec.rb": 30.66688632965088, + "qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb": 25.137597799301147, + "qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb": 72.90312123298645, + "qa/specs/features/browser_ui/3_create/repository/clone_spec.rb": 8.731743574142456, + "qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb": 0.0008337497711181641, + "qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb": 40.60329842567444, + "qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb": 48.4540741443634, + "qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb": 39.090237617492676, + "qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb": 22.633376359939575, + "qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb": 18.457061767578125, + "qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb": 49.273433685302734, + "qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb": 14.6923348903656, + "qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb": 81.94199562072754, + "qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb": 38.44519090652466, + "qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb": 46.04780888557434, + "qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb": 27.77385425567627, + "qa/specs/features/ee/browser_ui/1_manage/insights/default_insights_spec.rb": 28.850987195968628, + "qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb": 19.598198413848877, + "qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb": 65.70130896568298, + "qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb": 15.17819595336914, + "qa/specs/features/ee/browser_ui/1_manage/instance/instance_audit_logs_spec.rb": 104.32384181022644, + "qa/specs/features/ee/browser_ui/3_create/repository/code_owners_with_protected_branch_and_squashed_commits_spec.rb": 50.42676067352295, + "qa/specs/features/api/1_manage/user_access_termination_spec.rb": 6.3396782875061035, + "qa/specs/features/ee/browser_ui/secure/create_merge_request_with_secure_spec.rb": 71.55253982543945, + "qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb": 58.73203682899475, + "qa/specs/features/ee/browser_ui/4_verify/new_discussion_not_dropping_merge_trains_mr_spec.rb": 65.0450668334961, + "qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb": 42.83795666694641, + "qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb": 60.95837211608887, + "qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb": 17.03721809387207, + "qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb": 25.14606213569641, + "qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb": 70.44876503944397, + "qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb": 52.93111038208008, + "qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb": 48.3312201499939, + "qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb": 52.52523970603943, + "qa/specs/features/ee/browser_ui/secure/security_reports_spec.rb": 49.19262075424194, + "qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb": 120.86664414405823, + "qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb": 38.46292161941528, + "qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_2_spec.rb": 100.1787781715393, + "qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb": 22.37237572669983, + "qa/specs/features/ee/browser_ui/1_manage/group/group_file_template_spec.rb": 69.36870694160461, + "qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb": 69.17281556129456, + "qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb": 13.524356126785278, + "qa/specs/features/ee/browser_ui/1_manage/group/prevent_forking_outside_group_spec.rb": 37.17233395576477, + "qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb": 6.892294406890869, + "qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb": 40.91694402694702, + "qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb": 12.628767013549805, + "qa/specs/features/ee/browser_ui/secure/enable_sast_from_configuration_spec.rb": 86.38991785049438, + "qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb": 79.2712254524231, + "qa/specs/features/ee/browser_ui/3_create/repository/file_locking_spec.rb": 161.1801998615265, + "qa/specs/features/ee/browser_ui/4_verify/pipeline_for_project_mirror_github_spec.rb": 12.684113502502441, + "qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb": 31.481987714767456, + "qa/specs/features/ee/browser_ui/secure/vulnerability_management_spec.rb": 80.21465563774109, + "qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb": 12.836287260055542, + "qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb": 38.852850675582886, + "qa/specs/features/ee/browser_ui/3_create/repository/assign_code_owners_spec.rb": 34.88499307632446, + "qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb": 35.340261459350586, + "qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb": 19.719850540161133, + "qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb": 38.779794216156006, + "qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb": 6.86094856262207, + "qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb": 51.54451298713684, + "qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb": 25.940913677215576, + "qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb": 18.586050033569336, + "qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb": 35.587294578552246, + "qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb": 14.01547122001648, + "qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb": 20.370421409606934, + "qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb": 15.297787427902222, + "qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb": 42.507469177246094, + "qa/specs/features/ee/browser_ui/4_verify/pipeline_status_on_operation_dashboard_spec.rb": 46.77937316894531, + "qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_root_group_spec.rb": 131.23758912086487, + "qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb": 20.96509575843811, + "qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb": 44.40894651412964, + "qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb": 12.62861156463623, + "qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb": 49.85329723358154, + "qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb": 84.63548684120178, + "qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb": 15.584527254104614, + "qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb": 30.72457480430603, + "qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb": 10.70707631111145, + "qa/specs/features/ee/api/1_manage/user/minimal_access_user_spec.rb": 4.82462477684021, + "qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb": 16.23528742790222, + "qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb": 32.49313712120056, + "qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb": 32.37481236457825, + "qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb": 15.82662057876587, + "qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb": 16.573434114456177, + "qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb": 43.15674066543579, + "qa/specs/features/ee/browser_ui/secure/license_compliance_spec.rb": 31.000027179718018, + "qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb": 149.64519357681274, + "qa/specs/features/ee/browser_ui/1_manage/group/restrict_by_ip_address_spec.rb": 116.07316851615906, + "qa/specs/features/browser_ui/1_manage/login/register_spec.rb": 145.5431580543518, + "qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb": 19.418848514556885, + "qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb": 18.54582905769348, + "qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb": 65.43303656578064, + "qa/specs/features/api/5_package/container_registry_spec.rb": 3.93778920173645, + "qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb": 148.70570707321167, + "qa/specs/features/ee/browser_ui/6_release/multi-project_pipelines_spec.rb": 52.770936250686646, + "qa/specs/features/ee/browser_ui/3_create/contribution_analytics_spec.rb": 45.81806302070618, + "qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb": 20.386794805526733 +} @@ -8,6 +8,8 @@ require_relative '../lib/gitlab' require_relative '../lib/gitlab/utils' require_relative '../config/initializers/0_inject_enterprise_edition_module' +require 'chemlab' + module QA ## # Helper classes to represent frequently used sequences of actions @@ -65,9 +67,11 @@ module QA autoload :ApiFabricator, 'qa/resource/api_fabricator' autoload :Base, 'qa/resource/base' + autoload :GroupBase, 'qa/resource/group_base' autoload :Sandbox, 'qa/resource/sandbox' autoload :Group, 'qa/resource/group' autoload :Issue, 'qa/resource/issue' + autoload :ProjectIssueNote, 'qa/resource/project_issue_note' autoload :Project, 'qa/resource/project' autoload :Label, 'qa/resource/label' autoload :MergeRequest, 'qa/resource/merge_request' @@ -224,6 +228,7 @@ module QA autoload :Show, 'qa/page/group/show' autoload :Menu, 'qa/page/group/menu' autoload :Members, 'qa/page/group/members' + autoload :BulkImport, 'qa/page/group/bulk_import' module Milestone autoload :Index, 'qa/page/group/milestone/index' @@ -260,12 +265,15 @@ module QA module Project autoload :New, 'qa/page/project/new' - autoload :NewExperiment, 'qa/page/project/new_experiment' autoload :Show, 'qa/page/project/show' autoload :Activity, 'qa/page/project/activity' autoload :Menu, 'qa/page/project/menu' autoload :Members, 'qa/page/project/members' + module Artifact + autoload :Show, 'qa/page/project/artifact/show' + end + module Branches autoload :Show, 'qa/page/project/branches/show' end @@ -412,12 +420,17 @@ module QA end end + module User + autoload :Show, 'qa/page/user/show' + end + module Issuable autoload :New, 'qa/page/issuable/new' end module Alert autoload :AutoDevopsAlert, 'qa/page/alert/auto_devops_alert' + autoload :FreeTrial, 'qa/page/alert/free_trial' end module Layout @@ -505,6 +518,7 @@ module QA autoload :WikiPageForm, 'qa/page/component/wiki_page_form' autoload :AccessTokens, 'qa/page/component/access_tokens' autoload :CommitModal, 'qa/page/component/commit_modal' + autoload :VisibilitySetting, 'qa/page/component/visibility_setting' module Issuable autoload :Common, 'qa/page/component/issuable/common' @@ -528,6 +542,11 @@ module QA end end + module Trials + autoload :New, 'qa/page/trials/new' + autoload :Select, 'qa/page/trials/select' + end + module Modal autoload :DeleteWiki, 'qa/page/modal/delete_wiki' end diff --git a/qa/qa/fixtures/rubygems_package/mygem.gemspec b/qa/qa/fixtures/rubygems_package/mygem.gemspec new file mode 100644 index 00000000000..33d8c88e5ac --- /dev/null +++ b/qa/qa/fixtures/rubygems_package/mygem.gemspec @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +Gem::Specification.new do |s| + s.name = 'mygem' + s.authors = ['Tanuki Steve', 'Hal 9000'] + s.author = 'Tanuki Steve' + s.version = '0.0.1' + s.date = '2011-09-29' + s.summary = 'package is the best' + s.files = ['lib/hello_gem.rb'] + s.require_paths = ['lib'] + + s.description = 'A test package for GitLab.' + s.email = 'tanuki@not_real.com' + s.homepage = 'https://gitlab.com/ruby-co/my-package' + s.license = 'MIT' + + s.metadata = { + 'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues', + 'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md', + 'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs', + 'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme', + 'source_code_uri' => 'https://gitlab.com/ruby-co/my-package' + } + + s.bindir = 'bin' + s.platform = Gem::Platform::RUBY + s.post_install_message = 'Installed, thank you!' + s.rdoc_options = ['--main'] + s.required_ruby_version = '>= 2.7.0' + s.required_rubygems_version = '>= 1.8.11' + s.requirements = 'A high powered server or calculator' + s.rubygems_version = '1.8.09' + + s.add_dependency 'dependency_1', '~> 1.2.3' + s.add_dependency 'dependency_2', '3.0.0' + s.add_dependency 'dependency_3', '>= 1.0.0' + s.add_dependency 'dependency_4' +end diff --git a/qa/qa/flow/project.rb b/qa/qa/flow/project.rb index 8a9e2c86332..397806b33a3 100644 --- a/qa/qa/flow/project.rb +++ b/qa/qa/flow/project.rb @@ -6,11 +6,7 @@ module QA module_function def go_to_create_project_from_template - if Page::Project::NewExperiment.perform(&:shown?) - Page::Project::NewExperiment.perform(&:click_create_from_template_link) - else - Page::Project::New.perform(&:click_create_from_template_tab) - end + Page::Project::New.perform(&:click_create_from_template_link) end end end diff --git a/qa/qa/flow/saml.rb b/qa/qa/flow/saml.rb index c414d648198..7cbaba9fbd5 100644 --- a/qa/qa/flow/saml.rb +++ b/qa/qa/flow/saml.rb @@ -18,7 +18,9 @@ module QA end end - def enable_saml_sso(group, saml_idp_service, default_membership_role = 'Guest') + def enable_saml_sso(group, saml_idp_service, enforce_sso: false, default_membership_role: 'Guest') + Runtime::Feature.enable(:group_administration_nav_item) + page.visit Runtime::Scenario.gitlab_address Page::Main::Login.perform(&:sign_in_using_credentials) unless Page::Main::Menu.perform(&:signed_in?) @@ -27,6 +29,7 @@ module QA Support::Retrier.retry_on_exception do EE::Page::Group::Settings::SamlSSO.perform do |saml_sso| + saml_sso.enforce_sso if enforce_sso saml_sso.set_id_provider_sso_url(saml_idp_service.idp_sso_url) saml_sso.set_cert_fingerprint(saml_idp_service.idp_certificate_fingerprint) saml_sso.set_default_membership_role(default_membership_role) diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb index 37275465221..e55e156fb8a 100644 --- a/qa/qa/page/admin/menu.rb +++ b/qa/qa/page/admin/menu.rb @@ -107,4 +107,4 @@ module QA end end -QA::Page::Admin::Menu.prepend_if_ee('QA::EE::Page::Admin::Menu') +QA::Page::Admin::Menu.prepend_mod_with('Page::Admin::Menu', namespace: QA) diff --git a/qa/qa/page/admin/overview/groups/edit.rb b/qa/qa/page/admin/overview/groups/edit.rb index c96e953d05b..8e4650a1232 100644 --- a/qa/qa/page/admin/overview/groups/edit.rb +++ b/qa/qa/page/admin/overview/groups/edit.rb @@ -20,4 +20,4 @@ module QA end end -QA::Page::Admin::Overview::Groups::Edit.prepend_if_ee('QA::EE::Page::Admin::Overview::Groups::Edit') +QA::Page::Admin::Overview::Groups::Edit.prepend_mod_with('Page::Admin::Overview::Groups::Edit', namespace: QA) diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb index 1885644d226..f8c79b4f72c 100644 --- a/qa/qa/page/admin/overview/users/index.rb +++ b/qa/qa/page/admin/overview/users/index.rb @@ -29,7 +29,7 @@ module QA def click_user(username) within_element(:user_row_content, text: username) do - click_element(:username_link) + click_link(username) end end end diff --git a/qa/qa/page/alert/free_trial.rb b/qa/qa/page/alert/free_trial.rb new file mode 100644 index 00000000000..4a48d4ca277 --- /dev/null +++ b/qa/qa/page/alert/free_trial.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module QA + module Page + module Alert + class FreeTrial < Chemlab::Page + # TODO: Supplant with data-qa-selectors + h4 :trial_activated_message, class: 'gl-banner-title' + end + end + end +end diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 289094268b6..66040bb9849 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -132,16 +132,16 @@ module QA all(element_selector_css(name), **kwargs) end - def check_element(name, click_by_js = false) - if find_element(name, visible: false).checked? + def check_element(name, click_by_js = false, visibility = false) + if find_element(name, visible: visibility).checked? QA::Runtime::Logger.debug("#{name} is already checked") return end retry_until(sleep_interval: 1) do - click_checkbox_or_radio(name, click_by_js) - checked = find_element(name, visible: false).checked? + click_checkbox_or_radio(name, click_by_js, visibility) + checked = find_element(name, visible: visibility).checked? QA::Runtime::Logger.debug(checked ? "#{name} was checked" : "#{name} was not checked") @@ -149,16 +149,16 @@ module QA end end - def uncheck_element(name, click_by_js = false) - unless find_element(name, visible: false).checked? + def uncheck_element(name, click_by_js = false, visibility = false) + unless find_element(name, visible: visibility).checked? QA::Runtime::Logger.debug("#{name} is already unchecked") return end retry_until(sleep_interval: 1) do - click_checkbox_or_radio(name, click_by_js) - unchecked = !find_element(name, visible: false).checked? + click_checkbox_or_radio(name, click_by_js, visibility) + unchecked = !find_element(name, visible: visibility).checked? QA::Runtime::Logger.debug(unchecked ? "#{name} was unchecked" : "#{name} was not unchecked") @@ -167,21 +167,22 @@ module QA end # Method for selecting radios - def choose_element(name, click_by_js = false) - if find_element(name, visible: false).checked? + def choose_element(name, click_by_js = false, visibility = false) + if find_element(name, visible: visibility).checked? QA::Runtime::Logger.debug("#{name} is already selected") return end retry_until(sleep_interval: 1) do - click_checkbox_or_radio(name, click_by_js) - selected = find_element(name, visible: false).checked? + click_checkbox_or_radio(name, click_by_js, visibility) + selected = find_element(name, visible: visibility).checked? QA::Runtime::Logger.debug(selected ? "#{name} was selected" : "#{name} was not selected") selected end + wait_for_requests end # Use this to simulate moving the pointer to an element's coordinate @@ -226,10 +227,12 @@ module QA wait = kwargs.delete(:wait) || Capybara.default_max_wait_time text = kwargs.delete(:text) klass = kwargs.delete(:class) + visible = kwargs.delete(:visible) + visible = visible.nil? && true try_find_element = ->(wait) do if disabled.nil? - has_css?(element_selector_css(name, kwargs), text: text, wait: wait, class: klass) + has_css?(element_selector_css(name, kwargs), text: text, wait: wait, class: klass, visible: visible) else find_element(name, original_kwargs).disabled? == disabled end @@ -337,8 +340,10 @@ module QA end end - def scroll_to_element(name, *args) - scroll_to(element_selector_css(name), *args) + def scroll_to_element(name, *kwargs) + text = kwargs.delete(:text) + + scroll_to(element_selector_css(name, kwargs), text: text) end def element_selector_css(name, *attributes) @@ -399,7 +404,7 @@ module QA end def visible? - raise NoRequiredElementsError.new(self.class) if self.class.required_elements.empty? + raise NoRequiredElementsError, self.class if self.class.required_elements.empty? self.class.required_elements.each do |required_element| return false if has_no_element? required_element @@ -424,8 +429,8 @@ module QA private - def click_checkbox_or_radio(name, click_by_js) - box = find_element(name, visible: false) + def click_checkbox_or_radio(name, click_by_js, visibility) + box = find_element(name, visible: visibility) # Some checkboxes and radio buttons are hidden by their labels and cannot be clicked directly click_by_js ? page.execute_script("arguments[0].click();", box) : box.click end diff --git a/qa/qa/page/component/access_tokens.rb b/qa/qa/page/component/access_tokens.rb index d8e3d12b38b..3c8a6cf6a1d 100644 --- a/qa/qa/page/component/access_tokens.rb +++ b/qa/qa/page/component/access_tokens.rb @@ -19,7 +19,7 @@ module QA end base.view 'app/views/shared/tokens/_scopes_form.html.haml' do - element :api_radio, 'qa-#{scope}-radio' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck + element :api_checkbox, '#{scope}_checkbox' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck end base.view 'app/views/shared/access_tokens/_created_container.html.haml' do @@ -36,7 +36,7 @@ module QA end def check_api - check_element(:api_radio) + check_element(:api_checkbox) end def click_create_token_button diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb index dbf4dc30116..e0c8f73e1b0 100644 --- a/qa/qa/page/component/issue_board/show.rb +++ b/qa/qa/page/component/issue_board/show.rb @@ -137,4 +137,4 @@ module QA end end -QA::Page::Component::IssueBoard::Show.prepend_if_ee('QA::EE::Page::Component::IssueBoard::Show') +QA::Page::Component::IssueBoard::Show.prepend_mod_with('Page::Component::IssueBoard::Show', namespace: QA) diff --git a/qa/qa/page/component/visibility_setting.rb b/qa/qa/page/component/visibility_setting.rb new file mode 100644 index 00000000000..4370cfb4564 --- /dev/null +++ b/qa/qa/page/component/visibility_setting.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module VisibilitySetting + extend QA::Page::PageConcern + + def self.included(base) + super + + base.view 'app/views/shared/_visibility_radios.html.haml' do + element :visibility_radio, 'qa_selector: "#{visibility_level_label(level).downcase}_radio"' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck + end + end + + def set_visibility(visibility) + choose_element("#{visibility.downcase}_radio", false, true) + end + end + end + end +end diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb index b9e2383a3eb..8be11550233 100644 --- a/qa/qa/page/dashboard/projects.rb +++ b/qa/qa/page/dashboard/projects.rb @@ -45,4 +45,4 @@ module QA end end -QA::Page::Dashboard::Projects.prepend_if_ee('QA::EE::Page::Dashboard::Projects') +QA::Page::Dashboard::Projects.prepend_mod_with('Page::Dashboard::Projects', namespace: QA) diff --git a/qa/qa/page/dashboard/snippet/index.rb b/qa/qa/page/dashboard/snippet/index.rb index 8c4abfdf606..63589c376f6 100644 --- a/qa/qa/page/dashboard/snippet/index.rb +++ b/qa/qa/page/dashboard/snippet/index.rb @@ -10,10 +10,32 @@ module QA element :global_new_snippet_link end + view 'app/views/shared/snippets/_snippet.html.haml' do + element :snippet_link + element :snippet_visibility_content + element :snippet_file_count_content + end + def go_to_new_snippet_page click_element :new_menu_toggle click_element :global_new_snippet_link end + + def has_snippet_title?(snippet_title) + has_element?(:snippet_link, snippet_title: snippet_title) + end + + def has_visibility_level?(snippet_title, visibility) + within_element(:snippet_link, snippet_title: snippet_title) do + has_element?(:snippet_visibility_content, snippet_visibility: visibility) + end + end + + def has_number_of_files?(snippet_title, number) + within_element(:snippet_link, snippet_title: snippet_title) do + has_element?(:snippet_file_count_content, snippet_files: number) + end + end end end end diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb index 906f5f3581a..4c25e8a480b 100644 --- a/qa/qa/page/file/shared/commit_message.rb +++ b/qa/qa/page/file/shared/commit_message.rb @@ -11,7 +11,7 @@ module QA super base.view 'app/views/shared/_commit_message_container.html.haml' do - element :commit_message, "text_area_tag 'commit_message'" # rubocop:disable QA/ElementWithPattern + element :commit_message_field end base.view 'app/views/projects/commits/_commit.html.haml' do @@ -20,7 +20,7 @@ module QA end def add_commit_message(message) - fill_in 'commit_message', with: message + fill_element(:commit_message_field, message) end def has_commit_message?(text) diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb index 28b6b3be154..cefbbbcdba0 100644 --- a/qa/qa/page/file/show.rb +++ b/qa/qa/page/file/show.rb @@ -62,4 +62,4 @@ module QA end end -QA::Page::File::Show.prepend_if_ee('QA::EE::Page::File::Show') +QA::Page::File::Show.prepend_mod_with('Page::File::Show', namespace: QA) diff --git a/qa/qa/page/group/bulk_import.rb b/qa/qa/page/group/bulk_import.rb new file mode 100644 index 00000000000..11741bdf4cb --- /dev/null +++ b/qa/qa/page/group/bulk_import.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module QA + module Page + module Group + class BulkImport < Page::Base + view "app/assets/javascripts/import_entities/import_groups/components/import_table.vue" do + element :import_table + end + + view "app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue" do + element :import_item + element :target_namespace_selector_dropdown + element :target_group_dropdown_item + element :import_status_indicator + element :import_group_button + end + + # Import source group in to target group + # + # @param [String] source_group_name + # @param [String] target_group_name + # @return [void] + def import_group(source_group_name, target_group_name) + finished_loading? + + within_element(:import_item, source_group: source_group_name) do + click_element(:target_namespace_selector_dropdown) + click_element(:target_group_dropdown_item, group_name: target_group_name) + click_element(:import_group_button) + end + end + + # Check if import page has a successfully imported group + # + # @param [String] source_group_name + # @param [Integer] wait + # @return [Boolean] + def has_imported_group?(source_group_name, wait: QA::Support::WaitForRequests::DEFAULT_MAX_WAIT_TIME) + within_element(:import_item, source_group: source_group_name) do + has_element?(:import_status_indicator, text: "Complete", wait: wait) + end + end + end + end + end +end diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb index 10c0ee1f0a9..66e8b5d5863 100644 --- a/qa/qa/page/group/menu.rb +++ b/qa/qa/page/group/menu.rb @@ -11,7 +11,7 @@ module QA element :group_issues_item element :group_members_item element :group_milestones_link - element :group_settings_item + element :group_settings end view 'app/views/groups/sidebar/_packages_settings.html.haml' do @@ -31,7 +31,7 @@ module QA def click_settings within_sidebar do - click_element(:group_settings_item) + click_element(:group_settings) end end @@ -44,7 +44,7 @@ module QA end def click_group_general_settings_item - hover_element(:group_settings_item) do + hover_element(:group_settings) do within_submenu(:group_sidebar_submenu) do click_element(:general_settings_link) end @@ -60,8 +60,8 @@ module QA end def go_to_package_settings - scroll_to_element(:group_settings_item) - hover_element(:group_settings_item) do + scroll_to_element(:group_settings) + hover_element(:group_settings) do within_submenu(:group_sidebar_submenu) do click_element(:group_package_settings_link) end @@ -83,4 +83,4 @@ module QA end end -QA::Page::Group::Menu.prepend_if_ee('QA::EE::Page::Group::Menu') +QA::Page::Group::Menu.prepend_mod_with('Page::Group::Menu', namespace: QA) diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb index 5f43cfb49c0..5a908266597 100644 --- a/qa/qa/page/group/new.rb +++ b/qa/qa/page/group/new.rb @@ -4,28 +4,51 @@ module QA module Page module Group class New < Page::Base + include Page::Component::VisibilitySetting + view 'app/views/shared/_group_form.html.haml' do - element :group_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern - element :group_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern + element :group_path_field + element :group_name_field end view 'app/views/groups/_new_group_fields.html.haml' do element :create_group_button, "submit _('Create group')" # rubocop:disable QA/ElementWithPattern - element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern end - def set_path(path) - fill_in 'group_path', with: path - fill_in 'group_name', with: path + view 'app/views/groups/_import_group_from_another_instance_panel.html.haml' do + element :import_gitlab_url + element :import_gitlab_token + element :connect_instance_button end - def set_visibility(visibility) - choose visibility + def set_path(path) + fill_element(:group_path_field, path) + fill_element(:group_name_field, path) end def create click_button 'Create group' end + + def set_gitlab_url(url) + fill_element(:import_gitlab_url, url) + end + + def set_gitlab_token(token) + fill_element(:import_gitlab_token, token) + end + + # Connect gitlab instance + # + # @param [String] gitlab_url + # @param [String] gitlab_token + # @return [void] + def connect_gitlab_instance(gitlab_url, gitlab_token) + set_gitlab_url(gitlab_url) + set_gitlab_token(gitlab_token) + + click_element(:connect_instance_button) + end end end end diff --git a/qa/qa/page/group/settings/billing.rb b/qa/qa/page/group/settings/billing.rb new file mode 100644 index 00000000000..a83af47fc35 --- /dev/null +++ b/qa/qa/page/group/settings/billing.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module QA + module Page + module Group + module Settings + class Billing < Chemlab::Page + link :start_your_free_trial + end + end + end + end +end diff --git a/qa/qa/page/group/settings/general.rb b/qa/qa/page/group/settings/general.rb index 1ab849d10b1..4977e5c7105 100644 --- a/qa/qa/page/group/settings/general.rb +++ b/qa/qa/page/group/settings/general.rb @@ -6,6 +6,7 @@ module QA module Settings class General < QA::Page::Base include ::QA::Page::Settings::Common + include Page::Component::VisibilitySetting view 'app/views/groups/edit.html.haml' do element :permission_lfs_2fa_content @@ -21,10 +22,6 @@ module QA element :save_name_visibility_settings_button end - view 'app/views/shared/_visibility_radios.html.haml' do - element :internal_radio, 'qa_selector: "#{visibility_level_label(level).downcase}_radio"' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck - end - view 'app/views/groups/settings/_lfs.html.haml' do element :lfs_checkbox end @@ -56,47 +53,43 @@ module QA find_element(:group_name_field).set name end - def set_group_visibility(visibility) - find_element("#{visibility.downcase}_radio").click - end - def click_save_name_visibility_settings_button click_element(:save_name_visibility_settings_button) end def set_lfs_enabled expand_content(:permission_lfs_2fa_content) - check_element(:lfs_checkbox) + check_element(:lfs_checkbox, true) click_element(:save_permissions_changes_button) end def set_lfs_disabled expand_content(:permission_lfs_2fa_content) - uncheck_element(:lfs_checkbox) + uncheck_element(:lfs_checkbox, true) click_element(:save_permissions_changes_button) end def set_request_access_enabled expand_content(:permission_lfs_2fa_content) - check_element(:request_access_checkbox) + check_element(:request_access_checkbox, true) click_element(:save_permissions_changes_button) end def set_request_access_disabled expand_content(:permission_lfs_2fa_content) - uncheck_element(:request_access_checkbox) + uncheck_element(:request_access_checkbox, true) click_element(:save_permissions_changes_button) end def set_require_2fa_enabled expand_content(:permission_lfs_2fa_content) - check_element(:require_2fa_checkbox) + check_element(:require_2fa_checkbox, true) click_element(:save_permissions_changes_button) end def set_require_2fa_disabled expand_content(:permission_lfs_2fa_content) - uncheck_element(:require_2fa_checkbox) + uncheck_element(:require_2fa_checkbox, true) click_element(:save_permissions_changes_button) end @@ -109,10 +102,10 @@ module QA def toggle_request_access expand_content(:permission_lfs_2fa_content) - if find_element(:request_access_checkbox).checked? - uncheck_element(:request_access_checkbox) + if find_element(:request_access_checkbox, visible: false).checked? + uncheck_element(:request_access_checkbox, true) else - check_element(:request_access_checkbox) + check_element(:request_access_checkbox, true) end click_element(:save_permissions_changes_button) @@ -136,4 +129,4 @@ module QA end end -QA::Page::Group::Settings::General.prepend_if_ee('QA::EE::Page::Group::Settings::General') +QA::Page::Group::Settings::General.prepend_mod_with('Page::Group::Settings::General', namespace: QA) diff --git a/qa/qa/page/group/settings/package_registries.rb b/qa/qa/page/group/settings/package_registries.rb index ee5ca849a47..8a2802b0035 100644 --- a/qa/qa/page/group/settings/package_registries.rb +++ b/qa/qa/page/group/settings/package_registries.rb @@ -11,7 +11,7 @@ module QA element :package_registry_settings_content end - view 'app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue' do + view 'app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue' do element :allow_duplicates_toggle element :allow_duplicates_label end diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index 048119d65cb..3b3057a9acb 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -52,13 +52,17 @@ module QA using_wait_time 0 do set_initial_password_if_present - raise 'If an LDAP user is provided, it must be used for sign-in', QA::Resource::User::InvalidUserError if Runtime::User.ldap_user? && user && user.username != Runtime::User.ldap_username + if Runtime::User.ldap_user? && user && user.username != Runtime::User.ldap_username + raise 'If an LDAP user is provided, it must be used for sign-in', QA::Resource::User::InvalidUserError + end if Runtime::User.ldap_user? sign_in_using_ldap_credentials(user: user || Runtime::User) else sign_in_using_gitlab_credentials(user: user || Runtime::User, skip_page_validation: skip_page_validation) end + + set_up_new_password_if_required(user: user, skip_page_validation: skip_page_validation) end end @@ -70,7 +74,6 @@ module QA using_wait_time 0 do set_initial_password_if_present - sign_in_using_gitlab_credentials(user: admin) end @@ -168,6 +171,20 @@ module QA Page::Main::Menu.validate_elements_present! unless skip_page_validation end + # Handle request for password change + # Happens on clean GDK installations when seeded root admin password is expired + # + def set_up_new_password_if_required(user:, skip_page_validation:) + return unless has_content?('Set up new password') + + Profile::Password.perform do |new_password_page| + password = user&.password || Runtime::User.password + new_password_page.set_new_password(password, password) + end + + sign_in_using_credentials(user: user, skip_page_validation: skip_page_validation) + end + def set_initial_password_if_present return unless has_content?('Change your password') diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index f0df901a8f0..f796f4c9475 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -35,17 +35,24 @@ module QA element :your_projects_link end + view 'app/views/layouts/nav/groups_dropdown/_show.html.haml' do + element :create_group_link + element :import_group_link + end + view 'app/views/layouts/_search.html.haml' do element :search_term_field end def go_to_groups - within_top_menu do - click_element :groups_dropdown + within_groups_menu do + click_element :your_groups_link end + end - page.within('.qa-groups-dropdown-sidebar') do - click_element :your_groups_link + def go_to_import_group + within_groups_menu do + click_element :import_group_link end end @@ -125,6 +132,12 @@ module QA end end + def click_user_profile_link + within_user_menu do + click_element(:user_profile_link) + end + end + def search_for(term) fill_element :search_term_field, "#{term}\n" end @@ -167,6 +180,14 @@ module QA end end + def within_groups_menu(&block) + within_top_menu do + click_element :groups_dropdown + end + + page.within('.qa-groups-dropdown-sidebar', &block) + end + def click_admin_area within_top_menu { click_element :admin_area_link } end @@ -175,4 +196,4 @@ module QA end end -QA::Page::Main::Menu.prepend_if_ee('QA::EE::Page::Main::Menu') +QA::Page::Main::Menu.prepend_mod_with('Page::Main::Menu', namespace: QA) diff --git a/qa/qa/page/merge_request/new.rb b/qa/qa/page/merge_request/new.rb index 46b7bbeed84..71e51ddd504 100644 --- a/qa/qa/page/merge_request/new.rb +++ b/qa/qa/page/merge_request/new.rb @@ -41,4 +41,4 @@ module QA end end -QA::Page::MergeRequest::New.prepend_if_ee('QA::EE::Page::MergeRequest::New') +QA::Page::MergeRequest::New.prepend_mod_with('Page::MergeRequest::New', namespace: QA) diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index e1790deb3ec..5f52d48e9f6 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -7,50 +7,16 @@ module QA include Page::Component::Note include Page::Component::Issuable::Sidebar - view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do - element :download_dropdown - element :download_email_patches_menu_item - element :download_plain_diff_menu_item - element :open_in_web_ide_button - end - - view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue' do - element :merge_request_pipeline_info_content - element :pipeline_link - end - - view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do - element :merge_button - element :fast_forward_message_content - element :merge_moment_dropdown - element :merge_immediately_menu_item - end - - view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue' do - element :merge_request_status_content - end - - view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do - element :merged_status_content - end - - view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue' do - element :merge_request_error_content - end - - view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do - element :mr_rebase_button - element :no_fast_forward_message_content + view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do + element :review_preview_dropdown end - view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do - element :squash_checkbox + view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do + element :submit_review_button end - view 'app/views/projects/merge_requests/show.html.haml' do - element :notes_tab - element :commits_tab - element :diffs_tab + view 'app/assets/javascripts/batch_comments/components/review_bar.vue' do + element :review_bar_content end view 'app/assets/javascripts/diffs/components/compare_dropdown_layout.vue' do @@ -70,33 +36,60 @@ module QA view 'app/assets/javascripts/diffs/components/diff_row.vue' do element :diff_comment_button + element :new_diff_line_link end - view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do - element :new_diff_line_link + view 'app/assets/javascripts/notes/components/note_form.vue' do + element :start_review_button + element :comment_now_button end - view 'app/views/projects/merge_requests/_mr_title.html.haml' do - element :edit_button + view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do + element :download_dropdown + element :download_email_patches_menu_item + element :download_plain_diff_menu_item + element :open_in_web_ide_button end - view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do - element :submit_review_button + view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue' do + element :merge_request_pipeline_info_content + element :pipeline_link end - view 'app/assets/javascripts/batch_comments/components/review_bar.vue' do - element :review_bar_content + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue' do + element :merge_request_error_content end - view 'app/assets/javascripts/notes/components/note_form.vue' do - element :unresolve_review_discussion_checkbox - element :resolve_review_discussion_checkbox - element :start_review_button - element :comment_now_button + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do + element :cherry_pick_button + element :merged_status_content + element :revert_button end - view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do - element :review_preview_toggle + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do + element :mr_rebase_button + element :no_fast_forward_message_content + end + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do + element :merge_button + element :fast_forward_message_content + element :merge_moment_dropdown + element :merge_immediately_menu_item + end + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do + element :squash_checkbox + end + + view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do + element :apply_suggestion_dropdown + element :commit_message_field + element :commit_with_custom_message_button + end + + view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do + element :suggestion_button end view 'app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue' do @@ -104,19 +97,26 @@ module QA element :add_suggestion_batch_button end - view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do - element :suggestion_button + view 'app/views/projects/merge_requests/_description.html.haml' do + element :description_content end - view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do - element :revert_button - element :cherry_pick_button + view 'app/views/projects/merge_requests/_mr_box.html.haml' do + element :title_content end - view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do - element :apply_suggestion_button - element :commit_message_textbox - element :commit_with_custom_message_button + view 'app/views/projects/merge_requests/_mr_title.html.haml' do + element :edit_button + end + + view 'app/views/projects/merge_requests/show.html.haml' do + element :notes_tab + element :commits_tab + element :diffs_tab + end + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue' do + element :cancel_auto_merge_button end def start_review @@ -131,21 +131,13 @@ module QA click_element(:target_version_dropdown) end - def comment_now - click_element(:comment_now_button) - - # After clicking the button, wait for it to disappear - # before moving on to the next part of the test - has_no_element?(:comment_now_button) - end - def version_dropdown_content find_element(:dropdown_content).text end def submit_pending_reviews within_element(:review_bar_content) do - click_element(:review_preview_toggle) + click_element(:review_preview_dropdown) click_element(:submit_review_button) # After clicking the button, wait for it to disappear @@ -154,22 +146,6 @@ module QA end end - def discard_pending_reviews - within_element(:review_bar_content) do - click_element(:discard_review) - end - click_element(:modal_delete_pending_comments) - end - - def resolve_review_discussion - scroll_to_element(:start_review_button) - check_element(:resolve_review_discussion_checkbox) - end - - def unresolve_review_discussion - check_element(:unresolve_review_discussion_checkbox) - end - def add_comment_to_diff(text) wait_until(sleep_interval: 5) do has_css?('a[data-linenumber="1"]') @@ -230,11 +206,11 @@ module QA end def has_title?(title) - has_element?(:title, text: title) + has_element?(:title_content, text: title) end def has_description?(description) - has_element?(:description, text: description) + has_element?(:description_content, text: description) end def mark_to_squash @@ -253,11 +229,6 @@ module QA raise "Merge did not appear to be successful" unless merged? end - def merge_immediately! - click_element(:merge_moment_dropdown) - click_element(:merge_immediately_menu_item) - end - def merge_when_pipeline_succeeds! wait_until_ready_to_merge @@ -281,10 +252,6 @@ module QA has_element?(:merge_button, disabled: false) end - def merge_request_status - find_element(:merge_request_status_content).text - end - # Waits up 60 seconds and raises an error if unable to merge def wait_until_ready_to_merge has_element?(:merge_button) @@ -363,8 +330,8 @@ module QA end def apply_suggestion_with_message(message) - click_element(:apply_suggestion_button) - fill_element(:commit_message_textbox, message) + click_element(:apply_suggestion_dropdown) + fill_element(:commit_message_field, message) click_element(:commit_with_custom_message_button) end @@ -385,9 +352,13 @@ module QA click_element(:revert_button, Page::Component::CommitModal) click_element(:submit_commit_button) end + + def cancel_auto_merge! + click_element(:cancel_auto_merge_button) + end end end end end -QA::Page::MergeRequest::Show.prepend_if_ee('QA::EE::Page::MergeRequest::Show') +QA::Page::MergeRequest::Show.prepend_mod_with('Page::MergeRequest::Show', namespace: QA) diff --git a/qa/qa/page/milestone/show.rb b/qa/qa/page/milestone/show.rb index 42efbd4ea30..0ab966534a3 100644 --- a/qa/qa/page/milestone/show.rb +++ b/qa/qa/page/milestone/show.rb @@ -30,4 +30,4 @@ module QA end end -QA::Page::Milestone::Show.prepend_if_ee('QA::EE::Page::Milestone::Show') +QA::Page::Milestone::Show.prepend_mod_with('Page::Milestone::Show', namespace: QA) diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb index 41c350f94ef..a12db2918dc 100644 --- a/qa/qa/page/profile/menu.rb +++ b/qa/qa/page/profile/menu.rb @@ -56,4 +56,4 @@ module QA end end -QA::Page::Profile::Menu.prepend_if_ee('QA::EE::Page::Profile::Menu') +QA::Page::Profile::Menu.prepend_mod_with('Page::Profile::Menu', namespace: QA) diff --git a/qa/qa/page/profile/password.rb b/qa/qa/page/profile/password.rb index ce062f39edb..ee042450f8d 100644 --- a/qa/qa/page/profile/password.rb +++ b/qa/qa/page/profile/password.rb @@ -11,12 +11,26 @@ module QA element :save_password_button end + view 'app/views/profiles/passwords/new.html.haml' do + element :current_password_field + element :new_password_field + element :confirm_password_field + element :set_new_password_button + end + def update_password(new_password, current_password) find_element(:current_password_field).set current_password find_element(:new_password_field).set new_password find_element(:confirm_password_field).set new_password click_element(:save_password_button) end + + def set_new_password(new_password, current_password) + fill_element :current_password_field, current_password + fill_element :new_password_field, new_password + fill_element :confirm_password_field, new_password + click_element :set_new_password_button + end end end end diff --git a/qa/qa/page/project/artifact/show.rb b/qa/qa/page/project/artifact/show.rb new file mode 100644 index 00000000000..437363d4a98 --- /dev/null +++ b/qa/qa/page/project/artifact/show.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Artifact + class Show < QA::Page::Base + view 'app/views/projects/artifacts/_tree_directory.html.haml' do + element :directory_name_link + end + + def go_to_directory(name) + click_element(:directory_name_link, directory_name: name) + end + end + end + end + end +end diff --git a/qa/qa/page/project/commit/show.rb b/qa/qa/page/project/commit/show.rb index f732eb6565e..bc44a4e5e72 100644 --- a/qa/qa/page/project/commit/show.rb +++ b/qa/qa/page/project/commit/show.rb @@ -11,11 +11,18 @@ module QA view 'app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue' do element :options_button + element :revert_button element :cherry_pick_button element :email_patches element :plain_diff end + def revert_commit + click_element(:options_button) + click_element(:revert_button, Page::Component::CommitModal) + click_element(:submit_commit_button) + end + def cherry_pick_commit click_element(:options_button) click_element(:cherry_pick_button, Page::Component::CommitModal) diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb index 10ddd52719a..fc46f7a2936 100644 --- a/qa/qa/page/project/issue/index.rb +++ b/qa/qa/page/project/issue/index.rb @@ -85,4 +85,4 @@ module QA end end -QA::Page::Project::Issue::Index.prepend_if_ee('QA::EE::Page::Project::Issue::Index') +QA::Page::Project::Issue::Index.prepend_mod_with('Page::Project::Issue::Index', namespace: QA) diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb index db2f5f9b3dc..7a5a153db86 100644 --- a/qa/qa/page/project/issue/show.rb +++ b/qa/qa/page/project/issue/show.rb @@ -70,4 +70,4 @@ module QA end end -QA::Page::Project::Issue::Show.prepend_if_ee('QA::EE::Page::Project::Issue::Show') +QA::Page::Project::Issue::Show.prepend_mod_with('Page::Project::Issue::Show', namespace: QA) diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb index 8c70d0874c4..78b6bebe02e 100644 --- a/qa/qa/page/project/job/show.rb +++ b/qa/qa/page/project/job/show.rb @@ -75,4 +75,4 @@ module QA end end -QA::Page::Project::Job::Show.prepend_if_ee('QA::EE::Page::Project::Job::Show') +QA::Page::Project::Job::Show.prepend_mod_with('Page::Project::Job::Show', namespace: QA) diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb index cb7323ac62d..ffabaf30374 100644 --- a/qa/qa/page/project/menu.rb +++ b/qa/qa/page/project/menu.rb @@ -13,29 +13,15 @@ module QA include SubMenus::Settings include SubMenus::Packages - view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do - element :merge_requests_link - element :snippets_link - element :members_link - end - - view 'app/views/layouts/nav/sidebar/_wiki_link.html.haml' do - element :wiki_link - end - - view 'app/views/shared/nav/_sidebar_menu_item.html.haml' do - element :sidebar_menu_item_link - end - def click_merge_requests within_sidebar do - click_element(:merge_requests_link) + click_element(:sidebar_menu_link, menu_item: 'Merge requests') end end def click_wiki within_sidebar do - click_element(:wiki_link) + click_element(:sidebar_menu_link, menu_item: 'Wiki') end end @@ -47,13 +33,13 @@ module QA def click_snippets within_sidebar do - click_element(:snippets_link) + click_element(:sidebar_menu_link, menu_item: 'Snippets') end end def click_members within_sidebar do - click_element(:members_link) + click_element(:sidebar_menu_link, menu_item: 'Members') end end end @@ -61,4 +47,4 @@ module QA end end -QA::Page::Project::Menu.prepend_if_ee('QA::EE::Page::Project::Menu') +QA::Page::Project::Menu.prepend_mod_with('Page::Project::Menu', namespace: QA) diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb index d1033dbfca9..b14afa90442 100644 --- a/qa/qa/page/project/new.rb +++ b/qa/qa/page/project/new.rb @@ -4,13 +4,9 @@ module QA module Page module Project class New < Page::Base - include Page::Component::Select2 include Page::Component::Project::Templates - - view 'app/views/projects/new.html.haml' do - element :project_create_from_template_tab - element :import_project_tab, "Import project" # rubocop:disable QA/ElementWithPattern - end + include Page::Component::Select2 + include Page::Component::VisibilitySetting view 'app/views/projects/_new_project_fields.html.haml' do element :initialize_with_readme_checkbox @@ -28,6 +24,19 @@ module QA element :template_option_row end + view 'app/assets/javascripts/vue_shared/new_namespace/components/welcome.vue' do + element :blank_project_link, ':data-qa-selector="`${panel.name}_link`"' # rubocop:disable QA/ElementWithPattern + element :create_from_template_link, ':data-qa-selector="`${panel.name}_link`"' # rubocop:disable QA/ElementWithPattern + end + + def click_blank_project_link + click_element :blank_project_link + end + + def click_create_from_template_link + click_element :create_from_template_link + end + def choose_test_namespace choose_namespace(Runtime::Namespace.path) end @@ -75,4 +84,4 @@ module QA end end -QA::Page::Project::New.prepend_if_ee('QA::EE::Page::Project::New') +QA::Page::Project::New.prepend_mod_with('Page::Project::New', namespace: QA) diff --git a/qa/qa/page/project/new_experiment.rb b/qa/qa/page/project/new_experiment.rb deleted file mode 100644 index 813f7f6cefe..00000000000 --- a/qa/qa/page/project/new_experiment.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Project - class NewExperiment < Page::Base - view 'app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue' do - element :blank_project_link, ':data-qa-selector="`${panel.name}_link`"' # rubocop:disable QA/ElementWithPattern - element :create_from_template_link, ':data-qa-selector="`${panel.name}_link`"' # rubocop:disable QA/ElementWithPattern - end - - def shown? - has_element? :blank_project_link - end - - def click_blank_project_link - click_element :blank_project_link - end - - def click_create_from_template_link - click_element :create_from_template_link - end - end - end - end -end diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/operations/metrics/show.rb index 6e8a52ab2e6..22a7f1eed8f 100644 --- a/qa/qa/page/project/operations/metrics/show.rb +++ b/qa/qa/page/project/operations/metrics/show.rb @@ -134,4 +134,4 @@ module QA end end -QA::Page::Project::Operations::Metrics::Show.prepend_if_ee('QA::EE::Page::Project::Operations::Metrics::Show') +QA::Page::Project::Operations::Metrics::Show.prepend_mod_with('Page::Project::Operations::Metrics::Show', namespace: QA) diff --git a/qa/qa/page/project/packages/index.rb b/qa/qa/page/project/packages/index.rb index 396d3373b8a..7794677b9b5 100644 --- a/qa/qa/page/project/packages/index.rb +++ b/qa/qa/page/project/packages/index.rb @@ -27,4 +27,4 @@ module QA end end -QA::Page::Project::Packages::Index.prepend_if_ee('QA::EE::Page::Project::Packages::Index') +QA::Page::Project::Packages::Index.prepend_mod_with('Page::Project::Packages::Index', namespace: QA) diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb index 3cb466abce9..f7c5d149593 100644 --- a/qa/qa/page/project/pipeline/index.rb +++ b/qa/qa/page/project/pipeline/index.rb @@ -67,4 +67,4 @@ module QA end end -QA::Page::Project::Pipeline::Index.prepend_if_ee('QA::EE::Page::Project::Pipeline::Index') +QA::Page::Project::Pipeline::Index.prepend_mod_with('Page::Project::Pipeline::Index', namespace: QA) diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index c5887b84be6..d45eeac46f6 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -117,4 +117,4 @@ module QA end end -QA::Page::Project::Pipeline::Show.prepend_if_ee('QA::EE::Page::Project::Pipeline::Show') +QA::Page::Project::Pipeline::Show.prepend_mod_with('Page::Project::Pipeline::Show', namespace: QA) diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb index 7224fdae10e..c537db34a51 100644 --- a/qa/qa/page/project/settings/ci_cd.rb +++ b/qa/qa/page/project/settings/ci_cd.rb @@ -43,4 +43,4 @@ module QA end end -QA::Page::Project::Settings::CICD.prepend_if_ee("QA::EE::Page::Project::Settings::CICD") +QA::Page::Project::Settings::CICD.prepend_mod_with("Page::Project::Settings::CICD", namespace: QA) diff --git a/qa/qa/page/project/settings/deploy_keys.rb b/qa/qa/page/project/settings/deploy_keys.rb index 8d655b0684e..467799a14fb 100644 --- a/qa/qa/page/project/settings/deploy_keys.rb +++ b/qa/qa/page/project/settings/deploy_keys.rb @@ -6,59 +6,64 @@ module QA module Settings class DeployKeys < Page::Base view 'app/views/shared/deploy_keys/_form.html.haml' do - element :deploy_key_title, 'text_field :title' # rubocop:disable QA/ElementWithPattern - element :deploy_key_key, 'text_area :key' # rubocop:disable QA/ElementWithPattern + element :deploy_key_title_field + element :deploy_key_field + end + + view 'app/views/shared/deploy_keys/_project_group_form.html.haml' do + element :deploy_key_title_field + element :deploy_key_field + element :add_deploy_key_button end view 'app/assets/javascripts/deploy_keys/components/app.vue' do - element :deploy_keys_section, /class=".*deploy\-keys.*"/ # rubocop:disable QA/ElementWithPattern - element :project_deploy_keys + element :project_deploy_keys_container end view 'app/assets/javascripts/deploy_keys/components/key.vue' do - element :key - element :key_title - element :key_md5_fingerprint + element :key_container + element :key_title_content + element :key_md5_fingerprint_content end def add_key - click_on 'Add key' + click_element(:add_deploy_key_button) end def fill_key_title(title) - fill_in 'deploy_key_title', with: title + fill_element(:deploy_key_title_field, title) end def fill_key_value(key) - fill_in 'deploy_key_key', with: key + fill_element(:deploy_key_field, key) end def find_md5_fingerprint(title) within_project_deploy_keys do - find_element(:key, text: title) - .find(element_selector_css(:key_md5_fingerprint)).text.delete_prefix('MD5:') + find_element(:key_container, text: title) + .find(element_selector_css(:key_md5_fingerprint_content)).text.delete_prefix('MD5:') end end def has_key?(title, md5_fingerprint) within_project_deploy_keys do - find_element(:key, text: title) - .has_css?(element_selector_css(:key_md5_fingerprint), text: "MD5:#{md5_fingerprint}") + find_element(:key_container, text: title) + .has_css?(element_selector_css(:key_md5_fingerprint_content), text: "MD5:#{md5_fingerprint}") end end def key_title within_project_deploy_keys do - find_element(:key_title).text + find_element(:key_title_content).text end end private def within_project_deploy_keys - has_element?(:project_deploy_keys, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) + has_element?(:project_deploy_keys_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) - within_element(:project_deploy_keys) do + within_element(:project_deploy_keys_container) do yield end end diff --git a/qa/qa/page/project/settings/deploy_tokens.rb b/qa/qa/page/project/settings/deploy_tokens.rb index 3c3ed4f8716..b26cae86d8b 100644 --- a/qa/qa/page/project/settings/deploy_tokens.rb +++ b/qa/qa/page/project/settings/deploy_tokens.rb @@ -6,54 +6,54 @@ module QA module Settings class DeployTokens < Page::Base view 'app/views/shared/deploy_tokens/_form.html.haml' do - element :deploy_token_name - element :deploy_token_expires_at - element :deploy_token_read_repository - element :deploy_token_read_registry - element :create_deploy_token + element :deploy_token_name_field + element :deploy_token_expires_at_field + element :deploy_token_read_repository_checkbox + element :deploy_token_read_registry_checkbox + element :create_deploy_token_button end view 'app/views/shared/deploy_tokens/_new_deploy_token.html.haml' do - element :created_deploy_token_section - element :deploy_token_user - element :deploy_token + element :created_deploy_token_container + element :deploy_token_user_field + element :deploy_token_field end def fill_token_name(name) - fill_element :deploy_token_name, name + fill_element(:deploy_token_name_field, name) end def fill_token_expires_at(expires_at) - fill_element :deploy_token_expires_at, expires_at.to_s + "\n" + fill_element(:deploy_token_expires_at_field, expires_at.to_s + "\n") end def fill_scopes(read_repository:, read_registry:) - check_element :deploy_token_read_repository if read_repository - check_element :deploy_token_read_registry if read_registry + check_element(:deploy_token_read_repository_checkbox) if read_repository + check_element(:deploy_token_read_registry_checkbox) if read_registry end def add_token - click_element :create_deploy_token + click_element(:create_deploy_token_button) end def token_username within_new_project_deploy_token do - find_element(:deploy_token_user).value + find_element(:deploy_token_user_field).value end end def token_password within_new_project_deploy_token do - find_element(:deploy_token).value + find_element(:deploy_token_field).value end end private def within_new_project_deploy_token - has_element?(:created_deploy_token_section, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) + has_element?(:created_deploy_token_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) - within_element(:created_deploy_token_section) do + within_element(:created_deploy_token_container) do yield end end diff --git a/qa/qa/page/project/settings/integrations.rb b/qa/qa/page/project/settings/integrations.rb index 6f5c50eac52..420dcb63918 100644 --- a/qa/qa/page/project/settings/integrations.rb +++ b/qa/qa/page/project/settings/integrations.rb @@ -23,4 +23,4 @@ module QA end end -QA::Page::Project::Settings::Integrations.prepend_if_ee('QA::EE::Page::Project::Settings::Integrations') +QA::Page::Project::Settings::Integrations.prepend_mod_with('Page::Project::Settings::Integrations', namespace: QA) diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb index 48af635bb79..5efcb7bf23c 100644 --- a/qa/qa/page/project/settings/main.rb +++ b/qa/qa/page/project/settings/main.rb @@ -57,4 +57,4 @@ module QA end end -QA::Page::Project::Settings::Main.prepend_if_ee("QA::EE::Page::Project::Settings::Main") +QA::Page::Project::Settings::Main.prepend_mod_with("Page::Project::Settings::Main", namespace: QA) diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb index 0b4a12dbb2e..dbe804bfdd0 100644 --- a/qa/qa/page/project/settings/merge_request.rb +++ b/qa/qa/page/project/settings/merge_request.rb @@ -12,7 +12,7 @@ module QA end view 'app/views/projects/_merge_request_merge_method_settings.html.haml' do - element :merge_ff_radio_button + element :merge_ff_radio end view 'app/views/projects/_merge_request_merge_checks_settings.html.haml' do @@ -24,7 +24,7 @@ module QA end def enable_ff_only - click_element(:merge_ff_radio_button) + choose_element(:merge_ff_radio) click_save_changes end @@ -38,4 +38,4 @@ module QA end end -QA::Page::Project::Settings::MergeRequest.prepend_if_ee("QA::EE::Page::Project::Settings::MergeRequest") +QA::Page::Project::Settings::MergeRequest.prepend_mod_with("Page::Project::Settings::MergeRequest", namespace: QA) diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb index ce369c90a9f..5e7b68858c8 100644 --- a/qa/qa/page/project/settings/mirroring_repositories.rb +++ b/qa/qa/page/project/settings/mirroring_repositories.rb @@ -129,4 +129,4 @@ module QA end end -QA::Page::Project::Settings::MirroringRepositories.prepend_if_ee('QA::EE::Page::Project::Settings::MirroringRepositories') +QA::Page::Project::Settings::MirroringRepositories.prepend_mod_with('Page::Project::Settings::MirroringRepositories', namespace: QA) diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb index 6616921f34c..308cf6366a7 100644 --- a/qa/qa/page/project/settings/protected_branches.rb +++ b/qa/qa/page/project/settings/protected_branches.rb @@ -69,4 +69,4 @@ module QA end end -QA::Page::Project::Settings::ProtectedBranches.prepend_if_ee('QA::EE::Page::Project::Settings::ProtectedBranches') +QA::Page::Project::Settings::ProtectedBranches.prepend_mod_with('Page::Project::Settings::ProtectedBranches', namespace: QA) diff --git a/qa/qa/page/project/settings/protected_tags.rb b/qa/qa/page/project/settings/protected_tags.rb index bf8f349cfd5..d9f383154f9 100644 --- a/qa/qa/page/project/settings/protected_tags.rb +++ b/qa/qa/page/project/settings/protected_tags.rb @@ -43,4 +43,4 @@ module QA end end -QA::Page::Project::Settings::ProtectedTags.prepend_if_ee('QA::EE::Page::Project::Settings::ProtectedTags') +QA::Page::Project::Settings::ProtectedTags.prepend_mod_with('Page::Project::Settings::ProtectedTags', namespace: QA) diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb index 407c131fa73..a02b3d6a7d6 100644 --- a/qa/qa/page/project/settings/repository.rb +++ b/qa/qa/page/project/settings/repository.rb @@ -62,4 +62,4 @@ module QA end end -QA::Page::Project::Settings::Repository.prepend_if_ee('QA::EE::Page::Project::Settings::Repository') +QA::Page::Project::Settings::Repository.prepend_mod_with('Page::Project::Settings::Repository', namespace: QA) diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index d8c6b3881bd..c174d4b0c3f 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -147,7 +147,7 @@ module QA end def open_web_ide! - click_element :web_ide_button + click_element(:web_ide_button) end def has_edit_fork_button? @@ -180,4 +180,4 @@ module QA end end -QA::Page::Project::Show.prepend_if_ee('QA::EE::Page::Project::Show') +QA::Page::Project::Show.prepend_mod_with('Page::Project::Show', namespace: QA) diff --git a/qa/qa/page/project/snippet/index.rb b/qa/qa/page/project/snippet/index.rb index a221abc4196..fc677f96769 100644 --- a/qa/qa/page/project/snippet/index.rb +++ b/qa/qa/page/project/snippet/index.rb @@ -26,4 +26,4 @@ module QA end end -QA::Page::Project::Snippet::Index.prepend_if_ee('QA::EE::Page::Project::Snippet::Index') +QA::Page::Project::Snippet::Index.prepend_mod_with('Page::Project::Snippet::Index', namespace: QA) diff --git a/qa/qa/page/project/sub_menus/ci_cd.rb b/qa/qa/page/project/sub_menus/ci_cd.rb index 398712c04d2..7cb2fd6c655 100644 --- a/qa/qa/page/project/sub_menus/ci_cd.rb +++ b/qa/qa/page/project/sub_menus/ci_cd.rb @@ -12,16 +12,12 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common - - view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do - element :link_pipelines - end end end def click_ci_cd_pipelines within_sidebar do - click_element :link_pipelines + click_element(:sidebar_menu_link, menu_item: 'CI/CD') end end end diff --git a/qa/qa/page/project/sub_menus/common.rb b/qa/qa/page/project/sub_menus/common.rb index 85bf932be4a..c20710bc393 100644 --- a/qa/qa/page/project/sub_menus/common.rb +++ b/qa/qa/page/project/sub_menus/common.rb @@ -8,6 +8,20 @@ module QA extend QA::Page::PageConcern include QA::Page::SubMenus::Common + def self.included(base) + super + + base.class_eval do + view 'app/views/shared/nav/_sidebar_menu_item.html.haml' do + element :sidebar_menu_item_link + end + + view 'app/views/shared/nav/_sidebar_menu.html.haml' do + element :sidebar_menu_link + end + end + end + private def sidebar_element diff --git a/qa/qa/page/project/sub_menus/issues.rb b/qa/qa/page/project/sub_menus/issues.rb index 384af3fb53e..1df93d1118b 100644 --- a/qa/qa/page/project/sub_menus/issues.rb +++ b/qa/qa/page/project/sub_menus/issues.rb @@ -12,32 +12,25 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common - - view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do - element :issue_boards_link - element :issues_item - element :labels_link - element :milestones_link - end end end def click_issues within_sidebar do - click_link('Issues') + click_element(:sidebar_menu_link, menu_item: 'Issues') end end def click_milestones within_sidebar do - click_element :milestones_link + click_element(:sidebar_menu_item_link, menu_item: 'Milestones') end end def go_to_boards hover_issues do within_submenu do - click_element(:issue_boards_link) + click_element(:sidebar_menu_item_link, menu_item: 'Boards') end end end @@ -45,7 +38,7 @@ module QA def go_to_labels hover_issues do within_submenu do - click_element(:labels_link) + click_element(:sidebar_menu_item_link, menu_item: 'Labels') end end end @@ -53,7 +46,7 @@ module QA def go_to_milestones hover_issues do within_submenu do - click_element(:milestones_link) + click_element(:sidebar_menu_item_link, menu_item: 'Milestones') end end end @@ -62,8 +55,8 @@ module QA def hover_issues within_sidebar do - scroll_to_element(:issues_item) - find_element(:issues_item).hover + scroll_to_element(:sidebar_menu_link, menu_item: 'Issues') + find_element(:sidebar_menu_link, menu_item: 'Issues').hover yield end diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/operations.rb index af716d1af0d..077da697a63 100644 --- a/qa/qa/page/project/sub_menus/operations.rb +++ b/qa/qa/page/project/sub_menus/operations.rb @@ -12,20 +12,13 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common - - view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do - element :operations_link - element :operations_environments_link - element :operations_metrics_link - element :operations_incidents_link - end end end def go_to_operations_environments hover_operations do within_submenu do - click_element(:operations_environments_link) + click_element(:sidebar_menu_item_link, menu_item: 'Environments') end end end @@ -33,7 +26,7 @@ module QA def go_to_operations_metrics hover_operations do within_submenu do - click_element(:operations_metrics_link) + click_element(:sidebar_menu_item_link, menu_item: 'Metrics') end end end @@ -49,7 +42,7 @@ module QA def go_to_operations_incidents hover_operations do within_submenu do - click_element(:operations_incidents_link) + click_element(:sidebar_menu_item_link, menu_item: 'Incidents') end end end @@ -58,8 +51,8 @@ module QA def hover_operations within_sidebar do - scroll_to_element(:operations_link) - find_element(:operations_link).hover + scroll_to_element(:sidebar_menu_link, menu_item: 'Operations') + find_element(:sidebar_menu_link, menu_item: 'Operations').hover yield end diff --git a/qa/qa/page/project/sub_menus/packages.rb b/qa/qa/page/project/sub_menus/packages.rb index 46eae01e10d..88e2101a86d 100644 --- a/qa/qa/page/project/sub_menus/packages.rb +++ b/qa/qa/page/project/sub_menus/packages.rb @@ -7,19 +7,11 @@ module QA module Packages extend QA::Page::PageConcern - def self.included(base) - super - - base.class_eval do - view 'app/views/layouts/nav/sidebar/_project_packages_link.html.haml' do - element :packages_link - end - end - end - def click_packages_link - within_sidebar do - click_element :packages_link + hover_registry do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Package Registry') + end end end @@ -35,8 +27,8 @@ module QA def hover_registry within_sidebar do - scroll_to_element(:packages_link) - find_element(:packages_link).hover + scroll_to_element(:sidebar_menu_link, menu_item: 'Packages & Registries') + find_element(:sidebar_menu_link, menu_item: 'Packages & Registries').hover yield end diff --git a/qa/qa/page/project/sub_menus/project.rb b/qa/qa/page/project/sub_menus/project.rb index ecb3148b486..5499a0f71e3 100644 --- a/qa/qa/page/project/sub_menus/project.rb +++ b/qa/qa/page/project/sub_menus/project.rb @@ -12,10 +12,6 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common - - view 'app/views/shared/nav/_sidebar_menu.html.haml' do - element :sidebar_menu_link - end end end diff --git a/qa/qa/page/project/sub_menus/repository.rb b/qa/qa/page/project/sub_menus/repository.rb index 458f0cddab6..e35828ecd6a 100644 --- a/qa/qa/page/project/sub_menus/repository.rb +++ b/qa/qa/page/project/sub_menus/repository.rb @@ -12,14 +12,6 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common - - view 'app/views/shared/nav/_sidebar_menu_item.html.haml' do - element :sidebar_menu_item_link - end - - view 'app/views/shared/nav/_sidebar_menu.html.haml' do - element :sidebar_menu_link - end end end diff --git a/qa/qa/page/project/sub_menus/settings.rb b/qa/qa/page/project/sub_menus/settings.rb index 531c4686345..80f62c8efde 100644 --- a/qa/qa/page/project/sub_menus/settings.rb +++ b/qa/qa/page/project/sub_menus/settings.rb @@ -12,21 +12,13 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common - - view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do - element :settings_item - element :general_settings_link - element :integrations_settings_link - element :operations_settings_link - element :access_tokens_settings_link - end end end def go_to_ci_cd_settings hover_settings do within_submenu do - click_link('CI/CD') + click_element(:sidebar_menu_item_link, menu_item: 'CI/CD') end end end @@ -34,7 +26,7 @@ module QA def go_to_repository_settings hover_settings do within_submenu do - click_link('Repository') + click_element(:sidebar_menu_item_link, menu_item: 'Repository') end end end @@ -42,21 +34,21 @@ module QA def go_to_general_settings hover_settings do within_submenu do - click_element :general_settings_link + click_element(:sidebar_menu_item_link, menu_item: 'General') end end end def click_settings within_sidebar do - click_on 'Settings' + click_element(:sidebar_menu_link, menu_item: 'Settings') end end def go_to_integrations_settings hover_settings do within_submenu do - click_element :integrations_settings_link + click_element(:sidebar_menu_item_link, menu_item: 'Integrations') end end end @@ -64,7 +56,7 @@ module QA def go_to_operations_settings hover_settings do within_submenu do - click_element :operations_settings_link + click_element(:sidebar_menu_item_link, menu_item: 'Operations') end end end @@ -72,7 +64,7 @@ module QA def go_to_access_token_settings hover_settings do within_submenu do - click_element :access_tokens_settings_link + click_element(:sidebar_menu_item_link, menu_item: 'Access Tokens') end end end @@ -81,8 +73,8 @@ module QA def hover_settings within_sidebar do - scroll_to_element(:settings_item) - find_element(:settings_item).hover + scroll_to_element(:sidebar_menu_link, menu_item: 'Settings') + find_element(:sidebar_menu_link, menu_item: 'Settings').hover yield end diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb index fd68ac0de16..78b2db7d723 100644 --- a/qa/qa/page/project/web_ide/edit.rb +++ b/qa/qa/page/project/web_ide/edit.rb @@ -18,8 +18,8 @@ module QA end view 'app/assets/javascripts/ide/components/ide_tree.vue' do - element :new_file_button - element :new_directory_button + element :new_file_button, required: true + element :new_directory_button, required: true end view 'app/assets/javascripts/ide/components/ide_tree_list.vue' do @@ -36,7 +36,7 @@ module QA end view 'app/assets/javascripts/ide/components/commit_sidebar/actions.vue' do - element :commit_to_current_branch_radio + element :commit_to_current_branch_radio_container end view 'app/assets/javascripts/ide/components/commit_sidebar/form.vue' do @@ -44,6 +44,10 @@ module QA element :commit_button end + view 'app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue' do + element :commit_type_radio + end + view 'app/assets/javascripts/ide/components/repo_editor.vue' do element :editor_container end @@ -216,7 +220,9 @@ module QA # animation is still in process even when the buttons have the # expected visibility. commit_success = retry_until(sleep_interval: 5) do - click_element(:commit_to_current_branch_radio) if has_element?(:commit_to_current_branch_radio) + within_element(:commit_to_current_branch_radio_container) do + choose_element(:commit_type_radio) + end click_element(:commit_button) if has_element?(:commit_button) # If this is the first commit, the commit SHA only appears after reloading @@ -299,10 +305,30 @@ module QA def switch_to_commit_tab click_element(:commit_mode_tab) end + + def select_file(file_name) + # wait for the list of files to load + wait_until(reload: true) do + has_element?(:file_name_content, file_name: file_name) + end + click_element(:file_name_content, file_name: file_name) + end + + def link_line(line_number) + previous_url = page.current_url + wait_for_animated_element(:editor_container) + within_element(:editor_container) do + find('.line-numbers', text: line_number).hover.click + end + wait_until(max_duration: 5, reload: false) do + page.current_url != previous_url + end + page.current_url.to_s + end end end end end end -QA::Page::Project::WebIDE::Edit.prepend_if_ee('QA::EE::Page::Component::WebIDE::WebTerminalPanel') +QA::Page::Project::WebIDE::Edit.prepend_mod_with('Page::Component::WebIDE::WebTerminalPanel', namespace: QA) diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb index f3573e3cdd3..ac42405563a 100644 --- a/qa/qa/page/project/wiki/show.rb +++ b/qa/qa/page/project/wiki/show.rb @@ -14,4 +14,4 @@ module QA end end -QA::Page::Project::Wiki::Show.prepend_if_ee('QA::EE::Page::Project::Wiki::Show') +QA::Page::Project::Wiki::Show.prepend_mod_with('Page::Project::Wiki::Show', namespace: QA) diff --git a/qa/qa/page/registration/welcome.rb b/qa/qa/page/registration/welcome.rb index 394e94b6414..ff22e62b63e 100644 --- a/qa/qa/page/registration/welcome.rb +++ b/qa/qa/page/registration/welcome.rb @@ -21,4 +21,4 @@ module QA end end -QA::Page::Registration::Welcome.prepend_if_ee('QA::EE::Page::Registration::Welcome') +QA::Page::Registration::Welcome.prepend_mod_with('Page::Registration::Welcome', namespace: QA) diff --git a/qa/qa/page/trials/new.rb b/qa/qa/page/trials/new.rb new file mode 100644 index 00000000000..268f3b71717 --- /dev/null +++ b/qa/qa/page/trials/new.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + module Page + module Trials + class New < Chemlab::Page + path '/-/trials/new' + + # TODO: Supplant with data-qa-selectors + text_field :first_name, id: 'first_name' + text_field :last_name, id: 'last_name' + text_field :company_name, id: 'company_name' + select :number_of_employees, id: 'company_size' + text_field :telephone_number, id: 'phone_number' + text_field :number_of_users, id: 'number_of_users' + + select :country, id: 'country_select' + + button :continue, value: 'Continue' + end + end + end +end diff --git a/qa/qa/page/trials/select.rb b/qa/qa/page/trials/select.rb new file mode 100644 index 00000000000..3da0fb46322 --- /dev/null +++ b/qa/qa/page/trials/select.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module QA + module Page + module Trials + class Select < Chemlab::Page + path '/-/trials/select' + + # TODO: Supplant with data-qa-selectors + select :subscription_for, id: 'namespace_id' + text_field :new_group_name, id: 'new_group_name' + button :start_your_free_trial, value: 'Start your free trial' + radio :trial_company, id: 'trial_entity_company' + radio :trial_individual, id: 'trial_entity_individual' + end + end + end +end diff --git a/qa/qa/page/user/show.rb b/qa/qa/page/user/show.rb new file mode 100644 index 00000000000..ad2de331ad9 --- /dev/null +++ b/qa/qa/page/user/show.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module QA + module Page + module User + class Show < Page::Base + view 'app/views/users/show.html.haml' do + element :follow_user_link + element :following_link + end + + view 'app/views/shared/users/_user.html.haml' do + element :user_link + end + + view 'app/views/users/_overview.html.haml' do + element :user_activity_content + end + + def click_follow_user_link + click_element(:follow_user_link) + end + + def click_following_link + click_element(:following_link) + end + + def click_user_link(username) + click_element(:user_link, username: username) + end + + def has_activity?(activity) + within_element(:user_activity_content) do + has_text?(activity) + end + end + end + end + end +end diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb index fb7236f9f4c..c7565871b0b 100644 --- a/qa/qa/resource/group.rb +++ b/qa/qa/resource/group.rb @@ -2,10 +2,8 @@ module QA module Resource - class Group < Base - include Members - - attr_accessor :path, :description + class Group < GroupBase + attr_accessor :description attribute :sandbox do Sandbox.fabricate_via_api! do |sandbox| @@ -13,10 +11,6 @@ module QA end end - attribute :full_path - attribute :id - attribute :name - attribute :runners_token attribute :require_two_factor_authentication def initialize @@ -59,14 +53,6 @@ module QA "/groups/#{CGI.escape("#{sandbox.path}/#{path}")}" end - def api_put_path - "/groups/#{id}" - end - - def api_post_path - '/groups' - end - def api_post_body { parent_id: sandbox.id, @@ -77,17 +63,14 @@ module QA } end - def api_delete_path - "/groups/#{id}" - end - def set_require_two_factor_authentication(value:) put_body = { require_two_factor_authentication: value } response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body + return if response.code == HTTP_STATUS_OK - unless response.code == HTTP_STATUS_OK - raise ResourceUpdateFailedError, "Could not update require_two_factor_authentication to #{value}. Request returned (#{response.code}): `#{response}`." - end + raise(ResourceUpdateFailedError, <<~ERROR.strip) + Could not update require_two_factor_authentication to #{value}. Request returned (#{response.code}): `#{response}`. + ERROR end def change_repository_storage(new_storage) @@ -95,12 +78,20 @@ module QA response = post Runtime::API::Request.new(api_client, "/groups/#{id}/repository_storage_moves").url, post_body unless response.code.between?(200, 300) - raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`." + raise( + ResourceUpdateFailedError, + "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`." + ) end - wait_until(sleep_interval: 1) { Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) } + wait_until(sleep_interval: 1) do + Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) + end rescue Support::Repeater::RepeaterConditionExceededError - raise Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, 'Timed out while waiting for the group repository storage move to finish' + raise( + Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, + 'Timed out while waiting for the group repository storage move to finish' + ) end end end diff --git a/qa/qa/resource/group_base.rb b/qa/qa/resource/group_base.rb new file mode 100644 index 00000000000..bdd442a1c8b --- /dev/null +++ b/qa/qa/resource/group_base.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module QA + module Resource + # Base class for group classes Resource::Sandbox and Resource::Group + # + class GroupBase < Base + include Members + + attr_accessor :path + + attribute :id + attribute :runners_token + attribute :name + attribute :full_path + + # API post path + # + # @return [String] + def api_post_path + '/groups' + end + + # API put path + # + # @return [String] + def api_put_path + "/groups/#{id}" + end + + # API delete path + # + # @return [String] + def api_delete_path + "/groups/#{id}" + end + + # Object comparison + # + # @param [QA::Resource::GroupBase] other + # @return [Boolean] + def ==(other) + other.is_a?(GroupBase) && comparable_group == other.comparable_group + end + + # Override inspect for a better rspec failure diff output + # + # @return [String] + def inspect + JSON.pretty_generate(comparable_group) + end + + protected + + # Return subset of fields for comparing groups + # + # @return [Hash] + def comparable_group + reload! if api_response.nil? + + api_resource.except( + :id, + :web_url, + :visibility, + :full_name, + :full_path, + :created_at, + :parent_id, + :runners_token + ) + end + end + end +end diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index aaa882cffde..96a60381146 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -83,7 +83,7 @@ module QA end end - Page::Project::NewExperiment.perform(&:click_blank_project_link) if Page::Project::NewExperiment.perform(&:shown?) + Page::Project::New.perform(&:click_blank_project_link) Page::Project::New.perform do |new_page| new_page.choose_test_namespace diff --git a/qa/qa/resource/project_issue_note.rb b/qa/qa/resource/project_issue_note.rb new file mode 100644 index 00000000000..0eb34380332 --- /dev/null +++ b/qa/qa/resource/project_issue_note.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'securerandom' + +module QA + module Resource + class ProjectIssueNote < Base + attr_writer :body + + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-for-issue-notes' + resource.description = 'project for adding notes to issues' + end + end + + attribute :issue do + Issue.fabricate! do |resource| + resource.project = project + resource.title = 'Issue for adding notes.' + resource.description = 'Issue for adding notes.' + end + end + + attribute :id + attribute :body + + def initialize + @body = "Issue note body #{SecureRandom.hex(8)}" + end + + def fabricate! + issue.visit! + + Page::Project::Issue::Show.perform do |show| + show.comment(@body) + end + end + + def resource_web_url(resource) + super + rescue ResourceURLMissingError + # this particular resource does not expose a web_url property + end + + def api_get_path + "/projects/#{project.id}/issues/#{issue.iid}/notes/#{id}" + end + + def api_post_path + "/projects/#{project.id}/issues/#{issue.iid}/notes" + end + + def api_post_body + { + body: body + } + end + end + end +end diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb index ae183d55d89..913fd6ab9ec 100644 --- a/qa/qa/resource/sandbox.rb +++ b/qa/qa/resource/sandbox.rb @@ -6,16 +6,7 @@ module QA # Ensure we're in our sandbox namespace, either by navigating to it or by # creating it if it doesn't yet exist. # - class Sandbox < Base - include Members - - attr_accessor :path - - attribute :id - attribute :runners_token - attribute :name - attribute :full_path - + class Sandbox < GroupBase def initialize @path = Runtime::Namespace.sandbox_name end @@ -56,18 +47,6 @@ module QA "/groups/#{path}" end - def api_members_path - "#{api_get_path}/members" - end - - def api_post_path - '/groups' - end - - def api_delete_path - "/groups/#{id}" - end - def api_post_body { path: path, @@ -76,17 +55,14 @@ module QA } end - def api_put_path - "/groups/#{id}" - end - def update_group_setting(group_setting:, value:) - put_body = { "#{group_setting}": value } - response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body + response = put(Runtime::API::Request.new(api_client, api_put_path).url, { "#{group_setting}": value }) + return if response.code == HTTP_STATUS_OK - unless response.code == HTTP_STATUS_OK - raise ResourceUpdateFailedError, "Could not update #{group_setting} to #{value}. Request returned (#{response.code}): `#{response}`." - end + raise( + ResourceUpdateFailedError, + "Could not update #{group_setting} to #{value}. Request returned (#{response.code}): `#{response}`." + ) end end end diff --git a/qa/qa/resource/snippet.rb b/qa/qa/resource/snippet.rb index 6423dc7a41c..a94ae02b8fd 100644 --- a/qa/qa/resource/snippet.rb +++ b/qa/qa/resource/snippet.rb @@ -3,7 +3,7 @@ module QA module Resource class Snippet < Base - attr_accessor :title, :description, :file_content, :visibility, :file_name + attr_accessor :title, :description, :file_content, :visibility, :file_name, :files attribute :id attribute :http_url_to_repo diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb index d98b7d7c79d..8957dbcbe84 100644 --- a/qa/qa/resource/user.rb +++ b/qa/qa/resource/user.rb @@ -9,7 +9,7 @@ module QA attr_reader :unique_id attr_writer :username, :password - attr_accessor :admin, :provider, :extern_uid, :expect_fabrication_success + attr_accessor :admin, :provider, :extern_uid, :expect_fabrication_success, :hard_delete_on_api_removal attribute :id attribute :name @@ -19,6 +19,7 @@ module QA def initialize @admin = false + @hard_delete_on_api_removal = false @unique_id = SecureRandom.hex(8) @expect_fabrication_success = true end @@ -77,9 +78,7 @@ module QA def fabricate! # Don't try to log-out if we're not logged-in - if Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) } - Page::Main::Menu.perform { |main| main.sign_out } - end + Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) } if credentials_given? Page::Main::Login.perform do |login| @@ -103,9 +102,9 @@ module QA end def api_delete_path - "/users/#{id}" + "/users/#{id}?hard_delete=#{hard_delete_on_api_removal}" rescue NoValueError - "/users/#{fetch_id(username)}" + "/users/#{fetch_id(username)}?hard_delete=#{hard_delete_on_api_removal}" end def api_get_path @@ -135,12 +134,12 @@ module QA def self.fabricate_or_use(username = nil, password = nil) if Runtime::Env.signup_disabled? - self.fabricate_via_api! do |user| + fabricate_via_api! do |user| user.username = username user.password = password end else - self.fabricate! do |user| + fabricate! do |user| user.username = username if username user.password = password if password end @@ -149,10 +148,9 @@ module QA def block! response = post(Runtime::API::Request.new(api_client, api_block_path).url, nil) + return if response.code == HTTP_STATUS_CREATED - unless response.code == HTTP_STATUS_CREATED - raise ResourceUpdateFailedError, "Failed to block user. Request returned (#{response.code}): `#{response}`." - end + raise ResourceUpdateFailedError, "Failed to block user. Request returned (#{response.code}): `#{response}`." end private diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb index a3fce8bff88..3fe8552c063 100644 --- a/qa/qa/runtime/browser.rb +++ b/qa/qa/runtime/browser.rb @@ -6,6 +6,8 @@ require 'capybara/rspec' require 'capybara-screenshot/rspec' require 'selenium-webdriver' +require 'gitlab_handbook' + module QA module Runtime class Browser @@ -21,7 +23,7 @@ module QA def self.blank_page? ['', 'about:blank', 'data:,'].include?(Capybara.current_session.driver.browser.current_url) - rescue + rescue StandardError true end @@ -151,6 +153,12 @@ module QA # fail because of unexpected line breaks and other white space config.default_normalize_ws = true end + + Chemlab.configure do |config| + config.browser = Capybara.current_session.driver.browser # reuse Capybara session + config.libraries = [GitlabHandbook] + config.base_url = Runtime::Scenario.attributes[:gitlab_address] # reuse GitLab address + end end # rubocop: enable Metrics/AbcSize @@ -173,7 +181,7 @@ module QA simulate_slow_connection if Runtime::Env.simulate_slow_connection? - page_class.validate_elements_present! + page_class.validate_elements_present! if page_class.respond_to?(:validate_elements_present!) if QA::Runtime::Env.qa_cookies browser = Capybara.current_session.driver.browser diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index e4b92dc2e0d..e649084a394 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -403,4 +403,4 @@ module QA end end -QA::Runtime::Env.extend_if_ee('QA::EE::Runtime::Env') +QA::Runtime::Env.extend_mod_with('Runtime::Env', namespace: QA) diff --git a/qa/qa/runtime/release.rb b/qa/qa/runtime/release.rb index 1cd0c62563b..029c8fc037e 100644 --- a/qa/qa/runtime/release.rb +++ b/qa/qa/runtime/release.rb @@ -27,7 +27,7 @@ module QA def self.method_missing(name, *args) self.new.strategy.public_send(name, *args) - rescue + rescue StandardError saved = Capybara::Screenshot.screenshot_and_save_page QA::Runtime::Logger.error("Screenshot: #{saved[:image]}") if saved&.key?(:image) diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb index 0d517dffee8..d0a201e3d22 100644 --- a/qa/qa/scenario/template.rb +++ b/qa/qa/scenario/template.rb @@ -23,6 +23,15 @@ module QA def perform(options, *args) extract_address(:gitlab_address, options, args) + gitlab_address = URI(Runtime::Scenario.gitlab_address) + + # Define the "About" page as an `about` subdomain. + # @example + # Given *gitlab_address* = 'https://gitlab.com/' #=> https://about.gitlab.com/ + # Given *gitlab_address* = 'https://staging.gitlab.com/' #=> https://about.staging.gitlab.com/ + # Given *gitlab_address* = 'http://gitlab-abc123.test/' #=> http://about.gitlab-abc123.test/ + Runtime::Scenario.define(:about_address, URI(-> { gitlab_address.host = "about.#{gitlab_address.host}"; gitlab_address }.call).to_s) # rubocop:disable Style/Semicolon + ## # Perform before hooks, which are different for CE and EE # diff --git a/qa/qa/scenario/test/sanity/selectors.rb b/qa/qa/scenario/test/sanity/selectors.rb index b2c90ab2e2a..8b355c5faf6 100644 --- a/qa/qa/scenario/test/sanity/selectors.rb +++ b/qa/qa/scenario/test/sanity/selectors.rb @@ -58,4 +58,4 @@ module QA end end -QA::Scenario::Test::Sanity::Selectors.prepend_if_ee('QA::EE::Scenario::Test::Sanity::Selectors') +QA::Scenario::Test::Sanity::Selectors.prepend_mod_with('Scenario::Test::Sanity::Selectors', namespace: QA) diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb new file mode 100644 index 00000000000..055300122d4 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage', :requires_admin do + describe 'Group bulk import' do + let!(:api_client) { Runtime::API::Client.as_admin } + let!(:user) do + Resource::User.fabricate_via_api! do |usr| + usr.api_client = api_client + usr.hard_delete_on_api_removal = true + end + end + + let!(:personal_access_token) { Runtime::API::Client.new(user: user).personal_access_token } + + let!(:sandbox) do + Resource::Sandbox.fabricate_via_api! do |group| + group.api_client = api_client + end + end + + let!(:source_group) do + Resource::Sandbox.fabricate_via_api! do |group| + group.api_client = api_client + group.path = "source-group-for-import-#{SecureRandom.hex(4)}" + end + end + + let!(:subgroup) do + Resource::Group.fabricate_via_api! do |group| + group.api_client = api_client + group.sandbox = source_group + group.path = "subgroup-for-import-#{SecureRandom.hex(4)}" + end + end + + let(:imported_group) do + Resource::Group.new.tap do |group| + group.api_client = api_client + group.path = source_group.path + end + end + + let(:imported_subgroup) do + Resource::Group.new.tap do |group| + group.api_client = api_client + group.sandbox = imported_group + group.path = subgroup.path + end + end + + def staging? + Runtime::Scenario.gitlab_address.include?('staging.gitlab.com') + end + + before(:all) do + Runtime::Feature.enable(:bulk_import) + Runtime::Feature.enable(:top_level_group_creation_enabled) if staging? + end + + before do + sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER) + source_group.add_member(user, Resource::Members::AccessLevel::MAINTAINER) + + Flow::Login.sign_in(as: user) + Page::Main::Menu.new.go_to_import_group + Page::Group::New.new.connect_gitlab_instance(Runtime::Scenario.gitlab_address, personal_access_token) + end + + it( + 'performs bulk group import from another gitlab instance', + testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1785', + exclude: { job: ['ce:relative_url', 'ee:relative_url'] } # https://gitlab.com/gitlab-org/gitlab/-/issues/330344 + ) do + Page::Group::BulkImport.perform do |import_page| + import_page.import_group(source_group.path, sandbox.path) + + aggregate_failures do + expect(import_page).to have_imported_group(source_group.path, wait: 120) + expect(imported_group).to eq(source_group) + expect(imported_subgroup).to eq(subgroup) + end + end + end + + after do + user.remove_via_api! + source_group.remove_via_api! + end + + after(:all) do + Runtime::Feature.disable(:bulk_import) + Runtime::Feature.disable(:top_level_group_creation_enabled) if staging? + 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 5fbcd69817b..23a21d70cc1 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 @@ -138,7 +138,7 @@ module QA Page::Admin::Overview::Users::Index.perform do |index| index.click_pending_approval_tab index.search_user(user.username) - index.click_user(user.username) + index.click_user(user.name) end Page::Admin::Overview::Users::Show.perform do |show| diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb new file mode 100644 index 00000000000..964cd453049 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage' do + describe 'User', :requires_admin do + let(:admin_api_client) { Runtime::API::Client.as_admin } + + let(:user) do + Resource::User.fabricate_via_api! do |user| + user.api_client = admin_api_client + end + end + + let(:user_api_client) do + Runtime::API::Client.new(:gitlab, user: user) + end + + let(:group) do + group = QA::Resource::Group.fabricate_via_api! do |group| + group.path = "group_for_follow_user_activity_#{SecureRandom.hex(8)}" + end + group.add_member(user) + group + end + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-for-tags' + project.initialize_with_readme = true + project.api_client = user_api_client + project.group = group + end + end + + let(:merge_request) do + Resource::MergeRequest.fabricate_via_api! do |mr| + mr.project = project + mr.api_client = user_api_client + end + end + + let(:issue) do + Resource::Issue.fabricate_via_api! do |issue| + issue.project = project + issue.api_client = user_api_client + end + end + + let(:comment) do + Resource::ProjectIssueNote.fabricate_via_api! do |project_issue_note| + project_issue_note.project = project + project_issue_note.issue = issue + project_issue_note.body = 'This is a comment' + project_issue_note.api_client = user_api_client + end + end + + before do + # Create both tokens before logging in the first time so that we don't need to log out in the middle of the test + admin_api_client.personal_access_token + user_api_client.personal_access_token + end + + it 'can be followed and their activity seen', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1773' do + Flow::Login.sign_in + page.visit Runtime::Scenario.gitlab_address + "/#{user.username}" + Page::User::Show.perform(&:click_follow_user_link) + + expect(page).to have_text("No activities found") + + project + merge_request + issue + comment + + Page::Main::Menu.perform(&:click_user_profile_link) + Page::User::Show.perform do |show| + show.click_following_link + show.click_user_link(user.username) + + aggregate_failures do + expect(show).to have_activity('created project') + expect(show).to have_activity('opened merge request') + expect(show).to have_activity('opened issue') + expect(show).to have_activity('commented on issue') + end + end + end + + after do + project.api_client = admin_api_client + project.remove_via_api! + user.remove_via_api! + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb index 2a91c674a22..d9b5ffcdc47 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb @@ -49,7 +49,7 @@ module QA Page::File::Show.perform(&:click_edit) - expect(page).to have_text("You're not allowed to edit files in this project directly.") + expect(page).to have_text("You can’t edit files directly in this project.") end after do 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 b2b37fcd424..8c0b3da6004 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 @@ -9,7 +9,7 @@ module QA Flow::Login.sign_in end - it 'creates an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1167' do + it 'creates an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1793' do issue = Resource::Issue.fabricate_via_browser_ui! Page::Project::Menu.perform(&:click_issues) @@ -19,7 +19,7 @@ module QA end end - it 'closes an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1085' do + it 'closes an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1792' do closed_issue.visit! Page::Project::Issue::Show.perform do |issue_page| diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb index 34669eb3815..ca0eeb2403c 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -3,7 +3,7 @@ module QA RSpec.describe 'Create', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/323990', type: :flaky } do describe 'Merge request rebasing' do - it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1274' do + it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1800' do Flow::Login.sign_in project = Resource::Project.fabricate_via_api! do |project| diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb new file mode 100644 index 00000000000..089b87be423 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Reverting a commit' do + let(:file_name) { "secret_file.md" } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project' + project.initialize_with_readme = true + end + end + + let(:commit) do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add new file' + commit.add_files([ + { file_path: file_name, content: 'pssst!' } + ]) + end + end + + before do + Flow::Login.sign_in + commit.visit! + end + + it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1784' do + Page::Project::Commit::Show.perform(&:revert_commit) + Page::MergeRequest::New.perform(&:create_merge_request) + + Page::MergeRequest::Show.perform do |merge_request| + merge_request.click_diffs_tab + expect(merge_request).to have_file(file_name) + end + end + + after do + project.remove_via_api! + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb index 3574cdbe4ac..3574cdbe4ac 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb new file mode 100644 index 00000000000..db31cadb37d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Branch with unusual name' do + let(:branch_name) { 'unUsually/named#br--anch' } + let(:project) do + Resource::Project.fabricate_via_api! do |resource| + resource.name = 'unusually-named-branch-project' + resource.initialize_with_readme = true + end + end + + before do + Flow::Login.sign_in + end + + context 'when branch name contains slash, hash, double dash, and capital letter' do + it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1780' do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.branch = branch_name + commit.start_branch = project.default_branch + commit.commit_message = 'Add new file' + commit.add_files([ + { file_path: 'test-folder/test-file.md', content: 'new content' } + ]) + end + + project.visit! + + Page::Project::Show.perform do |show| + show.switch_to_branch(branch_name) + show.click_file('test-folder') + + expect(show).to have_file('test-file.md') + + show.click_file('test-file.md') + + expect(show).to have_content('new content') + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb new file mode 100644 index 00000000000..98d0a3c5706 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'File with unusual name' do + let(:file_name) { '-un:usually;named#file?.md' } + let(:project) do + Resource::Project.fabricate_via_api! do |resource| + resource.name = 'unusually-named-file-project' + resource.initialize_with_readme = true + end + end + + before do + Flow::Login.sign_in + end + + context 'when file name starts with a dash and contains hash, semicolon, colon, and question mark' do + it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1779' do + Resource::File.fabricate_via_api! do |file| + file.project = project + file.commit_message = 'Add new file' + file.name = "test-folder/#{file_name}" + file.content = "### Heading\n\n[Gitlab link](https://gitlab.com/)" + end + + project.visit! + + Page::Project::Show.perform do |show| + show.click_file('test-folder') + + expect(show).to have_file(file_name) + + show.click_file(file_name) + + aggregate_failures 'markdown file contents' do + expect(show).to have_content('Heading') + expect(show).to have_content('Gitlab link') + expect(show).not_to have_content('###') + expect(show).not_to have_content('https://gitlab.com/') + end + end + end + end + end + end +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 b67e0e54aa0..9d90ff189c6 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 @@ -71,7 +71,7 @@ module QA snippet.remove_via_api! end - it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/832' do + it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1794' do Resource::Repository::Push.fabricate! do |push| push.repository_ssh_uri = repository_uri_ssh push.ssh_key = ssh_key diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb new file mode 100644 index 00000000000..9c7dc868a2e --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Snippet index page' do + let(:personal_snippet_with_single_file) do + Resource::Snippet.fabricate_via_api! do |snippet| + snippet.title = "Personal snippet with one file-#{SecureRandom.hex(8)}" + snippet.visibility = 'Public' + end + end + + let(:personal_snippet_with_multiple_files) do + Resource::Snippet.fabricate_via_api! do |snippet| + snippet.title = "Personal snippet with multiple files-#{SecureRandom.hex(8)}" + snippet.visibility = 'Private' + snippet.file_name = 'First file name' + snippet.file_content = 'first file content' + + snippet.add_files do |files| + files.append(name: 'Second file name', content: 'second file content') + files.append(name: 'Third file name', content: 'third file content') + end + end + end + + let(:project_snippet_with_single_file) do + Resource::ProjectSnippet.fabricate_via_api! do |snippet| + snippet.title = "Project snippet with one file-#{SecureRandom.hex(8)}" + snippet.visibility = 'Private' + end + end + + let(:project_snippet_with_multiple_files) do + Resource::ProjectSnippet.fabricate_via_api! do |snippet| + snippet.title = "Project snippet with multiple files-#{SecureRandom.hex(8)}" + snippet.visibility = 'Public' + snippet.file_name = 'First file name' + snippet.file_content = 'first file content' + + snippet.add_files do |files| + files.append(name: 'Second file name', content: 'second file content') + files.append(name: 'Third file name', content: 'third file content') + end + end + end + + before do + Flow::Login.sign_in + end + + after do + personal_snippet_with_single_file.remove_via_api! + personal_snippet_with_multiple_files.remove_via_api! + project_snippet_with_single_file.remove_via_api! + project_snippet_with_multiple_files.remove_via_api! + end + + shared_examples 'displaying details on index page' do |snippet_type| + it "shows correct details of #{snippet_type} including file number" do + send(snippet_type) + Page::Main::Menu.perform do |menu| + menu.go_to_more_dropdown_option(:snippets_link) + end + + Page::Dashboard::Snippet::Index.perform do |snippet| + aggregate_failures 'file content verification' do + expect(snippet).to have_snippet_title(send(snippet_type).title) + expect(snippet).to have_visibility_level(send(snippet_type).title, send(snippet_type).visibility) + expect(snippet).to have_number_of_files(send(snippet_type).title, send(snippet_type).files.count) + end + end + end + end + + it_behaves_like 'displaying details on index page', :personal_snippet_with_single_file + it_behaves_like 'displaying details on index page', :personal_snippet_with_multiple_files + it_behaves_like 'displaying details on index page', :project_snippet_with_single_file + it_behaves_like 'displaying details on index page', :project_snippet_with_multiple_files + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb new file mode 100644 index 00000000000..c7fc01303b7 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Link to line in Web IDE' do + let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) } + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.template_name = 'express' + end + end + + before do + Flow::Login.sign_in + end + + after do + project.remove_via_api! + end + + it 'can link to a specific line of code in Web IDE', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1102' do + project.visit! + + Page::Project::Show.perform(&:open_web_ide!) + + Page::Project::WebIDE::Edit.perform do |ide| + ide.select_file('app.js') + @link = ide.link_line('26') + end + + Flow::Login.sign_in(as: user) + + page.visit(@link) + + Page::Project::WebIDE::Edit.perform do |ide| + expect(ide).to have_file('app.js') + end + + expect(page.driver.current_url).to include('app.js/#L26') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb index 5b976ae4126..4938ae3f969 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb @@ -115,7 +115,7 @@ module QA commit.add_files( [ { - file_path: "#{Faker::Lorem.word}.txt", + file_path: Faker::File.unique.file_name, content: Faker::Lorem.sentence } ] @@ -129,7 +129,7 @@ module QA merge_request.project = project merge_request.description = Faker::Lorem.sentence merge_request.target_new_branch = false - merge_request.file_name = "#{Faker::Lorem.word}.txt" + merge_request.file_name = Faker::File.unique.file_name merge_request.file_content = Faker::Lorem.sentence end end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb new file mode 100644 index 00000000000..253b5fb2af4 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Verify', :runner, :requires_admin do + describe 'Artifacts' do + context 'when locked' do + let(:file_name) { 'artifact.txt' } + let(:directory_name) { 'my_artifacts' } + let(:executor) { "qa-runner-#{Time.now.to_i}" } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-with-locked-artifacts' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = [executor] + end + end + + before do + Flow::Login.sign_in + end + + after do + runner.remove_via_api! + end + + it 'can be browsed' 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-artifacts: + tags: + - '#{executor}' + artifacts: + paths: + - '#{directory_name}' + expire_in: 1 sec + script: + - | + mkdir #{directory_name} + echo "CONTENTS" > #{directory_name}/#{file_name} + YAML + } + ] + ) + end.project.visit! + + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed') + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('test-artifacts') + end + + Page::Project::Job::Show.perform do |show| + expect(show).to have_browse_button + show.click_browse_button + end + + Page::Project::Artifact::Show.perform do |show| + show.go_to_directory(directory_name) + expect(show).to have_content(file_name) + end + 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 index 519777b32d9..c1625f1e679 100644 --- 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 @@ -5,34 +5,29 @@ require 'faker' module QA RSpec.describe 'Verify', :runner do describe 'Pass dotenv variables to downstream via bridge' do - let(:executor_1) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } - let(:executor_2) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } + let(:upstream_var) { Faker::Alphanumeric.alphanumeric(8) } + let(:group) { Resource::Group.fabricate_via_api! } let(:upstream_project) do Resource::Project.fabricate_via_api! do |project| - project.name = 'project-with-pipeline-1' + project.group = group + project.name = 'upstream-project-with-bridge' end end let(:downstream_project) do Resource::Project.fabricate_via_api! do |project| - project.name = 'project-with-pipeline-2' + project.group = group + project.name = 'downstream-project-with-bridge' end end - let!(:runner_1) do + let!(:runner) 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] + runner.name = executor + runner.tags = [executor] + runner.token = group.sandbox.runners_token end end @@ -45,8 +40,8 @@ module QA end after do - runner_1.remove_via_api! - runner_2.remove_via_api! + runner.remove_via_api! + group.remove_via_api! end it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1086' do @@ -58,6 +53,7 @@ module QA Page::Project::Job::Show.perform do |show| expect(show).to have_passed(timeout: 360) + expect(show.output).to have_content(upstream_var) end end @@ -77,8 +73,9 @@ module QA content: <<~YAML build: stage: build - tags: ["#{executor_1}"] - script: echo "MY_VAR=hello" >> variables.env + tags: ["#{executor}"] + script: + - echo "DYNAMIC_ENVIRONMENT_VAR=#{upstream_var}" >> variables.env artifacts: reports: dotenv: variables.env @@ -86,7 +83,7 @@ module QA trigger: stage: deploy variables: - PASSED_MY_VAR: $MY_VAR + PASSED_MY_VAR: $DYNAMIC_ENVIRONMENT_VAR trigger: #{downstream_project.full_path} YAML } @@ -98,8 +95,9 @@ module QA content: <<~YAML downstream_test: stage: test - tags: ["#{executor_2}"] - script: '[ "$PASSED_MY_VAR" = hello ]; exit "$?"' + tags: ["#{executor}"] + script: + - echo $PASSED_MY_VAR YAML } end diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb index 5e663d87ae3..7a71d1cfbaf 100644 --- a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :orchestrated do - describe 'Container Registry', only: { subdomain: :staging } do + RSpec.describe 'Package' do + describe 'Container Registry', :reliable, only: { subdomain: %i[staging pre] } do let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'project-with-registry' @@ -26,6 +26,10 @@ module QA - docker:19.03.12-dind variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + DOCKER_TLS_VERIFY: 1 + DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client" script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $IMAGE_TAG . diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb index 7234edb46d3..fb019290d4c 100644 --- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb @@ -9,6 +9,7 @@ module QA let(:group_id) { 'com.gitlab.qa' } let(:artifact_id) { "maven-#{SecureRandom.hex(8)}" } + let(:another_artifact_id) { "maven-#{SecureRandom.hex(8)}" } let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') } let(:auth_token) do unless Page::Main::Menu.perform(&:signed_in?) @@ -64,7 +65,7 @@ module QA <repositories> <repository> <id>#{project.name}</id> - <url>#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/maven</url> + <url>#{gitlab_address_with_port}/api/v4/groups/#{project.group.id}/-/packages/maven</url> </repository> </repositories> <distributionManagement> @@ -82,6 +83,43 @@ module QA } end + let(:pom_xml_another_project) do + { + file_path: 'pom.xml', + content: <<~XML + <project> + <groupId>#{group_id}</groupId> + <artifactId>#{another_artifact_id}</artifactId> + <version>1.0</version> + <modelVersion>4.0.0</modelVersion> + <repositories> + <repository> + <id>#{another_project.name}</id> + <url>#{gitlab_address_with_port}/api/v4/groups/#{another_project.group.id}/-/packages/maven</url> + </repository> + </repositories> + <distributionManagement> + <repository> + <id>#{another_project.name}</id> + <url>#{gitlab_address_with_port}/api/v4/projects/#{another_project.id}/packages/maven</url> + </repository> + <snapshotRepository> + <id>#{another_project.name}</id> + <url>#{gitlab_address_with_port}/api/v4/projects/#{another_project.id}/packages/maven</url> + </snapshotRepository> + </distributionManagement> + <dependencies> + <dependency> + <groupId>#{group_id}</groupId> + <artifactId>#{artifact_id}</artifactId> + <version>1.0</version> + </dependency> + </dependencies> + </project> + XML + } + end + let(:settings_xml) do { file_path: 'settings.xml', @@ -106,7 +144,7 @@ module QA } end - let(:gitlab_ci_yaml) do + let(:gitlab_ci_deploy_yml) do { file_path: '.gitlab-ci.yml', content: @@ -124,58 +162,90 @@ module QA } end + let(:gitlab_ci_install_yml) do + { + file_path: '.gitlab-ci.yml', + content: + <<~YAML + install: + image: maven:3.6-jdk-11 + script: + - "mvn install" + only: + - "#{project.default_branch}" + tags: + - "runner-for-#{another_project.group.name}" + YAML + } + end + after do runner.remove_via_api! + project.remove_via_api! + another_project.remove_via_api! end - it 'publishes a maven package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/943' do - # Use a maven docker container to deploy the package - with_fixtures([pom_xml, settings_xml]) do |dir| - Service::DockerRun::Maven.new(dir).publish! + it 'pushes and pulls a Maven package via CI and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1115' do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([ + gitlab_ci_deploy_yml, + settings_xml, + pom_xml + ]) end project.visit! - 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| - expect(show).to have_package_info(package_name, "1.0") + Flow::Pipeline.visit_latest_pipeline - show.click_delete + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('deploy') end - Page::Project::Packages::Index.perform do |index| - expect(index).to have_content("Package deleted successfully") - expect(index).not_to have_package(package_name) + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) end - end - it 'publishes and downloads a maven package via CI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1115' do Resource::Repository::Commit.fabricate_via_api! do |commit| - commit.project = project + commit.project = another_project commit.commit_message = 'Add .gitlab-ci.yml' commit.add_files([ - gitlab_ci_yaml, - settings_xml, - pom_xml + gitlab_ci_install_yml, + pom_xml_another_project ]) end - project.visit! + another_project.visit! Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| - pipeline.click_job('deploy') + pipeline.click_job('install') end Page::Project::Job::Show.perform do |job| expect(job).to be_successful(timeout: 800) end + + project.visit! + + 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| + expect(show).to have_package_info(package_name, "1.0") + show.click_delete + end + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_content("Package deleted successfully") + expect(index).not_to have_package(package_name) + end end context 'when "allow duplicate" setting is disabled' do @@ -204,7 +274,7 @@ module QA commit.project = another_project commit.commit_message = 'Add .gitlab-ci.yml' commit.add_files([ - gitlab_ci_yaml, + gitlab_ci_deploy_yml, settings_xml, pom_xml ]) @@ -249,7 +319,7 @@ module QA commit.project = another_project commit.commit_message = 'Add .gitlab-ci.yml' commit.add_files([ - gitlab_ci_yaml, + gitlab_ci_deploy_yml, settings_xml, pom_xml ]) diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb index 49b42bd1ff6..4d714affd65 100644 --- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb @@ -5,7 +5,7 @@ module QA describe 'npm registry' do include Runtime::Fixtures - let!(:registry_scope) { project.group.sandbox.path } + let!(:registry_scope) { Runtime::Namespace.sandbox_name } let(:auth_token) do unless Page::Main::Menu.perform(&:signed_in?) Flow::Login.sign_in @@ -14,28 +14,87 @@ module QA Resource::PersonalAccessToken.fabricate!.token end + let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) } + let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" } + let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" } + let!(:project) do Resource::Project.fabricate_via_api! do |project| - project.name = 'npm-registry-project' + project.name = 'npm-project' end end - let(:package) do - Resource::Package.new.tap do |package| - package.name = "@#{registry_scope}/#{project.name}" - package.project = project + let!(:another_project) do + Resource::Project.fabricate_via_api! do |another_project| + another_project.name = 'npm-another-project' + another_project.template_name = 'express' + another_project.group = project.group end end - after do - package.remove_via_api! + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.group.name}"] + runner.executor = :docker + runner.token = project.group.sandbox.runners_token + end + end + + let(:gitlab_ci_deploy_yaml) do + { + file_path: '.gitlab-ci.yml', + content: + <<~YAML + image: node:14-buster + + stages: + - deploy + + deploy: + stage: deploy + script: + - npm publish + only: + - "#{project.default_branch}" + tags: + - "runner-for-#{project.group.name}" + YAML + } end - it 'publishes an npm package and then deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/944' do - uri = URI.parse(Runtime::Scenario.gitlab_address) - gitlab_host_with_port = "#{uri.host}:#{uri.port}" - gitlab_address_with_port = "#{uri.scheme}://#{uri.host}:#{uri.port}" - package_json = { + let(:gitlab_ci_install_yaml) do + { + file_path: '.gitlab-ci.yml', + content: + <<~YAML + image: node:latest + + stages: + - install + + install: + stage: install + script: + - "npm config set @#{registry_scope}:registry #{gitlab_address_with_port}/api/v4/packages/npm/" + - "npm install #{package.name}" + cache: + key: ${CI_BUILD_REF_NAME} + paths: + - node_modules/ + artifacts: + paths: + - node_modules/ + only: + - "#{another_project.default_branch}" + tags: + - "runner-for-#{another_project.group.name}" + YAML + } + end + + let(:package_json) do + { file_path: 'package.json', content: <<~JSON { @@ -47,19 +106,79 @@ module QA } } JSON - } - npmrc = { + } + end + + let(:npmrc) do + { file_path: '.npmrc', content: <<~NPMRC //#{gitlab_host_with_port}/api/v4/projects/#{project.id}/packages/npm/:_authToken=#{auth_token} - //#{gitlab_host_with_port}/api/v4/packages/npm/:_authToken=#{auth_token} - @#{registry_scope}:registry=#{gitlab_address_with_port}/api/v4/packages/npm/ + @#{registry_scope}:registry=#{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/npm/ NPMRC } + end + + let(:package) do + Resource::Package.new.tap do |package| + package.name = "@#{registry_scope}/#{project.name}" + package.project = project + end + end + + after do + package.remove_via_api! + runner.remove_via_api! + project.remove_via_api! + another_project.remove_via_api! + end + + it 'push and pull a npm package via CI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1772' do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([ + gitlab_ci_deploy_yaml, + npmrc, + package_json + ]) + 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 + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = another_project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([ + gitlab_ci_install_yaml + ]) + end + + another_project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('install') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + job.click_browse_button + end - # Use a node docker container to publish the package - with_fixtures([npmrc, package_json]) do |dir| - Service::DockerRun::NodeJs.new(dir).publish! + Page::Project::Artifact::Show.perform do |artifacts| + artifacts.go_to_directory('node_modules') + artifacts.go_to_directory("@#{registry_scope}") + expect(artifacts).to have_content( "#{project.name}") end project.visit! 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 index c0d84d82e51..3db5b9671d9 100644 --- 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 @@ -21,33 +21,24 @@ module QA end let(:another_project) do - Resource::Project.fabricate_via_api! do |project| - project.name = 'nuget-package-install-project' - project.template_name = 'dotnetcore' + Resource::Project.fabricate_via_api! do |another_project| + another_project.name = 'nuget-package-install-project' + another_project.template_name = 'dotnetcore' + another_project.group = project.group 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!(:another_runner) do - Resource::Runner.fabricate! do |runner| - runner.name = "qa-runner-#{Time.now.to_i}" - runner.tags = ["runner-for-#{another_project.name}"] + runner.tags = ["runner-for-#{project.group.sandbox.name}"] runner.executor = :docker - runner.project = another_project + runner.token = project.group.sandbox.runners_token end end after do runner.remove_via_api! - another_runner.remove_via_api! package.remove_via_api! end @@ -78,7 +69,7 @@ module QA only: - "#{project.default_branch}" tags: - - "runner-for-#{project.name}" + - "runner-for-#{project.group.sandbox.name}" YAML } ] @@ -137,7 +128,7 @@ module QA only: - "#{another_project.default_branch}" tags: - - "runner-for-#{another_project.name}" + - "runner-for-#{project.group.sandbox.name}" YAML } ] diff --git a/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb new file mode 100644 index 00000000000..5d15885cd67 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/rubygems_registry_spec.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :requires_admin, :packages do + describe 'RubyGems Repository' do + include Runtime::Fixtures + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'rubygems-package-project' + end + end + + let(:package) do + Resource::Package.new.tap do |package| + package.name = 'mygem' + package.project = 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 + Runtime::Feature.enable(:rubygem_packages, project: project) + end + + after do + Runtime::Feature.disable(:rubygem_packages, project: project) + runner.remove_via_api! + package.remove_via_api! + project.remove_via_api! + end + + it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1131' do + Flow::Login.sign_in + + Resource::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.directory = Pathname + .new(__dir__) + .join('../../../../fixtures/rubygems_package') + push.commit_message = 'RubyGems package' + end + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add mygem.gemspec' + commit.add_files( + [ + { + file_path: '.gitlab-ci.yml', + content: + <<~YAML + image: ruby + + test_package: + stage: deploy + before_script: + - mkdir ~/.gem + - echo "---" > ~/.gem/credentials + - | + echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials + - chmod 0600 ~/.gem/credentials + script: + - gem build mygem + - gem push mygem-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems + tags: + - "runner-for-#{project.name}" + YAML + }, + { + file_path: 'lib/hello_gem.rb', + content: + <<~RUBY + class HelloWorld + def self.hi + puts "Hello world!" + end + end + RUBY + } + ] + ) + end + + project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('test_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(&:click_delete) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_content("Package deleted successfully") + expect(index).not_to have_package(package.name) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb index 5ea7a7bb4cb..2cb2ea2d636 100644 --- a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb @@ -30,7 +30,7 @@ module QA pipeline.visit! end - it 'runs a Pages-specific pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/877' do + it 'runs a Pages-specific pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1783' do Page::Project::Pipeline::Show.perform do |show| expect(show).to have_job(:pages) show.click_job(:pages) diff --git a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb index 07fc4f0e7fa..94df408f9aa 100644 --- a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb +++ b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_relative 'cluster_with_prometheus.rb' +require_relative 'cluster_with_prometheus' module QA RSpec.describe 'Monitor', :orchestrated, :kubernetes, :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/241448', type: :investigating } do diff --git a/qa/qa/tools/revoke_all_personal_access_tokens.rb b/qa/qa/tools/revoke_all_personal_access_tokens.rb index 0aaf1ed6f7f..63a7b0d2d8e 100644 --- a/qa/qa/tools/revoke_all_personal_access_tokens.rb +++ b/qa/qa/tools/revoke_all_personal_access_tokens.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative '../../qa' -require 'net/protocol.rb' +require 'net/protocol' # This script revokes all personal access tokens with the name of 'api-test-token' on the host specified by GITLAB_ADDRESS # Required environment variables: GITLAB_USERNAME, GITLAB_PASSWORD and GITLAB_ADDRESS # Run `rake revoke_personal_access_tokens` diff --git a/qa/spec/scenario/template_spec.rb b/qa/spec/scenario/template_spec.rb index f07d817ea16..9800f92b306 100644 --- a/qa/spec/scenario/template_spec.rb +++ b/qa/spec/scenario/template_spec.rb @@ -3,6 +3,7 @@ RSpec.describe QA::Scenario::Template do let(:feature) { spy('Runtime::Feature') } let(:release) { spy('Runtime::Release') } + let(:gitlab_address) { 'https://gitlab.com/' } before do stub_const('QA::Runtime::Release', release) @@ -12,7 +13,7 @@ RSpec.describe QA::Scenario::Template do end it 'allows a feature to be enabled' do - subject.perform({ enable_feature: 'a-feature' }) + subject.perform({ gitlab_address: gitlab_address, enable_feature: 'a-feature' }) expect(feature).to have_received(:enable).with('a-feature') end @@ -21,7 +22,7 @@ RSpec.describe QA::Scenario::Template do allow(QA::Runtime::Feature).to receive(:enabled?) .with('another-feature').and_return(true) - subject.perform({ disable_feature: 'another-feature' }) + subject.perform({ gitlab_address: gitlab_address, disable_feature: 'another-feature' }) expect(feature).to have_received(:disable).with('another-feature') end @@ -30,7 +31,7 @@ RSpec.describe QA::Scenario::Template do allow(QA::Runtime::Feature).to receive(:enabled?) .with('another-feature').and_return(false) - subject.perform({ disable_feature: 'another-feature' }) + subject.perform({ gitlab_address: gitlab_address, disable_feature: 'another-feature' }) expect(feature).not_to have_received(:disable).with('another-feature') end @@ -38,7 +39,7 @@ RSpec.describe QA::Scenario::Template do it 'ensures an enabled feature is disabled afterwards' do allow(QA::Specs::Runner).to receive(:perform).and_raise('failed test') - expect { subject.perform({ enable_feature: 'a-feature' }) }.to raise_error('failed test') + expect { subject.perform({ gitlab_address: gitlab_address, enable_feature: 'a-feature' }) }.to raise_error('failed test') expect(feature).to have_received(:enable).with('a-feature') expect(feature).to have_received(:disable).with('a-feature') @@ -50,7 +51,7 @@ RSpec.describe QA::Scenario::Template do allow(QA::Runtime::Feature).to receive(:enabled?) .with('another-feature').and_return(true) - expect { subject.perform({ disable_feature: 'another-feature' }) }.to raise_error('failed test') + expect { subject.perform({ gitlab_address: gitlab_address, disable_feature: 'another-feature' }) }.to raise_error('failed test') expect(feature).to have_received(:disable).with('another-feature') expect(feature).to have_received(:enable).with('another-feature') @@ -62,9 +63,21 @@ RSpec.describe QA::Scenario::Template do allow(QA::Runtime::Feature).to receive(:enabled?) .with('another-feature').and_return(false) - expect { subject.perform({ disable_feature: 'another-feature' }) }.to raise_error('failed test') + expect { subject.perform({ gitlab_address: gitlab_address, disable_feature: 'another-feature' }) }.to raise_error('failed test') expect(feature).not_to have_received(:disable).with('another-feature') expect(feature).not_to have_received(:enable).with('another-feature') end + + it 'defines an about address by default' do + subject.perform( { gitlab_address: gitlab_address }) + + expect(QA::Runtime::Scenario.gitlab_address).to eq(gitlab_address) + expect(QA::Runtime::Scenario.about_address).to eq('https://about.gitlab.com/') + + subject.perform({ gitlab_address: 'http://gitlab-abc.test/' }) + + expect(QA::Runtime::Scenario.gitlab_address).to eq('http://gitlab-abc.test/') + expect(QA::Runtime::Scenario.about_address).to eq('http://about.gitlab-abc.test/') + end end diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb index 631ebf65893..0c9643c830b 100644 --- a/qa/spec/spec_helper.rb +++ b/qa/spec/spec_helper.rb @@ -3,6 +3,7 @@ require_relative '../qa' require 'rspec/retry' require 'rspec-parameterized' +require 'active_support/core_ext/hash' if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK'] require 'knapsack' diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb index 642d9e0745b..021ce9091e0 100644 --- a/qa/spec/specs/runner_spec.rb +++ b/qa/spec/specs/runner_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'active_support/core_ext/hash' - RSpec.describe QA::Specs::Runner do shared_examples 'excludes orchestrated, transient, and geo' do it 'excludes the orchestrated, transient, and geo tags, and includes default args' do diff --git a/qa/spec/support/shared_examples/scenario_shared_examples.rb b/qa/spec/support/shared_examples/scenario_shared_examples.rb index 637cfb9a05d..5e448349cf9 100644 --- a/qa/spec/support/shared_examples/scenario_shared_examples.rb +++ b/qa/spec/support/shared_examples/scenario_shared_examples.rb @@ -18,6 +18,7 @@ module QA stub_const('QA::Runtime::Scenario', attributes) stub_const('QA::Runtime::Feature', feature) + allow(attributes).to receive(:gitlab_address).and_return(args[:gitlab_address]) allow(runner).to receive(:perform).and_yield(runner) allow(QA::Runtime::Address).to receive(:valid?).and_return(true) end |