Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
commit43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch)
treedceebdc68925362117480a5d672bcff122fb625b /qa
parent20c84b99005abd1c82101dfeff264ac50d2df211 (diff)
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'qa')
-rw-r--r--qa/Dockerfile7
-rw-r--r--qa/Gemfile20
-rw-r--r--qa/Gemfile.lock65
-rw-r--r--qa/README.md41
-rwxr-xr-xqa/gdk/launch5
-rw-r--r--qa/lib/gitlab/page/group/settings/billing.rb9
-rw-r--r--qa/lib/gitlab/page/group/settings/usage_quotas.rb10
-rw-r--r--qa/qa.rb4
-rw-r--r--qa/qa/ce/strategy.rb3
-rw-r--r--qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb111
-rw-r--r--qa/qa/fixtures/mocks/import/github.yml368
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb8
-rw-r--r--qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb23
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb2
-rw-r--r--qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb2
-rw-r--r--qa/qa/flow/login.rb4
-rw-r--r--qa/qa/flow/pipeline.rb12
-rw-r--r--qa/qa/flow/project.rb11
-rw-r--r--qa/qa/flow/saml.rb2
-rw-r--r--qa/qa/flow/user_onboarding.rb6
-rw-r--r--qa/qa/page/admin/applications.rb70
-rw-r--r--qa/qa/page/admin/menu.rb70
-rw-r--r--qa/qa/page/admin/sidebar/overview.rb25
-rw-r--r--qa/qa/page/admin/sidebar/settings.rb41
-rw-r--r--qa/qa/page/base.rb25
-rw-r--r--qa/qa/page/component/breadcrumbs.rb2
-rw-r--r--qa/qa/page/component/content_editor.rb2
-rw-r--r--qa/qa/page/component/dropdown.rb18
-rw-r--r--qa/qa/page/component/groups_filter.rb15
-rw-r--r--qa/qa/page/component/import/selection.rb4
-rw-r--r--qa/qa/page/component/note.rb2
-rw-r--r--qa/qa/page/component/snippet.rb12
-rw-r--r--qa/qa/page/component/wiki_page_form.rb5
-rw-r--r--qa/qa/page/dashboard/snippet/index.rb13
-rw-r--r--qa/qa/page/file/show.rb2
-rw-r--r--qa/qa/page/group/menu.rb15
-rw-r--r--qa/qa/page/group/sub_menus/common.rb2
-rw-r--r--qa/qa/page/group/sub_menus/super_sidebar/build.rb25
-rw-r--r--qa/qa/page/group/sub_menus/super_sidebar/main.rb27
-rw-r--r--qa/qa/page/group/sub_menus/super_sidebar/operate.rb23
-rw-r--r--qa/qa/page/main/login.rb19
-rw-r--r--qa/qa/page/main/menu.rb144
-rw-r--r--qa/qa/page/merge_request/new.rb2
-rw-r--r--qa/qa/page/merge_request/show.rb56
-rw-r--r--qa/qa/page/profile/menu.rb38
-rw-r--r--qa/qa/page/profile/super_sidebar/menu.rb31
-rw-r--r--qa/qa/page/project/branches/show.rb2
-rw-r--r--qa/qa/page/project/import/github.rb22
-rw-r--r--qa/qa/page/project/import/repo_by_url.rb15
-rw-r--r--qa/qa/page/project/issue/index.rb11
-rw-r--r--qa/qa/page/project/issue/new.rb2
-rw-r--r--qa/qa/page/project/issue/show.rb16
-rw-r--r--qa/qa/page/project/job/show.rb8
-rw-r--r--qa/qa/page/project/menu.rb22
-rw-r--r--qa/qa/page/project/monitor/alerts/index.rb12
-rw-r--r--qa/qa/page/project/monitor/alerts/show.rb25
-rw-r--r--qa/qa/page/project/monitor/incidents/index.rb12
-rw-r--r--qa/qa/page/project/new.rb16
-rw-r--r--qa/qa/page/project/pipeline/show.rb11
-rw-r--r--qa/qa/page/project/pipeline_editor/show.rb6
-rw-r--r--qa/qa/page/project/settings/alerts.rb5
-rw-r--r--qa/qa/page/project/settings/branch_rules.rb33
-rw-r--r--qa/qa/page/project/settings/branch_rules_details.rb35
-rw-r--r--qa/qa/page/project/settings/ci_variables.rb9
-rw-r--r--qa/qa/page/project/settings/deploy_keys.rb1
-rw-r--r--qa/qa/page/project/settings/main.rb1
-rw-r--r--qa/qa/page/project/settings/merge_request.rb5
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb7
-rw-r--r--qa/qa/page/project/settings/repository.rb8
-rw-r--r--qa/qa/page/project/show.rb33
-rw-r--r--qa/qa/page/project/sub_menus/ci_cd.rb2
-rw-r--r--qa/qa/page/project/sub_menus/common.rb4
-rw-r--r--qa/qa/page/project/sub_menus/create_new_menu.rb54
-rw-r--r--qa/qa/page/project/sub_menus/issues.rb4
-rw-r--r--qa/qa/page/project/sub_menus/monitor.rb16
-rw-r--r--qa/qa/page/project/sub_menus/packages.rb4
-rw-r--r--qa/qa/page/project/sub_menus/repository.rb2
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/build.rb49
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/code.rb49
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/main.rb27
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/monitor.rb41
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/operate.rb41
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/plan.rb33
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/secure.rb25
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/settings.rb41
-rw-r--r--qa/qa/page/project/tag/show.rb5
-rw-r--r--qa/qa/page/project/web_ide/edit.rb2
-rw-r--r--qa/qa/page/project/web_ide/vscode.rb2
-rw-r--r--qa/qa/page/registration/welcome.rb6
-rw-r--r--qa/qa/page/sub_menus/common.rb54
-rw-r--r--qa/qa/page/sub_menus/create_new_menu.rb41
-rw-r--r--qa/qa/page/sub_menus/super_sidebar/context_switcher.rb44
-rw-r--r--qa/qa/page/sub_menus/super_sidebar/main.rb21
-rw-r--r--qa/qa/page/sub_menus/super_sidebar/manage.rb35
-rw-r--r--qa/qa/page/sub_menus/super_sidebar/operate.rb31
-rw-r--r--qa/qa/page/sub_menus/super_sidebar/plan.rb31
-rw-r--r--qa/qa/page/sub_menus/super_sidebar/settings.rb47
-rw-r--r--qa/qa/page/user/show.rb8
-rw-r--r--qa/qa/resource/api_fabricator.rb135
-rw-r--r--qa/qa/resource/base.rb35
-rw-r--r--qa/qa/resource/ci_cd_settings.rb47
-rw-r--r--qa/qa/resource/ci_variable.rb13
-rw-r--r--qa/qa/resource/events/project.rb10
-rw-r--r--qa/qa/resource/group.rb4
-rw-r--r--qa/qa/resource/instance_oauth_application.rb49
-rw-r--r--qa/qa/resource/integrations/web_hook/smockerable.rb41
-rw-r--r--qa/qa/resource/issue.rb2
-rw-r--r--qa/qa/resource/members.rb19
-rw-r--r--qa/qa/resource/merge_request_from_fork.rb15
-rw-r--r--qa/qa/resource/pipeline.rb2
-rw-r--r--qa/qa/resource/project.rb5
-rw-r--r--qa/qa/resource/project_imported_from_github.rb4
-rw-r--r--qa/qa/resource/project_web_hook.rb44
-rw-r--r--qa/qa/resource/runner_base.rb18
-rw-r--r--qa/qa/resource/snippet.rb6
-rw-r--r--qa/qa/resource/web_hook_base.rb46
-rw-r--r--qa/qa/runtime/allure_report.rb19
-rw-r--r--qa/qa/runtime/application_settings.rb3
-rw-r--r--qa/qa/runtime/browser.rb45
-rw-r--r--qa/qa/runtime/env.rb92
-rw-r--r--qa/qa/service/cluster_provider/gcloud.rb10
-rw-r--r--qa/qa/service/docker_run/base.rb4
-rw-r--r--qa/qa/service/docker_run/gitlab.rb45
-rw-r--r--qa/qa/service/docker_run/gitlab_runner.rb15
-rw-r--r--qa/qa/service/docker_run/k3s.rb3
-rw-r--r--qa/qa/service/kubernetes_cluster.rb14
-rw-r--r--qa/qa/specs/features/api/1_manage/group_access_token_spec.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb11
-rw-r--r--qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb134
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb12
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb8
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb10
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/project_access_token_spec.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/rate_limits_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb21
-rw-r--r--qa/qa/specs/features/api/3_create/repository/files_spec.rb1
-rw-r--r--qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb2
-rw-r--r--qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb2
-rw-r--r--qa/qa/specs/features/api/4_verify/file_variable_spec.rb2
-rw-r--r--qa/qa/specs/features/api/9_data_stores/user_inherited_access_spec.rb (renamed from qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb)51
-rw-r--r--qa/qa/specs/features/api/9_data_stores/users_spec.rb (renamed from qa/qa/specs/features/api/1_manage/users_spec.rb)10
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb18
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb118
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb39
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_github_spec.rb18
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb101
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb)46
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_creation_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb)10
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_manipulation_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb)6
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_directory_management_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb)4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb)7
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_list_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb)6
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_page_deletion_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb)4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb74
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb15
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb57
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb84
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_new/add_new_directory_in_web_ide_spec.rb73
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/add_file_template_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb)17
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/create_first_file_in_web_ide_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb)15
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/link_to_line_in_web_ide_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb)12
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/open_web_ide_from_diff_tab_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb)15
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/review_merge_request_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb)15
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/server_hooks_custom_error_message_spec.rb)18
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb (renamed from qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb)14
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_parent_child_pipelines_spec.rb321
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb204
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb51
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb100
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_multiple_projects_spec.rb154
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb78
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb109
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb21
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/alert_management/recovery_alert_resolves_correct_alert_spec.rb53
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/incident_management/recovery_alert_closes_correct_incident_spec.rb56
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/group/group_member_access_request_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/group/group_member_access_request_spec.rb)8
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_group_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb)6
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb)10
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/add_project_member_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb)2
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/create_project_badge_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb)12
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/create_project_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb)2
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/dashboard_images_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb)4
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/invite_group_to_project_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb)23
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/project_owner_permissions_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb)4
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/project/view_project_activity_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb)6
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/user/follow_user_activity_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb)23
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/user/parent_group_access_termination_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/user/parent_group_access_termination_spec.rb)6
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/user/user_inherited_access_spec.rb (renamed from qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb)20
-rw-r--r--qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb21
-rw-r--r--qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb2
-rw-r--r--qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb1
-rw-r--r--qa/qa/specs/features/shared_contexts/packages_registry_shared_context.rb14
-rw-r--r--qa/qa/specs/features/shared_contexts/sends_and_resolves_test_alerts.rb75
-rw-r--r--qa/qa/specs/helpers/context_selector.rb92
-rw-r--r--qa/qa/specs/spec_helper.rb2
-rw-r--r--qa/qa/support/helpers/import_source.rb19
-rw-r--r--qa/qa/support/json_formatter.rb8
-rw-r--r--qa/qa/support/loglinking.rb24
-rw-r--r--qa/qa/support/matchers/have_matcher.rb4
-rw-r--r--qa/qa/support/page/logging.rb52
-rw-r--r--qa/qa/support/wait_for_requests.rb6
-rw-r--r--qa/qa/tools/test_resource_data_processor.rb2
-rw-r--r--qa/qa/tools/test_resources_handler.rb2
-rw-r--r--qa/qa/vendor/github/page/base.rb14
-rw-r--r--qa/qa/vendor/github/page/login.rb36
-rw-r--r--qa/qa/vendor/one_password/cli.rb59
-rw-r--r--qa/qa/vendor/smocker/event_payload.rb61
-rw-r--r--qa/qa/vendor/smocker/history_response.rb7
-rw-r--r--qa/qa/vendor/smocker/smocker_api.rb19
-rw-r--r--qa/qa/vendor/smocker/verify_response.rb46
-rw-r--r--qa/spec/fixtures/ff/async_commit_diff_files.yml (renamed from qa/spec/fixtures/ff/bulk_import_projects.yml)10
-rw-r--r--qa/spec/page/logging_spec.rb16
-rw-r--r--qa/spec/resource/api_fabricator_spec.rb2
-rw-r--r--qa/spec/resource/project_web_hook_spec.rb70
-rw-r--r--qa/spec/runtime/env_spec.rb73
-rw-r--r--qa/spec/specs/helpers/context_selector_spec.rb158
-rw-r--r--qa/spec/specs/helpers/feature_flag_spec.rb64
-rw-r--r--qa/spec/tools/ci/ff_changes_spec.rb8
-rw-r--r--qa/spec/vendor/smocker_api_spec.rb18
-rw-r--r--qa/tasks/ci.rake2
-rw-r--r--qa/tasks/webdrivers.rake1
287 files changed, 4809 insertions, 1940 deletions
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 6efc8ac09fa..2bf668abc49 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -22,6 +22,13 @@ RUN apt-get update \
&& rm -rf /var/lib/apt/lists/*
##
+# Install 1Password CLI
+#
+RUN wget -P /tmp/ https://downloads.1password.com/linux/debian/$(dpkg --print-architecture)/stable/1password-cli-$(dpkg --print-architecture)-latest.deb
+RUN dpkg -i /tmp/1password-cli-$(dpkg --print-architecture)-latest.deb
+RUN op --version
+
+##
# Install root certificate
#
RUN mkdir -p /usr/share/ca-certificates/gitlab
diff --git a/qa/Gemfile b/qa/Gemfile
index 9e41b5ddeed..e8d3a435766 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -2,27 +2,29 @@
source 'https://rubygems.org'
-gem 'gitlab-qa', '~> 9', require: 'gitlab/qa'
+gem 'gitlab-qa', '~> 10', '>= 10.3.0', require: 'gitlab/qa'
+gem 'gitlab_quality-test_tooling', '~> 0.4.0', require: false
gem 'activesupport', '~> 6.1.7.2' # This should stay in sync with the root's Gemfile
gem 'allure-rspec', '~> 2.20.0'
-gem 'capybara', '~> 3.38.0'
+gem 'capybara', '~> 3.39.1'
gem 'capybara-screenshot', '~> 1.0.26'
gem 'rake', '~> 13', '>= 13.0.6'
gem 'rspec', '~> 3.12'
-gem 'selenium-webdriver', '~> 4.8'
+# 4.9.1 drops Ruby 2.7 support. We can upgrade further after we drop Ruby 2.7 support.
+gem 'selenium-webdriver', '= 4.9.0'
gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
gem 'rest-client', '~> 2.1.0'
gem 'rspec-retry', '~> 0.6.2', require: 'rspec/retry'
gem 'rspec_junit_formatter', '~> 0.6.0'
-gem 'faker', '~> 3.1', '>= 3.1.1'
+gem 'faker', '~> 3.2'
gem 'knapsack', '~> 4.0'
-gem 'parallel_tests', '~> 4.2'
+gem 'parallel_tests', '~> 4.2', '>= 4.2.1'
gem 'rotp', '~> 6.2.2'
-gem 'parallel', '~> 1.22', '>= 1.22.1'
+gem 'parallel', '~> 1.23'
gem 'rainbow', '~> 3.1.1'
gem 'rspec-parameterized', '~> 1.0.0'
-gem 'octokit', '~> 6.0.1'
-gem "faraday-retry", "~> 2.0"
+gem 'octokit', '~> 6.1.1'
+gem "faraday-retry", "~> 2.1"
gem 'webdrivers', '~> 5.2'
gem 'zeitwerk', '~> 2.6', '>= 2.6.7'
gem 'influxdb-client', '~> 2.9'
@@ -38,7 +40,7 @@ gem 'chemlab', '~> 0.10'
gem 'chemlab-library-www-gitlab-com', '~> 0.1', '>= 0.1.1'
# dependencies for jenkins client
-gem 'nokogiri', '~> 1.14', '>= 1.14.2'
+gem 'nokogiri', '~> 1.14', '>= 1.14.4'
gem 'deprecation_toolkit', '~> 2.0.3', require: false
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index d544aa685a5..9b2b8acfb87 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -29,7 +29,7 @@ GEM
debug_inspector (>= 0.0.1)
builder (3.2.4)
byebug (11.1.3)
- capybara (3.38.0)
+ capybara (3.39.1)
addressable
matrix
mini_mime (>= 0.1.3)
@@ -51,7 +51,7 @@ GEM
chemlab (~> 0.4)
coderay (1.1.2)
colorize (0.8.1)
- concurrent-ruby (1.1.10)
+ concurrent-ruby (1.2.2)
confiner (0.4.0)
gitlab (>= 4.17)
zeitwerk (>= 2.5, < 3)
@@ -63,13 +63,13 @@ GEM
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
excon (0.92.4)
- faker (3.1.1)
+ faker (3.2.0)
i18n (>= 1.8.11, < 2)
faraday (2.5.2)
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
faraday-net_http (3.0.0)
- faraday-retry (2.0.0)
+ faraday-retry (2.1.0)
faraday (~> 2.0)
ffi (1.15.5)
ffi-compiler (1.0.1)
@@ -102,11 +102,21 @@ GEM
gitlab (4.18.0)
httparty (~> 0.18)
terminal-table (>= 1.5.1)
- gitlab-qa (9.0.0)
+ gitlab-qa (10.3.0)
activesupport (~> 6.1)
gitlab (~> 4.18.0)
http (~> 5.0)
nokogiri (~> 1.10)
+ parallel (>= 1, < 2)
+ rainbow (>= 3, < 4)
+ table_print (= 1.5.7)
+ zeitwerk (>= 2, < 3)
+ gitlab_quality-test_tooling (0.4.0)
+ activesupport (~> 6.1)
+ gitlab (~> 4.18.0)
+ http (~> 5.0)
+ nokogiri (~> 1.10)
+ parallel (>= 1, < 2)
rainbow (>= 3, < 4)
table_print (= 1.5.7)
zeitwerk (>= 2, < 3)
@@ -151,8 +161,8 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
http-form_data (2.3.0)
- httparty (0.20.0)
- mime-types (~> 3.0)
+ httparty (0.21.0)
+ mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
i18n (1.12.0)
@@ -173,23 +183,23 @@ GEM
method_source (1.0.0)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
- mime-types-data (3.2022.0105)
+ mime-types-data (3.2023.0218.1)
mini_mime (1.1.0)
mini_portile2 (2.8.1)
- minitest (5.17.0)
+ minitest (5.18.0)
multi_json (1.15.0)
multi_xml (0.6.0)
netrc (0.11.0)
- nokogiri (1.14.2)
+ nokogiri (1.14.4)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
- octokit (6.0.1)
+ octokit (6.1.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
oj (3.13.23)
os (1.1.4)
- parallel (1.22.1)
- parallel_tests (4.2.0)
+ parallel (1.23.0)
+ parallel_tests (4.2.1)
parallel
parser (3.1.3.0)
ast (~> 2.4.1)
@@ -203,7 +213,7 @@ GEM
pry-byebug (3.10.1)
byebug (~> 11.0)
pry (>= 0.13, < 0.15)
- public_suffix (5.0.0)
+ public_suffix (5.0.1)
racc (1.6.2)
rack (2.2.3.1)
rack-test (1.1.0)
@@ -259,7 +269,7 @@ GEM
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
- selenium-webdriver (4.8.0)
+ selenium-webdriver (4.9.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
@@ -274,13 +284,13 @@ GEM
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
- tzinfo (2.0.5)
+ tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
- unicode-display_width (2.3.0)
+ unicode-display_width (2.4.2)
unparser (0.6.5)
diff-lcs (~> 1.3)
parser (>= 3.1.0)
@@ -307,23 +317,24 @@ DEPENDENCIES
activesupport (~> 6.1.7.2)
airborne (~> 0.3.7)
allure-rspec (~> 2.20.0)
- capybara (~> 3.38.0)
+ capybara (~> 3.39.1)
capybara-screenshot (~> 1.0.26)
chemlab (~> 0.10)
chemlab-library-www-gitlab-com (~> 0.1, >= 0.1.1)
confiner (~> 0.4)
deprecation_toolkit (~> 2.0.3)
- faker (~> 3.1, >= 3.1.1)
- faraday-retry (~> 2.0)
+ faker (~> 3.2)
+ faraday-retry (~> 2.1)
fog-core (= 2.1.0)
fog-google (~> 1.19)
- gitlab-qa (~> 9)
+ gitlab-qa (~> 10, >= 10.3.0)
+ gitlab_quality-test_tooling (~> 0.4.0)
influxdb-client (~> 2.9)
knapsack (~> 4.0)
- nokogiri (~> 1.14, >= 1.14.2)
- octokit (~> 6.0.1)
- parallel (~> 1.22, >= 1.22.1)
- parallel_tests (~> 4.2)
+ nokogiri (~> 1.14, >= 1.14.4)
+ octokit (~> 6.1.1)
+ parallel (~> 1.23)
+ parallel_tests (~> 4.2, >= 4.2.1)
pry-byebug (~> 3.10.1)
rainbow (~> 3.1.1)
rake (~> 13, >= 13.0.6)
@@ -334,7 +345,7 @@ DEPENDENCIES
rspec-retry (~> 0.6.2)
rspec_junit_formatter (~> 0.6.0)
ruby-debug-ide (~> 0.7.3)
- selenium-webdriver (~> 4.8)
+ selenium-webdriver (= 4.9.0)
slack-notifier (~> 2.4)
terminal-table (~> 3.0.2)
warning (~> 1.3)
@@ -342,4 +353,4 @@ DEPENDENCIES
zeitwerk (~> 2.6, >= 2.6.7)
BUNDLED WITH
- 2.4.6
+ 2.4.13
diff --git a/qa/README.md b/qa/README.md
index e6520867642..d8670d4da02 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -48,6 +48,37 @@ Tests are executed in merge request pipelines as part of the development lifecyc
- [Review app environment](../doc/development/testing_guide/review_apps.md)
- [e2e:package-and-test](../doc/development/testing_guide/end_to_end/index.md#testing-code-in-merge-requests)
+### Including tests in other projects
+
+Pipeline template for `package-and-test` E2E tests is designed in a way so it can be included as a child pipeline in other projects.
+
+Minimal configuration example would look like this:
+
+```yaml
+qa-test:
+ stage: test
+ variables:
+ RELEASE: EE
+ trigger:
+ strategy: depend
+ forward:
+ yaml_variables: true
+ pipeline_variables: true
+ include:
+ - project: gitlab-org/gitlab
+ ref: master
+ file: .gitlab/ci/package-and-test/main.gitlab-ci.yml
+```
+
+To set GitLab version used for testing, following environment variables can be used:
+
+- `RELEASE`: `omnibus` release, can be string value `EE` or `CE` for nightly release of enterprise or community edition of GitLab or can be fully qualified Docker image name
+- `QA_IMAGE`: Docker image of qa code. By default inferred from `RELEASE` but can be explicitly overridden with this variable
+
+#### Test specific environment variables
+
+Special GitLab configurations require various specific environment variables to be present for tests to work. These can be provisioned automatically using `terraform` setup in [engineering-productivity-infrastructure](https://gitlab.com/gitlab-org/quality/engineering-productivity-infrastructure/-/tree/main/qa-resources/modules/e2e-ci) project.
+
### Logging
By default tests on CI use `info` log level. `debug` level is still available in case of failure debugging. Logs are stored in jobs artifacts.
@@ -98,7 +129,7 @@ See the section above for situations that might require adjustment to the comman
1. Use the following command to start an instance that you can visit at `http://127.0.0.1`:
- ```
+ ```bash
docker run \
--hostname 127.0.0.1 \
--publish 80:80 --publish 22:22 \
@@ -137,7 +168,7 @@ See the section above for situations that might require adjustment to the comman
2. Use the following command to start an instance that you can visit at `http://127.0.0.1`. You might need to grant admin rights if asked:
- ```
+ ```bash
docker run --hostname 127.0.0.1 --publish 80:80 --publish 22:22 --name gitlab --shm-size 256m --env GITLAB_OMNIBUS_CONFIG="gitlab_rails['initial_root_password']='5iveL\!fe';" gitlab/gitlab-ee:nightly
```
@@ -184,7 +215,7 @@ Those tests are tagged `:transient` and therefore can be run via:
bundle exec rspec --tag transient
```
-#### Overriding gitlab address
+#### Overriding GitLab address
When running tests against GDK, the default address is `http://127.0.0.1:3000`. This value can be overridden by providing environment variable `QA_GITLAB_URL`:
@@ -228,7 +259,7 @@ All [supported environment variables are here](https://gitlab.com/gitlab-org/git
#### Sending additional cookies
The environment variable `QA_COOKIES` can be set to send additional cookies
-on every request. This is necessary on gitlab.com to direct traffic to the
+on every request. This is necessary on `gitlab.com` to direct traffic to the
canary fleet. To do this set `QA_COOKIES="gitlab_canary=true"`.
To set multiple cookies, separate them with the `;` character, for example: `QA_COOKIES="cookie1=value;cookie2=value2"`
@@ -274,7 +305,7 @@ bundle exec rspec --tag quarantine
### Running tests with a custom bin/qa test runner
-`bin/qa` is an additional custom wrapper script that abstracts away some of the more complicated setups that some tests require. This option requires test scenario and test instance's Gitlab address to be specified in the command. For example, to run any `Instance` scenario test, the following command can be used:
+`bin/qa` is an additional custom wrapper script that abstracts away some of the more complicated setups that some tests require. This option requires test scenario and test instance's GitLab address to be specified in the command. For example, to run any `Instance` scenario test, the following command can be used:
```shell
bundle exec bin/qa Test::Instance::All http://localhost:3000
diff --git a/qa/gdk/launch b/qa/gdk/launch
index 4b1fc6ae191..249484b417c 100755
--- a/qa/gdk/launch
+++ b/qa/gdk/launch
@@ -1,6 +1,6 @@
#!/bin/bash
-COMMIT_REF=${1:-$CI_COMMIT_REF_SLUG}
+COMMIT_REF=${1:-$CI_COMMIT_SHA}
RSPEC_ARGS=$2
if [ -z "${COMMIT_REF}" ]; then
@@ -36,5 +36,4 @@ cd qa
bundle install --jobs=$(nproc) --retry=3 --quiet
# Run the tests
-bundle exec rake "knapsack:download[test]"
-bundle exec bin/qa Test::Instance::All http://gdk.test:3000 -- $RSPEC_ARGS || true
+bundle exec bin/qa Test::Instance::All http://gdk.test:3000 -- $RSPEC_ARGS
diff --git a/qa/lib/gitlab/page/group/settings/billing.rb b/qa/lib/gitlab/page/group/settings/billing.rb
index d0d73278890..1cb31c995f6 100644
--- a/qa/lib/gitlab/page/group/settings/billing.rb
+++ b/qa/lib/gitlab/page/group/settings/billing.rb
@@ -29,6 +29,15 @@ module Gitlab
refresh_seats
::QA::Support::WaitForRequests.wait_for_requests
end
+
+ # Waits for subscription to be synced and UI to be updated
+ #
+ # @param subscription_plan [String]
+ def wait_for_subscription(subscription_plan, page:)
+ ::QA::Support::Waiter.wait_until(max_duration: 30, sleep_interval: 3, reload_page: page) do
+ billing_plan_header.match?(/currently using the #{subscription_plan} saas plan/i)
+ end
+ end
end
end
end
diff --git a/qa/lib/gitlab/page/group/settings/usage_quotas.rb b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
index 3cb501efe13..a6d9cfa7846 100644
--- a/qa/lib/gitlab/page/group/settings/usage_quotas.rb
+++ b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
@@ -11,7 +11,9 @@ module Gitlab
p :seats_used
p :seats_owed
table :subscription_users
+ div :pending_members_alert
button :remove_user
+ button :view_pending_approvals, text: /View pending approvals/
# Pipelines section
link :pipelines_tab
@@ -23,12 +25,11 @@ module Gitlab
# Storage section
link :storage_tab
link :purchase_more_storage
- div :used_storage_message
+ div :namespace_usage_total
div :group_usage_message
div :dependency_proxy_usage
span :dependency_proxy_size
div :container_registry_usage
- div :project_storage_used
div :project
div :storage_type_legend
span :container_registry_size
@@ -36,6 +37,11 @@ module Gitlab
div :storage_purchase_successful_alert, text: /You have successfully purchased a storage/
div :additional_storage_alert, text: /purchase additional storage/
+ # Pending members
+ div :pending_members
+ button :approve_member
+ button :confirm_member_approval, text: /^OK$/
+
def plan_ci_limits
plan_ci_minutes[/(\d+){2}/]
end
diff --git a/qa/qa.rb b/qa/qa.rb
index cb1278771d9..f6fba30c079 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -82,7 +82,9 @@ module QA
"jetbrains" => "JetBrains",
"vscode" => "VSCode",
"registry_with_cdn" => "RegistryWithCDN",
- "fips" => "FIPS"
+ "fips" => "FIPS",
+ "ci_cd_settings" => "CICDSettings",
+ "cli" => "CLI"
)
loader.setup
diff --git a/qa/qa/ce/strategy.rb b/qa/qa/ce/strategy.rb
index 8143595a18b..2587da17739 100644
--- a/qa/qa/ce/strategy.rb
+++ b/qa/qa/ce/strategy.rb
@@ -16,6 +16,9 @@ module QA
QA::Runtime::Env.personal_access_token)
end
+ QA::Runtime::Logger.info("Browser: #{QA::Runtime::Env.browser}")
+ QA::Runtime::Logger.info("Browser version: #{QA::Runtime::Env.browser_version}")
+
# The login page could take some time to load the first time it is visited.
# We visit the login page and wait for it to properly load only once before the tests.
QA::Runtime::Logger.info("Performing sanity check for environment!")
diff --git a/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb b/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
deleted file mode 100644
index e6ec4528d0d..00000000000
--- a/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb
+++ /dev/null
@@ -1,111 +0,0 @@
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- name: gitlab-agent
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: gitlab-agent
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: gitlab-agent
- template:
- metadata:
- labels:
- app: gitlab-agent
- spec:
- serviceAccountName: gitlab-agent
- containers:
- - name: agent
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<%= Runtime::Env.gitlab_agentk_version %>"
- args:
- - --token-file=/config/token
- - --kas-address
- - "<%= kas_wss_address %>"
- <% if QA::Runtime::Env.qa_cookies.to_s.include?("gitlab_canary=true") %>
- - --kas-header
- - "Cookie: gitlab_canary=true"
- <% end %>
- volumeMounts:
- - name: token-volume
- mountPath: /config
- env:
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
- - name: SERVICE_ACCOUNT_NAME
- valueFrom:
- fieldRef:
- fieldPath: spec.serviceAccountName
- volumes:
- - name: token-volume
- secret:
- secretName: gitlab-agent-token
- strategy:
- type: RollingUpdate
- rollingUpdate:
- maxSurge: 0
- maxUnavailable: 1
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- name: gitlab-agent-write
-rules:
- - resources:
- - "*"
- apiGroups:
- - "*"
- verbs:
- - create
- - update
- - delete
- - patch
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- name: gitlab-agent-write-binding
-roleRef:
- name: gitlab-agent-write
- kind: ClusterRole
- apiGroup: rbac.authorization.k8s.io
-subjects:
- - name: gitlab-agent
- kind: ServiceAccount
- namespace: default
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- name: gitlab-agent-read
-rules:
- - resources:
- - "*"
- apiGroups:
- - "*"
- verbs:
- - get
- - list
- - watch
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- name: gitlab-agent-read-binding
-roleRef:
- name: gitlab-agent-read
- kind: ClusterRole
- apiGroup: rbac.authorization.k8s.io
-subjects:
- - name: gitlab-agent
- kind: ServiceAccount
- namespace: default
diff --git a/qa/qa/fixtures/mocks/import/github.yml b/qa/qa/fixtures/mocks/import/github.yml
index 9cabdee1025..6ee6be471c4 100644
--- a/qa/qa/fixtures/mocks/import/github.yml
+++ b/qa/qa/fixtures/mocks/import/github.yml
@@ -215,6 +215,23 @@
]
- request:
+ path: /user/orgs
+ method: GET
+ query_params:
+ page: '1'
+ per_page: '25'
+ headers:
+ Host: api.github.com
+ response:
+ status: 200
+ headers:
+ Content-Type: application/json; charset=utf-8
+ X-Ratelimit-Limit: '5000'
+ X-Ratelimit-Remaining: '5000'
+ body: |
+ []
+
+- request:
path:
matcher: ShouldMatch
value: (\/repositories\/466994992$|\/repos\/gitlab-qa-github\/import-test$)
@@ -346,175 +363,6 @@
}
- request:
- path: /repos/gitlab-qa-github/import-test/issues
- method: GET
- headers:
- Host: api.github.com
- response:
- status: 200
- headers:
- Content-Type: application/json; charset=utf-8
- X-Ratelimit-Limit: '5000'
- X-Ratelimit-Remaining: '5000'
- body: |
- [
- {
- "active_lock_reason": null,
- "assignee": {
- "avatar_url": "https://avatars.githubusercontent.com/u/59606922?v=4",
- "events_url": "https://api.github.com/users/gitlab-qa-github/events{/privacy}",
- "followers_url": "https://api.github.com/users/gitlab-qa-github/followers",
- "following_url": "https://api.github.com/users/gitlab-qa-github/following{/other_user}",
- "gists_url": "https://api.github.com/users/gitlab-qa-github/gists{/gist_id}",
- "gravatar_id": "",
- "html_url": "https://github.com/gitlab-qa-github",
- "id": 59606922,
- "login": "gitlab-qa-github",
- "node_id": "MDQ6VXNlcjU5NjA2OTIy",
- "organizations_url": "https://api.github.com/users/gitlab-qa-github/orgs",
- "received_events_url": "https://api.github.com/users/gitlab-qa-github/received_events",
- "repos_url": "https://api.github.com/users/gitlab-qa-github/repos",
- "site_admin": false,
- "starred_url": "https://api.github.com/users/gitlab-qa-github/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/gitlab-qa-github/subscriptions",
- "type": "User",
- "url": "https://api.github.com/users/gitlab-qa-github"
- },
- "assignees": [
- {
- "avatar_url": "https://avatars.githubusercontent.com/u/59606922?v=4",
- "events_url": "https://api.github.com/users/gitlab-qa-github/events{/privacy}",
- "followers_url": "https://api.github.com/users/gitlab-qa-github/followers",
- "following_url": "https://api.github.com/users/gitlab-qa-github/following{/other_user}",
- "gists_url": "https://api.github.com/users/gitlab-qa-github/gists{/gist_id}",
- "gravatar_id": "",
- "html_url": "https://github.com/gitlab-qa-github",
- "id": 59606922,
- "login": "gitlab-qa-github",
- "node_id": "MDQ6VXNlcjU5NjA2OTIy",
- "organizations_url": "https://api.github.com/users/gitlab-qa-github/orgs",
- "received_events_url": "https://api.github.com/users/gitlab-qa-github/received_events",
- "repos_url": "https://api.github.com/users/gitlab-qa-github/repos",
- "site_admin": false,
- "starred_url": "https://api.github.com/users/gitlab-qa-github/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/gitlab-qa-github/subscriptions",
- "type": "User",
- "url": "https://api.github.com/users/gitlab-qa-github"
- }
- ],
- "author_association": "OWNER",
- "body": "Test pull request body",
- "closed_at": null,
- "comments": 1,
- "comments_url": "https://api.github.com/repos/gitlab-qa-github/import-test/issues/2/comments",
- "created_at": "2022-03-07T07:58:10Z",
- "draft": false,
- "events_url": "https://api.github.com/repos/gitlab-qa-github/import-test/issues/2/events",
- "html_url": "https://github.com/gitlab-qa-github/import-test/pull/2",
- "id": 1161030385,
- "labels": [
- {
- "color": "0075ca",
- "default": true,
- "description": "Improvements or additions to documentation",
- "id": 3902072341,
- "name": "documentation",
- "node_id": "LA_kwDOG9XHMM7olOYV",
- "url": "https://api.github.com/repos/gitlab-qa-github/import-test/labels/documentation"
- }
- ],
- "labels_url": "https://api.github.com/repos/gitlab-qa-github/import-test/issues/2/labels{/name}",
- "locked": false,
- "milestone": {
- "closed_at": null,
- "closed_issues": 0,
- "created_at": "2022-03-07T07:54:43Z",
- "creator": {
- "avatar_url": "https://avatars.githubusercontent.com/u/59606922?v=4",
- "events_url": "https://api.github.com/users/gitlab-qa-github/events{/privacy}",
- "followers_url": "https://api.github.com/users/gitlab-qa-github/followers",
- "following_url": "https://api.github.com/users/gitlab-qa-github/following{/other_user}",
- "gists_url": "https://api.github.com/users/gitlab-qa-github/gists{/gist_id}",
- "gravatar_id": "",
- "html_url": "https://github.com/gitlab-qa-github",
- "id": 59606922,
- "login": "gitlab-qa-github",
- "node_id": "MDQ6VXNlcjU5NjA2OTIy",
- "organizations_url": "https://api.github.com/users/gitlab-qa-github/orgs",
- "received_events_url": "https://api.github.com/users/gitlab-qa-github/received_events",
- "repos_url": "https://api.github.com/users/gitlab-qa-github/repos",
- "site_admin": false,
- "starred_url": "https://api.github.com/users/gitlab-qa-github/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/gitlab-qa-github/subscriptions",
- "type": "User",
- "url": "https://api.github.com/users/gitlab-qa-github"
- },
- "description": null,
- "due_on": null,
- "html_url": "https://github.com/gitlab-qa-github/import-test/milestone/1",
- "id": 7741550,
- "labels_url": "https://api.github.com/repos/gitlab-qa-github/import-test/milestones/1/labels",
- "node_id": "MI_kwDOG9XHMM4AdiBu",
- "number": 1,
- "open_issues": 2,
- "state": "open",
- "title": "0.0.1",
- "updated_at": "2022-07-07T10:01:32Z",
- "url": "https://api.github.com/repos/gitlab-qa-github/import-test/milestones/1"
- },
- "node_id": "PR_kwDOG9XHMM40Bfnz",
- "number": 2,
- "performed_via_github_app": null,
- "pull_request": {
- "diff_url": "https://github.com/gitlab-qa-github/import-test/pull/2.diff",
- "html_url": "https://github.com/gitlab-qa-github/import-test/pull/2",
- "merged_at": null,
- "patch_url": "https://github.com/gitlab-qa-github/import-test/pull/2.patch",
- "url": "https://api.github.com/repos/gitlab-qa-github/import-test/pulls/2"
- },
- "reactions": {
- "+1": 0,
- "-1": 0,
- "confused": 0,
- "eyes": 0,
- "heart": 0,
- "hooray": 0,
- "laugh": 0,
- "rocket": 0,
- "total_count": 0,
- "url": "https://api.github.com/repos/gitlab-qa-github/import-test/issues/2/reactions"
- },
- "repository_url": "https://api.github.com/repos/gitlab-qa-github/import-test",
- "state": "open",
- "state_reason": null,
- "timeline_url": "https://api.github.com/repos/gitlab-qa-github/import-test/issues/2/timeline",
- "title": "Test pull request",
- "updated_at": "2022-12-27T09:57:21Z",
- "url": "https://api.github.com/repos/gitlab-qa-github/import-test/issues/2",
- "user": {
- "avatar_url": "https://avatars.githubusercontent.com/u/59606922?v=4",
- "events_url": "https://api.github.com/users/gitlab-qa-github/events{/privacy}",
- "followers_url": "https://api.github.com/users/gitlab-qa-github/followers",
- "following_url": "https://api.github.com/users/gitlab-qa-github/following{/other_user}",
- "gists_url": "https://api.github.com/users/gitlab-qa-github/gists{/gist_id}",
- "gravatar_id": "",
- "html_url": "https://github.com/gitlab-qa-github",
- "id": 59606922,
- "login": "gitlab-qa-github",
- "node_id": "MDQ6VXNlcjU5NjA2OTIy",
- "organizations_url": "https://api.github.com/users/gitlab-qa-github/orgs",
- "received_events_url": "https://api.github.com/users/gitlab-qa-github/received_events",
- "repos_url": "https://api.github.com/users/gitlab-qa-github/repos",
- "site_admin": false,
- "starred_url": "https://api.github.com/users/gitlab-qa-github/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/gitlab-qa-github/subscriptions",
- "type": "User",
- "url": "https://api.github.com/users/gitlab-qa-github"
- }
- }
- ]
-
-- request:
path: /repos/gitlab-qa-github/import-test/labels
method: GET
query_params:
@@ -1288,8 +1136,6 @@
path: /repos/gitlab-qa-github/import-test/issues
method: GET
query_params:
- per_page: '100'
- sort: created
state: all
headers:
Host: api.github.com
@@ -2741,3 +2587,183 @@
},
"url": "https://api.github.com/repos/gitlab-qa-github/import-test/branches/release/protection"
}
+
+- request:
+ path: /repos/gitlab-qa-github/import-test/collaborators
+ method: GET
+ query_params:
+ page: '1'
+ per_page: '100'
+ headers:
+ Host: api.github.com
+ response:
+ status: 200
+ headers:
+ Content-Type: application/json; charset=utf-8
+ X-Ratelimit-Limit: '5000'
+ X-Ratelimit-Remaining: '5000'
+ body: |
+ [
+ {
+ "avatar_url": "https://avatars.githubusercontent.com/u/40021320?v=4",
+ "events_url": "https://api.github.com/users/gitlab-qa/events{/privacy}",
+ "followers_url": "https://api.github.com/users/gitlab-qa/followers",
+ "following_url": "https://api.github.com/users/gitlab-qa/following{/other_user}",
+ "gists_url": "https://api.github.com/users/gitlab-qa/gists{/gist_id}",
+ "gravatar_id": "",
+ "html_url": "https://github.com/gitlab-qa",
+ "id": 40021320,
+ "login": "gitlab-qa",
+ "node_id": "MDQ6VXNlcjQwMDIxMzIw",
+ "organizations_url": "https://api.github.com/users/gitlab-qa/orgs",
+ "permissions": {
+ "admin": false,
+ "maintain": false,
+ "pull": true,
+ "push": true,
+ "triage": true
+ },
+ "received_events_url": "https://api.github.com/users/gitlab-qa/received_events",
+ "repos_url": "https://api.github.com/users/gitlab-qa/repos",
+ "role_name": "write",
+ "site_admin": false,
+ "starred_url": "https://api.github.com/users/gitlab-qa/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/gitlab-qa/subscriptions",
+ "type": "User",
+ "url": "https://api.github.com/users/gitlab-qa"
+ },
+ {
+ "avatar_url": "https://avatars.githubusercontent.com/u/59606922?v=4",
+ "events_url": "https://api.github.com/users/gitlab-qa-github/events{/privacy}",
+ "followers_url": "https://api.github.com/users/gitlab-qa-github/followers",
+ "following_url": "https://api.github.com/users/gitlab-qa-github/following{/other_user}",
+ "gists_url": "https://api.github.com/users/gitlab-qa-github/gists{/gist_id}",
+ "gravatar_id": "",
+ "html_url": "https://github.com/gitlab-qa-github",
+ "id": 59606922,
+ "login": "gitlab-qa-github",
+ "node_id": "MDQ6VXNlcjU5NjA2OTIy",
+ "organizations_url": "https://api.github.com/users/gitlab-qa-github/orgs",
+ "permissions": {
+ "admin": true,
+ "maintain": true,
+ "pull": true,
+ "push": true,
+ "triage": true
+ },
+ "received_events_url": "https://api.github.com/users/gitlab-qa-github/received_events",
+ "repos_url": "https://api.github.com/users/gitlab-qa-github/repos",
+ "role_name": "admin",
+ "site_admin": false,
+ "starred_url": "https://api.github.com/users/gitlab-qa-github/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/gitlab-qa-github/subscriptions",
+ "type": "User",
+ "url": "https://api.github.com/users/gitlab-qa-github"
+ }
+ ]
+
+- request:
+ path: /users/gitlab-qa-github
+ method: GET
+ headers:
+ Host: api.github.com
+ response:
+ status: 200
+ headers:
+ Content-Type: application/json; charset=utf-8
+ X-Ratelimit-Limit: '5000'
+ X-Ratelimit-Remaining: '5000'
+ body: |
+ {
+ "avatar_url": "https://avatars.githubusercontent.com/u/59606922?v=4",
+ "bio": null,
+ "blog": "",
+ "collaborators": 0,
+ "company": null,
+ "created_at": "2020-01-07T11:47:11Z",
+ "disk_usage": 841,
+ "email": null,
+ "events_url": "https://api.github.com/users/gitlab-qa-github/events{/privacy}",
+ "followers": 0,
+ "followers_url": "https://api.github.com/users/gitlab-qa-github/followers",
+ "following": 0,
+ "following_url": "https://api.github.com/users/gitlab-qa-github/following{/other_user}",
+ "gists_url": "https://api.github.com/users/gitlab-qa-github/gists{/gist_id}",
+ "gravatar_id": "",
+ "hireable": null,
+ "html_url": "https://github.com/gitlab-qa-github",
+ "id": 59606922,
+ "location": null,
+ "login": "gitlab-qa-github",
+ "name": null,
+ "node_id": "MDQ6VXNlcjU5NjA2OTIy",
+ "organizations_url": "https://api.github.com/users/gitlab-qa-github/orgs",
+ "owned_private_repos": 0,
+ "plan": {
+ "collaborators": 0,
+ "name": "free",
+ "private_repos": 10000,
+ "space": 976562499
+ },
+ "private_gists": 0,
+ "public_gists": 0,
+ "public_repos": 4,
+ "received_events_url": "https://api.github.com/users/gitlab-qa-github/received_events",
+ "repos_url": "https://api.github.com/users/gitlab-qa-github/repos",
+ "site_admin": false,
+ "starred_url": "https://api.github.com/users/gitlab-qa-github/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/gitlab-qa-github/subscriptions",
+ "total_private_repos": 0,
+ "twitter_username": null,
+ "two_factor_authentication": true,
+ "type": "User",
+ "updated_at": "2023-04-27T11:22:33Z",
+ "url": "https://api.github.com/users/gitlab-qa-github"
+ }
+
+- request:
+ path: /users/gitlab-qa
+ method: GET
+ headers:
+ Host: api.github.com
+ response:
+ status: 200
+ headers:
+ Content-Type: application/json; charset=utf-8
+ X-Ratelimit-Limit: '5000'
+ X-Ratelimit-Remaining: '5000'
+ body: |
+ {
+ "avatar_url": "https://avatars.githubusercontent.com/u/40021320?v=4",
+ "bio": null,
+ "blog": "",
+ "company": null,
+ "created_at": "2018-06-07T08:07:41Z",
+ "email": null,
+ "events_url": "https://api.github.com/users/gitlab-qa/events{/privacy}",
+ "followers": 0,
+ "followers_url": "https://api.github.com/users/gitlab-qa/followers",
+ "following": 0,
+ "following_url": "https://api.github.com/users/gitlab-qa/following{/other_user}",
+ "gists_url": "https://api.github.com/users/gitlab-qa/gists{/gist_id}",
+ "gravatar_id": "",
+ "hireable": null,
+ "html_url": "https://github.com/gitlab-qa",
+ "id": 40021320,
+ "location": null,
+ "login": "gitlab-qa",
+ "name": null,
+ "node_id": "MDQ6VXNlcjQwMDIxMzIw",
+ "organizations_url": "https://api.github.com/users/gitlab-qa/orgs",
+ "public_gists": 0,
+ "public_repos": 2,
+ "received_events_url": "https://api.github.com/users/gitlab-qa/received_events",
+ "repos_url": "https://api.github.com/users/gitlab-qa/repos",
+ "site_admin": false,
+ "starred_url": "https://api.github.com/users/gitlab-qa/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/gitlab-qa/subscriptions",
+ "twitter_username": null,
+ "type": "User",
+ "updated_at": "2023-05-11T05:59:28Z",
+ "url": "https://api.github.com/users/gitlab-qa"
+ }
diff --git a/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb
new file mode 100644
index 00000000000..394c6689eef
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb
@@ -0,0 +1,8 @@
+install:
+ image: maven:3.6-jdk-11
+ script:
+ - "mvn install -U -s settings.xml"
+ only:
+ - "<%= imported_project.default_branch %>"
+ tags:
+ - "runner-for-<%= imported_project.group.name %>" \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb
new file mode 100644
index 00000000000..4bcd63b3c6d
--- /dev/null
+++ b/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb
@@ -0,0 +1,23 @@
+<settings>
+ <servers>
+ <server>
+ <id>central-proxy</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value><%= personal_access_token %></value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ <mirrors>
+ <mirror>
+ <id>central-proxy</id>
+ <name>GitLab proxy of central repo</name>
+ <url><%= gitlab_address_with_port %>/api/v4/groups/<%= imported_project.group.id %>/-/packages/maven</url>
+ <mirrorOf>central</mirrorOf>
+ </mirror>
+ </mirrors>
+</settings> \ No newline at end of file
diff --git a/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb
index a396fc98e95..07f426c3bfa 100644
--- a/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb
+++ b/qa/qa/fixtures/package_managers/npm/npm_install_package_instance.yaml.erb
@@ -9,7 +9,7 @@ install:
- "npm config set @<%= registry_scope %>:registry <%= gitlab_address_with_port %>/api/v4/packages/npm/"
- "npm install <%= package.name %>"
cache:
- key: ${CI_BUILD_REF_NAME}
+ key: ${CI_COMMIT_REF_NAME}
paths:
- node_modules/
artifacts:
diff --git a/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb b/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb
index 5f2ff31b318..b5277a2c315 100644
--- a/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb
+++ b/qa/qa/fixtures/package_managers/npm/npm_upload_install_package_project.yaml.erb
@@ -20,7 +20,7 @@ install:
- "npm config set @<%= registry_scope %>:registry <%= gitlab_address_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/npm/"
- "npm install <%= package.name %>"
cache:
- key: ${CI_BUILD_REF_NAME}
+ key: ${CI_COMMIT_REF_NAME}
paths:
- node_modules/
artifacts:
diff --git a/qa/qa/flow/login.rb b/qa/qa/flow/login.rb
index 564a51ee483..2702b52f2ef 100644
--- a/qa/qa/flow/login.rb
+++ b/qa/qa/flow/login.rb
@@ -21,8 +21,8 @@ module QA
def sign_in(as: nil, address: :gitlab, skip_page_validation: false, admin: false)
Page::Main::Login.perform { |p| p.redirect_to_login_page(address) }
- unless Page::Main::Login.perform(&:on_login_page?)
- Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform(&:signed_in?)
+ if !Page::Main::Login.perform(&:on_login_page?) && Page::Main::Menu.perform(&:signed_in?)
+ Page::Main::Menu.perform(&:sign_out)
end
Page::Main::Login.perform do |login|
diff --git a/qa/qa/flow/pipeline.rb b/qa/qa/flow/pipeline.rb
index fb6a5425a6e..d1cfe8dae09 100644
--- a/qa/qa/flow/pipeline.rb
+++ b/qa/qa/flow/pipeline.rb
@@ -9,7 +9,7 @@ module QA
# canceled, created, failed, manual, passed
# pending, running, skipped
def visit_latest_pipeline(status: nil, wait: nil, skip_wait: true)
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
Page::Project::Pipeline::Index.perform do |index|
index.has_any_pipeline?(wait: wait)
index.wait_for_latest_pipeline(status: status, wait: wait) if status || !skip_wait
@@ -18,12 +18,20 @@ module QA
end
def wait_for_latest_pipeline(status: nil, wait: nil)
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
Page::Project::Pipeline::Index.perform do |index|
index.has_any_pipeline?(wait: wait)
index.wait_for_latest_pipeline(status: status, wait: wait)
end
end
+
+ def visit_pipeline_job_page(job_name:, pipeline: nil)
+ pipeline.visit! unless pipeline.nil?
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job(job_name)
+ end
+ end
end
end
end
diff --git a/qa/qa/flow/project.rb b/qa/qa/flow/project.rb
index 70bdcfcb719..20c1fa77e24 100644
--- a/qa/qa/flow/project.rb
+++ b/qa/qa/flow/project.rb
@@ -8,6 +8,17 @@ module QA
def go_to_create_project_from_template
Page::Project::New.perform(&:click_create_from_template_link)
end
+
+ def archive_project(project)
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_general_settings)
+ Page::Project::Settings::Main.perform(&:expand_advanced_settings)
+ Page::Project::Settings::Advanced.perform(&:archive_project)
+ Support::Waiter.wait_until do
+ Page::Project::Show.perform { |show| show.has_text?("Archived project!") }
+ end
+ end
end
end
end
diff --git a/qa/qa/flow/saml.rb b/qa/qa/flow/saml.rb
index 8a0ebb9f551..1cf29e75c67 100644
--- a/qa/qa/flow/saml.rb
+++ b/qa/qa/flow/saml.rb
@@ -19,8 +19,6 @@ module QA
end
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?)
diff --git a/qa/qa/flow/user_onboarding.rb b/qa/qa/flow/user_onboarding.rb
index 8c6a50f251f..5c26b0eb5bc 100644
--- a/qa/qa/flow/user_onboarding.rb
+++ b/qa/qa/flow/user_onboarding.rb
@@ -5,11 +5,11 @@ module QA
module UserOnboarding
extend self
- def onboard_user
+ def onboard_user(wait: Capybara.default_max_wait_time)
Page::Registration::Welcome.perform do |welcome_page|
- if welcome_page.has_get_started_button?
+ if welcome_page.has_get_started_button?(wait: wait)
welcome_page.select_role('Other')
- welcome_page.choose_setup_for_company_if_available
+ welcome_page.choose_setup_for_just_me_if_available
welcome_page.choose_create_a_new_project_if_available
welcome_page.click_get_started_button
end
diff --git a/qa/qa/page/admin/applications.rb b/qa/qa/page/admin/applications.rb
new file mode 100644
index 00000000000..56880a4b22c
--- /dev/null
+++ b/qa/qa/page/admin/applications.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ class Applications < Page::Base
+ view 'app/views/admin/applications/index.html.haml' do
+ element :new_application_button
+ end
+
+ view 'app/views/admin/applications/_form.html.haml' do
+ element :name_field
+ element :redirect_uri_field
+ element :trusted_checkbox
+ element :save_application_button
+ end
+
+ view 'app/views/shared/tokens/_scopes_form.html.haml' do
+ element :api_label, '#{scope}_label' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
+ end
+
+ view 'app/views/shared/doorkeeper/applications/_show.html.haml' do
+ element :application_id_field
+ element :id_of_application_field
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue' do
+ element :clipboard_button
+ end
+
+ def click_new_application_button
+ click_element :new_application_button
+ end
+
+ def fill_name(name)
+ fill_element :name_field, name
+ end
+
+ def fill_redirect_uri(redirect_uri)
+ fill_element :redirect_uri_field, redirect_uri
+ end
+
+ def set_trusted_checkbox(value)
+ check_element :trusted_checkbox, value
+ end
+
+ def set_scope(scope)
+ click_element "#{scope}_label".to_sym
+ end
+
+ def save_application
+ click_element :save_application_button
+ end
+
+ def get_secret_id
+ find_element(:clipboard_button)['data-clipboard-text']
+ end
+
+ def get_application_id
+ find_element(:application_id_field).value
+ end
+
+ # Returns the ID of the resource
+ def get_id_of_application
+ find_element(:id_of_application_field, visible: false).value
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb
index 42dd1083bbe..f58d672efe8 100644
--- a/qa/qa/page/admin/menu.rb
+++ b/qa/qa/page/admin/menu.rb
@@ -4,81 +4,73 @@ module QA
module Page
module Admin
class Menu < Page::Base
- view 'app/views/layouts/nav/sidebar/_admin.html.haml' do
- element :admin_sidebar_content
- element :admin_monitoring_menu_link
- element :admin_monitoring_submenu_content
+ include SubMenus::Common
+
+ if QA::Runtime::Env.super_sidebar_enabled?
+ prepend Sidebar::Overview
+ prepend Sidebar::Settings
+ end
+
+ view 'lib/sidebars/admin/menus/admin_overview_menu.rb' do
element :admin_overview_submenu_content
- element :admin_overview_users_link
- element :admin_overview_groups_link
- element :admin_settings_menu_link
- element :admin_settings_submenu_content
- element :admin_settings_general_link
- element :admin_settings_integrations_link
- element :admin_settings_metrics_and_profiling_link
- element :admin_settings_network_link
- element :admin_settings_preferences_link
- element :admin_settings_repository_link
+ end
+
+ view 'lib/sidebars/admin/menus/analytics_menu.rb' do
+ element :admin_sidebar_analytics_submenu_content
+ end
+
+ view 'lib/sidebars/admin/menus/monitoring_menu.rb' do
+ element :admin_monitoring_menu_link
end
def go_to_preferences_settings
hover_element(:admin_settings_menu_link) do
- within_submenu(:admin_settings_submenu_content) do
- click_element :admin_settings_preferences_link
- end
+ click_element :admin_settings_preferences_link
end
end
def go_to_repository_settings
hover_element(:admin_settings_menu_link) do
- within_submenu(:admin_settings_submenu_content) do
- click_element :admin_settings_repository_link
- end
+ click_element :admin_settings_repository_link
end
end
def go_to_integration_settings
hover_element(:admin_settings_menu_link) do
- within_submenu(:admin_settings_submenu_content) do
- click_element :admin_settings_integrations_link
- end
+ click_element :admin_settings_integrations_link
end
end
def go_to_general_settings
hover_element(:admin_settings_menu_link) do
- within_submenu(:admin_settings_submenu_content) do
- click_element :admin_settings_general_link
- end
+ click_element :admin_settings_general_link
end
end
def go_to_metrics_and_profiling_settings
hover_element(:admin_settings_menu_link) do
- within_submenu(:admin_settings_submenu_content) do
- click_element :admin_settings_metrics_and_profiling_link
- end
+ click_element :admin_settings_metrics_and_profiling_link
end
end
def go_to_network_settings
hover_element(:admin_settings_menu_link) do
- within_submenu(:admin_settings_submenu_content) do
- click_element :admin_settings_network_link
- end
+ click_element :admin_settings_network_link
end
end
def go_to_users_overview
- within_submenu(:admin_overview_submenu_content) do
- click_element :admin_overview_users_link
- end
+ click_element :admin_overview_users_link
end
def go_to_groups_overview
- within_submenu(:admin_overview_submenu_content) do
- click_element :admin_overview_groups_link
- end
+ click_element :admin_overview_groups_link
+ end
+
+ def go_to_applications
+ return click_element(:nav_item_link, submenu_item: 'Applications') if Runtime::Env.super_sidebar_enabled?
+
+ click_element(:sidebar_menu_link, menu_item: 'Applications')
end
private
@@ -93,7 +85,7 @@ module QA
end
def within_sidebar(&block)
- within_element(:admin_sidebar_content, &block)
+ page.within('.sidebar-top-level-items', &block)
end
def within_submenu(element, &block)
diff --git a/qa/qa/page/admin/sidebar/overview.rb b/qa/qa/page/admin/sidebar/overview.rb
new file mode 100644
index 00000000000..5bd542a2e52
--- /dev/null
+++ b/qa/qa/page/admin/sidebar/overview.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Sidebar
+ module Overview
+ def go_to_users_overview
+ open_overview_submenu("Users")
+ end
+
+ def go_to_groups_overview
+ open_overview_submenu("Groups")
+ end
+
+ private
+
+ def open_overview_submenu(sub_menu)
+ open_submenu("Overview", sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/sidebar/settings.rb b/qa/qa/page/admin/sidebar/settings.rb
new file mode 100644
index 00000000000..1eb6ac2c119
--- /dev/null
+++ b/qa/qa/page/admin/sidebar/settings.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Sidebar
+ module Settings
+ def go_to_preferences_settings
+ open_settings_submenu("Preferences")
+ end
+
+ def go_to_repository_settings
+ open_settings_submenu("Repository")
+ end
+
+ def go_to_integration_settings
+ open_settings_submenu("Integration")
+ end
+
+ def go_to_general_settings
+ open_settings_submenu("General")
+ end
+
+ def go_to_metrics_and_profiling_settings
+ open_settings_submenu("Metrics and profiling")
+ end
+
+ def go_to_network_settings
+ open_settings_submenu("Network")
+ end
+
+ private
+
+ def open_settings_submenu(sub_menu)
+ open_submenu("Settings", sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index ab83da7dacf..7452077de67 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -6,7 +6,7 @@ module QA
module Page
class Base
prepend Support::Page::Logging
- prepend Mobile::Page::Base if QA::Runtime::Env.remote_mobile_device_name
+ prepend Mobile::Page::Base if QA::Runtime::Env.mobile_layout?
include Capybara::DSL
include Scenario::Actable
@@ -234,13 +234,14 @@ module QA
page.validate_elements_present! if page
end
- # Uses capybara to locate and click an element instead of `click_element`.
- # This can be used when it's not possible to add a QA selector but we still want to log the click
+ # Uses capybara to locate and interact with an element instead of using `*_element`.
+ # This can be used when it's not possible to add a QA selector but we still want to log the action
#
# @param [String] method the capybara method to use
# @param [String] locator the selector used to find the element
- def click_via_capybara(method, locator)
- page.public_send(method, locator)
+ # @param [Hash] **kwargs optional arguments
+ def act_via_capybara(method, locator, **kwargs)
+ page.public_send(method, locator, **kwargs)
end
def fill_element(name, content)
@@ -283,17 +284,13 @@ module QA
false
end
- # Check for the element before waiting for requests, just in case unrelated requests are in progress.
- # This is to avoid waiting unnecessarily after the element we're interested in has already appeared.
- return true if try_find_element.call(wait)
+ # Check to see if we can return early, without the need to wait for all network requests to complete
+ # We don't want to add overhead to cases where wait=0 as the caller in these cases is indicating that they
+ # don't want any overhead
+ return true if wait > 1 && try_find_element.call(1)
- # If the element didn't appear, wait for requests and then check again
wait_for_requests(skip_finished_loading_check: !!kwargs.delete(:skip_finished_loading_check))
-
- # We only wait one second now because we previously waited the full expected duration,
- # plus however long it took for requests to complete. One second should be enough
- # for the UI to update after requests complete.
- try_find_element.call(1)
+ try_find_element.call(wait)
end
def has_no_element?(name, **kwargs)
diff --git a/qa/qa/page/component/breadcrumbs.rb b/qa/qa/page/component/breadcrumbs.rb
index 2576e376e4e..f2343da489e 100644
--- a/qa/qa/page/component/breadcrumbs.rb
+++ b/qa/qa/page/component/breadcrumbs.rb
@@ -9,7 +9,7 @@ module QA
def self.included(base)
super
- base.view 'app/views/layouts/nav/_breadcrumbs.html.haml' do
+ base.view 'app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml' do
element :breadcrumb_links_content
end
end
diff --git a/qa/qa/page/component/content_editor.rb b/qa/qa/page/component/content_editor.rb
index a9abda42610..f2733e4b065 100644
--- a/qa/qa/page/component/content_editor.rb
+++ b/qa/qa/page/component/content_editor.rb
@@ -17,7 +17,7 @@ module QA
element :text_style_dropdown
end
- base.view 'app/assets/javascripts/content_editor/components/toolbar_image_button.vue' do
+ base.view 'app/assets/javascripts/content_editor/components/toolbar_attachment_button.vue' do
element :file_upload_field
end
diff --git a/qa/qa/page/component/dropdown.rb b/qa/qa/page/component/dropdown.rb
index 01ef3533ff8..767cd40daa2 100644
--- a/qa/qa/page/component/dropdown.rb
+++ b/qa/qa/page/component/dropdown.rb
@@ -4,8 +4,18 @@ module QA
module Page
module Component
module Dropdown
- def select_item(item_text)
- find('li.gl-new-dropdown-item', text: item_text, match: :prefer_exact).click
+ # Find and click item using css selector and matching text
+ # If item_text is not provided, select the first item that matches the given css selector
+ #
+ # @param [String] item_text
+ # @param [String] css - css selector of the item
+ # @return [void]
+ def select_item(item_text, css: 'li.gl-new-dropdown-item')
+ if item_text
+ find(css, text: item_text, match: :prefer_exact).click
+ else
+ find(css, match: :first).click
+ end
end
def has_item?(item_text)
@@ -65,8 +75,8 @@ module QA
find('li.gl-new-dropdown-item span:nth-child(2)', text: item_text, exact_text: true).click
end
- def expand_select_list
- find('.gl-new-dropdown-toggle').click
+ def expand_select_list(css: '.gl-new-dropdown-toggle')
+ find(css).click
end
def wait_for_search_to_complete
diff --git a/qa/qa/page/component/groups_filter.rb b/qa/qa/page/component/groups_filter.rb
index ea91ced8679..266c0dfa1af 100644
--- a/qa/qa/page/component/groups_filter.rb
+++ b/qa/qa/page/component/groups_filter.rb
@@ -16,10 +16,6 @@ module QA
base.view 'app/assets/javascripts/groups/components/groups.vue' do
element :groups_list_tree_container
end
-
- base.view 'app/views/dashboard/_groups_head.html.haml' do
- element :public_groups_tab
- end
end
private
@@ -29,14 +25,8 @@ module QA
# @return [Boolean] whether a group with given name exists
def has_filtered_group?(name)
filter_group(name)
- return true if page.has_link?(name, wait: 0) # element containing link to group
- return false unless has_element?(:public_groups_tab, wait: 0)
-
- # Check public groups
- click_element(:public_groups_tab)
- filter_group(name)
- page.has_link?(name, wait: 0)
+ page.has_link?(name, wait: 0) # element containing link to group
end
# Filter by group name
@@ -44,7 +34,8 @@ module QA
# @return [Boolean] whether the filter returned any group
def filter_group(name)
fill_element(:groups_filter_field, name).send_keys(:return)
- finished_loading?
+ # Loading starts a moment after `return` is sent. We mustn't jump ahead
+ wait_for_requests if spinner_exists?
has_element?(:groups_list_tree_container, wait: 1)
end
end
diff --git a/qa/qa/page/component/import/selection.rb b/qa/qa/page/component/import/selection.rb
index 6cacdd84f13..db2ff74e0f8 100644
--- a/qa/qa/page/component/import/selection.rb
+++ b/qa/qa/page/component/import/selection.rb
@@ -14,6 +14,10 @@ module QA
end
def click_gitlab
+ retry_until(reload: true, max_attempts: 10, message: 'Waiting for import source to be enabled') do
+ has_element?(:gitlab_import_button)
+ end
+
click_element(:gitlab_import_button)
end
end
diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb
index 37c833e77c2..db9492ea516 100644
--- a/qa/qa/page/component/note.rb
+++ b/qa/qa/page/component/note.rb
@@ -28,7 +28,7 @@ module QA
end
base.view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
- element :discussion_preferences_dropdown, required: true
+ element :discussion_preferences_dropdown
element :filter_menu_item
end
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index 4e1c7f3e2bb..05d59acd8e8 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -84,7 +84,7 @@ module QA
element :copy_contents_button
end
- base.view 'app/views/layouts/nav/_breadcrumbs.html.haml' do
+ base.view 'app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml' do
element :breadcrumb_links_content
element :breadcrumb_current_link
end
@@ -156,8 +156,14 @@ module QA
end
end
- def has_embed_dropdown?
- has_element?(:snippet_embed_dropdown)
+ RSpec::Matchers.define :have_embed_dropdown do
+ match do |page|
+ page.has_element?(:snippet_embed_dropdown)
+ end
+
+ match_when_negated do |page|
+ page.has_no_element?(:snippet_embed_dropdown)
+ end
end
def click_edit_button
diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb
index 9143a25d9ab..335790c5b27 100644
--- a/qa/qa/page/component/wiki_page_form.rb
+++ b/qa/qa/page/component/wiki_page_form.rb
@@ -19,7 +19,7 @@ module QA
element :markdown_editor_form_field
end
- base.view 'app/assets/javascripts/vue_shared/components/markdown/editor_mode_dropdown.vue' do
+ base.view 'app/assets/javascripts/vue_shared/components/markdown/editor_mode_switcher.vue' do
element :editing_mode_switcher
end
@@ -59,9 +59,6 @@ module QA
def use_new_editor
click_element(:editing_mode_switcher)
- within_element(:editing_mode_switcher) do
- find('button', text: 'Rich text').click
- end
wait_until(reload: false) do
has_element?(:content_editor_container)
diff --git a/qa/qa/page/dashboard/snippet/index.rb b/qa/qa/page/dashboard/snippet/index.rb
index 088fff17578..51d7bd3f20b 100644
--- a/qa/qa/page/dashboard/snippet/index.rb
+++ b/qa/qa/page/dashboard/snippet/index.rb
@@ -5,25 +5,12 @@ module QA
module Dashboard
module Snippet
class Index < Page::Base
- view 'app/views/layouts/header/_new_dropdown.html.haml' do
- element :new_menu_toggle
- end
-
- view 'app/helpers/nav/new_dropdown_helper.rb' do
- 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
diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb
index 31899d9a0c7..011b1ea5d81 100644
--- a/qa/qa/page/file/show.rb
+++ b/qa/qa/page/file/show.rb
@@ -5,8 +5,6 @@ module QA
module File
class Show < Page::Base
include Shared::CommitMessage
- include Project::SubMenus::Settings
- include Project::SubMenus::Common
include Layout::Flash
include Page::Component::BlobContent
diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb
index 9418593133e..157bc3abaf6 100644
--- a/qa/qa/page/group/menu.rb
+++ b/qa/qa/page/group/menu.rb
@@ -6,6 +6,15 @@ module QA
class Menu < Page::Base
include SubMenus::Common
+ if Runtime::Env.super_sidebar_enabled?
+ prepend Page::SubMenus::SuperSidebar::Manage
+ prepend Page::SubMenus::SuperSidebar::Plan
+ prepend Page::SubMenus::SuperSidebar::Settings
+ prepend SubMenus::SuperSidebar::Main
+ prepend SubMenus::SuperSidebar::Build
+ prepend SubMenus::SuperSidebar::Operate
+ end
+
def click_group_members_item
hover_group_information do
within_submenu do
@@ -15,6 +24,8 @@ module QA
end
def click_subgroup_members_item
+ return go_to_members if Runtime::Env.super_sidebar_enabled?
+
hover_subgroup_information do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Members')
@@ -29,6 +40,8 @@ module QA
end
def click_group_general_settings_item
+ return go_to_general_settings if Runtime::Env.super_sidebar_enabled?
+
hover_group_settings do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'General')
@@ -61,6 +74,8 @@ module QA
end
def go_to_group_packages
+ return go_to_package_registry if Runtime::Env.super_sidebar_enabled?
+
hover_group_packages do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Package Registry')
diff --git a/qa/qa/page/group/sub_menus/common.rb b/qa/qa/page/group/sub_menus/common.rb
index 2f8a3fdeb4e..3cbca3db359 100644
--- a/qa/qa/page/group/sub_menus/common.rb
+++ b/qa/qa/page/group/sub_menus/common.rb
@@ -21,7 +21,7 @@ module QA
private
def sidebar_element
- :group_sidebar
+ QA::Runtime::Env.super_sidebar_enabled? ? :navbar : :group_sidebar
end
end
end
diff --git a/qa/qa/page/group/sub_menus/super_sidebar/build.rb b/qa/qa/page/group/sub_menus/super_sidebar/build.rb
new file mode 100644
index 00000000000..0b8bf030622
--- /dev/null
+++ b/qa/qa/page/group/sub_menus/super_sidebar/build.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Group
+ module SubMenus
+ module SuperSidebar
+ module Build
+ extend QA::Page::PageConcern
+
+ def go_to_runners
+ open_build_submenu("Runners")
+ end
+
+ private
+
+ def open_build_submenu(sub_menu)
+ open_submenu("Build", sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/group/sub_menus/super_sidebar/main.rb b/qa/qa/page/group/sub_menus/super_sidebar/main.rb
new file mode 100644
index 00000000000..e470c03b9e5
--- /dev/null
+++ b/qa/qa/page/group/sub_menus/super_sidebar/main.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Group
+ module SubMenus
+ module SuperSidebar
+ module Main
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::SuperSidebar::Main
+ end
+ end
+
+ def go_to_group_overview
+ click_element(:nav_item_link, submenu_item: 'Group overview')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/group/sub_menus/super_sidebar/operate.rb b/qa/qa/page/group/sub_menus/super_sidebar/operate.rb
new file mode 100644
index 00000000000..640e1e969de
--- /dev/null
+++ b/qa/qa/page/group/sub_menus/super_sidebar/operate.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Group
+ module SubMenus
+ module SuperSidebar
+ module Operate
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::SuperSidebar::Operate
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index f4f8820bc04..bea01a5bbc7 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -40,6 +40,8 @@ module QA
view 'app/helpers/auth_helper.rb' do
element :saml_login_button
+ element :github_login_button
+ element :oidc_login_button
end
view 'app/views/layouts/devise.html.haml' do
@@ -106,7 +108,7 @@ module QA
# 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')
+ return unless has_content?('Set up new password', wait: 1)
Profile::Password.perform do |new_password_page|
password = user&.password || Runtime::User.password
@@ -177,11 +179,21 @@ module QA
click_element :standard_tab
end
+ def sign_in_with_github
+ set_initial_password_if_present
+ click_element :github_login_button
+ end
+
def sign_in_with_saml
set_initial_password_if_present
click_element :saml_login_button
end
+ def sign_in_with_oidc
+ set_initial_password_if_present
+ click_element :oidc_login_button
+ end
+
def sign_out_and_sign_in_as(user:)
Menu.perform(&:sign_out_if_signed_in)
has_sign_in_tab?
@@ -226,6 +238,10 @@ module QA
Support::WaitForRequests.wait_for_requests
+ wait_until(sleep_interval: 5, message: '502 - GitLab is taking too much time to respond') do
+ has_no_text?('GitLab is taking too much time to respond')
+ end
+
# For debugging invalid login attempts
has_notice?('Invalid login or password')
@@ -233,6 +249,7 @@ module QA
terms.accept_terms if terms.visible?
end
+ Page::Main::Menu.perform(&:enable_new_navigation) if Runtime::Env.super_sidebar_enabled?
Page::Main::Menu.validate_elements_present! unless skip_page_validation
end
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index 1e050d79e23..934aa182b12 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -4,23 +4,56 @@ module QA
module Page
module Main
class Menu < Page::Base
- prepend Mobile::Page::Main::Menu if Runtime::Env.mobile_layout?
+ # We need to check phone_layout? instead of mobile_layout? here
+ # since tablets have the regular top navigation bar
+ prepend Mobile::Page::Main::Menu if Runtime::Env.phone_layout?
- view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
- element :sign_out_link
- element :edit_profile_link
- element :user_profile_link
+ if Runtime::Env.super_sidebar_enabled?
+ prepend SubMenus::CreateNewMenu
+ include SubMenus::SuperSidebar::ContextSwitcher
end
- view 'app/views/layouts/header/_default.html.haml' do
- element :navbar, required: true
- element :canary_badge_link
- element :user_avatar_content, required: !QA::Runtime::Env.mobile_layout?
- element :user_menu, required: !QA::Runtime::Env.mobile_layout?
- element :stop_impersonation_link
- element :issues_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
- element :merge_requests_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
- element :todos_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
+ if QA::Runtime::Env.super_sidebar_enabled?
+ # Define alternative navbar (super sidebar) which does not yet implement all the same elements
+ view 'app/assets/javascripts/super_sidebar/components/super_sidebar.vue' do
+ element :navbar, required: true # TODO: rename to sidebar once it's default implementation
+ element :user_menu, required: !Runtime::Env.phone_layout?
+ element :user_avatar_content, required: !Runtime::Env.phone_layout?
+ end
+
+ view 'app/assets/javascripts/super_sidebar/components/user_menu.vue' do
+ element :sign_out_link
+ element :edit_profile_link
+ end
+
+ view 'app/assets/javascripts/super_sidebar/components/user_name_group.vue' do
+ element :user_profile_link
+ end
+
+ view 'app/assets/javascripts/super_sidebar/components/user_bar.vue' do
+ element :global_search_button
+ end
+
+ view 'app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue' do
+ element :global_search_input
+ end
+ else
+ view 'app/views/layouts/header/_default.html.haml' do
+ element :navbar, required: true
+ element :canary_badge_link
+ element :user_avatar_content, required: !Runtime::Env.phone_layout?
+ element :user_menu, required: !Runtime::Env.phone_layout?
+ element :stop_impersonation_link
+ element :issues_shortcut_button, required: !Runtime::Env.phone_layout?
+ element :merge_requests_shortcut_button, required: !Runtime::Env.phone_layout?
+ element :todos_shortcut_button, required: !Runtime::Env.phone_layout?
+ end
+
+ view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
+ element :sign_out_link
+ element :edit_profile_link
+ element :user_profile_link
+ end
end
view 'app/assets/javascripts/nav/components/top_nav_app.vue' do
@@ -39,20 +72,15 @@ module QA
element :admin_area_link
element :projects_dropdown
element :groups_dropdown
- element :snippets_link
element :menu_item_link
end
- view 'app/views/layouts/_search.html.haml' do
- element :search_term_field
- end
-
view 'app/views/layouts/_header_search.html.haml' do
element :search_box
end
view 'app/assets/javascripts/header_search/components/app.vue' do
- element :search_term_field
+ element :global_search_input
end
view 'app/views/layouts/header/_new_dropdown.html.haml' do
@@ -62,23 +90,49 @@ module QA
view 'app/helpers/nav/new_dropdown_helper.rb' do
element :global_new_group_link
element :global_new_project_link
+ element :global_new_snippet_link
+ end
+
+ view 'app/assets/javascripts/nav/components/new_nav_toggle.vue' do
+ element :new_navigation_toggle
+ end
+
+ def go_to_projects
+ return click_element(:nav_item_link, submenu_item: 'Projects') if Runtime::Env.super_sidebar_enabled?
+
+ click_element(:sidebar_menu_link, menu_item: 'Projects')
end
def go_to_groups
- within_groups_menu do
- click_element(:menu_item_link, title: 'View all groups')
+ # This needs to be fixed in the tests themselves. Fullfillment tests try to go to groups view from the
+ # group. Instead of having a global hack, explicit test should navigate to correct view first.
+ # see: https://gitlab.com/gitlab-org/gitlab/-/issues/403589#note_1383040061
+ if Runtime::Env.super_sidebar_enabled?
+ go_to_your_work unless has_element?(:nav_item_link, submenu_item: 'Groups', wait: 0)
+ click_element(:nav_item_link, submenu_item: 'Groups')
+ elsif has_element?(:sidebar_menu_link, menu_item: 'Groups')
+ # Use new functionality to visit Groups where possible
+ click_element(:sidebar_menu_link, menu_item: 'Groups')
+ else
+ # Otherwise fallback to previous functionality
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/403589
+ # and related issues
+ within_groups_menu do
+ click_element(:menu_item_link, title: 'View all groups')
+ end
end
end
- def go_to_create_group
- click_element(:new_menu_toggle)
- click_element(:global_new_group_link)
+ def go_to_snippets
+ return click_element(:nav_item_link, submenu_item: 'Snippets') if Runtime::Env.super_sidebar_enabled?
+
+ click_element(:sidebar_menu_link, menu_item: 'Snippets')
end
- def go_to_projects
- within_projects_menu do
- click_element(:menu_item_link, title: 'View all projects')
- end
+ def go_to_workspaces
+ return click_element(:nav_item_link, submenu_item: 'Workspaces') if Runtime::Env.super_sidebar_enabled?
+
+ click_element(:sidebar_menu_link, menu_item: 'Workspaces')
end
def go_to_create_project
@@ -86,7 +140,19 @@ module QA
click_element(:global_new_project_link)
end
+ def go_to_create_group
+ click_element(:new_menu_toggle)
+ click_element(:global_new_group_link)
+ end
+
+ def go_to_create_snippet
+ click_element(:new_menu_toggle)
+ click_element(:global_new_snippet_link)
+ end
+
def go_to_menu_dropdown_option(option_name)
+ return click_element(option_name) if QA::Runtime::Env.super_sidebar_enabled?
+
within_top_menu do
click_element(:navbar_dropdown, title: 'Menu')
click_element(option_name)
@@ -106,9 +172,9 @@ module QA
end
def go_to_admin_area
- click_admin_area
+ Runtime::Env.super_sidebar_enabled? ? super : click_admin_area
- return unless has_text?('Enter Admin Mode', wait: 1.0)
+ return unless has_text?('Enter admin mode', wait: 1.0)
Admin::NewSession.perform do |new_session|
new_session.set_password(Runtime::User.admin_password)
@@ -123,11 +189,13 @@ module QA
end
def signed_in_as_user?(user)
- return false if has_no_personal_area?
+ return false unless has_personal_area?
within_user_menu do
has_element?(:user_profile_link, text: /#{user.username}/)
end
+ # we need to close user menu because plain user link check will leave it open
+ click_element :user_avatar_content if has_element?(:user_profile_link, wait: 0)
end
def not_signed_in?
@@ -171,8 +239,8 @@ module QA
end
def search_for(term)
- click_element(:search_box)
- fill_element :search_term_field, "#{term}\n"
+ click_element(Runtime::Env.super_sidebar_enabled? ? :global_search_button : :search_box)
+ fill_element(:global_search_input, "#{term}\n")
end
def has_personal_area?(wait: Capybara.default_max_wait_time)
@@ -211,6 +279,14 @@ module QA
has_element?(:canary_badge_link)
end
+ def enable_new_navigation
+ Runtime::Logger.info("Enabling super sidebar!")
+ return Runtime::Logger.info("User is not signed in, skipping") unless has_element?(:navbar, wait: 2)
+ return Runtime::Logger.info("Super sidebar is already enabled") if has_css?('[data-testid="super-sidebar"]')
+
+ within_user_menu { click_element(:new_navigation_toggle) }
+ end
+
private
def within_top_menu(&block)
diff --git a/qa/qa/page/merge_request/new.rb b/qa/qa/page/merge_request/new.rb
index a1d91621090..90022616674 100644
--- a/qa/qa/page/merge_request/new.rb
+++ b/qa/qa/page/merge_request/new.rb
@@ -4,6 +4,8 @@ module QA
module Page
module MergeRequest
class New < Page::Issuable::New
+ include QA::Page::Component::Dropdown
+
view 'app/views/shared/issuable/_form.html.haml' do
element :issuable_create_button, required: true
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index df0c0ec4202..e10db796f8e 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -31,6 +31,7 @@ module QA
view 'app/assets/javascripts/diffs/components/tree_list.vue' do
element :file_tree_container
+ element :diff_tree_search
end
view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
@@ -198,7 +199,15 @@ module QA
end
def click_diffs_tab
- click_element(:diffs_tab)
+ # Do not wait for spinner due to https://gitlab.com/gitlab-org/gitlab/-/issues/398584
+ click_element(:diffs_tab, skip_finished_loading_check: true)
+
+ # If the diff isn't available when we navigate to the Changes tab
+ # we must reload the page. https://gitlab.com/gitlab-org/gitlab/-/issues/398557
+ wait_until(reload: true, skip_finished_loading_check_on_refresh: true) do
+ QA::Runtime::Logger.debug('Ensuring that diff has loaded async')
+ has_element?(:file_tree_button, skip_finished_loading_check: true, wait: 5)
+ end
end
def click_pipeline_link
@@ -206,7 +215,10 @@ module QA
end
def edit!
- click_element(:edit_button)
+ # Click by JS is needed to bypass the Moved MR actions popover
+ # Change back to regular click_element when moved_mr_sidebar FF is removed
+ # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/385460
+ click_by_javascript(find_element(:edit_button))
end
def fast_forward_not_possible?
@@ -215,14 +227,25 @@ module QA
def has_file?(file_name)
open_file_tree
+
+ return true if has_element?(:file_name_content, file_name: file_name)
+
+ # Since the file tree uses virtual scrolling, search for file in case it is outside of viewport
+ search_file_tree(file_name)
has_element?(:file_name_content, file_name: file_name)
end
def has_no_file?(file_name)
- open_file_tree
+ # Since the file tree uses virtual scrolling, search for file to ensure non-existence
+ search_file_tree(file_name)
has_no_element?(:file_name_content, file_name: file_name)
end
+ def search_file_tree(file_name)
+ open_file_tree
+ fill_element(:diff_tree_search, file_name)
+ end
+
def open_file_tree
click_element(:file_tree_button) unless has_element?(:file_tree_container)
end
@@ -233,6 +256,17 @@ module QA
has_element?(:merge_button)
end
+ def has_no_merge_button?
+ refresh
+
+ has_no_element?(:merge_button)
+ end
+
+ RSpec::Matchers.define :have_merge_button do
+ match(&:has_merge_button?)
+ match_when_negated(&:has_no_merge_button?)
+ end
+
def has_pipeline_status?(text)
# Pipelines can be slow, so we wait a bit longer than the usual 10 seconds
wait_until(max_duration: 120, sleep_interval: 5, reload: true) do
@@ -359,12 +393,18 @@ module QA
end
def view_email_patches
- click_element(:mr_code_dropdown)
+ # Click by JS is needed to bypass the Moved MR actions popover
+ # Change back to regular click_element when moved_mr_sidebar FF is removed
+ # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/385460
+ click_by_javascript(find_element(:mr_code_dropdown))
visit_link_in_element(:download_email_patches_menu_item)
end
def view_plain_diff
- click_element(:mr_code_dropdown)
+ # Click by JS is needed to bypass the Moved MR actions popover
+ # Change back to regular click_element when moved_mr_sidebar FF is removed
+ # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/385460
+ click_by_javascript(find_element(:mr_code_dropdown))
visit_link_in_element(:download_plain_diff_menu_item)
end
@@ -375,7 +415,10 @@ module QA
end
def click_open_in_web_ide
- click_element(:mr_code_dropdown)
+ # Click by JS is needed to bypass the Moved MR actions popover
+ # Change back to regular click_element when moved_mr_sidebar FF is removed
+ # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/385460
+ click_by_javascript(find_element(:mr_code_dropdown))
click_element(:open_in_web_ide_button)
page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
wait_for_requests
@@ -386,6 +429,7 @@ module QA
click_element(:dropdown_button)
click_element(:edit_in_ide_button)
end
+ page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
end
def add_suggestion_to_diff(suggestion, line)
diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb
index 947fa2fec0f..f9493dbefcc 100644
--- a/qa/qa/page/profile/menu.rb
+++ b/qa/qa/page/profile/menu.rb
@@ -4,29 +4,39 @@ module QA
module Page
module Profile
class Menu < Page::Base
- # We need to check remote_mobile_device_name instead of mobile_layout? here
- # since tablets have the regular top navigation bar but still close the left nav
- prepend QA::Mobile::Page::SubMenus::Common if QA::Runtime::Env.remote_mobile_device_name
-
- view 'app/views/layouts/nav/sidebar/_profile.html.haml' do
- element :access_token_link, 'link_to profile_personal_access_tokens_path' # rubocop:disable QA/ElementWithPattern
- element :access_token_title, 'Access Tokens' # rubocop:disable QA/ElementWithPattern
- element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern
- element :ssh_keys, 'SSH Keys' # rubocop:disable QA/ElementWithPattern
+ prepend QA::Mobile::Page::SubMenus::Common if QA::Runtime::Env.mobile_layout?
+ # TODO: integrate back once super sidebar becomes default
+ prepend QA::Page::Profile::SuperSidebar::Menu if QA::Runtime::Env.super_sidebar_enabled?
+
+ view 'lib/sidebars/user_settings/menus/access_tokens_menu.rb' do
+ element :access_token_link
+ end
+
+ view 'lib/sidebars/user_settings/menus/ssh_keys_menu.rb' do
+ element :ssh_keys_link
+ end
+
+ view 'lib/sidebars/user_settings/menus/emails_menu.rb' do
element :profile_emails_link
+ end
+
+ view 'lib/sidebars/user_settings/menus/password_menu.rb' do
element :profile_password_link
+ end
+
+ view 'lib/sidebars/user_settings/menus/account_menu.rb' do
element :profile_account_link
end
def click_access_tokens
within_sidebar do
- click_link('Access Tokens')
+ click_element(:access_token_link)
end
end
def click_ssh_keys
within_sidebar do
- click_link('SSH Keys')
+ click_element(:ssh_keys_link)
end
end
@@ -50,10 +60,8 @@ module QA
private
- def within_sidebar
- page.within('.sidebar-top-level-items') do
- yield
- end
+ def within_sidebar(&block)
+ page.within('.sidebar-top-level-items', &block)
end
end
end
diff --git a/qa/qa/page/profile/super_sidebar/menu.rb b/qa/qa/page/profile/super_sidebar/menu.rb
new file mode 100644
index 00000000000..ade9c47313d
--- /dev/null
+++ b/qa/qa/page/profile/super_sidebar/menu.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Profile
+ module SuperSidebar
+ module Menu
+ def click_ssh_keys
+ click_element(:nav_item_link, submenu_item: 'SSH Keys')
+ end
+
+ def click_account
+ click_element(:nav_item_link, submenu_item: 'Account')
+ end
+
+ def click_emails
+ click_element(:nav_item_link, submenu_item: 'Emails')
+ end
+
+ def click_password
+ click_element(:nav_item_link, submenu_item: 'Password')
+ end
+
+ def click_access_tokens
+ click_element(:nav_item_link, submenu_item: 'Access Tokens')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb
index 7163bc7464d..a97d0afd160 100644
--- a/qa/qa/page/project/branches/show.rb
+++ b/qa/qa/page/project/branches/show.rb
@@ -24,6 +24,7 @@ module QA
end
view 'app/assets/javascripts/branches/components/delete_merged_branches.vue' do
+ element :delete_merged_branches_dropdown_button
element :delete_merged_branches_button
element :delete_merged_branches_input
element :delete_merged_branches_confirmation_button
@@ -54,6 +55,7 @@ module QA
end
def delete_merged_branches(branches_length)
+ click_element(:delete_merged_branches_dropdown_button)
click_element(:delete_merged_branches_button)
fill_element(:delete_merged_branches_input, branches_length)
click_element(:delete_merged_branches_confirmation_button)
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index bb1095371a8..898bf78b46a 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -32,6 +32,8 @@ module QA
# In this case skip this step and proceed to import project row
return unless has_element?(:personal_access_token_field)
+ raise ArgumentError, "No personal access token was provided" if personal_access_token.empty?
+
fill_element(:personal_access_token_field, personal_access_token)
click_element(:authenticate_button)
finished_loading?
@@ -71,7 +73,11 @@ module QA
# @param [String] source_project_name
# @param [Integer] wait
# @return [Boolean]
- def has_imported_project?(gh_project_name, wait: QA::Support::WaitForRequests::DEFAULT_MAX_WAIT_TIME)
+ def has_imported_project?(
+ gh_project_name,
+ wait: QA::Support::WaitForRequests::DEFAULT_MAX_WAIT_TIME,
+ allow_partial_import: false
+ )
within_element(:project_import_row, source_project: gh_project_name, skip_finished_loading_check: true) do
wait_until(
max_duration: wait,
@@ -80,18 +86,12 @@ module QA
skip_finished_loading_check_on_refresh: true
) do
status_selector = 'import_status_indicator'
- is_partial_import = has_css?(status_selector, text: "Partial import")
- # Temporarily adding this for investigation purposes. This makes sure that the details section is
- # expanded when the screenshot is taken when the test fails. This can be removed or repurposed later
- # after investigation. Related: https://gitlab.com/gitlab-org/gitlab/-/issues/385252#note_1211218434
- if is_partial_import
- within_element_by_index(:import_status_indicator, 0) do
- find('button').click
- end
- end
+ next has_element?(status_selector, text: "Complete", wait: 1) unless allow_partial_import
- has_element?(status_selector, text: "Complete")
+ ["Partially completed", "Complete"].any? do |status|
+ has_element?(status_selector, text: status, wait: 1)
+ end
end
end
end
diff --git a/qa/qa/page/project/import/repo_by_url.rb b/qa/qa/page/project/import/repo_by_url.rb
index 4a8d08d6499..1adfe001573 100644
--- a/qa/qa/page/project/import/repo_by_url.rb
+++ b/qa/qa/page/project/import/repo_by_url.rb
@@ -10,6 +10,10 @@ module QA
element :select_namespace_dropdown_search_field
end
+ view 'app/views/projects/_new_project_fields.html.haml' do
+ element :project_create_button
+ end
+
def import!(gitlab_repo_path, name)
fill_git_repository_url_link(gitlab_repo_path)
fill_project_name(name)
@@ -17,8 +21,6 @@ module QA
click_create_button
wait_for_success
-
- go_to_project(name)
end
private
@@ -44,7 +46,7 @@ module QA
end
def click_create_button
- find('.btn-confirm').click
+ click_element(:project_create_button)
end
def wait_for_success
@@ -52,13 +54,6 @@ module QA
page.has_no_content?('Import in progress', wait: 3.0)
end
end
-
- def go_to_project(name)
- Page::Main::Menu.perform(&:go_to_projects)
- Page::Dashboard::Projects.perform do |dashboard|
- dashboard.go_to_project(name)
- end
- end
end
end
end
diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb
index 7d162c6e48f..a4f4f6e3cf1 100644
--- a/qa/qa/page/project/issue/index.rb
+++ b/qa/qa/page/project/issue/index.rb
@@ -22,6 +22,13 @@ module QA
view 'app/assets/javascripts/issuable/components/csv_import_export_buttons.vue' do
element :export_as_csv_button
element :import_from_jira_link
+ end
+
+ view 'app/assets/javascripts/issues/list/components/issues_list_app.vue' do
+ element :issues_list_more_actions_dropdown
+ end
+
+ view 'app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue' do
element :import_issues_dropdown
end
@@ -59,6 +66,10 @@ module QA
click_element(:import_issues_dropdown)
end
+ def click_issues_list_more_actions_dropdown
+ click_element(:issues_list_more_actions_dropdown)
+ end
+
def export_issues_modal
find_element(:export_issuable_modal)
end
diff --git a/qa/qa/page/project/issue/new.rb b/qa/qa/page/project/issue/new.rb
index c90a09dce2e..7f52cda7c15 100644
--- a/qa/qa/page/project/issue/new.rb
+++ b/qa/qa/page/project/issue/new.rb
@@ -17,3 +17,5 @@ module QA
end
end
end
+
+QA::Page::Project::Issue::New.prepend_mod_with('Page::Project::Issue::New', namespace: QA)
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 2f8ffc634ac..05f38968718 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -8,7 +8,9 @@ module QA
include Page::Component::Note
include Page::Component::DesignManagement
include Page::Component::Issuable::Sidebar
- prepend Mobile::Page::Project::Issue::Show if Runtime::Env.mobile_layout?
+ # We need to check phone_layout? instead of mobile_layout? here
+ # since tablets have the regular top navigation bar
+ prepend Mobile::Page::Project::Issue::Show if Runtime::Env.phone_layout?
view 'app/assets/javascripts/issuable/components/related_issuable_item.vue' do
element :remove_related_issue_button
@@ -64,7 +66,10 @@ module QA
end
def click_close_issue_button
- click_element :close_issue_button
+ # Click by JS is needed to bypass the Moved MR actions popover
+ # Change back to regular click_element when moved_mr_sidebar FF is removed
+ # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/385460
+ click_by_javascript(find_element(:close_issue_button))
end
def has_reopen_issue_button?
@@ -72,12 +77,15 @@ module QA
end
def has_delete_issue_button?
- click_element(:issue_actions_ellipsis_dropdown)
+ # Click by JS is needed to bypass the Moved MR actions popover
+ # Change back to regular click_element when moved_mr_sidebar FF is removed
+ # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/385460
+ click_by_javascript(find('[data-qa-selector="issue_actions_ellipsis_dropdown"] > button'))
has_element?(:delete_issue_button)
end
def delete_issue
- click_element(:issue_actions_ellipsis_dropdown)
+ has_delete_issue_button?
click_element(:delete_issue_button,
Page::Modal::DeleteIssue,
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 24fd34b4d22..41a2986e300 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -68,6 +68,14 @@ module QA
end
end
+ def has_locked_artifact?
+ has_element? :artifacts_locked_message_content
+ end
+
+ def has_unlocked_artifact?
+ has_element? :artifacts_unlocked_message_content
+ end
+
private
def loaded?(wait: 60)
diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb
index db70d3e1d02..23b3ee61077 100644
--- a/qa/qa/page/project/menu.rb
+++ b/qa/qa/page/project/menu.rb
@@ -14,20 +14,38 @@ module QA
include SubMenus::Repository
include SubMenus::Settings
include SubMenus::Packages
+ include SubMenus::CreateNewMenu
+
+ if Runtime::Env.super_sidebar_enabled?
+ include Page::SubMenus::SuperSidebar::Manage
+ include SubMenus::SuperSidebar::Plan
+ include SubMenus::SuperSidebar::Settings
+ include SubMenus::SuperSidebar::Code
+ include SubMenus::SuperSidebar::Build
+ include SubMenus::SuperSidebar::Operate
+ include SubMenus::SuperSidebar::Monitor
+ include SubMenus::SuperSidebar::Main
+ end
def click_merge_requests
+ return go_to_merge_requests if Runtime::Env.super_sidebar_enabled?
+
within_sidebar do
click_element(:sidebar_menu_link, menu_item: 'Merge requests')
end
end
def click_wiki
+ return go_to_wiki if Runtime::Env.super_sidebar_enabled?
+
within_sidebar do
click_element(:sidebar_menu_link, menu_item: 'Wiki')
end
end
def click_activity
+ return go_to_activity if Runtime::Env.super_sidebar_enabled?
+
hover_project_information do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Activity')
@@ -36,12 +54,16 @@ module QA
end
def click_snippets
+ return go_to_snippets if Runtime::Env.super_sidebar_enabled?
+
within_sidebar do
click_element(:sidebar_menu_link, menu_item: 'Snippets')
end
end
def click_members
+ return go_to_members if Runtime::Env.super_sidebar_enabled?
+
hover_project_information do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Members')
diff --git a/qa/qa/page/project/monitor/alerts/index.rb b/qa/qa/page/project/monitor/alerts/index.rb
index 1363fb32498..1738ce170f2 100644
--- a/qa/qa/page/project/monitor/alerts/index.rb
+++ b/qa/qa/page/project/monitor/alerts/index.rb
@@ -13,6 +13,18 @@ module QA
def has_alert_with_title?(title)
has_link?(title, wait: 5)
end
+
+ def go_to_alert(title)
+ click_link_with_text(title)
+ end
+
+ def has_no_alert_with_title?(title)
+ has_no_link?(title, wait: 5)
+ end
+
+ def go_to_tab(name)
+ click_link_with_text(name)
+ end
end
end
end
diff --git a/qa/qa/page/project/monitor/alerts/show.rb b/qa/qa/page/project/monitor/alerts/show.rb
new file mode 100644
index 00000000000..1f3c52d8988
--- /dev/null
+++ b/qa/qa/page/project/monitor/alerts/show.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Monitor
+ module Alerts
+ class Show < Page::Base
+ view 'app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue' do
+ element :alert_system_note_container
+ end
+
+ def go_to_activity_feed_tab
+ click_link_with_text('Activity feed')
+ end
+
+ def has_system_note?(text)
+ has_element?(:alert_system_note_container, text: text)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/monitor/incidents/index.rb b/qa/qa/page/project/monitor/incidents/index.rb
index 1b30e484723..04cb23da389 100644
--- a/qa/qa/page/project/monitor/incidents/index.rb
+++ b/qa/qa/page/project/monitor/incidents/index.rb
@@ -15,8 +15,16 @@ module QA
click_element :create_incident_button
end
- def has_incident?(wait: Support::Repeater::DEFAULT_MAX_WAIT_TIME)
- wait_until(max_duration: wait) { has_element?(:incident_link) }
+ def has_incident?(wait: Support::Repeater::DEFAULT_MAX_WAIT_TIME, title: nil)
+ wait_until(max_duration: wait) { has_element?(:incident_link, text: title) }
+ end
+
+ def has_no_incident?(title: nil)
+ has_no_element?(:incident_link, text: title)
+ end
+
+ def go_to_tab(tab)
+ click_link_with_text(tab)
end
end
end
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index f7434656be3..8ea0b57ef3e 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -48,11 +48,9 @@ module QA
end
def choose_namespace(namespace)
- retry_on_exception do
- click_element :select_namespace_dropdown
- fill_element :select_namespace_dropdown_search_field, namespace
- click_button namespace
- end
+ click_element :select_namespace_dropdown
+ fill_element :select_namespace_dropdown_search_field, namespace
+ within_element(:select_namespace_dropdown) { click_button namespace }
end
def click_import_project
@@ -89,11 +87,15 @@ module QA
end
def click_github_link
- click_link 'GitHub'
+ retry_until(reload: true, max_attempts: 10, message: 'Waiting for import source to be enabled') do
+ click_link 'GitHub'
+ end
end
def click_repo_by_url_link
- click_button 'Repository by URL'
+ retry_until(reload: true, max_attempts: 10, message: 'Waiting for import source to be enabled') do
+ click_button 'Repository by URL'
+ end
end
def disable_initialize_with_readme
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index e4511ababfd..2455555f06c 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -44,6 +44,17 @@ module QA
element :jobs_dropdown_menu
end
+ view 'app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml' do
+ element :breadcrumb_links_content
+ element :breadcrumb_current_link
+ end
+
+ def pipeline_id
+ within_element(:breadcrumb_links_content) do
+ find_element(:breadcrumb_current_link).text.delete_prefix('#')
+ end
+ end
+
def running?(wait: 0)
within_element(:pipeline_header) do
page.has_content?('running', wait: wait)
diff --git a/qa/qa/page/project/pipeline_editor/show.rb b/qa/qa/page/project/pipeline_editor/show.rb
index 0a7a4460d18..6a95d461639 100644
--- a/qa/qa/page/project/pipeline_editor/show.rb
+++ b/qa/qa/page/project/pipeline_editor/show.rb
@@ -60,7 +60,7 @@ module QA
def initialize
wait_for_requests(skip_finished_loading_check: true)
- dismiss_file_tree_popover if has_element?(:file_tree_popover)
+ dismiss_file_tree_popover
super
end
@@ -122,8 +122,8 @@ module QA
go_to_tab('Visualize')
end
- def go_to_view_merged_yaml_tab
- go_to_tab('View merged YAML')
+ def go_to_full_configuration_tab
+ go_to_tab('Full configuration')
end
def go_to_validate_tab
diff --git a/qa/qa/page/project/settings/alerts.rb b/qa/qa/page/project/settings/alerts.rb
index 901a668f082..3ff4ef20bde 100644
--- a/qa/qa/page/project/settings/alerts.rb
+++ b/qa/qa/page/project/settings/alerts.rb
@@ -5,11 +5,12 @@ module QA
module Project
module Settings
class Alerts < Page::Base
+ include ::QA::Page::Component::Dropdown
+
view 'app/assets/javascripts/alerts_settings/components/alerts_form.vue' do
element :create_incident_checkbox
element :incident_templates_dropdown
element :save_changes_button
- element :incident_templates_item
element :enable_email_notification_checkbox
end
@@ -42,7 +43,7 @@ module QA
def select_issue_template(template)
click_element(:incident_templates_dropdown)
within_element :incident_templates_dropdown do
- find_element(:incident_templates_item, text: template).click
+ select_item(template)
end
end
diff --git a/qa/qa/page/project/settings/branch_rules.rb b/qa/qa/page/project/settings/branch_rules.rb
new file mode 100644
index 00000000000..b01f493addf
--- /dev/null
+++ b/qa/qa/page/project/settings/branch_rules.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class BranchRules < Page::Base
+ view 'app/assets/javascripts/projects/settings/repository/branch_rules/app.vue' do
+ element :add_branch_rule_button
+ end
+
+ view 'app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue' do
+ element :branch_content
+ element :details_button
+ end
+
+ def click_add_branch_rule
+ click_element(:add_branch_rule_button)
+ click_button('Create protected branch')
+ end
+
+ def navigate_to_branch_rules_details(branch_name)
+ within_element(:branch_content, branch_name: branch_name) do
+ click_element(:details_button)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+QA::Page::Project::Settings::BranchRules.prepend_mod_with('Page::Project::Settings::BranchRules', namespace: QA)
diff --git a/qa/qa/page/project/settings/branch_rules_details.rb b/qa/qa/page/project/settings/branch_rules_details.rb
new file mode 100644
index 00000000000..f6806a30efa
--- /dev/null
+++ b/qa/qa/page/project/settings/branch_rules_details.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class BranchRulesDetails < Page::Base
+ view 'app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue' do
+ element :allowed_to_push_content
+ element :allowed_to_merge_content
+ end
+
+ view 'app/assets/javascripts/projects/settings/branch_rules/components/view/protection_row.vue' do
+ element :access_level_content
+ end
+
+ def has_allowed_to_push?(role)
+ within_element(:allowed_to_push_content) do
+ has_element?(:access_level_content, role: role)
+ end
+ end
+
+ def has_allowed_to_merge?(role)
+ within_element(:allowed_to_merge_content) do
+ has_element?(:access_level_content, role: role)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+QA::Page::Project::Settings::BranchRulesDetails.prepend_mod_with( # rubocop:disable Cop/InjectEnterpriseEditionModule
+ 'Page::Project::Settings::BranchRulesDetails', namespace: QA)
diff --git a/qa/qa/page/project/settings/ci_variables.rb b/qa/qa/page/project/settings/ci_variables.rb
index 8df0aaa9f27..1315ed8ca73 100644
--- a/qa/qa/page/project/settings/ci_variables.rb
+++ b/qa/qa/page/project/settings/ci_variables.rb
@@ -11,7 +11,6 @@ module QA
element :ci_variable_key_field
element :ci_variable_value_field
element :ci_variable_save_button
- element :ci_variable_delete_button
end
def fill_variable(key, value, masked = false)
@@ -37,14 +36,6 @@ module QA
def click_ci_variable_save_button
click_element :ci_variable_save_button
end
-
- def click_reveal_ci_variable_value_button
- click_element :reveal_ci_variable_value_button
- end
-
- def click_ci_variable_delete_button
- click_element :ci_variable_delete_button
- end
end
end
end
diff --git a/qa/qa/page/project/settings/deploy_keys.rb b/qa/qa/page/project/settings/deploy_keys.rb
index 297d29550e3..b94dbbea533 100644
--- a/qa/qa/page/project/settings/deploy_keys.rb
+++ b/qa/qa/page/project/settings/deploy_keys.rb
@@ -13,6 +13,7 @@ module QA
view 'app/views/shared/deploy_keys/_project_group_form.html.haml' do
element :deploy_key_title_field
element :deploy_key_field
+ element :deploy_key_expires_at_field
element :add_deploy_key_button
end
diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb
index 8b9b72758d8..0d45efdcb70 100644
--- a/qa/qa/page/project/settings/main.rb
+++ b/qa/qa/page/project/settings/main.rb
@@ -6,7 +6,6 @@ module QA
module Settings
class Main < Page::Base
include QA::Page::Settings::Common
- include SubMenus::Project
include Component::Breadcrumbs
include Layout::Flash
diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb
index c42a4e0bebe..3530726feeb 100644
--- a/qa/qa/page/project/settings/merge_request.rb
+++ b/qa/qa/page/project/settings/merge_request.rb
@@ -27,11 +27,6 @@ module QA
choose_element(:merge_ff_radio, true)
click_save_changes
end
-
- def enable_merge_if_all_disscussions_are_resolved
- check_element(:only_allow_merge_if_all_discussions_are_resolved_checkbox, true)
- click_save_changes
- end
end
end
end
diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb
index 61ee3e4f03c..c9ce80076e2 100644
--- a/qa/qa/page/project/settings/mirroring_repositories.rb
+++ b/qa/qa/page/project/settings/mirroring_repositories.rb
@@ -29,7 +29,6 @@ module QA
view 'app/views/shared/_remote_mirror_update_button.html.haml' do
element :update_now_button
- element :updating_button
end
view 'app/views/projects/mirrors/_ssh_host_keys.html.haml' do
@@ -86,11 +85,10 @@ module QA
def update(url)
row_index = find_repository_row_index(url)
-
within_element_by_index(:mirrored_repository_row_container, row_index) do
# When a repository is first mirrored, the update process might
# already be started, so the button is already "clicked"
- click_element :update_now_button unless has_element? :updating_button
+ click_element :update_now_button if has_element?(:update_now_button, wait: 0)
end
end
@@ -120,7 +118,8 @@ module QA
all_elements(:mirror_repository_url_content, minimum: 1).index do |url|
# The url might be a sanitized url but the target_url won't be so
# we compare just the paths instead of the full url
- URI.parse(url.text).path == target_url.path
+ # We also must remove any badges from the url (e.g. All Branches)
+ URI.parse(url.text.split("\n").first).path == target_url.path
end
end
end
diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb
index 6931d26b259..d9aaacbde32 100644
--- a/qa/qa/page/project/settings/repository.rb
+++ b/qa/qa/page/project/settings/repository.rb
@@ -27,6 +27,10 @@ module QA
element :protected_tag_settings_content
end
+ view 'app/views/projects/branch_rules/_show.html.haml' do
+ element :branch_rules_content
+ end
+
def expand_deploy_tokens(&block)
expand_content(:deploy_tokens_settings_content) do
Settings::DeployTokens.perform(&block)
@@ -57,6 +61,10 @@ module QA
end
end
+ def expand_branch_rules
+ expand_content(:branch_rules_content)
+ end
+
def expand_default_branch(&block)
within('#branch-defaults-settings') do
find('.btn-default').click do
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 3c2b8d56f1d..daaee280b84 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -7,9 +7,11 @@ module QA
include Layout::Flash
include Page::Component::ClonePanel
include Page::Component::Breadcrumbs
- include Page::Project::SubMenus::Settings
include Page::File::Shared::CommitMessage
- prepend Mobile::Page::Project::Show if Runtime::Env.mobile_layout?
+ include Page::Component::Dropdown
+ # We need to check phone_layout? instead of mobile_layout? here
+ # since tablets have the regular top navigation bar
+ prepend Mobile::Page::Project::Show if Runtime::Env.phone_layout?
view 'app/assets/javascripts/repository/components/preview/index.vue' do
element :blob_viewer_content
@@ -27,10 +29,6 @@ module QA
element :new_menu_toggle
end
- view 'app/helpers/nav/new_dropdown_helper.rb' do
- element :new_issue_link
- end
-
view 'app/views/projects/_last_push.html.haml' do
element :create_merge_request_button
end
@@ -68,11 +66,6 @@ module QA
element :web_ide_button
end
- view 'app/views/shared/_ref_switcher.html.haml' do
- element :branches_dropdown
- element :branches_dropdown_content
- end
-
view 'app/views/projects/blob/viewers/_loading.html.haml' do
element :spinner_placeholder
end
@@ -81,6 +74,10 @@ module QA
element :download_source_code_button
end
+ view 'app/views/projects/tree/_tree_header.html.haml' do
+ element :ref_dropdown_container
+ end
+
def wait_for_viewers_to_load
has_no_element?(:spinner_placeholder, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
end
@@ -122,11 +119,6 @@ module QA
end
end
- def go_to_new_issue
- click_element(:new_menu_toggle)
- click_element(:new_issue_link)
- end
-
def has_create_merge_request_button?
has_css?(element_selector_css(:create_merge_request_button))
end
@@ -163,10 +155,12 @@ module QA
def open_web_ide!
click_element(:web_ide_button)
+ page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
end
def open_web_ide_via_shortcut
page.driver.send_keys('.')
+ page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
end
def has_edit_fork_button?
@@ -182,10 +176,9 @@ module QA
end
def switch_to_branch(branch_name)
- find_element(:branches_dropdown).click
-
- within_element(:branches_dropdown_content) do
- click_on branch_name
+ within_element(:ref_dropdown_container) do
+ expand_select_list
+ select_item(branch_name)
end
end
diff --git a/qa/qa/page/project/sub_menus/ci_cd.rb b/qa/qa/page/project/sub_menus/ci_cd.rb
index 4ae51798e54..3547ea76182 100644
--- a/qa/qa/page/project/sub_menus/ci_cd.rb
+++ b/qa/qa/page/project/sub_menus/ci_cd.rb
@@ -15,7 +15,7 @@ module QA
end
end
- def click_ci_cd_pipelines
+ def go_to_pipelines
within_sidebar do
click_element(:sidebar_menu_link, menu_item: 'CI/CD')
end
diff --git a/qa/qa/page/project/sub_menus/common.rb b/qa/qa/page/project/sub_menus/common.rb
index 112f49a90ee..e8952f9e064 100644
--- a/qa/qa/page/project/sub_menus/common.rb
+++ b/qa/qa/page/project/sub_menus/common.rb
@@ -20,7 +20,7 @@ module QA
element :sidebar_menu_link
end
- view 'app/views/layouts/nav/_breadcrumbs.html.haml' do
+ view 'app/views/layouts/nav/_top_bar.html.haml' do
element :toggle_mobile_nav_button
end
end
@@ -29,7 +29,7 @@ module QA
private
def sidebar_element
- :project_sidebar
+ QA::Runtime::Env.super_sidebar_enabled? ? :navbar : :project_sidebar
end
end
end
diff --git a/qa/qa/page/project/sub_menus/create_new_menu.rb b/qa/qa/page/project/sub_menus/create_new_menu.rb
new file mode 100644
index 00000000000..cfb91c29d5e
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/create_new_menu.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module CreateNewMenu
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ # TODO: remove this when the super sidebar is enabled by default
+ view 'app/helpers/nav/new_dropdown_helper.rb' do
+ element :new_issue_link
+ end
+
+ view 'app/helpers/sidebars_helper.rb' do
+ element :create_menu_item
+ end
+ end
+ end
+
+ def go_to_new_issue
+ within_new_item_menu do
+ next click_element(:new_issue_link) unless QA::Runtime::Env.super_sidebar_enabled?
+
+ click_element(:create_menu_item, create_menu_item: 'new_issue')
+ end
+ end
+
+ def go_to_new_merge_request
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'new_mr')
+ end
+ end
+
+ def go_to_new_project_snippet
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'new_snippet')
+ end
+ end
+
+ def go_to_invite_members
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'invite')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/issues.rb b/qa/qa/page/project/sub_menus/issues.rb
index 7fa19063653..b5b918e076d 100644
--- a/qa/qa/page/project/sub_menus/issues.rb
+++ b/qa/qa/page/project/sub_menus/issues.rb
@@ -15,7 +15,7 @@ module QA
end
end
- def click_issues
+ def go_to_issues
within_sidebar do
click_element(:sidebar_menu_link, menu_item: 'Issues')
end
@@ -27,7 +27,7 @@ module QA
end
end
- def go_to_boards
+ def go_to_issue_boards
hover_issues do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Boards')
diff --git a/qa/qa/page/project/sub_menus/monitor.rb b/qa/qa/page/project/sub_menus/monitor.rb
index 27fb58fb146..00774261467 100644
--- a/qa/qa/page/project/sub_menus/monitor.rb
+++ b/qa/qa/page/project/sub_menus/monitor.rb
@@ -31,6 +31,22 @@ module QA
end
end
+ def go_to_monitor_on_call_schedules
+ hover_monitor do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'On-call Schedules')
+ end
+ end
+ end
+
+ def go_to_monitor_escalation_policies
+ hover_monitor do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Escalation Policies')
+ end
+ end
+ end
+
private
def hover_monitor
diff --git a/qa/qa/page/project/sub_menus/packages.rb b/qa/qa/page/project/sub_menus/packages.rb
index 9600540c5bc..9f3446bfd39 100644
--- a/qa/qa/page/project/sub_menus/packages.rb
+++ b/qa/qa/page/project/sub_menus/packages.rb
@@ -7,7 +7,7 @@ module QA
module Packages
extend QA::Page::PageConcern
- def click_packages_link
+ def go_to_package_registry
hover_registry do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Package Registry')
@@ -26,7 +26,7 @@ module QA
def go_to_infrastructure_registry
hover_registry do
within_submenu do
- click_link('Infrastructure Registry')
+ click_link('Terraform modules')
end
end
end
diff --git a/qa/qa/page/project/sub_menus/repository.rb b/qa/qa/page/project/sub_menus/repository.rb
index f9d55c0009c..b8ebaa10a49 100644
--- a/qa/qa/page/project/sub_menus/repository.rb
+++ b/qa/qa/page/project/sub_menus/repository.rb
@@ -40,7 +40,7 @@ module QA
def go_to_repository_contributors
hover_repository do
within_submenu do
- click_element(:sidebar_menu_item_link, menu_item: 'Contributors')
+ click_element(:sidebar_menu_item_link, menu_item: 'Contributor statistics')
end
end
end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/build.rb b/qa/qa/page/project/sub_menus/super_sidebar/build.rb
new file mode 100644
index 00000000000..7d772d9d192
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/build.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Build
+ extend QA::Page::PageConcern
+
+ def go_to_pipelines
+ open_build_submenu('Pipelines')
+ end
+
+ def go_to_pipeline_editor
+ open_build_submenu('Pipeline editor')
+ end
+
+ def go_to_jobs
+ open_build_submenu('Jobs')
+ end
+
+ def go_to_schedules
+ open_build_submenu('Pipeline schedules')
+ end
+
+ def go_to_environments
+ open_operations_submenu('Environments')
+ end
+
+ def go_to_feature_flags
+ open_operations_submenu('Feature Flags')
+ end
+
+ def go_to_releases
+ open_operations_submenu('Releases')
+ end
+
+ private
+
+ def open_build_submenu(sub_menu)
+ open_submenu('Build', sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/code.rb b/qa/qa/page/project/sub_menus/super_sidebar/code.rb
new file mode 100644
index 00000000000..44d46725b47
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/code.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Code
+ extend QA::Page::PageConcern
+
+ def go_to_repository
+ open_code_submenu('Repository')
+ end
+
+ def go_to_repository_commits
+ open_code_submenu('Commits')
+ end
+
+ def go_to_repository_branches
+ open_code_submenu('Branches')
+ end
+
+ def go_to_repository_tags
+ open_code_submenu('Tags')
+ end
+
+ def go_to_snippets
+ open_code_submenu('Snippets')
+ end
+
+ def go_to_graph
+ open_code_submenu('Repository graph')
+ end
+
+ def go_to_compare_revisions
+ open_code_submenu('Compare revisions')
+ end
+
+ private
+
+ def open_code_submenu(sub_menu)
+ open_submenu('Code', sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/main.rb b/qa/qa/page/project/sub_menus/super_sidebar/main.rb
new file mode 100644
index 00000000000..63641248b15
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/main.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Main
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::SuperSidebar::Main
+ end
+ end
+
+ def click_project
+ click_element(:nav_item_link, submenu_item: 'Project overview')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/monitor.rb b/qa/qa/page/project/sub_menus/super_sidebar/monitor.rb
new file mode 100644
index 00000000000..65ed9dbb4f8
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/monitor.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Monitor
+ extend QA::Page::PageConcern
+
+ def go_to_monitor_error_tracking
+ open_monitor_submenu('Error tracking')
+ end
+
+ def go_to_monitor_alerts
+ open_monitor_submenu('Alerts')
+ end
+
+ def go_to_monitor_incidents
+ open_monitor_submenu('Incidents')
+ end
+
+ def go_to_monitor_escalation_policies
+ open_monitor_submenu('Escalation Policies')
+ end
+
+ def go_to_monitor_on_call_schedules
+ open_monitor_submenu('On-call Schedules')
+ end
+
+ private
+
+ def open_monitor_submenu(sub_menu)
+ open_submenu('Monitor', sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/operate.rb b/qa/qa/page/project/sub_menus/super_sidebar/operate.rb
new file mode 100644
index 00000000000..8191f2263ef
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/operate.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Operate
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::SuperSidebar::Operate
+ end
+ end
+
+ def go_to_infrastructure_registry
+ open_operate_submenu('Terraform modules')
+ end
+
+ def go_to_kubernetes_clusters
+ open_operate_submenu('Kubernetes clusters')
+ end
+
+ def go_to_terraform
+ open_operate_submenu('Terraform states')
+ end
+
+ private
+
+ def open_operate_submenu(sub_menu)
+ open_submenu('Operate', sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/plan.rb b/qa/qa/page/project/sub_menus/super_sidebar/plan.rb
new file mode 100644
index 00000000000..fe45bb6bb65
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/plan.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Plan
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::SuperSidebar::Plan
+ end
+ end
+
+ def go_to_requirements
+ open_plan_submenu("Requirements")
+ end
+
+ def go_to_jira_issues
+ open_plan_submenu("Jira issues")
+ end
+
+ def go_to_open_jira
+ open_plan_submenu("Open Jira")
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/secure.rb b/qa/qa/page/project/sub_menus/super_sidebar/secure.rb
new file mode 100644
index 00000000000..ab1717a447a
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/secure.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Secure
+ extend QA::Page::PageConcern
+
+ def go_to_security_configuration
+ open_secure_submenu('Security configuration')
+ end
+
+ private
+
+ def open_secure_submenu(sub_menu)
+ open_submenu('Secure', sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/sub_menus/super_sidebar/settings.rb b/qa/qa/page/project/sub_menus/super_sidebar/settings.rb
new file mode 100644
index 00000000000..3aca6cf00af
--- /dev/null
+++ b/qa/qa/page/project/sub_menus/super_sidebar/settings.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module SubMenus
+ module SuperSidebar
+ module Settings
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::SuperSidebar::Settings
+ end
+ end
+
+ def go_to_merge_request_settings
+ open_settings_submenu('Merge requests')
+ end
+
+ def go_to_pages_settings
+ open_settings_submenu('Pages')
+ end
+
+ def go_to_monitor_settings
+ open_settings_submenu('Monitor')
+ end
+
+ private
+
+ def open_settings_submenu(sub_menu)
+ open_submenu('Settings', sub_menu)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/tag/show.rb b/qa/qa/page/project/tag/show.rb
index 1974448a7c5..b9703f46a50 100644
--- a/qa/qa/page/project/tag/show.rb
+++ b/qa/qa/page/project/tag/show.rb
@@ -8,7 +8,6 @@ module QA
view 'app/views/projects/tags/show.html.haml' do
element :tag_name_content
element :tag_message_content
- element :tag_release_notes_content
end
def has_tag_name?(text)
@@ -18,10 +17,6 @@ module QA
def has_tag_message?(text)
has_element?(:tag_message_content, text: text)
end
-
- def has_tag_release_notes?(text)
- has_element?(:tag_release_notes_content, text: text)
- end
end
end
end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index 975d3c8ea14..dda329ab582 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -111,7 +111,7 @@ module QA
# Used for stablility, due to feature_caching of vscode_web_ide
def wait_until_ide_loads
- Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page,
+ Support::Waiter.wait_until(sleep_interval: 2, max_duration: 120, reload_page: page,
retry_on_exception: true) do
has_element?(:commit_mode_tab)
end
diff --git a/qa/qa/page/project/web_ide/vscode.rb b/qa/qa/page/project/web_ide/vscode.rb
index dd5222cfd93..1a9fad56a10 100644
--- a/qa/qa/page/project/web_ide/vscode.rb
+++ b/qa/qa/page/project/web_ide/vscode.rb
@@ -57,7 +57,7 @@ module QA
page.has_content?(folder_name)
# Commit Button
- page.find('a.monaco-description-button').click
+ page.find('a.monaco-text-button').click
page.has_css?('.notification-list-item-details-row', visible: true)
end
end
diff --git a/qa/qa/page/registration/welcome.rb b/qa/qa/page/registration/welcome.rb
index 77cdbe8fd9e..bf7b970f12e 100644
--- a/qa/qa/page/registration/welcome.rb
+++ b/qa/qa/page/registration/welcome.rb
@@ -9,15 +9,15 @@ module QA
element :role_dropdown
end
- def has_get_started_button?
- has_element?(:get_started_button)
+ def has_get_started_button?(wait: Capybara.default_max_wait_time)
+ has_element?(:get_started_button, wait: wait)
end
def select_role(role)
select_element(:role_dropdown, role)
end
- def choose_setup_for_company_if_available
+ def choose_setup_for_just_me_if_available
# Only implemented in EE
end
diff --git a/qa/qa/page/sub_menus/common.rb b/qa/qa/page/sub_menus/common.rb
index 518b3b4e84e..28b4cb37333 100644
--- a/qa/qa/page/sub_menus/common.rb
+++ b/qa/qa/page/sub_menus/common.rb
@@ -4,9 +4,7 @@ module QA
module Page
module SubMenus
module Common
- # We need to check remote_mobile_device_name instead of mobile_layout? here
- # since tablets have the regular top navigation bar but still close the left nav
- prepend Mobile::Page::SubMenus::Common if QA::Runtime::Env.remote_mobile_device_name
+ prepend Mobile::Page::SubMenus::Common if QA::Runtime::Env.mobile_layout?
def hover_element(element)
within_sidebar do
@@ -15,38 +13,52 @@ module QA
end
end
- def within_sidebar
+ def within_sidebar(&block)
wait_for_requests
- within_element(sidebar_element) do
- yield
- end
+ within_element(sidebar_element, &block)
end
- def within_submenu(element = nil)
+ def within_submenu(element = nil, &block)
if element
- within_element(element) do
- yield
- end
+ within_element(element, &block)
else
- within_submenu_without_element do
- yield
- end
+ within_submenu_without_element(&block)
end
end
private
- def within_submenu_without_element
- if has_css?('.fly-out-list')
- within('.fly-out-list') do
- yield
- end
- else
- yield
+ # Opens the new item menu and yields to the block
+ #
+ # @return [void]
+ def within_new_item_menu
+ click_element(:new_menu_toggle)
+
+ yield
+ end
+
+ # Implementation for super-sidebar, will replace within_submenu
+ #
+ # @param [String] parent_menu_name
+ # @param [String] parent_section_id
+ # @param [String] sub_menu
+ # @return [void]
+ def open_submenu(parent_menu_name, sub_menu)
+ # prevent closing sub-menu if it was already open
+ unless has_element?(:menu_section, section_name: parent_menu_name, wait: 0)
+ click_element(:menu_section_button, section_name: parent_menu_name)
+ end
+
+ within_element(:menu_section, section_name: parent_menu_name) do
+ click_element(:nav_item_link, submenu_item: sub_menu)
end
end
+ def within_submenu_without_element(&block)
+ has_css?('.fly-out-list') ? within('.fly-out-list', &block) : yield
+ end
+
def sidebar_element
raise NotImplementedError
end
diff --git a/qa/qa/page/sub_menus/create_new_menu.rb b/qa/qa/page/sub_menus/create_new_menu.rb
new file mode 100644
index 00000000000..1f8641827be
--- /dev/null
+++ b/qa/qa/page/sub_menus/create_new_menu.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module CreateNewMenu
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ include QA::Page::SubMenus::Common
+
+ view 'app/helpers/sidebars_helper.rb' do
+ element :create_menu_item
+ end
+ end
+ end
+
+ def go_to_create_project
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'general_new_project')
+ end
+ end
+
+ def go_to_create_snippet
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'general_new_snippet')
+ end
+ end
+
+ def go_to_create_group
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'general_new_group')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/super_sidebar/context_switcher.rb b/qa/qa/page/sub_menus/super_sidebar/context_switcher.rb
new file mode 100644
index 00000000000..1fd35e57dc2
--- /dev/null
+++ b/qa/qa/page/sub_menus/super_sidebar/context_switcher.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module SuperSidebar
+ module ContextSwitcher
+ extend QA::Page::PageConcern
+
+ def self.prepended(base)
+ super
+
+ base.class_eval do
+ view 'app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue' do
+ element :context_switcher
+ element :context_navigation
+ end
+ end
+ end
+
+ def go_to_your_work
+ go_to_context("Your work")
+ end
+
+ def go_to_explore
+ go_to_context("Explore")
+ end
+
+ def go_to_admin_area
+ go_to_context("Admin Area")
+ end
+
+ private
+
+ def go_to_context(sub_menu)
+ click_element(:context_switcher) unless has_element?(:context_navigation, wait: 0)
+
+ click_element(:nav_item_link, submenu_item: sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/super_sidebar/main.rb b/qa/qa/page/sub_menus/super_sidebar/main.rb
new file mode 100644
index 00000000000..aadb24369ea
--- /dev/null
+++ b/qa/qa/page/sub_menus/super_sidebar/main.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module SuperSidebar
+ module Main
+ extend QA::Page::PageConcern
+
+ def go_to_issues
+ click_element(:nav_item_link, submenu_item: 'Issues')
+ end
+
+ def go_to_merge_requests
+ click_element(:nav_item_link, submenu_item: 'Merge requests')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/super_sidebar/manage.rb b/qa/qa/page/sub_menus/super_sidebar/manage.rb
new file mode 100644
index 00000000000..535b29e607f
--- /dev/null
+++ b/qa/qa/page/sub_menus/super_sidebar/manage.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module SuperSidebar
+ module Manage
+ extend QA::Page::PageConcern
+
+ def go_to_activity
+ open_manage_submenu('Activity')
+ end
+
+ def go_to_members
+ open_manage_submenu('Members')
+ end
+
+ def go_to_labels
+ open_manage_submenu('Labels')
+ end
+
+ def go_to_milestones
+ open_manage_submenu('Milestones')
+ end
+
+ private
+
+ def open_manage_submenu(sub_menu)
+ open_submenu('Manage', sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/super_sidebar/operate.rb b/qa/qa/page/sub_menus/super_sidebar/operate.rb
new file mode 100644
index 00000000000..1ffbb6872da
--- /dev/null
+++ b/qa/qa/page/sub_menus/super_sidebar/operate.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module SuperSidebar
+ module Operate
+ extend QA::Page::PageConcern
+
+ def go_to_package_registry
+ open_operate_submenu('Package Registry')
+ end
+
+ def go_to_container_registry
+ open_operate_submenu('Container Registry')
+ end
+
+ def go_to_dependency_proxy
+ open_operate_submenu('Dependency proxy')
+ end
+
+ private
+
+ def open_operate_submenu(sub_menu)
+ open_submenu('Operate', sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/super_sidebar/plan.rb b/qa/qa/page/sub_menus/super_sidebar/plan.rb
new file mode 100644
index 00000000000..e4b9fcf099c
--- /dev/null
+++ b/qa/qa/page/sub_menus/super_sidebar/plan.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module SuperSidebar
+ module Plan
+ extend QA::Page::PageConcern
+
+ def go_to_issue_boards
+ open_plan_submenu("Issue boards")
+ end
+
+ def go_to_service_desk
+ open_plan_submenu("Service Desk")
+ end
+
+ def go_to_wiki
+ open_plan_submenu("Wiki")
+ end
+
+ private
+
+ def open_plan_submenu(sub_menu)
+ open_submenu("Plan", sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/super_sidebar/settings.rb b/qa/qa/page/sub_menus/super_sidebar/settings.rb
new file mode 100644
index 00000000000..ff38ab2b043
--- /dev/null
+++ b/qa/qa/page/sub_menus/super_sidebar/settings.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module SuperSidebar
+ module Settings
+ extend QA::Page::PageConcern
+
+ def go_to_general_settings
+ open_settings_submenu('General')
+ end
+
+ def go_to_integrations_settings
+ open_settings_submenu('Integrations')
+ end
+
+ def go_to_webhooks_settings
+ open_settings_submenu('Webhooks')
+ end
+
+ def go_to_access_token_settings
+ open_settings_submenu('Access Tokens')
+ end
+
+ def go_to_repository_settings
+ open_settings_submenu('Repository')
+ end
+
+ def go_to_ci_cd_settings
+ open_settings_submenu('CI/CD')
+ end
+
+ def go_to_package_settings
+ open_settings_submenu('Packages and registries')
+ end
+
+ private
+
+ def open_settings_submenu(sub_menu)
+ open_submenu('Settings', sub_menu)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/user/show.rb b/qa/qa/page/user/show.rb
index ad2de331ad9..f14ddea3e8b 100644
--- a/qa/qa/page/user/show.rb
+++ b/qa/qa/page/user/show.rb
@@ -6,7 +6,7 @@ module QA
class Show < Page::Base
view 'app/views/users/show.html.haml' do
element :follow_user_link
- element :following_link
+ element :following_tab
end
view 'app/views/shared/users/_user.html.haml' do
@@ -21,8 +21,10 @@ module QA
click_element(:follow_user_link)
end
- def click_following_link
- click_element(:following_link)
+ def click_following_tab
+ return click_element(:nav_item_link, submenu_item: 'Following') if Runtime::Env.super_sidebar_enabled?
+
+ click_element(:following_tab)
end
def click_user_link(username)
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index d7a220bc83f..3f9d2b92a0a 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -10,6 +10,7 @@ module QA
include Support::API
include Errors
+ attr_reader :api_fabrication_http_method
attr_writer :api_client
attr_accessor :api_user, :api_resource, :api_response
@@ -49,22 +50,6 @@ module QA
end
end
- def api_put(body = api_put_body)
- response = put(
- Runtime::API::Request.new(api_client, api_put_path).url,
- body)
-
- unless response.code == HTTP_STATUS_OK
- raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}"
- end
-
- process_api_response(parse_body(response))
- end
-
- def api_fabrication_http_method
- @api_fabrication_http_method ||= :post
- end
-
# Checks if a resource already exists
#
# @return [Boolean] true if the resource returns HTTP status code 200
@@ -84,14 +69,15 @@ module QA
private
- def resource_web_url(resource)
- resource.fetch(:web_url) do
- raise ResourceURLMissingError, "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`."
- end
- end
-
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def api_get
- process_api_response(parse_body(api_get_from(api_get_path)))
+ process_api_response(parse_body(api_get_from(api_get_path))).tap do
+ # Record method that was used to create certain resource
+ # :get - resource already existed in GitLab instance and was fetched via get request
+ # :post - resource was created from scratch using post request
+ # :put - resource was created from scratch using put request
+ @api_fabrication_http_method ||= :get
+ end
end
def api_get_from(get_path)
@@ -100,27 +86,24 @@ module QA
response = get(request.url)
if response.code == HTTP_STATUS_SERVER_ERROR
- raise InternalServerError, "Failed to GET #{request.mask_url} - (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}"
+ raise(InternalServerError, <<~MSG.strip)
+ Failed to GET #{request.mask_url} - (#{response.code}): `#{response}`.
+ #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}
+ MSG
elsif response.code != HTTP_STATUS_OK
- raise ResourceNotFoundError, "Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}"
+ raise(ResourceNotFoundError, <<~MSG.strip)
+ Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`.
+ #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}
+ MSG
end
- @api_fabrication_http_method ||= :get # rubocop:disable Gitlab/ModuleWithInstanceVariables
-
response
end
- # Query parameters formatted as `?key1=value1&key2=value2...`
- #
- # @return [String]
- def query_parameters_to_string
- query_parameters.each_with_object([]) do |(k, v), arr|
- arr << "#{k}=#{v}"
- end.join('&').prepend('?').chomp('?') # prepend `?` unless the string is blank
- end
-
def api_post
- process_api_response(api_post_to(api_post_path, api_post_body))
+ process_api_response(api_post_to(api_post_path, api_post_body)).tap do
+ @api_fabrication_http_method ||= :post
+ end
end
def api_post_to(post_path, post_body, args = {})
@@ -131,8 +114,9 @@ module QA
body = flatten_hash(parse_body(graphql_response))
unless graphql_response.code == HTTP_STATUS_OK && (body[:errors].nil? || body[:errors].empty?)
- raise(ResourceFabricationFailedError, <<~MSG)
- Fabrication of #{self.class.name} using the API failed (#{graphql_response.code}) with `#{graphql_response}`.
+ action = post_body =~ /mutation {\s+destroy/ ? 'Deletion' : 'Fabrication'
+ raise(ResourceFabricationFailedError, <<~MSG.strip)
+ #{action} of #{self.class.name} using the API failed (#{graphql_response.code}) with `#{graphql_response}`.
#{QA::Support::Loglinking.failure_metadata(graphql_response.headers[:x_request_id])}
MSG
end
@@ -144,36 +128,68 @@ module QA
response = post(Runtime::API::Request.new(api_client, post_path).url, post_body, args)
unless response.code == HTTP_STATUS_CREATED
- raise(
- ResourceFabricationFailedError,
- "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}"
- )
+ raise(ResourceFabricationFailedError, <<~MSG.strip)
+ Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`.
+ #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}
+ MSG
end
parse_body(response)
end
end
- def flatten_hash(param)
- param.each_pair.reduce({}) do |a, (k, v)|
- v.is_a?(Hash) ? a.merge(flatten_hash(v)) : a.merge(k.to_sym => v)
+ def api_put
+ process_api_response(api_put_to(api_put_path, api_put_body)).tap do
+ @api_fabrication_http_method ||= :put
end
end
+ def api_put_to(put_path, body)
+ response = put(Runtime::API::Request.new(api_client, put_path).url, body)
+
+ unless response.code == HTTP_STATUS_OK
+ raise(ResourceFabricationFailedError, <<~MSG.strip)
+ Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`.
+ #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}
+ MSG
+ end
+
+ parse_body(response)
+ end
+
def api_delete
- request = Runtime::API::Request.new(api_client, api_delete_path)
- response = delete(request.url)
+ if api_delete_path == "/graphql"
+ api_post_to(api_delete_path, api_delete_body)
+ else
+ request = Runtime::API::Request.new(api_client, api_delete_path)
+ response = delete(request.url)
- unless [HTTP_STATUS_NO_CONTENT, HTTP_STATUS_ACCEPTED].include? response.code
- raise ResourceNotDeletedError, "Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}"
+ unless [HTTP_STATUS_NO_CONTENT, HTTP_STATUS_ACCEPTED].include? response.code
+ raise(ResourceNotDeletedError, <<~MSG.strip)
+ Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`.
+ #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}
+ MSG
+ end
+
+ response
end
+ end
- response
+ def resource_web_url(resource)
+ resource.fetch(:web_url) do
+ raise ResourceURLMissingError,
+ "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`."
+ end
end
def api_client
- @api_client ||= Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'), user: api_user)
+ @api_client ||= Runtime::API::Client.new(
+ :gitlab,
+ is_new_session: !current_url.start_with?('http'),
+ user: api_user
+ )
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def process_api_response(parsed_response)
self.api_response = parsed_response
@@ -191,6 +207,21 @@ module QA
def request_url(path, **opts)
Runtime::API::Request.new(api_client, path, **opts).url
end
+
+ # Query parameters formatted as `?key1=value1&key2=value2...`
+ #
+ # @return [String]
+ def query_parameters_to_string
+ query_parameters.each_with_object([]) do |(k, v), arr|
+ arr << "#{k}=#{v}"
+ end.join('&').prepend('?').chomp('?') # prepend `?` unless the string is blank
+ end
+
+ def flatten_hash(param)
+ param.each_pair.reduce({}) do |a, (k, v)|
+ v.is_a?(Hash) ? a.merge(flatten_hash(v)) : a.merge(k.to_sym => v)
+ end
+ end
end
end
end
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
index 2abe1904c92..6c03f45bdfd 100644
--- a/qa/qa/resource/base.rb
+++ b/qa/qa/resource/base.rb
@@ -45,7 +45,7 @@ module QA
resource = options.fetch(:resource) { new }
parents = options.fetch(:parents) { [] }
- do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ do_fabricate!(resource: resource, prepare_block: prepare_block) do
log_and_record_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
current_url
@@ -61,7 +61,7 @@ module QA
resource.eager_load_api_client!
- do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ do_fabricate!(resource: resource, prepare_block: prepare_block) do
log_and_record_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
end
end
@@ -73,14 +73,14 @@ module QA
resource.eager_load_api_client!
- do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ do_fabricate!(resource: resource, prepare_block: prepare_block) do
log_and_record_fabrication(:api, resource, parents, args) { resource.remove_via_api! }
end
end
private
- def do_fabricate!(resource:, prepare_block:, parents: [])
+ def do_fabricate!(resource:, prepare_block:)
prepare_block.call(resource) if prepare_block
resource_web_url = yield
@@ -89,17 +89,12 @@ module QA
resource
end
- def log_and_record_fabrication(fabrication_method, resource, parents, args)
+ def log_and_record_fabrication(fabrication_method, resource, parents, _args)
start = Time.now
Support::FabricationTracker.start_fabrication
result = yield.tap do
fabrication_time = Time.now - start
- fabrication_http_method = if resource.api_fabrication_http_method == :get || resource.retrieved_from_cache
- "Retrieved"
- else
- "Built"
- end
Support::FabricationTracker.save_fabrication(:"#{fabrication_method}_fabrication", fabrication_time)
@@ -114,7 +109,7 @@ module QA
Runtime::Logger.info do
msg = ["==#{'=' * parents.size}>"]
- msg << "#{fabrication_http_method} a #{Rainbow(name).black.bg(:white)}"
+ msg << "#{fabrication_type(resource, fabrication_method)} a #{Rainbow(name).black.bg(:white)}"
msg << resource.identifier
msg << "as a dependency of #{parents.last}" if parents.any?
msg << "via #{resource.retrieved_from_cache ? 'cache' : fabrication_method}"
@@ -129,6 +124,19 @@ module QA
result
end
+ # Fetch type of fabrication, either resource was built or fetched
+ #
+ # @param [Resource] resource
+ # @param [Symbol] method
+ # @return [String]
+ def fabrication_type(resource, method)
+ return "Built" if method == :browser_ui || [:post, :put].include?(resource.api_fabrication_http_method)
+ return "Retrieved" if resource.api_fabrication_http_method == :get || resource.retrieved_from_cache
+
+ Runtime::Logger.warn("Resource fabrication http method has not been set properly, assuming :get value!")
+ "Built"
+ end
+
# Define custom attribute
#
# @param [Symbol] name
@@ -215,8 +223,7 @@ module QA
def diff(other)
return if self == other
- diff_values = self.comparable.to_a - other.comparable.to_a
- diff_values.to_h
+ (comparable.to_a - other.comparable.to_a).to_h
end
def identifier
@@ -271,7 +278,7 @@ module QA
def all_attributes
@all_attributes ||= self.class.ancestors
.select { |clazz| clazz <= QA::Resource::Base }
- .map { |clazz| clazz.instance_variable_get(:@attribute_names) }
+ .map { |clazz| clazz.instance_variable_get(:@attribute_names) } # rubocop:disable Performance/FlatMap
.flatten
.compact
end
diff --git a/qa/qa/resource/ci_cd_settings.rb b/qa/qa/resource/ci_cd_settings.rb
new file mode 100644
index 00000000000..8240321137b
--- /dev/null
+++ b/qa/qa/resource/ci_cd_settings.rb
@@ -0,0 +1,47 @@
+# rubocop:todo Naming/FileName
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class CICDSettings < QA::Resource::Base
+ attributes :project_path,
+ :inbound_job_token_scope_enabled
+
+ attribute :mutation_id do
+ SecureRandom.hex(6)
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ '/graphql'
+ end
+
+ alias_method :api_post_path, :api_get_path
+
+ def api_post_body
+ <<~GQL
+ mutation {
+ projectCiCdSettingsUpdate(input: {
+ clientMutationId: "#{mutation_id}"
+ inboundJobTokenScopeEnabled: #{inbound_job_token_scope_enabled}
+ fullPath: "#{project_path}"
+ })
+ {
+ ciCdSettings {
+ inboundJobTokenScopeEnabled
+ }
+ errors
+ }
+ }
+ GQL
+ end
+ end
+ end
+end
+
+# rubocop:enable Naming/FileName
diff --git a/qa/qa/resource/ci_variable.rb b/qa/qa/resource/ci_variable.rb
index b632446623d..4123b8fe62b 100644
--- a/qa/qa/resource/ci_variable.rb
+++ b/qa/qa/resource/ci_variable.rb
@@ -18,19 +18,6 @@ module QA
@variable_type = 'env_var'
end
- def fabricate!
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_ci_cd_settings)
-
- Page::Project::Settings::CiCd.perform do |setting|
- setting.expand_ci_variables do |page|
- page.click_add_variable
- page.fill_variable(key, value, masked)
- end
- end
- end
-
def fabricate_via_api!
resource_web_url(api_get)
rescue ResourceNotFoundError
diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb
index 410edd417c1..c1bd921c3cf 100644
--- a/qa/qa/resource/events/project.rb
+++ b/qa/qa/resource/events/project.rb
@@ -7,32 +7,32 @@ module QA
include Events::Base
def push_events(commit_message)
- QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait for and fetch push events"])
+ QA::Runtime::Logger.info(%Q[#{self.class.name} - wait for and fetch push events"])
fetch_events do
events(action: 'pushed').select { |event| event.dig(:push_data, :commit_title) == commit_message }
end
end
def wait_for_merge(title)
- QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_merge with title "#{title}"])
+ QA::Runtime::Logger.info(%Q[#{self.class.name} - wait_for_merge with title "#{title}"])
wait_for_event do
events(action: 'accepted', target_type: 'merge_request').any? { |event| event[:target_title] == title }
end
end
def wait_for_push(commit_message)
- QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_push with commit message "#{commit_message}"])
+ QA::Runtime::Logger.info(%Q[#{self.class.name} - wait_for_push with commit message "#{commit_message}"])
wait_for_event do
events(action: 'pushed').any? { |event| event.dig(:push_data, :commit_title) == commit_message }
end
rescue EventNotFoundError
- QA::Runtime::Logger.debug("Push events: #{events(action: 'pushed')}")
+ QA::Runtime::Logger.info("Push events: #{events(action: 'pushed')}")
raise
end
def wait_for_push_new_branch(branch_name = self.default_branch)
- QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"])
+ QA::Runtime::Logger.info(%Q[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"])
wait_for_event do
events(action: 'pushed').any? { |event| event.dig(:push_data, :ref) == branch_name }
end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index f53bb531d9a..c88cf4aca10 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -57,6 +57,10 @@ module QA
sandbox.visit!
end
+ unless group_show.has_subgroup?(path)
+ raise ResourceFabricationFailedError, "Resource at #{path} could not be found under #{sandbox.path}"
+ end
+
group_show.click_subgroup(path)
@id = group_show.group_id
end
diff --git a/qa/qa/resource/instance_oauth_application.rb b/qa/qa/resource/instance_oauth_application.rb
new file mode 100644
index 00000000000..7aa3661717b
--- /dev/null
+++ b/qa/qa/resource/instance_oauth_application.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class InstanceOauthApplication < Base
+ attr_accessor :name, :redirect_uri, :scopes, :trusted
+
+ attributes :id, :application_id, :application_secret
+
+ def initialize
+ @name = "Instance OAuth Application #{SecureRandom.hex(8)}"
+ @redirect_uri = ''
+ @scopes = []
+ @trusted = true
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ '/applications'
+ end
+
+ def api_delete_path
+ "/applications/#{id}"
+ end
+
+ def fabricate!
+ Flow::Login.sign_in_as_admin
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_applications)
+ Page::Admin::Applications.perform do |app|
+ app.click_new_application_button
+ app.fill_name(name)
+ app.fill_redirect_uri(redirect_uri)
+ app.set_trusted_checkbox(trusted)
+ scopes.each { |scope| app.set_scope(scope) }
+ app.save_application
+ self.application_id = app.get_application_id
+ self.application_secret = app.get_secret_id
+ self.id = app.get_id_of_application
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/integrations/web_hook/smockerable.rb b/qa/qa/resource/integrations/web_hook/smockerable.rb
new file mode 100644
index 00000000000..f1d2022477e
--- /dev/null
+++ b/qa/qa/resource/integrations/web_hook/smockerable.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Integrations
+ module WebHook
+ module Smockerable
+ def teardown!
+ Service::DockerRun::Smocker.teardown!
+ end
+
+ def setup(mock = Vendor::Smocker::SmockerApi::DEFAULT_MOCK, session: nil, **event_args)
+ Service::DockerRun::Smocker.init(wait: 10) do |smocker|
+ smocker.register(mock, session: session)
+
+ webhook = fabricate_via_api! do |hook|
+ hook.url = smocker.url
+
+ event_args.each do |event, bool|
+ hook.send("#{event}_events=", bool)
+ end
+
+ hook
+ end
+
+ def smocker.events(session_id = nil)
+ history(session_id).map do |history_response|
+ history_response.request.fetch(:body, {})
+ end
+ end
+
+ yield(webhook, smocker)
+
+ smocker.reset
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index 15c2c25757f..fb957ccf285 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -30,7 +30,7 @@ module QA
def fabricate!
project.visit!
- Page::Project::Show.perform(&:go_to_new_issue)
+ Page::Project::Menu.perform(&:go_to_new_issue)
Page::Project::Issue::New.perform do |new_page|
new_page.fill_title(@title)
diff --git a/qa/qa/resource/members.rb b/qa/qa/resource/members.rb
index 7f31808d2ff..1aa49ef3d37 100644
--- a/qa/qa/resource/members.rb
+++ b/qa/qa/resource/members.rb
@@ -2,21 +2,32 @@
module QA
module Resource
- #
# Included in Resource::Project and Resource::Group to allow changes to
# project/group membership
- #
module Members
+ # Add single user to group or project
+ #
+ # @param [Resource::User] user
+ # @param [Integer] access_level
def add_member(user, access_level = AccessLevel::DEVELOPER)
Support::Retrier.retry_until do
QA::Runtime::Logger.info(%(Adding user #{user.username} to #{full_path} #{self.class.name}))
response = post Runtime::API::Request.new(api_client, api_members_path).url,
-{ user_id: user.id, access_level: access_level }
+ { user_id: user.id, access_level: access_level }
break true if response.code == QA::Support::API::HTTP_STATUS_CREATED
break true if response.body.include?('Member already exists')
end
end
+ # Add multiple users to group or project with default access level
+ #
+ # @param [Array<Resource::User>] users
+ def add_members(*users)
+ users.each do |user|
+ add_member(user)
+ end
+ end
+
def remove_member(user)
QA::Runtime::Logger.info(%(Removing user #{user.username} from #{full_path} #{self.class.name}))
@@ -40,7 +51,7 @@ module QA
QA::Runtime::Logger.info(%(Sharing #{self.class.name} with #{group.name}))
response = post Runtime::API::Request.new(api_client, api_share_path).url,
-{ group_id: group.id, group_access: access_level }
+ { group_id: group.id, group_access: access_level }
response.code == QA::Support::API::HTTP_STATUS_CREATED
end
end
diff --git a/qa/qa/resource/merge_request_from_fork.rb b/qa/qa/resource/merge_request_from_fork.rb
index 512f3eb7bfc..3e849aea862 100644
--- a/qa/qa/resource/merge_request_from_fork.rb
+++ b/qa/qa/resource/merge_request_from_fork.rb
@@ -23,13 +23,14 @@ module QA
fork.project.visit!
- mr_url = Flow::Login.while_signed_in(as: fork.user) do
- Page::Project::Show.perform(&:new_merge_request)
- Page::MergeRequest::New.perform(&:create_merge_request)
-
- current_url
- end
-
+ # Ensure we are signed in as fork user and create the MR
+ Flow::Login.sign_in_unless_signed_in(user: fork.user)
+ Page::Project::Show.perform(&:new_merge_request)
+ Page::MergeRequest::New.perform(&:create_merge_request)
+ Support::WaitForRequests.wait_for_requests
+ mr_url = current_url
+
+ # Sign back in as original user
Flow::Login.sign_in
visit(mr_url)
end
diff --git a/qa/qa/resource/pipeline.rb b/qa/qa/resource/pipeline.rb
index 7d5036c5cf4..e57784ca3b5 100644
--- a/qa/qa/resource/pipeline.rb
+++ b/qa/qa/resource/pipeline.rb
@@ -28,7 +28,7 @@ module QA
def fabricate!
project.visit!
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
Page::Project::Pipeline::Index.perform(&:click_run_pipeline_button)
Page::Project::Pipeline::New.perform(&:click_run_pipeline_button)
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 019617325e0..37ff2315329 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -123,12 +123,13 @@ module QA
resource_web_url(api_get)
rescue ResourceNotFoundError
response = super
+ return response unless template_name || import
# If a project is being imported, wait until it completes before we let the test continue.
# Otherwise we see Git repository errors
# See https://gitlab.com/gitlab-org/gitlab/-/issues/356101
- Support::Retrier.retry_until(max_duration: 60, sleep_interval: 5) do
- %w[none finished].include?(reload!.api_resource[:import_status])
+ Support::Retrier.retry_until(max_duration: 60, sleep_interval: 5, retry_on_exception: true) do
+ reload!.api_resource[:import_status] == "finished"
end
response
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
index 1e6b2ff620e..ed8074b1440 100644
--- a/qa/qa/resource/project_imported_from_github.rb
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -3,7 +3,7 @@
module QA
module Resource
class ProjectImportedFromGithub < Resource::Project
- attr_accessor :issue_events_import, :full_notes_import, :attachments_import
+ attr_accessor :issue_events_import, :full_notes_import, :attachments_import, :allow_partial_import
attribute :github_repo_id do
github_client.repository(github_repository_path).id
@@ -24,7 +24,7 @@ module QA
import_page.select_advanced_option(:attachments_import) if attachments_import
import_page.import!(github_repository_path, group.full_path, name)
- import_page.wait_for_success(github_repository_path, wait: 240)
+ import_page.wait_for_success(github_repository_path, wait: 240, allow_partial_import: allow_partial_import)
end
reload!
diff --git a/qa/qa/resource/project_web_hook.rb b/qa/qa/resource/project_web_hook.rb
index 86e662932e1..c8b6c2a6332 100644
--- a/qa/qa/resource/project_web_hook.rb
+++ b/qa/qa/resource/project_web_hook.rb
@@ -2,7 +2,17 @@
module QA
module Resource
- class ProjectWebHook < Base
+ class ProjectWebHook < WebHookBase
+ extend Integrations::WebHook::Smockerable
+
+ attributes :disabled_until, :alert_status
+
+ attribute :project do
+ Project.fabricate_via_api! do |resource|
+ resource.name = 'project-with-webhooks'
+ end
+ end
+
EVENT_TRIGGERS = %i[
issues
job
@@ -10,24 +20,13 @@ module QA
note
pipeline
push
+ releases
tag_push
wiki_page
confidential_issues
confidential_note
].freeze
- attr_accessor :url, :enable_ssl
-
- attribute :disabled_until
- attribute :id
- attribute :alert_status
-
- attribute :project do
- Project.fabricate_via_api! do |resource|
- resource.name = 'project-with-webhooks'
- end
- end
-
EVENT_TRIGGERS.each do |trigger|
attribute "#{trigger}_events".to_sym do
false
@@ -35,18 +34,13 @@ module QA
end
def initialize
- @id = nil
- @enable_ssl = false
- @alert_status = nil
- @url = nil
- end
+ super
- def fabricate_via_api!
- resource_web_url = super
-
- @id = api_response[:id]
+ @push_events_branch_filter = []
+ end
- resource_web_url
+ def add_push_event_branch_filter(branch)
+ @push_events_branch_filter << branch
end
def resource_web_url(resource)
@@ -65,7 +59,9 @@ module QA
body = {
id: project.id,
url: url,
- enable_ssl_verification: enable_ssl
+ enable_ssl_verification: enable_ssl_verification,
+ token: token,
+ push_events_branch_filter: @push_events_branch_filter.join(',')
}
EVENT_TRIGGERS.each_with_object(body) do |trigger, memo|
attr = "#{trigger}_events"
diff --git a/qa/qa/resource/runner_base.rb b/qa/qa/resource/runner_base.rb
index 399d1153dc2..1a977affec8 100644
--- a/qa/qa/resource/runner_base.rb
+++ b/qa/qa/resource/runner_base.rb
@@ -35,9 +35,9 @@ module QA
@config = nil
@run_untagged = nil
@name = "qa-runner-#{SecureRandom.hex(4)}"
- @image = 'registry.gitlab.com/gitlab-org/gitlab-runner:alpine-v15.8.3'
@executor = :shell
- @executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
+ @executor_image = "#{QA::Runtime::Env.container_registry_host}/
+ gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7"
end
# Initially we only support fabricate via API
@@ -50,11 +50,17 @@ module QA
#
def fabricate_via_api!
api_get
- rescue NoValueError
+ rescue NoValueError => e
+ Runtime::Logger.info("Runner api_get exception caught and handled: #{e}")
# Start container on initial fabrication and populate all attributes once id is known
# see: https://docs.gitlab.com/ee/api/runners.html#get-runners-details
start_container_and_register
- api_get
+ # Temporary workaround for https://gitlab.com/gitlab-org/gitlab/-/issues/409089
+ Support::Retrier.retry_on_exception(max_attempts: 6, sleep_interval: 10,
+ message: "Retrying GET for runners/:id"
+ ) do
+ api_get
+ end
end
def remove_via_api!
@@ -95,6 +101,8 @@ module QA
def start_container_and_register
@docker_container ||= Service::DockerRun::GitlabRunner.new(name).tap do |runner|
+ runner.image = image if image
+
Support::Retrier.retry_on_exception(sleep_interval: 5) do
runner.pull
end
@@ -102,7 +110,6 @@ module QA
runner.token = token
runner.address = Runtime::Scenario.gitlab_address
runner.tags = tags if tags
- runner.image = image
runner.config = config if config
runner.executor = executor
runner.executor_image = executor_image if executor == :docker
@@ -118,6 +125,7 @@ module QA
def populate_initial_id
tag_list = tags ? { tag_list: tags.compact.join(',') } : {}
runner = runner(**tag_list)
+ Runtime::Logger.debug("Details of the runner fetched using tag_list: #{runner}")
@id = runner[:id]
end
diff --git a/qa/qa/resource/snippet.rb b/qa/qa/resource/snippet.rb
index a79e8c7de6b..df9843bcfca 100644
--- a/qa/qa/resource/snippet.rb
+++ b/qa/qa/resource/snippet.rb
@@ -22,11 +22,7 @@ module QA
end
def fabricate!
- Page::Main::Menu.perform do |menu|
- menu.go_to_menu_dropdown_option(:snippets_link)
- end
-
- Page::Dashboard::Snippet::Index.perform(&:go_to_new_snippet_page)
+ Page::Main::Menu.perform(&:go_to_create_snippet)
Page::Dashboard::Snippet::New.perform do |new_page|
new_page.fill_title(@title)
diff --git a/qa/qa/resource/web_hook_base.rb b/qa/qa/resource/web_hook_base.rb
new file mode 100644
index 00000000000..d7469466212
--- /dev/null
+++ b/qa/qa/resource/web_hook_base.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class WebHookBase < Base
+ attributes :id, :url
+
+ attribute :token do
+ nil
+ end
+
+ attribute :enable_ssl_verification do
+ false
+ end
+
+ def fabricate_via_api!
+ resource_web_url = super
+
+ @id = api_response[:id]
+
+ resource_web_url
+ end
+
+ # @return [String] the api path to fetch the resource
+ def api_get_path
+ raise NotImplementedError, not_implemented_message(__callee__)
+ end
+
+ # @return [String] the api path to create the resource
+ def api_post_path
+ raise NotImplementedError, not_implemented_message(__callee__)
+ end
+
+ # @return [Hash] the payload needed to create the resource
+ def api_post_body
+ raise NotImplementedError, not_implemented_message(__callee__)
+ end
+
+ private
+
+ def not_implemented_message(callee)
+ "#{self.class} must implement ##{callee}"
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/allure_report.rb b/qa/qa/runtime/allure_report.rb
index a9152a5555c..e726f7a316f 100644
--- a/qa/qa/runtime/allure_report.rb
+++ b/qa/qa/runtime/allure_report.rb
@@ -25,11 +25,8 @@ module QA
#
# @return [void]
def configure_allure
- # Match job names like ee:relative, ce:update etc. and set as execution environment
- env_matcher = /^(?<env>\w{2}:\S+)/
-
AllureRspec.configure do |config|
- config.results_directory = 'tmp/allure-results'
+ config.results_directory = ENV['QA_ALLURE_RESULTS_DIRECTORY'] || 'tmp/allure-results'
config.clean_results_directory = true
# automatically attach links to testcases and issues
@@ -38,11 +35,11 @@ module QA
config.issue_tag = :issue
config.link_issue_pattern = '{}'
- config.environment_properties = environment_info if Env.running_in_ci?
-
- # Set custom environment name to separate same specs executed on different environments
- if Env.running_in_ci? && Env.ci_job_name.match?(env_matcher)
- config.environment = Env.ci_job_name.match(env_matcher).named_captures['env']
+ if Env.running_in_ci?
+ config.environment_properties = environment_info
+ # Set custom environment name to separate same specs executed in different jobs
+ # Drop number postfixes from parallel jobs by only matching non whitespace characters
+ config.environment = Env.ci_job_name.match(/^\S+/)[0]
end
end
end
@@ -77,7 +74,7 @@ module QA
config.add_formatter(QA::Support::Formatters::AllureMetadataFormatter)
config.add_formatter(AllureRspecFormatter)
- config.append_after do |example|
+ config.append_after do
Allure.add_attachment(
name: 'browser.log',
source: Capybara.current_session.driver.browser.logs.get(:browser).map(&:to_s).join("\n\n"),
@@ -92,7 +89,7 @@ module QA
#
# @return [Hash]
def environment_info
- lambda do
+ -> do
return {} unless Env.admin_personal_access_token || Env.personal_access_token
client = Env.admin_personal_access_token ? API::Client.as_admin : API::Client.new
diff --git a/qa/qa/runtime/application_settings.rb b/qa/qa/runtime/application_settings.rb
index 53ed6a9266b..4cbce0972b6 100644
--- a/qa/qa/runtime/application_settings.rb
+++ b/qa/qa/runtime/application_settings.rb
@@ -22,7 +22,8 @@ module QA
r = put(Runtime::API::Request.new(api_client, APPLICATION_SETTINGS_PATH).url, **application_settings)
return if r.code == QA::Support::API::HTTP_STATUS_OK
- raise "Couldn't set application settings #{application_settings.inspect}"
+ body = parse_body(r)
+ raise("Couldn't set application settings #{application_settings.inspect}, code: '#{r.code}', body: #{body}")
end
def get_application_settings(api_client: admin_api_client)
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index f01657c8deb..b67db792419 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -17,6 +17,9 @@ module QA
NotRespondingError = Class.new(RuntimeError)
CAPYBARA_MAX_WAIT_TIME = Env.max_capybara_wait_time
+ DEFAULT_WINDOW_SIZE = '1480,2200'
+ PHONE_VIDEO_SIZE = '500x900'
+ TABLET_VIDEO_SIZE = '800x1100'
def self.blank_page?
['', 'about:blank', 'data:,'].include?(Capybara.current_session.driver.browser.current_url)
@@ -96,11 +99,14 @@ module QA
capabilities['goog:chromeOptions'][:args] << 'disable-dev-shm-usage' if QA::Runtime::Env.disable_dev_shm?
# Set chrome default download path
-
- capabilities['goog:chromeOptions'][:prefs] = {
- 'download.default_directory' => File.expand_path(QA::Runtime::Env.chrome_default_download_path),
- 'download.prompt_for_download' => false
- }
+ # TODO: Set for remote grid as well once Sauce Labs tests are deprecated and Options.chrome is added
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112258
+ unless QA::Runtime::Env.remote_grid
+ capabilities['goog:chromeOptions'][:prefs] = {
+ 'download.default_directory' => File.expand_path(QA::Runtime::Env.chrome_default_download_path),
+ 'download.prompt_for_download' => false
+ }
+ end
# Specify the user-agent to allow challenges to be bypassed
# See https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11938
@@ -114,7 +120,7 @@ module QA
capabilities['appium:deviceName'] = QA::Runtime::Env.remote_mobile_device_name
capabilities['appium:platformVersion'] = 'latest'
else
- capabilities['goog:chromeOptions'][:args] << 'window-size=1480,2200'
+ capabilities['goog:chromeOptions'][:args] << "window-size=#{DEFAULT_WINDOW_SIZE}"
end
# Slack tries to open an external URL handler
@@ -159,6 +165,9 @@ module QA
when :firefox
capabilities['acceptInsecureCerts'] = true if QA::Runtime::Env.accept_insecure_certs?
+
+ when :edge
+ capabilities['ms:edgeOptions'] = { args: ["--window-size=#{DEFAULT_WINDOW_SIZE}"] }
end
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
@@ -172,11 +181,23 @@ module QA
}
if QA::Runtime::Env.remote_grid
+ selenium_options[:browser] = :remote
selenium_options[:url] = QA::Runtime::Env.remote_grid
- capabilities[:browserVersion] = 'latest'
+ capabilities[:browserVersion] = QA::Runtime::Env.browser_version
+ end
+
+ if QA::Runtime::Env.remote_tunnel_id
capabilities['sauce:options'] = { tunnelIdentifier: QA::Runtime::Env.remote_tunnel_id }
end
+ if QA::Runtime::Env.record_video?
+ capabilities['selenoid:options'] = {
+ enableVideo: true,
+ videoScreenSize: video_screen_size,
+ videoName: "#{QA::Runtime::Env.browser}-#{QA::Runtime::Env.browser_version}-#{Time.now}.mp4"
+ }
+ end
+
Capybara::Selenium::Driver.new(
app,
**selenium_options
@@ -232,6 +253,16 @@ module QA
::File.expand_path('../../tmp/qa-profile', __dir__)
end
+ def self.video_screen_size
+ if QA::Runtime::Env.phone_layout?
+ PHONE_VIDEO_SIZE
+ elsif QA::Runtime::Env.tablet_layout?
+ TABLET_VIDEO_SIZE
+ else
+ ''
+ end
+ end
+
class Session
include Capybara::DSL
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index b53c2320537..cde36ba80c4 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -58,6 +58,22 @@ module QA
browser == :chrome && interception_enabled?
end
+ def release
+ ENV['RELEASE']
+ end
+
+ def release_registry_url
+ ENV['RELEASE_REGISTRY_URL']
+ end
+
+ def release_registry_username
+ ENV['RELEASE_REGISTRY_USERNAME']
+ end
+
+ def release_registry_password
+ ENV['RELEASE_REGISTRY_PASSWORD']
+ end
+
def ci_job_url
ENV['CI_JOB_URL']
end
@@ -187,14 +203,38 @@ module QA
ENV['QA_BROWSER'].nil? ? :chrome : ENV['QA_BROWSER'].to_sym
end
+ def browser_version
+ ENV['QA_BROWSER_VERSION'] || 'latest'
+ end
+
def remote_mobile_device_name
- ENV['QA_REMOTE_MOBILE_DEVICE_NAME']
+ ENV['QA_REMOTE_MOBILE_DEVICE_NAME']&.downcase
+ end
+
+ def layout
+ ENV['QA_LAYOUT']&.downcase || ''
+ end
+
+ def tablet_layout?
+ return true if remote_mobile_device_name && !phone_layout?
+
+ layout.include?('tablet')
+ end
+
+ def phone_layout?
+ return true if layout.include?('phone')
+
+ return false unless remote_mobile_device_name
+
+ !(remote_mobile_device_name.include?('ipad') || remote_mobile_device_name.include?('tablet'))
end
def mobile_layout?
- return false if ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].blank?
+ phone_layout? || tablet_layout? || remote_mobile_device_name
+ end
- !(ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].downcase.include?('ipad') || ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].downcase.include?('tablet'))
+ def record_video?
+ enabled?(ENV['QA_RECORD_VIDEO'], default: false)
end
def user_username
@@ -210,11 +250,11 @@ module QA
end
def github_username
- ENV['GITHUB_USERNAME']
+ ENV['QA_GITHUB_USERNAME']
end
def github_password
- ENV['GITHUB_PASSWORD']
+ ENV['QA_GITHUB_PASSWORD']
end
def forker?
@@ -282,11 +322,11 @@ module QA
end
def jira_admin_username
- ENV['JIRA_ADMIN_USERNAME']
+ ENV['QA_JIRA_ADMIN_USERNAME']
end
def jira_admin_password
- ENV['JIRA_ADMIN_PASSWORD']
+ ENV['QA_JIRA_ADMIN_PASSWORD']
end
def jira_hostname
@@ -376,13 +416,13 @@ module QA
# Specifies the token that can be used for the GitHub API
def github_access_token
- ENV['GITHUB_ACCESS_TOKEN'].to_s.strip
+ ENV['QA_GITHUB_ACCESS_TOKEN'].to_s.strip
end
def require_github_access_token!
return unless github_access_token.empty?
- raise ArgumentError, "Please provide GITHUB_ACCESS_TOKEN"
+ raise ArgumentError, "Please provide QA_GITHUB_ACCESS_TOKEN"
end
def require_admin_access_token!
@@ -463,6 +503,16 @@ module QA
enabled?(ENV['QA_SAVE_TEST_METRICS'], default: false)
end
+ def ee_license
+ return ENV["QA_EE_LICENSE"] if ENV["QA_EE_LICENSE"]
+
+ ENV["EE_LICENSE"].tap do |license|
+ next unless license
+
+ Runtime::Logger.warn("EE_LICENSE environment variable is deprecated, please use QA_EE_LICENSE instead!")
+ end
+ end
+
def ee_activation_code
ENV['QA_EE_ACTIVATION_CODE']
end
@@ -479,6 +529,10 @@ module QA
enabled?(ENV['QA_SKIP_SMOKE_RELIABLE'], default: false)
end
+ def container_registry_host
+ ENV.fetch('QA_CONTAINER_REGISTRY_HOST', 'registry.gitlab.com')
+ end
+
# ENV variables for authenticating against a private container registry
# These need to be set if using the
# Service::DockerRun::Mixins::ThirdPartyDocker module
@@ -514,6 +568,10 @@ module QA
ENV['DEFAULT_CHROME_DOWNLOAD_PATH'] || Dir.tmpdir
end
+ def super_sidebar_enabled?
+ enabled?(ENV['QA_SUPER_SIDEBAR_ENABLED'], default: false)
+ end
+
def require_slack_env!
missing_env = %i[slack_workspace slack_email slack_password].select do |method|
::QA::Runtime::Env.public_send(method).nil?
@@ -523,6 +581,22 @@ module QA
raise "Missing Slack env: #{missing_env.map(&:upcase).join(', ')}"
end
+ def one_p_email
+ ENV['QA_1P_EMAIL']
+ end
+
+ def one_p_password
+ ENV['QA_1P_PASSWORD']
+ end
+
+ def one_p_secret
+ ENV['QA_1P_SECRET']
+ end
+
+ def one_p_github_uuid
+ ENV['QA_1P_GITHUB_UUID']
+ end
+
private
def remote_grid_credentials
diff --git a/qa/qa/service/cluster_provider/gcloud.rb b/qa/qa/service/cluster_provider/gcloud.rb
index 749ebca8897..d33ae4915b5 100644
--- a/qa/qa/service/cluster_provider/gcloud.rb
+++ b/qa/qa/service/cluster_provider/gcloud.rb
@@ -33,8 +33,7 @@ module QA
delete_cluster
end
- # kas is hardcoded to staging since this test should only run in staging for now
- def install_kubernetes_agent(agent_token)
+ def install_kubernetes_agent(agent_token:, kas_address:)
install_helm
shell <<~CMD.tr("\n", ' ')
@@ -45,7 +44,8 @@ module QA
--create-namespace
--set image.tag=#{Runtime::Env.gitlab_agentk_version}
--set config.token=#{agent_token}
- --set config.kasAddress=wss://kas.staging.gitlab.com
+ --set config.kasAddress=#{kas_address}
+ --set config.kasHeaders="{Cookie: gitlab_canary=#{target_canary?}}"
CMD
end
@@ -59,6 +59,10 @@ module QA
CMD
end
+ def target_canary?
+ Runtime::Env.qa_cookies.to_s.include?("gitlab_canary=true")
+ end
+
def login_if_not_already_logged_in
if Runtime::Env.has_gcloud_credentials?
attempt_login_with_env_vars
diff --git a/qa/qa/service/docker_run/base.rb b/qa/qa/service/docker_run/base.rb
index bf85b640586..ce558849abd 100644
--- a/qa/qa/service/docker_run/base.rb
+++ b/qa/qa/service/docker_run/base.rb
@@ -85,6 +85,10 @@ module QA
shell "docker restart #{@name}"
end
+
+ def health
+ shell("docker inspect --format='{{json .State.Health.Status}}' #{@name}").delete('"')
+ end
end
end
end
diff --git a/qa/qa/service/docker_run/gitlab.rb b/qa/qa/service/docker_run/gitlab.rb
new file mode 100644
index 00000000000..ce8ab17f2b5
--- /dev/null
+++ b/qa/qa/service/docker_run/gitlab.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module QA
+ module Service
+ module DockerRun
+ class Gitlab < Base
+ def initialize(name:, omnibus_config: '', image: '')
+ @image = image
+ @name = name
+ @omnibus_configuration = omnibus_config
+ super()
+ end
+
+ def login
+ return unless release_variables_available?
+
+ super(Runtime::Env.release_registry_url,
+ user: Runtime::Env.release_registry_username,
+ password: Runtime::Env.release_registry_password)
+ end
+
+ def register!
+ shell <<~CMD.tr("\n", ' ')
+ docker run -d --rm
+ --network #{network}
+ --hostname #{host_name}
+ --publish 80:80
+ #{RUBY_PLATFORM.include?('arm64') ? '--platform linux/amd64' : ''}
+ --env GITLAB_OMNIBUS_CONFIG="#{@omnibus_configuration}"
+ --name #{@name}
+ #{@image}
+ CMD
+ end
+
+ private
+
+ def release_variables_available?
+ Runtime::Env.release_registry_url &&
+ Runtime::Env.release_registry_username &&
+ Runtime::Env.release_registry_password
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/service/docker_run/gitlab_runner.rb b/qa/qa/service/docker_run/gitlab_runner.rb
index a8fcf8f9332..078a3048cad 100644
--- a/qa/qa/service/docker_run/gitlab_runner.rb
+++ b/qa/qa/service/docker_run/gitlab_runner.rb
@@ -16,11 +16,12 @@ module QA
MSG
def initialize(name)
- @image = 'gitlab/gitlab-runner:alpine-v15.8.3'
+ @image = "#{QA::Runtime::Env.container_registry_host}/gitlab-org/gitlab-runner:alpine"
@name = name || "qa-runner-#{SecureRandom.hex(4)}"
@run_untagged = true
@executor = :shell
- @executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
+ @executor_image = "#{QA::Runtime::Env.container_registry_host}/
+ gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7"
super()
end
@@ -104,7 +105,15 @@ module QA
# Ping Cloudflare DNS, should fail
# Ping Registry, should fail to resolve
def prove_airgap
- gitlab_ip = Resolv.getaddress 'registry.gitlab.com'
+ begin
+ gitlab_ip = Resolv.getaddress 'registry.gitlab.com'
+ rescue Resolv::ResolvError => e
+ Runtime::Logger.debug("prove_airgap unable to get ip address for endpoint - #{e.message}")
+ # If Resolv.getaddress fails, it implies we cannot access the URL in question
+ # This may occur in offline-environment/airgapped testing
+ return 'true'
+ end
+
<<~CMD
echo "Checking airgapped connectivity..."
nc -zv -w 10 #{gitlab_ip} 80 && (echo "Airgapped network faulty. Connectivity netcat check failed." && exit 1) || (echo "Connectivity netcat check passed." && exit 0)
diff --git a/qa/qa/service/docker_run/k3s.rb b/qa/qa/service/docker_run/k3s.rb
index a09b62cb613..f2463c39639 100644
--- a/qa/qa/service/docker_run/k3s.rb
+++ b/qa/qa/service/docker_run/k3s.rb
@@ -7,7 +7,8 @@ module QA
attr_accessor :cni_enabled
def initialize
- @image = 'registry.gitlab.com/gitlab-org/cluster-integration/test-utils/k3s-gitlab-ci/releases/v0.9.1'
+ @image = "#{QA::Runtime::Env.container_registry_host}/
+ gitlab-org/cluster-integration/test-utils/k3s-gitlab-ci/releases/v0.9.1"
@name = 'k3s'
@cni_enabled = false
super
diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb
index 5362124bee5..ed57d825643 100644
--- a/qa/qa/service/kubernetes_cluster.rb
+++ b/qa/qa/service/kubernetes_cluster.rb
@@ -5,6 +5,7 @@ require 'mkmf'
module QA
module Service
class KubernetesCluster
+ include Support::API
include Service::Shellout
attr_reader :api_url, :ca_certificate, :token, :rbac, :provider
@@ -36,7 +37,7 @@ module QA
end
def install_kubernetes_agent(agent_token)
- @provider.install_kubernetes_agent(agent_token)
+ @provider.install_kubernetes_agent(agent_token: agent_token, kas_address: fetch_kas_address)
end
def create_secret(secret, secret_name)
@@ -73,6 +74,17 @@ module QA
`kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'`
end
+ def fetch_kas_address
+ api_client = Runtime::API::Client.new(:gitlab)
+
+ Support::Retrier.retry_until do
+ response = get(Runtime::API::Request.new(api_client, '/metadata').url)
+ body = parse_body(response)
+
+ body.dig(:kas, :externalUrl) || raise("Failed to fetch KAS address from #{body}")
+ end
+ end
+
def fetch_credentials
return global_credentials unless rbac
diff --git a/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
index e0db758dde3..fc400fbb9c7 100644
--- a/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/group_access_token_spec.rb
@@ -26,6 +26,9 @@ module QA
file.name = "text-#{SecureRandom.hex(8)}.txt"
file.content = 'New file'
end
+ rescue StandardError => e
+ QA::Runtime::Logger.error("Full failure message: #{e.message}")
+ raise
end.not_to raise_error
end
@@ -42,6 +45,9 @@ module QA
commit.commit_message = 'Add new file'
commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
+ rescue StandardError => e
+ QA::Runtime::Logger.error("Full failure message: #{e.message}")
+ raise
end.not_to raise_error
end
end
diff --git a/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
index 9017aba8e4a..c13ddb2b746 100644
--- a/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import/import_github_repo_spec.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
module QA
- # https://github.com/gitlab-qa-github/import-test <- project under test
- #
- RSpec.describe 'Manage', product_group: :import, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391228',
- type: :waiting_on
- } do
+ RSpec.describe 'Manage', product_group: :import_and_integrate do
describe 'GitHub import' do
include_context 'with github import'
+ before do
+ QA::Support::Helpers::ImportSource.enable('github')
+ end
+
context 'when imported via api' do
it 'imports project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347670' do
expect_project_import_finished_successfully
diff --git a/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb
index 64ab8d8fc43..b81cb70eb18 100644
--- a/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb
@@ -7,7 +7,7 @@ require "etc"
# rubocop:disable Rails/Pluck
module QA
RSpec.describe 'Manage', :github, requires_admin: 'creates users', only: { job: 'large-github-import' } do
- describe 'Project import', product_group: :import do # rubocop:disable RSpec/MultipleMemoizedHelpers
+ describe 'Project import', product_group: :import_and_integrate do # rubocop:disable RSpec/MultipleMemoizedHelpers
let(:github_repo) { ENV['QA_LARGE_IMPORT_REPO'] || 'rspec/rspec-core' }
let(:import_max_duration) { ENV['QA_LARGE_IMPORT_DURATION']&.to_i || 7200 }
let(:logger) { Runtime::Logger.logger }
diff --git a/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb b/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
index 8439b881ed7..53c81b0e187 100644
--- a/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb
@@ -2,78 +2,57 @@
module QA
RSpec.describe 'Manage' do
- describe 'WebHooks integration', :requires_admin, :integrations, :orchestrated, product_group: :integrations do
+ describe(
+ 'WebHooks integration',
+ :requires_admin,
+ :integrations,
+ :orchestrated,
+ product_group: :import_and_integrate
+ ) do
before(:context) do
toggle_local_requests(true)
end
after(:context) do
- Service::DockerRun::Smocker.teardown!
+ Resource::ProjectWebHook.teardown!
end
let(:session) { SecureRandom.hex(5) }
let(:tag_name) { SecureRandom.hex(5) }
it 'sends a push event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348945' do
- setup_webhook(push: true) do |webhook, smocker|
+ Resource::ProjectWebHook.setup(session: session, push: true) do |webhook, smocker|
Resource::Repository::ProjectPush.fabricate! do |project_push|
project_push.project = webhook.project
end
- wait_until do
- !smocker.history(session).empty?
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].push?).to be(true), "Not push event: \n#{events[0].raw}"
- end
+ expect_web_hook_single_event_success(webhook, smocker, type: 'push')
end
end
it 'sends a merge request event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349720' do
- setup_webhook(merge_requests: true) do |webhook, smocker|
+ Resource::ProjectWebHook.setup(session: session, merge_requests: true) do |webhook, smocker|
Resource::MergeRequest.fabricate_via_api! do |merge_request|
merge_request.project = webhook.project
end
- wait_until do
- !smocker.history(session).empty?
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].mr?).to be(true), "Not MR event: \n#{events[0].raw}"
- end
+ expect_web_hook_single_event_success(webhook, smocker, type: 'merge_request')
end
end
it 'sends a wiki page event', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349722' do
- setup_webhook(wiki_page: true) do |webhook, smocker|
+ Resource::ProjectWebHook.setup(session: session, wiki_page: true) do |webhook, smocker|
Resource::Wiki::ProjectPage.fabricate_via_api! do |page|
page.project = webhook.project
end
- wait_until do
- !smocker.history(session).empty?
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].wiki?).to be(true), "Not wiki event: \n#{events[0].raw}"
- end
+ expect_web_hook_single_event_success(webhook, smocker, type: 'wiki_page')
end
end
it 'sends an issues and note event',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
- setup_webhook(issues: true, note: true) do |webhook, smocker|
+ Resource::ProjectWebHook.setup(session: session, issues: true, note: true) do |webhook, smocker|
issue = Resource::Issue.fabricate_via_api! do |issue_init|
issue_init.project = webhook.project
end
@@ -83,25 +62,24 @@ module QA
note.issue = issue
end
- wait_until do
- smocker.history(session).size > 1
- end
+ expect { smocker.events(session).size }.to eventually_eq(2)
+ .within(max_duration: 30, sleep_interval: 2),
+ -> { "Should have 2 events, got: #{smocker.stringified_history(session)}" }
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- issue_event = events.find(&:issue?)
- note_event = events.find(&:note?)
+ events = smocker.events(session)
- expect(events.size).to be(2), "Should have 2 events: \n#{events.map(&:raw).join("\n")}"
- expect(issue_event).not_to be(nil), "Not issue event: \n#{events[0].raw}"
- expect(note_event).not_to be(nil), "Not note event: \n#{events[1].raw}"
+ aggregate_failures do
+ expect(events).to include(
+ a_hash_including(object_kind: 'note'),
+ a_hash_including(object_kind: 'issue')
+ )
end
end
end
it 'sends a tag event',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/383577' do
- setup_webhook(tag_push: true) do |webhook, smocker|
+ Resource::ProjectWebHook.setup(session: session, tag_push: true) do |webhook, smocker|
project_push = Resource::Repository::ProjectPush.fabricate! do |project_push|
project_push.project = webhook.project
end
@@ -112,16 +90,7 @@ module QA
tag.name = tag_name
end
- wait_until do
- smocker.history(session).size == 1
- end
-
- events = smocker.history(session).map(&:as_hook_event)
- aggregate_failures do
- expect(events.size).to be(1), "Should have 1 event: \n#{events.map(&:raw).join("\n")}"
- expect(events[0].project_name).to eql(webhook.project.name)
- expect(events[0].tag?).to be(true), "Not tag event: \n#{events[0].raw}"
- end
+ expect_web_hook_single_event_success(webhook, smocker, type: 'tag_push')
end
end
@@ -143,17 +112,23 @@ module QA
let(:disabled_after) { 4 }
it 'hook is auto-disabled',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/389595' do
- setup_webhook(fail_mock, issues: true) do |webhook, smocker|
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/389595', quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/393274',
+ type: :investigating
+ } do
+ Resource::ProjectWebHook.setup(fail_mock, session: session, issues: true) do |webhook, smocker|
hook_trigger_times.times do
Resource::Issue.fabricate_via_api! do |issue_init|
issue_init.project = webhook.project
end
+
+ # using sleep to give rate limiter a chance to activate.
+ sleep 0.5
end
- expect { smocker.history(session).size }.to eventually_eq(disabled_after)
+ expect { smocker.events(session).size }.to eventually_eq(disabled_after)
.within(max_duration: 30, sleep_interval: 2),
- -> { "Should have #{disabled_after} events, got: #{smocker.history(session).size}" }
+ -> { "Should have #{disabled_after} events, got: #{smocker.events(session).size}" }
webhook.reload!
@@ -161,34 +136,27 @@ module QA
end
end
end
+ end
- private
-
- def setup_webhook(mock = Vendor::Smocker::SmockerApi::DEFAULT_MOCK, **event_args)
- Service::DockerRun::Smocker.init(wait: 10) do |smocker|
- smocker.register(mock, session: session)
-
- webhook = Resource::ProjectWebHook.fabricate_via_api! do |hook|
- hook.url = smocker.url
-
- event_args.each do |event, bool|
- hook.send("#{event}_events=", bool)
- end
- end
+ private
- yield(webhook, smocker)
+ def expect_web_hook_single_event_success(webhook, smocker, type:)
+ expect { smocker.events(session).size }.to eventually_eq(1)
+ .within(max_duration: 30, sleep_interval: 2),
+ -> { "Should have 1 events, got: #{smocker.stringified_history(session)}" }
- smocker.reset
- end
- end
+ event = smocker.events(session).first
- def toggle_local_requests(on)
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
+ aggregate_failures do
+ expect(event).to match(a_hash_including(
+ object_kind: type,
+ project: a_hash_including(name: webhook.project.name)
+ ))
end
+ end
- def wait_until(timeout = 120, &block)
- Support::Waiter.wait_until(max_duration: timeout, reload_page: false, raise_on_failure: false, &block)
- end
+ def toggle_local_requests(on)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
index 1f0c37df101..ac85795b2bb 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe "Manage", :reliable, product_group: :import do
+ RSpec.describe "Manage", :reliable, product_group: :import_and_integrate do
include_context "with gitlab group migration"
describe "Gitlab migration" do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
index 2dcbbadb4aa..bff1837f51b 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration', product_group: :import do
+ describe 'Gitlab migration', product_group: :import_and_integrate do
include_context 'with gitlab project migration'
let!(:source_issue) do
@@ -15,7 +15,7 @@ module QA
let(:source_issue_comments) do
source_issue.comments.map do |note|
- { **note.except(:id, :noteable_id), author: note[:author].except(:web_url) }
+ { **note.except(:id, :noteable_id, :project_id), author: note[:author].except(:web_url) }
end
end
@@ -32,7 +32,7 @@ module QA
let(:imported_issue_comments) do
imported_issue.comments.map do |note|
- { **note.except(:id, :noteable_id), author: note[:author].except(:web_url) }
+ { **note.except(:id, :noteable_id, :project_id), author: note[:author].except(:web_url) }
end
end
@@ -67,11 +67,7 @@ module QA
it(
'preserves related merge request',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386305',
- quarantine: {
- type: :bug,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/386308'
- }
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386305'
) do
expect_project_import_finished_successfully
expect(imported_related_mrs).to eq([source_mr.iid])
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
index 9ce028318c3..ac8399b391d 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
@@ -5,7 +5,7 @@
# rubocop:disable Rails/Pluck, Layout/LineLength, RSpec/MultipleMemoizedHelpers
module QA
RSpec.describe "Manage", :skip_live_env, only: { job: "large-gitlab-import" } do
- describe "Gitlab migration", orchestrated: false, product_group: :import do
+ describe "Gitlab migration", orchestrated: false, product_group: :import_and_integrate do
include_context "with gitlab group migration"
let!(:logger) { Runtime::Logger.logger }
@@ -65,10 +65,6 @@ module QA
let(:mrs) { fetch_mrs(imported_project, api_client) }
let(:issues) { fetch_issues(imported_project, api_client) }
- before do
- Runtime::Feature.enable(:bulk_import_projects) unless Runtime::Feature.enabled?(:bulk_import_projects)
- end
-
# rubocop:disable RSpec/InstanceVariable
after do |example|
next unless defined?(@import_time)
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
index 42793406e6c..ed79281b328 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_members_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration', product_group: :import do
+ describe 'Gitlab migration', product_group: :import_and_integrate do
include_context 'with gitlab project migration'
let!(:source_member) do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
index 127db36052f..7d785630a57 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration', product_group: :import do
+ describe 'Gitlab migration', product_group: :import_and_integrate do
include_context 'with gitlab project migration'
let!(:source_project_with_readme) { true }
@@ -37,7 +37,7 @@ module QA
let!(:source_mr_approvers) { [source_admin_user.email] }
let(:source_mr_comments) do
source_mr.comments.map do |note|
- { **note.except(:id, :noteable_id), author: note[:author].except(:web_url) }
+ { **note.except(:id, :noteable_id, :project_id), author: note[:author].except(:web_url) }
end
end
@@ -52,11 +52,11 @@ module QA
let(:imported_mr_comments) do
imported_mr.comments.map do |note|
- { **note.except(:id, :noteable_id), author: note[:author].except(:web_url) }
+ { **note.except(:id, :noteable_id, :project_id), author: note[:author].except(:web_url) }
end
end
- let(:imported_mr_reviewers) { imported_mr.reviewers.map { |reviewer| reviewer[:username] } }
+ let(:imported_mr_reviewers) { imported_mr.reviewers.pluck(:username) }
let(:imported_mr_approvers) do
imported_mr.approval_configuration[:approved_by].map { |usr| usr.dig(:user, :username) }
end
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
index 8d631808d17..2f80f4c07ed 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration', product_group: :import do
+ describe 'Gitlab migration', product_group: :import_and_integrate do
include_context 'with gitlab project migration'
context 'with ci pipeline' do
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
index 60ece89844d..b74ac89917f 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration', product_group: :import do
+ describe 'Gitlab migration', product_group: :import_and_integrate do
include_context 'with gitlab project migration'
# this spec is used as a sanity test for gitlab migration because it can run outside of orchestrated setup
@@ -11,14 +11,14 @@ module QA
let!(:source_gitlab_address) { Runtime::Scenario.gitlab_address }
let!(:source_admin_api_client) { admin_api_client }
+ # do not use top level group (sandbox) to avoid issues when applying permissions etc. because it will contain
+ # a lot subgroups and projects on live envs
let!(:source_sandbox) do
- Resource::Sandbox.fabricate_via_api! do |group|
+ Resource::Group.fabricate_via_api! do |group|
group.api_client = admin_api_client
end
end
- let!(:target_sandbox) { source_sandbox }
-
let!(:source_group) do
Resource::Group.fabricate_via_api! do |group|
group.api_client = admin_api_client
@@ -28,6 +28,8 @@ module QA
end
end
+ let!(:target_sandbox) { source_sandbox }
+
let(:destination_group_path) { "target-group-for-import-#{SecureRandom.hex(4)}" }
let(:cleanup!) { user.remove_via_api! }
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
index b3510cef3e9..2443887c3d4 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage' do
- describe 'Gitlab migration', product_group: :import do
+ describe 'Gitlab migration', product_group: :import_and_integrate do
include_context 'with gitlab project migration'
context 'with release' do
diff --git a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
index d693bbd43ff..eeeb78e17d7 100644
--- a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
@@ -24,6 +24,9 @@ module QA
file.name = "text-#{SecureRandom.hex(8)}.txt"
file.content = 'New file'
end
+ rescue StandardError => e
+ QA::Runtime::Logger.error("Full failure message: #{e.message}")
+ raise
end.not_to raise_error
end
@@ -37,6 +40,9 @@ module QA
commit.commit_message = 'Add new file'
commit.add_files([{ file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }])
end
+ rescue StandardError => e
+ QA::Runtime::Logger.error("Full failure message: #{e.message}")
+ raise
end.not_to raise_error
end
end
diff --git a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
index 24088057abc..86fc154c1cf 100644
--- a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do
- describe 'rate limits', :reliable, product_group: :integrations do
+ describe 'rate limits', :reliable, product_group: :import_and_integrate do
let(:rate_limited_user) { Resource::User.fabricate_via_api! }
let(:api_client) { Runtime::API::Client.new(:gitlab, user: rate_limited_user) }
let!(:request) { Runtime::API::Request.new(api_client, '/users') }
diff --git a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
index b7d0d72297a..8759c36f43f 100644
--- a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
@@ -2,7 +2,8 @@
module QA
RSpec.describe 'Manage' do
- describe 'User', :requires_admin, :reliable, product_group: :authentication_and_authorization do
+ # TODO: `:reliable` should be added back once https://gitlab.com/gitlab-org/gitlab/-/issues/359278 is resolved
+ describe 'User', :requires_admin, product_group: :authentication_and_authorization do
before(:all) do
admin_api_client = Runtime::API::Client.as_admin
@@ -12,14 +13,20 @@ module QA
@user_api_client = Runtime::API::Client.new(:gitlab, user: @user)
- @group = QA::Resource::Group.fabricate_via_api! do |group|
+ @sandbox = Resource::Sandbox.fabricate! do |sandbox_group|
+ sandbox_group.path = "sandbox-for-access-termination-#{SecureRandom.hex(4)}"
+ sandbox_group.api_client = admin_api_client
+ end
+
+ group = QA::Resource::Group.fabricate_via_api! do |group|
group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}"
+ group.sandbox = @sandbox
end
- @group.sandbox.add_member(@user)
+ @sandbox.add_member(@user)
@project = Resource::Project.fabricate_via_api! do |project|
- project.group = @group
+ project.group = group
project.name = "project-for-user-group-access-termination"
project.initialize_with_readme = true
end
@@ -27,7 +34,7 @@ module QA
context 'after parent group membership termination' do
before do
- @group.sandbox.remove_member(@user)
+ @sandbox.remove_member(@user)
end
it 'is not allowed to push code via the CLI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347863' do
@@ -77,9 +84,7 @@ module QA
end
after(:all) do
- @user.remove_via_api!
- @project.remove_via_api!
- @group.remove_via_api!
+ @sandbox.remove_via_api!
end
end
end
diff --git a/qa/qa/specs/features/api/3_create/repository/files_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
index 71bd03fab17..7e329371745 100644
--- a/qa/qa/specs/features/api/3_create/repository/files_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
@@ -99,7 +99,6 @@ module QA
#
expect(response.headers[:cache_control]).to include("no-store")
expect(response.headers[:cache_control]).to include("no-cache")
- expect(response.headers[:pragma]).to eq("no-cache")
expect(response.headers[:expires]).to eq("Fri, 01 Jan 1990 00:00:00 GMT")
expect(response.headers[:content_disposition]).to include("attachment")
expect(response.headers[:content_disposition]).not_to include("inline")
diff --git a/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb b/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb
index 60dace0938e..9e6e15963c4 100644
--- a/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb
+++ b/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Snippet repository storage', :requires_admin, :orchestrated, :repository_storage do
let(:source_storage) { { type: :gitaly, name: 'default' } }
let(:destination_storage) { { type: :gitaly, name: QA::Runtime::Env.additional_repository_storage } }
diff --git a/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb b/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb
index 8890b3ff317..c66bd16afe9 100644
--- a/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb
+++ b/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'Pipeline API defined variable inheritance' do
include_context 'variable inheritance test prep'
diff --git a/qa/qa/specs/features/api/4_verify/file_variable_spec.rb b/qa/qa/specs/features/api/4_verify/file_variable_spec.rb
index bd0ec13b1f8..2d9deec399c 100644
--- a/qa/qa/specs/features/api/4_verify/file_variable_spec.rb
+++ b/qa/qa/specs/features/api/4_verify/file_variable_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'Pipeline with project file variables' do
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
diff --git a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb b/qa/qa/specs/features/api/9_data_stores/user_inherited_access_spec.rb
index 124b6c9cd44..48e9d3dc164 100644
--- a/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
+++ b/qa/qa/specs/features/api/9_data_stores/user_inherited_access_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'User', :requires_admin, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'User', :requires_admin, product_group: :tenant_scale do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:parent_group) do
@@ -41,6 +41,10 @@ module QA
parent_group.add_member(parent_group_user)
end
+ after do
+ parent_group_user.remove_via_api!
+ end
+
it(
'is allowed to push code to sub-group project via the CLI',
:reliable,
@@ -79,23 +83,24 @@ module QA
'is allowed to commit to sub-group project via the API',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363349'
) do
- expect do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.api_client = parent_group_user_api_client
- commit.project = sub_group_project
- commit.branch = "new_branch_#{SecureRandom.hex(8)}"
- commit.start_branch = sub_group_project.default_branch
- commit.commit_message = 'Add new file'
- commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
- end
- rescue StandardError => e
- QA::Runtime::Logger.error("Full failure message: #{e.message}")
- raise
- end.not_to raise_error
- end
-
- after do
- parent_group_user.remove_via_api!
+ # Retry is needed due to delays with project authorization updates
+ # Long term solution to accessing the status of a project authorization update
+ # has been proposed in https://gitlab.com/gitlab-org/gitlab/-/issues/393369
+ QA::Support::Retrier.retry_on_exception(max_attempts: 5, sleep_interval: 2) do
+ expect do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = parent_group_user_api_client
+ commit.project = sub_group_project
+ commit.branch = "new_branch_#{SecureRandom.hex(8)}"
+ commit.start_branch = sub_group_project.default_branch
+ commit.commit_message = 'Add new file'
+ commit.add_files([{ file_path: 'test.txt', content: 'new file' }])
+ end
+ rescue StandardError => e
+ QA::Runtime::Logger.error("Full failure message: #{e.message}")
+ raise
+ end.not_to raise_error
+ end
end
end
@@ -122,6 +127,10 @@ module QA
sub_group.add_member(sub_group_user)
end
+ after do
+ sub_group_user.remove_via_api!
+ end
+
it(
'is not allowed to push code to parent group project via the CLI',
:reliable,
@@ -172,10 +181,6 @@ module QA
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError,
/403 Forbidden - You are not allowed to push into this branch/)
end
-
- after do
- sub_group_user.remove_via_api!
- end
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/9_data_stores/users_spec.rb
index 08e1b7a1e0c..4be20bd1932 100644
--- a/qa/qa/specs/features/api/1_manage/users_spec.rb
+++ b/qa/qa/specs/features/api/9_data_stores/users_spec.rb
@@ -3,8 +3,8 @@
require 'airborne'
module QA
- RSpec.describe 'Manage' do
- describe 'Users API', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Users API', :reliable, product_group: :tenant_scale do
let(:api_client) { Runtime::API::Client.new(:gitlab) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }
@@ -14,7 +14,8 @@ module QA
expect_status(200)
end
- it 'GET /users/:username with a valid username', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347886' do
+ it 'GET /users/:username with a valid username',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347886' do
get request.url, { params: { username: Runtime::User.username } }
expect_status(200)
@@ -23,7 +24,8 @@ module QA
)
end
- it 'GET /users/:username with an invalid username', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347883' do
+ it 'GET /users/:username with an invalid username',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347883' do
get request.url, { params: { username: SecureRandom.hex(10) } }
expect_status(200)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb
index 461928cbf1f..a2eca6278d0 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/import/import_github_repo_spec.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', product_group: :import, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391230',
- type: :waiting_on
- } do
+ RSpec.describe 'Manage', :requires_admin, product_group: :import_and_integrate do
describe 'GitHub import' do
include_context 'with github import'
@@ -32,6 +29,8 @@ module QA
end
before do
+ QA::Support::Helpers::ImportSource.enable('github')
+
Flow::Login.sign_in(as: user)
Page::Main::Menu.perform(&:go_to_create_project)
Page::Project::New.perform do |project_page|
@@ -51,7 +50,7 @@ module QA
import_page.import!(github_repo, group.full_path, imported_project.name)
aggregate_failures do
- expect(import_page).to have_imported_project(github_repo, wait: 240)
+ expect(import_page).to have_imported_project(github_repo, wait: import_wait_duration)
# validate link is present instead of navigating to avoid dealing with multiple tabs
# which makes the test more complicated
expect(import_page).to have_go_to_project_link(github_repo)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb
index b8d00c2faee..913317afc70 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do
- describe 'Jenkins integration', product_group: :integrations do
+ describe 'Jenkins integration', product_group: :import_and_integrate do
let(:jenkins_server) { Service::DockerRun::Jenkins.new }
let(:jenkins_client) do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb
index 5a4031b4305..f6f4a6b3786 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb
@@ -4,7 +4,7 @@ module QA
RSpec.describe 'Manage' do
include Support::API
- describe 'Jira integration', :jira, :orchestrated, :requires_admin, product_group: :integrations do
+ describe 'Jira integration', :jira, :orchestrated, :requires_admin, product_group: :import_and_integrate do
let(:jira_project_key) { 'JITP' }
let(:project) do
Resource::Project.fabricate_via_api! do |project|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb
index 7e46276be92..02224406e6d 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Manage', :reliable do
- describe 'Jira issue import', :jira, :orchestrated, :requires_admin, product_group: :integrations do
+ describe 'Jira issue import', :jira, :orchestrated, :requires_admin, product_group: :import_and_integrate do
let(:jira_project_key) { "JITD" }
let(:jira_issue_title) { "[#{jira_project_key}-1] Jira to GitLab Test Issue" }
let(:jira_issue_description) { "This issue is for testing importing Jira issues to GitLab." }
@@ -18,14 +18,12 @@ module QA
set_up_jira_integration
import_jira_issues
- QA::Support::Retrier.retry_on_exception do
- Page::Project::Menu.perform(&:click_issues)
-
- Page::Project::Issue::Index.perform do |issues_page|
- expect(issues_page).to have_content("2 issues successfully imported")
-
- issues_page.click_issue_link(jira_issue_title)
- end
+ Page::Project::Menu.perform(&:go_to_issues)
+ Page::Project::Issue::Index.perform do |issues_page|
+ expect { issues_page }.to eventually_have_content(jira_issue_title).within(
+ max_attempts: 5, sleep_interval: 1, reload_page: issues_page
+ )
+ issues_page.click_issue_link(jira_issue_title)
end
expect(page).to have_content(jira_issue_description)
@@ -58,7 +56,7 @@ module QA
end
def import_jira_issues
- Page::Project::Menu.perform(&:click_issues)
+ Page::Project::Menu.perform(&:go_to_issues)
Page::Project::Issue::Index.perform(&:go_to_jira_import_form)
Page::Project::Issue::JiraImport.perform do |form|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb
index da49573b960..1ea19144a74 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb
@@ -24,7 +24,7 @@ module QA
end
end
- RSpec.describe 'Manage', :orchestrated, :runner, :requires_admin, :smtp, product_group: :integrations do
+ RSpec.describe 'Manage', :orchestrated, :runner, :requires_admin, :smtp, product_group: :import_and_integrate do
describe 'Pipeline status emails' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
let(:emails) { %w[foo@bar.com baz@buzz.com] }
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
index cf9282c1149..54fb2aca990 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
@@ -43,7 +43,12 @@ module QA
it(
'allows enforcing 2FA via UI and logging in with 2FA',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347931'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347931',
+ quarantine: {
+ type: :bug,
+ only: { condition: -> { QA::Runtime::Env.super_sidebar_enabled? } },
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/409336'
+ }
) do
enforce_two_factor_authentication_on_group(group)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb
new file mode 100644
index 00000000000..1be51f40f0e
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage', :skip_live_env, requires_admin: 'creates users and instance OAuth application',
+ product_group: :authentication_and_authorization do
+ let!(:user) { Resource::User.fabricate_via_api! }
+ let(:oidc_consumer_name) { 'gitlab-oidc-consumer' }
+ let(:oidc_consumer_host) { "http://#{oidc_consumer_name}.#{Runtime::Env.running_in_ci? ? 'test' : 'bridge'}" }
+ let(:instance_oauth_app) do
+ Resource::InstanceOauthApplication.fabricate! do |application|
+ application.redirect_uri = "#{oidc_consumer_host}/users/auth/openid_connect/callback"
+ application.scopes = %w[openid profile email]
+ end
+ end
+
+ after do
+ instance_oauth_app.remove_via_api!
+ remove_gitlab_service(oidc_consumer_name)
+ end
+
+ # The host GitLab instance with address Runtime::Scenario.gitlab_address is the OIDC idP - OIDC application will be
+ # created here.
+ # GitLab instance stood up in docker with address gitlab-oidc-consumer.test (or gitlab-oidc-consumer.bridge) is
+ # the consumer - The GitLab OIDC Login button will be displayed here.
+ describe 'OIDC' do
+ it(
+ 'creates GitLab OIDC application and uses it to login',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/405137',
+ quarantine: {
+ only: { pipeline: :nightly },
+ type: :investigating,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/408317'
+ }
+ ) do
+ instance_oauth_app
+
+ Page::Main::Menu.perform(&:sign_out_if_signed_in)
+
+ app_id = instance_oauth_app.application_id
+ app_secret = instance_oauth_app.application_secret
+
+ consumer_gitlab_service = run_gitlab_service(name: oidc_consumer_name, app_id: app_id, app_secret: app_secret)
+
+ wait_for_service(consumer_gitlab_service)
+
+ page.visit oidc_consumer_host
+
+ expect(page.driver.current_url).to include(oidc_consumer_host)
+
+ Page::Main::Login.perform(&:sign_in_with_oidc)
+
+ expect(page.driver.current_url).to include(Runtime::Scenario.gitlab_address)
+
+ Flow::Login.sign_in(as: user)
+
+ expect(page.driver.current_url).to include(oidc_consumer_host)
+
+ Page::Dashboard::Welcome.perform do |welcome|
+ expect(welcome).to have_welcome_title("Welcome to GitLab")
+ end
+ end
+
+ def run_gitlab_service(name:, app_id:, app_secret:)
+ Service::DockerRun::Gitlab.new(
+ image: Runtime::Env.release,
+ name: name,
+ omnibus_config: omnibus_configuration(app_id: app_id, app_secret: app_secret)).tap do |gitlab|
+ gitlab.login
+ gitlab.pull
+ gitlab.register!
+ end
+ end
+
+ def remove_gitlab_service(name)
+ Service::DockerRun::Gitlab.new(name: name).remove!
+ end
+
+ def wait_for_service(service)
+ Support::Waiter.wait_until(max_duration: 900, sleep_interval: 5, raise_on_failure: true) do
+ service.health == "healthy"
+ end
+ end
+
+ def omnibus_configuration(app_id:, app_secret:)
+ <<~OMNIBUS
+ gitlab_rails['initial_root_password']='5iveL\!fe';
+ gitlab_rails['omniauth_enabled'] = true;
+ gitlab_rails['omniauth_allow_single_sign_on'] = true;
+ gitlab_rails['omniauth_block_auto_created_users'] = false;
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'openid_connect',
+ label: 'GitLab OIDC',
+ args: {
+ name: 'openid_connect',
+ scope: ['openid','profile','email'],
+ response_type: 'code',
+ issuer: '#{Runtime::Scenario.gitlab_address}',
+ discovery: false,
+ uid_field: 'preferred_username',
+ send_scope_to_token_endpoint: 'false',
+ client_options: {
+ identifier: '#{app_id}',
+ secret: '#{app_secret}',
+ redirect_uri: '#{oidc_consumer_host}/users/auth/openid_connect/callback',
+ jwks_uri: '#{Runtime::Scenario.gitlab_address}/oauth/discovery/keys',
+ userinfo_endpoint: '#{Runtime::Scenario.gitlab_address}/oauth/userinfo',
+ token_endpoint: '#{Runtime::Scenario.gitlab_address}/oauth/token',
+ authorization_endpoint: '#{Runtime::Scenario.gitlab_address}/oauth/authorize'
+ }
+ }
+ }
+ ];
+ OMNIBUS
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
deleted file mode 100644
index dd39b0c8835..00000000000
--- a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Manage', only: { subdomain: %i[staging staging-canary] }, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344213', type: :stale } do
- describe 'basic user', product_group: :authentication_and_authorization do
- it 'remains logged in when redirected from canary to non-canary node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347626' do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
-
- Support::Retrier.retry_until(sleep_interval: 0.5) do
- Page::Main::Login.perform(&:can_sign_in?)
- end
-
- Runtime::Browser::Session.target_canary(true)
- Flow::Login.sign_in
-
- verify_session_on_canary(true)
-
- Runtime::Browser::Session.target_canary(false)
-
- verify_session_on_canary(false)
-
- Support::Retrier.retry_until(sleep_interval: 0.5) do
- Page::Main::Menu.perform(&:sign_out)
-
- Page::Main::Login.perform(&:can_sign_in?)
- end
- end
-
- def verify_session_on_canary(enable_canary)
- Page::Main::Menu.perform do |menu|
- aggregate_failures 'testing session log in' do
- expect(menu.canary?).to be(enable_canary)
- expect(menu).to have_personal_area
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_github_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_github_spec.rb
new file mode 100644
index 00000000000..3ac050c1649
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_github_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage', :orchestrated, :oauth, product_group: :authentication_and_authorization do
+ describe 'OAuth' do
+ it 'connects and logs in with GitHub OAuth',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/402405' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ Page::Main::Login.perform(&:sign_in_with_github)
+
+ Vendor::Github::Page::Login.perform(&:login)
+
+ expect(page).to have_content('Welcome to GitLab')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
index 3f5842d756e..f257f1edbc1 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
@@ -16,7 +16,8 @@ module QA
end
RSpec.describe 'Manage', :skip_signup_disabled, :requires_admin, product_group: :authentication_and_authorization do
- describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347934' do
+ describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls,
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347934' do
before do
# When LDAP is enabled, a previous test might have created a token for the LDAP 'tanuki' user who is not an admin
# So we need to set it to nil in order to create a new token for admin user so that we are able to set_application_settings
@@ -29,22 +30,22 @@ module QA
ldap_username = Runtime::Env.ldap_username
Runtime::Env.ldap_username = nil
- set_require_admin_approval_after_user_signup_via_api(false)
+ set_require_admin_approval_after_user_signup(false)
Runtime::Env.ldap_username = ldap_username
end
- it_behaves_like 'registration and login'
-
after do
Runtime::Env.personal_access_token = @personal_access_token
end
+
+ it_behaves_like 'registration and login'
end
describe 'standard', :reliable, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347867' do
context 'when admin approval is not required' do
before(:all) do
- set_require_admin_approval_after_user_signup_via_api(false)
+ set_require_admin_approval_after_user_signup(false)
end
it_behaves_like 'registration and login'
@@ -70,7 +71,15 @@ module QA
Support::Waiter.wait_until(max_duration: 120, sleep_interval: 3) { !user.exists? }
end
- it 'allows recreating with same credentials', :reliable, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347868' do
+ after do
+ if @recreated_user
+ @recreated_user.api_client = admin_api_client
+ @recreated_user.remove_via_api!
+ end
+ end
+
+ it 'allows recreating with same credentials', :reliable,
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347868' do
expect(Page::Main::Menu.perform(&:signed_in?)).to be_falsy
Flow::Login.sign_in(as: user, skip_page_validation: true)
@@ -86,13 +95,6 @@ module QA
expect(Page::Main::Menu.perform(&:signed_in?)).to be_truthy
end
- after do
- if @recreated_user
- @recreated_user.api_client = admin_api_client
- @recreated_user.remove_via_api!
- end
- end
-
def admin_api_client
@admin_api_client ||= Runtime::API::Client.as_admin
end
@@ -100,29 +102,42 @@ module QA
end
context 'when admin approval is required' do
- let(:signed_up_waiting_approval_text) { 'You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator.' }
- let(:pending_approval_blocked_text) { 'Your account is pending approval from your GitLab administrator and hence blocked. Please contact your GitLab administrator if you think this is an error.' }
+ let(:signed_up_waiting_approval_text) do
+ 'You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator.'
+ end
- before do
- enable_require_admin_approval_after_user_signup_via_ui
+ let(:pending_approval_blocked_text) do
+ 'Your account is pending approval from your GitLab administrator and hence blocked. Please contact your GitLab administrator if you think this is an error.'
+ end
- Support::Retrier.retry_on_exception do
- @user = Resource::User.fabricate_via_browser_ui! do |user|
- user.expect_fabrication_success = false
- end
+ let(:user) do
+ Resource::User.fabricate_via_browser_ui! do |user|
+ user.expect_fabrication_success = false
end
end
- it 'allows user login after approval', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347871' do
+ before do
+ set_require_admin_approval_after_user_signup(true)
+ end
+
+ after do
+ set_require_admin_approval_after_user_signup(false)
+ user.remove_via_api! if user
+ end
+
+ it 'allows user login after approval',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347871' do
+ user # sign up user
+
expect(page).to have_text(signed_up_waiting_approval_text)
- Flow::Login.sign_in(as: @user, skip_page_validation: true)
+ Flow::Login.sign_in(as: user, skip_page_validation: true)
expect(page).to have_text(pending_approval_blocked_text)
- approve_user(@user)
+ approve_user(user)
- Flow::Login.sign_in(as: @user, skip_page_validation: true)
+ Flow::Login.sign_in(as: user, skip_page_validation: true)
Flow::UserOnboarding.onboard_user
@@ -131,11 +146,6 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Dashboard::Welcome)
Page::Main::Menu.perform(&:has_personal_area?)
end
-
- after do
- set_require_admin_approval_after_user_signup_via_api(false)
- @user.remove_via_api! if @user
- end
end
end
@@ -158,36 +168,17 @@ module QA
end
end
- def set_require_admin_approval_after_user_signup_via_api(enable_or_disable)
- return if get_require_admin_approval_after_user_signup_via_api == enable_or_disable
+ def set_require_admin_approval_after_user_signup(enable_or_disable)
+ return if get_require_admin_approval_after_user_signup == enable_or_disable
Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: enable_or_disable)
-
- sleep 10 # It takes a moment for the setting to come into effect
+ QA::Support::Retrier.retry_until(max_duration: 10, sleep_interval: 1) do
+ get_require_admin_approval_after_user_signup == enable_or_disable
+ end
end
- def get_require_admin_approval_after_user_signup_via_api
+ def get_require_admin_approval_after_user_signup
Runtime::ApplicationSettings.get_application_settings[:require_admin_approval_after_user_signup]
end
-
- def enable_require_admin_approval_after_user_signup_via_ui
- unless get_require_admin_approval_after_user_signup_via_api
- QA::Support::Retrier.retry_until do
- Flow::Login.while_signed_in_as_admin do
- Page::Main::Menu.perform(&:go_to_admin_area)
- QA::Page::Admin::Menu.perform(&:go_to_general_settings)
- Page::Admin::Settings::General.perform do |setting|
- setting.expand_sign_up_restrictions do |settings|
- settings.require_admin_approval_after_user_signup
- end
- end
- end
-
- sleep 15 # It takes a moment for the setting to come into effect
-
- get_require_admin_approval_after_user_signup_via_api
- end
- end
- end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb
index 4bcd2c44617..d8d8b66712a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- describe 'Manage', :reliable, product_group: :import do
+ describe 'Manage', :reliable, product_group: :import_and_integrate do
describe 'Gitlab migration' do
include_context "with gitlab group migration"
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 e2fd0ec9cef..821f885c4c8 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
@@ -26,7 +26,7 @@ module QA
) do
issue = Resource::Issue.fabricate_via_browser_ui! { |issue| issue.project = project }
- Page::Project::Menu.perform(&:click_issues)
+ Page::Project::Menu.perform(&:go_to_issues)
Page::Project::Issue::Index.perform do |index|
expect(index).to have_issue(issue)
@@ -46,7 +46,7 @@ module QA
expect(issue_page).to have_reopen_issue_button
end
- Page::Project::Menu.perform(&:click_issues)
+ Page::Project::Menu.perform(&:go_to_issues)
Page::Project::Issue::Index.perform do |index|
expect(index).not_to have_issue(closed_issue)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
index 61fd743f920..5e989cdb03f 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
@@ -19,11 +19,13 @@ module QA
end
project.visit!
- Page::Project::Menu.perform(&:click_issues)
+ Page::Project::Menu.perform(&:go_to_issues)
end
it 'successfully exports issues list as CSV', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347968' do
Page::Project::Issue::Index.perform do |index|
+ index.click_issues_list_more_actions_dropdown
+
index.click_export_as_csv_button
expect(index.export_issues_modal).to have_content('2 issues selected')
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
index 45541939606..c85ea5e8a69 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
@@ -14,7 +14,7 @@ module QA
end
it 'shows issue suggestions when creating a new issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347995' do
- Page::Project::Show.perform(&:go_to_new_issue)
+ Page::Project::Menu.perform(&:go_to_new_issue)
Page::Project::Issue::New.perform do |new_page|
new_page.fill_title("issue")
expect(new_page).to have_content(issue_title)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
index 83e178ae4c3..7377b0ff8af 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
@@ -16,7 +16,7 @@ module QA
it 'focuses on issue board', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347996' do
project.visit!
- Page::Project::Menu.perform(&:go_to_boards)
+ Page::Project::Menu.perform(&:go_to_issue_boards)
Page::Component::IssueBoard::Show.perform do |show|
show.click_focus_mode_button
diff --git a/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb
index a214af19fca..7368ca34683 100644
--- a/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb
@@ -1,18 +1,17 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create',
- :gitlab_pages,
- :orchestrated,
- except: { job: 'review-qa-*' },
- quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383215',
- type: :test_environment,
- only: { subdomain: 'staging-ref' }
- },
- feature_flag: { name: 'show_pages_in_deployments_menu' } do
+ RSpec.describe 'Plan',
+ :gitlab_pages,
+ :orchestrated,
+ except: { job: 'review-qa-*' },
+ quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383215',
+ type: :flaky
+ },
+ feature_flag: { name: 'show_pages_in_deployments_menu' } do
# TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906
- describe 'Pages', product_group: :editor do
+ describe 'Pages', product_group: :knowledge do
let!(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'gitlab-pages-project'
@@ -23,9 +22,10 @@ module QA
let(:pipeline) do
Resource::Pipeline.fabricate_via_api! do |pipeline|
pipeline.project = project
- pipeline.variables =
+ pipeline.variables = [
{ key: :CI_PAGES_DOMAIN, value: 'nip.io', variable_type: :env_var },
{ key: :CI_PAGES_URL, value: 'http://127.0.0.1.nip.io', variable_type: :env_var }
+ ]
end
end
@@ -46,7 +46,7 @@ module QA
end
it 'creates a Pages website',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do
Page::Project::Pipeline::Show.perform do |show|
expect(show).to have_job(:pages)
show.click_job(:pages)
@@ -56,14 +56,18 @@ module QA
expect(show).to have_passed(timeout: 300)
end
- Page::Project::Show.perform(&:go_to_pages_settings)
- QA::Page::Project::Settings::Pages.perform do |pages|
- pages.go_to_access_page
- Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page,
- retry_on_exception: true) do
- expect(page).to have_content(
- 'This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.')
- end
+ Page::Project::Menu.perform(&:go_to_pages_settings)
+ Page::Project::Settings::Pages.perform(&:go_to_access_page)
+
+ Support::Waiter.wait_until(
+ sleep_interval: 2,
+ max_duration: 60,
+ reload_page: page,
+ retry_on_exception: true
+ ) do
+ expect(page).to have_content(
+ 'This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.'
+ )
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_creation_spec.rb
index feb0f28763c..e1f73acd375 100644
--- a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_creation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_creation_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Plan', product_group: :knowledge do
describe 'Testing wiki content creation inside a project' do
let(:new_wiki_title) { "just_another_wiki_page" }
let(:new_wiki_content) { "this content is changed or added" }
@@ -15,7 +15,7 @@ module QA
end
it 'by adding a home page to the wiki',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347809' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347809' do
project.visit!
Page::Project::Menu.perform(&:click_wiki)
@@ -36,7 +36,7 @@ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347809' do
end
it 'by adding a second page to the wiki',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347808' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347808' do
wiki.visit!
Page::Project::Wiki::Show.perform(&:click_new_page)
@@ -56,7 +56,7 @@ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347808' do
end
it 'by adding a home page to the wiki using git push',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347806' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347806' do
empty_wiki = Resource::Wiki::ProjectPage.new do |empty_wiki|
empty_wiki.project = project
end
@@ -76,7 +76,7 @@ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347806' do
end
it 'by adding a second page to the wiki using git push',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347807' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347807' do
Resource::Repository::WikiPush.fabricate! do |push|
push.file_name = "#{new_wiki_title}.md"
push.file_content = new_wiki_content
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_manipulation_spec.rb
index dcac2ad3a9d..a9850b71a39 100644
--- a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_content_manipulation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_manipulation_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Plan', product_group: :knowledge do
describe 'Testing wiki content manipulation inside a project' do
let(:new_wiki_title) { "just_another_wiki_page" }
let(:new_wiki_content) { "this content is changed or added" }
@@ -14,7 +14,7 @@ module QA
end
it 'by manipulating content on the page',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347810' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347810' do
wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
@@ -34,7 +34,7 @@ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347810' do
end
it 'by manipulating content on the page using git push',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347811' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347811' do
Resource::Repository::WikiPush.fabricate! do |push|
push.file_content = new_wiki_content
push.commit_message = commit_message
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_directory_management_spec.rb
index 7edbb01a522..0056441d8f8 100644
--- a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_directory_management_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_directory_management_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Plan', product_group: :knowledge do
describe 'A project wiki' do
let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
let(:new_path) { "a/new/path-with-spaces" }
@@ -11,7 +11,7 @@ module QA
end
it 'can change the directory path of a page',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347821' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347821' do
initial_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb
index c782139823e..a044bfa2054 100644
--- a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_file_upload_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb
@@ -1,7 +1,12 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :reliable, product_group: :editor do
+ RSpec.describe 'Plan', :reliable, product_group: :knowledge,
+ quarantine: {
+ only: { job: 'relative-url' },
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/409541',
+ type: :bug
+ } do
describe 'Testing project wiki file upload' do
let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
let(:page_title) { 'Content Editor Page' }
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_list_spec.rb
index e0699bccff6..f05fafa483f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_list_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_list_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Plan', product_group: :knowledge do
describe 'Project Wiki' do
let(:small_number_of_pages) { 5 }
let(:large_number_of_pages) { 15 }
@@ -16,7 +16,7 @@ module QA
context 'with Wiki Sidebar' do
it 'has all expected links that work',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347814' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347814' do
small_wiki.visit!
small_number_of_pages.times do |index|
@@ -37,7 +37,7 @@ module QA
context 'with Wiki Page List' do
it 'has all expected links that work',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347813' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347813' do
large_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_view_all_pages)
diff --git a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_page_deletion_spec.rb
index fef6b8ad65f..94ee9a53462 100644
--- a/qa/qa/specs/features/browser_ui/3_create/project_wiki/project_based_page_deletion_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_page_deletion_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
- describe 'Testing project wiki', product_group: :editor do
+ RSpec.describe 'Plan' do
+ describe 'Testing project wiki', product_group: :knowledge do
let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
before do
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index d27ec32fdda..56e1f3d4a9a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -17,11 +17,7 @@ module QA
merge_request.fork.remove_via_api!
end
- it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347818', quarantine: {
- only: :production,
- type: :investigating,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/372258'
- } do
+ it 'can merge source branch from fork into upstream repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347818' do
merge_request.visit!
Page::MergeRequest::Show.perform do |merge_request|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
index 1b82543a5d4..38831f6f158 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
@@ -50,7 +50,10 @@ module QA
runner&.remove_via_api!
end
- it 'merges after pipeline succeeds' do
+ it 'merges after pipeline succeeds', quarantine: {
+ type: :flaky,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/403017'
+ } do
transient_test = repeat > 1
repeat.times do |i|
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 236af93716f..349fa054ff0 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
@@ -17,11 +17,9 @@ module QA
settings.enable_ff_only
end
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = merge_request.project
- push.file_name = "other.txt"
- push.file_content = "New file added!"
- push.new_branch = false
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = merge_request.project
+ commit.add_files([{ file_path: 'other.txt', content: 'New file added!' }])
end
merge_request.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
index 82e2136cd22..54e9d3ed6c8 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Merged merge request', product_group: :code_review do
+ describe 'Merged merge request', :requires_admin, product_group: :code_review do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'revert'
@@ -16,6 +16,8 @@ module QA
end
before do
+ QA::Support::Helpers::ImportSource.enable(%w[gitlab_project])
+
Flow::Login.sign_in
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
index a969b48f0fc..994baea7ad9 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Download merge request patch and diff', product_group: :code_review do
+ describe 'Download merge request patch and diff', :requires_admin, product_group: :code_review do
let(:merge_request) do
Resource::MergeRequest.fabricate_via_api! do |merge_request|
merge_request.title = 'This is a merge request'
@@ -11,11 +11,13 @@ module QA
end
before do
+ QA::Support::Helpers::ImportSource.enable(%w[gitlab_project])
+
Flow::Login.sign_in
merge_request.visit!
end
- it 'views the merge request email patches', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347742' do
+ it 'views the merge request patches', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347742' do
Page::MergeRequest::Show.perform(&:view_email_patches)
expect(page.text).to start_with('From')
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb
new file mode 100644
index 00000000000..3d68de30d57
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Branch Rules Overview', product_group: :source_code,
+ feature_flag: {
+ name: 'branch_rules',
+ scope: :project
+ },
+ quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/403583',
+ type: :flaky
+ } do
+ let(:branch_name) { 'new-branch' }
+ let(:allowed_to_push_role) { Resource::ProtectedBranch::Roles::NO_ONE }
+ let(:allowed_to_merge_role) { Resource::ProtectedBranch::Roles::MAINTAINERS }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'branch-rule-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ before do
+ Runtime::Feature.enable(:branch_rules, project: project)
+
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.branch = branch_name
+ commit.start_branch = project.default_branch
+ commit.commit_message = 'First commit'
+ commit.add_files([{ file_path: 'new_file.rb', content: '# new content' }])
+ end
+ end
+
+ after do
+ Runtime::Feature.disable(:branch_rules, project: project)
+ end
+
+ it 'adds a new branch rule', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/397587' do
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_repository_settings)
+
+ Page::Project::Settings::Repository.perform(&:expand_branch_rules)
+
+ Page::Project::Settings::BranchRules.perform(&:click_add_branch_rule)
+
+ Page::Project::Settings::ProtectedBranches.perform do |settings|
+ settings.select_branch(branch_name)
+ settings.select_allowed_to_push(roles: allowed_to_push_role)
+ settings.select_allowed_to_merge(roles: allowed_to_merge_role)
+ settings.protect_branch
+ end
+
+ Page::Project::Settings::Repository.perform(&:expand_branch_rules)
+
+ Page::Project::Settings::BranchRules.perform do |rules|
+ expect(rules).to have_content(branch_name)
+ rules.navigate_to_branch_rules_details(branch_name)
+ end
+
+ Page::Project::Settings::BranchRulesDetails.perform do |details|
+ aggregate_failures 'branch rules details' do
+ expect(details).to have_allowed_to_push(allowed_to_push_role[:description])
+ expect(details).to have_allowed_to_merge(allowed_to_merge_role[:description])
+ end
+ end
+ end
+ end
+ end
+end
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
index b98bb8592d3..afa9be034eb 100644
--- 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
@@ -2,10 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Branch with unusual name', product_group: :source_code, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/364565',
- type: :bug
- } do
+ describe 'Branch with unusual name', product_group: :source_code do
let(:branch_name) { 'unUsually/named#br--anch' }
let(:project) do
Resource::Project.fabricate_via_api! do |resource|
@@ -33,14 +30,8 @@ module QA
Page::Project::Show.perform do |show|
show.switch_to_branch(branch_name)
- # It takes a few seconds for console errors to appear
- sleep 3
-
- errors = page.driver.browser.logs.get(:browser)
- .select { |e| e.level == "SEVERE" }
- .to_a
-
- raise("Console error(s):\n#{errors.join("\n\n")}") if errors.present?
+ # To prevent false positives: https://gitlab.com/gitlab-org/gitlab/-/issues/383863
+ expect(show).to have_no_content('An error occurred')
show.click_file('test-folder')
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
index a391e6313a6..a13b1517740 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
@@ -37,6 +37,7 @@ module QA
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = second_fork_project
+ push.user = user
push.file_name = 'new_file'
push.file_content = '# This is a new file'
push.commit_message = 'Add new file'
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
index f4ca7955a0f..479c5816938 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
@@ -20,13 +20,12 @@ module QA
let(:tag_name) { 'v0.0.1' }
let(:tag_message) { 'Version 0.0.1' }
- let(:tag_release_notes) { 'Release It!' }
shared_examples 'successful tag creation' do |user, testcase|
it "can be created by #{user}", testcase: testcase do
Flow::Login.sign_in(as: send(user))
- create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
+ create_tag_for_project(project, tag_name, tag_message)
Page::Project::Tag::Show.perform do |show|
expect(show).to have_tag_name(tag_name)
@@ -40,7 +39,7 @@ module QA
it "cannot be created by an unauthorized #{user}", testcase: testcase do
Flow::Login.sign_in(as: send(user))
- create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
+ create_tag_for_project(project, tag_name, tag_message)
Page::Project::Tag::New.perform do |new_tag|
expect(new_tag).to have_content('You are not allowed to create this tag as it is protected.')
@@ -73,7 +72,7 @@ module QA
it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347928'
end
- def create_tag_for_project(project, name, message, release_notes)
+ def create_tag_for_project(project, name, message)
project.visit!
Page::Project::Menu.perform(&:go_to_repository_tags)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
index 815a8696ff7..b8a018552c6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :source_code, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/352525',
- type: :test_environment,
- only: { job: 'review-qa-*' }
- } do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Push mirror a repository over HTTP' do
it 'configures and syncs LFS objects for a (push) mirrored repository', :aggregate_failures, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347847' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
index db180b729c8..c971ab869cd 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Adding comments on snippets' do
let(:comment_author) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:comment_content) { 'Comment 123' }
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
index 20a4866baee..fba12d25640 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Multiple file snippet' do
let(:personal_snippet) do
Resource::Snippet.fabricate_via_api! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
index 833d3bd6126..d9d6a50ad83 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Version control for personal snippets' do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
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 a6bdac8c205..69ee62e262a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Version control for project snippets' do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
index 1a614e538ea..ce4fd6fff4e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :reliable, product_group: :editor, quarantine: {
- only: { subdomain: 'pre' },
- type: :investigating,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/378697'
- } do
+ RSpec.describe 'Create', :reliable, product_group: :source_code do
describe 'Multiple file snippet' do
let(:first_file_content) { 'First file content' }
let(:second_file_content) { 'Second file content' }
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
index aeb8e7d27bf..ccb93bc9d0a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :smoke, product_group: :editor do
+ RSpec.describe 'Create', :smoke, product_group: :source_code do
describe 'Personal snippet creation' do
let(:snippet) do
Resource::Snippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
index 66376769419..2bfc4d3af69 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Multiple file snippet', :reliable, product_group: :editor do
+ describe 'Multiple file snippet', :reliable, product_group: :source_code do
let(:snippet) do
Resource::Snippet.fabricate_via_browser_ui! do |snippet|
snippet.title = 'Personal snippet with multiple files'
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
index 0e10a9908f4..89b76abe6df 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do # to be converted to a smoke test once proved to be stable
+ RSpec.describe 'Create', product_group: :source_code do # to be converted to a smoke test once proved to be stable
describe 'Project snippet creation' do
let(:snippet) do
Resource::ProjectSnippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb
index 3c94107950c..f5e33aeb4a3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :reliable, product_group: :editor do
+ RSpec.describe 'Create', :reliable, product_group: :source_code do
describe 'Multiple file snippet' do
let(:snippet) do
Resource::ProjectSnippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
index 906ac6e09b7..8d8f153dc8e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Multiple file snippet', :reliable, product_group: :editor do
+ describe 'Multiple file snippet', :reliable, product_group: :source_code do
let(:personal_snippet) do
Resource::Snippet.fabricate_via_api! do |snippet|
snippet.title = 'Personal snippet to delete file from'
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
index b58b487531e..7e182fc2020 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Sharing snippets', :reliable, product_group: :editor do
+ describe 'Sharing snippets', :reliable, product_group: :source_code do
let(:snippet) do
Resource::Snippet.fabricate! do |snippet|
snippet.title = 'Shared snippet'
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
index 63e9fdbb881..6180b9e6585 100644
--- 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', product_group: :editor do
+ RSpec.describe 'Create', product_group: :source_code do
describe 'Snippet index page' do
let(:personal_snippet_with_single_file) do
Resource::Snippet.fabricate_via_api! do |snippet|
@@ -52,9 +52,7 @@ module QA
shared_examples 'displaying details on index page' do |snippet_type, testcase|
it "shows correct details of #{snippet_type} including file number", testcase: testcase do
send(snippet_type)
- Page::Main::Menu.perform do |menu|
- menu.go_to_menu_dropdown_option(:snippets_link)
- end
+ Page::Main::Menu.perform(&:go_to_snippets)
Page::Dashboard::Snippet::Index.perform do |snippet|
aggregate_failures 'file content verification' do
diff --git a/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb b/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb
index b8617de2e47..435b9321601 100644
--- a/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb
@@ -2,7 +2,7 @@
# tagged transient due to feature-flag caching flakiness. Remove tag along with feature flag removal.
module QA
RSpec.describe 'Create', feature_flag: { name: 'source_editor_toolbar', scope: :global } do
- describe 'Source editor toolbar preview', product_group: :editor do
+ describe 'Source editor toolbar preview', product_group: :source_code do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'empty-project-with-md'
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
index ded1b1c9d7c..af3d064a37c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387029',
- type: :stale
- } do
+ RSpec.describe 'Create', product_group: :ide,
+ quarantine: {
+ only: { job: 'slow-network' },
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387609',
+ type: :flaky
+ } do
describe 'Add a directory in Web IDE' do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
@@ -14,15 +16,10 @@ module QA
end
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
project.visit!
end
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
context 'when a directory with the same name already exists' do
let(:directory_name) { 'first_directory' }
@@ -37,23 +34,18 @@ module QA
}
])
end
-
project.visit!
-
- Page::Project::Show.perform(&:open_web_ide!)
end
- it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347733' do
- Page::Project::WebIDE::Edit.perform do |ide|
- # Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page,
- # retry_on_exception: true) do
- # expect(ide).to have_element(:commit_mode_tab)
- # end
- ide.wait_until_ide_loads
- ide.add_directory(directory_name)
+ it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386760' do
+ Page::Project::Show.perform(&:open_web_ide!)
+ Page::Project::WebIDE::VSCode.perform do |ide|
+ ide.wait_for_ide_to_load
+ ide.create_new_folder(directory_name)
+ ide.within_vscode_editor do
+ expect(page).to have_content('A file or folder first_directory already exists at this location.')
+ end
end
-
- expect(page).to have_content('The name "first_directory" is already taken in this directory.')
end
end
@@ -64,18 +56,15 @@ module QA
Page::Project::Show.perform(&:open_web_ide!)
end
- it 'shows in the tree view but cannot be committed', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347732' do
- Page::Project::WebIDE::Edit.perform do |ide|
- ide.wait_until_ide_loads
- ide.add_directory(directory_name)
-
- expect(ide).to have_file(directory_name)
- expect(ide).to have_folder_icon(directory_name)
- expect(ide).not_to have_file_addition_icon(directory_name)
-
- ide.switch_to_commit_tab
-
- expect(ide).not_to have_file_to_commit(directory_name)
+ it 'shows successfully but not able to be committed',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386761' do
+ Page::Project::WebIDE::VSCode.perform do |ide|
+ ide.wait_for_ide_to_load
+ ide.create_new_folder(directory_name)
+ ide.commit_and_push(directory_name)
+ ide.within_vscode_editor do
+ expect(page).to have_content('No changes found. Not able to commit.')
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
deleted file mode 100644
index 7195dd5c970..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor do
- describe 'Open a fork in Web IDE',
- skip: {
- issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/351696",
- type: :flaky
- } do
- let(:parent_project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'parent-project'
- project.initialize_with_readme = true
- end
- end
-
- before do
- Runtime::Feature.disable(:vscode_web_ide)
- end
-
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
- context 'when a user does not have permissions to commit to the project' do
- let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) }
-
- context 'when no fork is present' do
- it 'suggests to create a fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347823' do
- Flow::Login.sign_in(as: user)
-
- parent_project.visit!
- Page::Project::Show.perform(&:open_web_ide!)
-
- Page::Project::WebIDE::Edit.perform(&:fork_project!)
-
- submit_merge_request_upstream
- end
- end
-
- context 'when a fork is already created' do
- let(:fork_project) do
- Resource::Fork.fabricate_via_api! do |fork|
- fork.user = user
- fork.upstream = parent_project
- end
- end
-
- it 'opens the fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347824' do
- Flow::Login.sign_in(as: user)
- fork_project.upstream.visit!
- Page::Project::Show.perform do |project_page|
- expect(project_page).to have_edit_fork_button
-
- project_page.open_web_ide!
- end
-
- submit_merge_request_upstream
- end
-
- after do
- fork_project.project.remove_via_api!
- end
- end
-
- def submit_merge_request_upstream
- Page::Project::WebIDE::Edit.perform do |ide|
- ide.wait_until_ide_loads
- expect(ide).to have_project_path("#{user.username}/#{parent_project.name}")
-
- ide.add_file('new file', 'some random text')
- ide.commit_changes(open_merge_request: true)
- end
-
- Page::MergeRequest::New.perform(&:create_merge_request)
-
- parent_project.visit!
- Page::Project::Menu.perform(&:click_merge_requests)
- expect(page).to have_content('Update new file')
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide_new/add_new_directory_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_new/add_new_directory_in_web_ide_spec.rb
deleted file mode 100644
index 7b40c8a62c1..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide_new/add_new_directory_in_web_ide_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor do
- describe 'Add a directory in Web IDE' do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'add-directory-project'
- project.initialize_with_readme = true
- end
- end
-
- before do
- Runtime::Feature.enable(:vscode_web_ide)
- Flow::Login.sign_in
- project.visit!
- end
-
- after do
- Runtime::Feature.disable(:vscode_web_ide)
- end
-
- context 'when a directory with the same name already exists' do
- let(:directory_name) { 'first_directory' }
-
- before do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.add_files(
- [
- {
- file_path: 'first_directory/test_file.txt',
- content: "Test file content"
- }
- ])
- end
- project.visit!
- end
-
- it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386760' do
- Page::Project::Show.perform(&:open_web_ide!)
- Page::Project::WebIDE::VSCode.perform do |ide|
- ide.wait_for_ide_to_load
- ide.create_new_folder(directory_name)
- ide.within_vscode_editor do
- expect(page).to have_content('A file or folder first_directory already exists at this location.')
- end
- end
- end
- end
-
- context 'when user adds a new empty directory' do
- let(:directory_name) { 'new_empty_directory' }
-
- before do
- Page::Project::Show.perform(&:open_web_ide!)
- end
-
- it 'shows successfully but not able to be committed',
-testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386761' do
- Page::Project::WebIDE::VSCode.perform do |ide|
- ide.wait_for_ide_to_load
- ide.create_new_folder(directory_name)
- ide.commit_and_push(directory_name)
- ide.within_vscode_editor do
- expect(page).to have_content('No changes found. Not able to commit.')
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/add_file_template_spec.rb
index 6cbbfb9e7e5..3e24fb496e7 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/add_file_template_spec.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global },
- product_group: :editor,
- quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387033',
- type: :stale
- } do
+ RSpec.describe 'Create', :skip_live_env, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
describe 'Web IDE file templates' do
include Runtime::Fixtures
@@ -16,11 +16,6 @@ module QA
project.description = 'Add file templates via the Web IDE'
project.initialize_with_readme = true
end
- Runtime::Feature.disable(:vscode_web_ide)
- end
-
- after(:all) do
- Runtime::Feature.enable(:vscode_web_ide)
end
templates = [
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/create_first_file_in_web_ide_spec.rb
index 45499ea1999..775e14500d5 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/create_first_file_in_web_ide_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387723',
- type: :stale
- } do
+ RSpec.describe 'Create', :skip_live_env, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
describe 'First file using Web IDE' do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
@@ -16,14 +18,9 @@ module QA
let(:file_name) { 'the very first file.txt' }
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
end
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
it "creates the first file in an empty project via Web IDE", testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347803' do
project.visit!
Page::Project::Show.perform(&:create_first_new_file!)
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_old/link_to_line_in_web_ide_spec.rb
index 3ea87d90c2d..bea2e906d5e 100644
--- 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_old/link_to_line_in_web_ide_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387035',
- type: :stale
- } do
+ RSpec.describe 'Create', :skip_live_env, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
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
@@ -14,12 +16,10 @@ module QA
end
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
end
after do
- Runtime::Feature.enable(:vscode_web_ide)
project.remove_via_api!
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/open_web_ide_from_diff_tab_spec.rb
index 02d2710656d..c4ed2038f4c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/open_web_ide_from_diff_tab_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387031',
- type: :stale
- } do
+ RSpec.describe 'Create', :skip_live_env, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
describe 'Open Web IDE from Diff Tab' do
files = [
{
@@ -47,15 +49,10 @@ module QA
end
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
merge_request.visit!
end
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
it 'opens and edits a multi-file merge request in Web IDE from Diff Tab', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347724' do
Page::MergeRequest::Show.perform do |show|
show.click_diffs_tab
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/review_merge_request_spec.rb
index 4c21581781d..1043e9051e3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/review_merge_request_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', feature_flag: { name: 'vscode_web_ide', scope: :global }, product_group: :editor, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387043',
- type: :stale
- } do
+ RSpec.describe 'Create', :skip_live_env, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
describe 'Review a merge request in Web IDE' do
let(:new_file) { 'awesome_new_file.txt' }
let(:original_text) { 'Text' }
@@ -26,15 +28,10 @@ module QA
end
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
merge_request.visit!
end
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
it 'opens and edits a merge request in Web IDE', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347786' do
Page::MergeRequest::Show.perform do |show|
show.click_open_in_web_ide
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/server_hooks_custom_error_message_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb
index 080832990c9..99be95492e6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/server_hooks_custom_error_message_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', :skip_live_env, except: { job: 'review-qa-*' },
- feature_flag: { name: 'vscode_web_ide', scope: :global },
- product_group: :editor,
- quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387928',
- type: :stale
- } do
+ RSpec.describe 'Create', :skip_live_env, except: { job: 'review-qa-*' }, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
describe 'Git Server Hooks' do
let(:file_path) { File.join(Runtime::Path.fixtures_path, 'web_ide', 'README.md') }
@@ -20,15 +19,10 @@ module QA
end
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
project.visit!
end
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
context 'with custom error messages' do
it 'renders preconfigured error message when user hook failed on commit in WebIDE',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/364751' do
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb
index b83a95694de..f15f5b3a1d9 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb
@@ -1,9 +1,12 @@
# frozen_string_literal: true
+# TODO: remove this test when coverage is replaced or deemed irrelevant
module QA
- RSpec.describe 'Create', product_group: :editor,
- feature_flag: { name: 'vscode_web_ide', scope: :global },
- quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387032', type: :stale } do
+ RSpec.describe 'Create', :skip_live_env, product_group: :ide do
+ before do
+ skip("Skipped but kept as reference. https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115741#note_1330720944")
+ end
+
describe 'Upload a file in Web IDE' do
let(:file_path) { File.join(Runtime::Path.fixtures_path, 'web_ide', file_name) }
@@ -15,17 +18,12 @@ module QA
end
before do
- Runtime::Feature.disable(:vscode_web_ide)
Flow::Login.sign_in
project.visit!
Page::Project::Show.perform(&:open_web_ide!)
end
- after do
- Runtime::Feature.enable(:vscode_web_ide)
- end
-
context 'when a file with the same name already exists' do
let(:file_name) { 'README.md' }
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_parent_child_pipelines_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_parent_child_pipelines_spec.rb
new file mode 100644
index 00000000000..b08a36b0d43
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_parent_child_pipelines_spec.rb
@@ -0,0 +1,321 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
+ describe "Unlocking job artifacts across parent-child pipelines" do
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'unlock-job-artifacts-parent-child-project'
+ end
+ end
+
+ let!(:runner) do
+ Resource::ProjectRunner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ end
+
+ context 'without strategy:depend' do
+ let(:strategy) { nil }
+
+ before do
+ add_parent_child_ci_files(
+ parent_job_name: 'parent_1', parent_script: 'echo parent',
+ child_job_name: 'child_1', child_script: 'echo child'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ context 'when latest pipeline family is successful' do
+ before do
+ update_parent_child_ci_files(
+ parent_job_name: 'parent_2', parent_script: 'echo parent',
+ child_job_name: 'child_2', child_script: 'echo child'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ it 'unlocks job artifacts from previous successful pipeline family',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/395516' do
+ find_job('parent_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('parent_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+
+ find_job('child_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+ end
+ end
+
+ context 'when latest parent pipeline failed' do
+ before do
+ update_parent_child_ci_files(
+ parent_job_name: 'parent_2', parent_script: 'exit 1',
+ child_job_name: 'child_2', child_script: 'echo child'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'failed')
+ end
+
+ it 'does not unlock job artifacts from previous successful pipeline family',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396243' do
+ find_job('parent_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('parent_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+ end
+ end
+
+ context 'when latest child pipeline failed' do
+ before do
+ update_parent_child_ci_files(
+ parent_job_name: 'parent_2', parent_script: 'echo parent',
+ child_job_name: 'child_2', child_script: 'exit 1'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ it 'unlocks job artifacts from previous successful pipeline family because the latest parent is successful',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396244' do
+ find_job('parent_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('parent_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+
+ find_job('child_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+ end
+ end
+ end
+
+ context 'with strategy:depend' do
+ let(:strategy) { 'depend' }
+
+ before do
+ add_parent_child_ci_files(
+ parent_job_name: 'parent_1', parent_script: 'echo parent',
+ child_job_name: 'child_1', child_script: 'echo child'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ context 'when latest pipeline family is successful' do
+ before do
+ update_parent_child_ci_files(
+ parent_job_name: 'parent_2', parent_script: 'echo parent',
+ child_job_name: 'child_2', child_script: 'echo child'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ it 'unlocks job artifacts from previous successful pipeline family',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396245' do
+ find_job('parent_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('parent_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+
+ find_job('child_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+ end
+ end
+
+ context 'when latest parent pipeline failed' do
+ before do
+ update_parent_child_ci_files(
+ parent_job_name: 'parent_2', parent_script: 'exit 1',
+ child_job_name: 'child_2', child_script: 'echo child'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'failed')
+ end
+
+ it 'does not unlock job artifacts from previous successful pipeline family',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396246' do
+ find_job('parent_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('parent_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+ end
+ end
+
+ context 'when latest child pipeline failed' do
+ before do
+ update_parent_child_ci_files(
+ parent_job_name: 'parent_2', parent_script: 'echo parent',
+ child_job_name: 'child_2', child_script: 'exit 1'
+ )
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'failed')
+ end
+
+ it 'does not unlock job artifacts from previous successful pipeline family',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396248' do
+ find_job('parent_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('parent_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('child_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+ end
+ end
+ end
+
+ private
+
+ def update_parent_child_ci_files(parent_job_name:, parent_script:, child_job_name:, child_script:)
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Update parent and child pipelines CI files.'
+ commit.update_files(
+ [
+ parent_ci_file(parent_job_name, parent_script),
+ child_ci_file(child_job_name, child_script)
+ ]
+ )
+ end
+ end
+
+ def add_parent_child_ci_files(parent_job_name:, parent_script:, child_job_name:, child_script:)
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add parent and child pipelines CI files.'
+ commit.add_files(
+ [
+ parent_ci_file(parent_job_name, parent_script),
+ child_ci_file(child_job_name, child_script)
+ ]
+ )
+ end
+ end
+
+ def parent_ci_file(job_name, script)
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ trigger-child:
+ stage: test
+ trigger:
+ include: ".child-ci.yml"
+ strategy: #{strategy}
+
+ #{job_name}:
+ stage: test
+ tags: ["#{executor}"]
+ script: #{script}
+ artifacts:
+ paths: ['.gitlab-ci.yml']
+ when: always
+ YAML
+ }
+ end
+
+ def child_ci_file(job_name, script)
+ {
+ file_path: '.child-ci.yml',
+ content: <<~YAML
+ #{job_name}:
+ stage: test
+ tags: ["#{executor}"]
+ script: #{script}
+ artifacts:
+ paths: ['.child-ci.yml']
+ when: always
+ YAML
+ }
+ end
+
+ def find_job(job_name)
+ Resource::Job.fabricate_via_api! do |job|
+ job.project = project
+ job.id = project.job_by_name(job_name)[:id]
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb
new file mode 100644
index 00000000000..f1a433984d8
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb
@@ -0,0 +1,204 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
+ describe "Unlocking job artifacts across pipelines" do
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'unlock-job-artifacts-project'
+ end
+ end
+
+ let!(:runner) do
+ Resource::ProjectRunner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ end
+
+ context 'when latest pipeline is successful' do
+ before do
+ add_ci_file(job_name: 'job_1', script: 'echo test')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ it 'unlocks job artifacts from previous successful pipeline',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/394807' do
+ find_job('job_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ update_ci_file(job_name: 'job_2', script: 'echo test')
+
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+
+ find_job('job_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('job_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+ end
+ end
+
+ context 'when latest pipeline failed' do
+ before do
+ add_ci_file(job_name: 'successful_job_1', script: 'echo test')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ it 'keeps job artifacts from latest failed pipelines and from latest successful pipeline',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/394808',
+ quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/266958',
+ type: :bug
+ } do
+ update_ci_file(job_name: 'failed_job_1', script: 'exit 1')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'failed')
+
+ update_ci_file(job_name: 'failed_job_2', script: 'exit 2')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'failed')
+
+ find_job('failed_job_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('failed_job_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+
+ find_job('successful_job_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+ end
+ end
+
+ context 'when latest pipeline is blocked' do
+ before do
+ add_ci_file(job_name: 'successful_job_1', script: 'echo test')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'passed')
+ end
+
+ it 'keeps job artifacts from the latest blocked pipeline and from latest successful pipeline',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/395511',
+ quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387087',
+ type: :bug
+ } do
+ update_ci_with_manual_job(job_name: 'successful_job_with_manual_1', script: 'echo test')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'blocked')
+
+ update_ci_with_manual_job(job_name: 'successful_job_with_manual_2', script: 'echo test')
+ Flow::Pipeline.wait_for_latest_pipeline(status: 'blocked')
+
+ find_job('successful_job_with_manual_2').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+
+ find_job('successful_job_with_manual_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_unlocked_artifact
+ end
+
+ find_job('successful_job_1').visit!
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to have_locked_artifact
+ end
+ end
+ end
+
+ private
+
+ def add_ci_file(job_name:, script:)
+ ci_file = ci_file_with_job_artifact(job_name, script)
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = "Set job #{job_name} script #{script}"
+ commit.add_files([ci_file])
+ end
+ end
+
+ def update_ci_file(job_name:, script:)
+ ci_file = ci_file_with_job_artifact(job_name, script)
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = "Set job #{job_name} script #{script}"
+ commit.update_files([ci_file])
+ end
+ end
+
+ def update_ci_with_manual_job(job_name:, script:)
+ ci_file = ci_file_with_manual_job(job_name, script)
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = "Set job #{job_name} script #{script}"
+ commit.update_files([ci_file])
+ end
+ end
+
+ def ci_file_with_job_artifact(job_name, script)
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ #{job_name}:
+ stage: test
+ tags: ["#{executor}"]
+ script: #{script}
+ artifacts:
+ paths: ['.gitlab-ci.yml']
+ when: always
+ YAML
+ }
+ end
+
+ def ci_file_with_manual_job(job_name, script)
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ #{job_name}:
+ stage: test
+ tags: ["#{executor}"]
+ script: #{script}
+ artifacts:
+ paths: ['.gitlab-ci.yml']
+
+ manual-job:
+ stage: test
+ tags: ["#{executor}"]
+ rules:
+ - when: manual
+ script: "echo 'this job is manual'"
+ artifacts:
+ paths: ['.gitlab-ci.yml']
+ YAML
+ }
+ end
+
+ def find_job(job_name)
+ Resource::Job.fabricate_via_api! do |job|
+ job.project = project
+ job.id = project.job_by_name(job_name)[:id]
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
deleted file mode 100644
index aec0da99a5c..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Verify' do
- describe 'Add or Remove CI variable via UI', :smoke, product_group: :pipeline_authoring do
- let(:project) do
- Resource::Project.fabricate_via_api_unless_fips! do |project|
- project.name = 'project-with-ci-variables'
- project.description = 'project with CI variables'
- end
- end
-
- before do
- Flow::Login.sign_in
- project.visit!
- add_ci_variable
- end
-
- it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348027' do
- Page::Project::Settings::CiVariables.perform do |ci_variable|
- expect(ci_variable).to have_text('VARIABLE_KEY')
- expect(ci_variable).not_to have_text('some_CI_variable')
-
- ci_variable.click_reveal_ci_variable_value_button
-
- expect(ci_variable).to have_text('some_CI_variable')
- end
- end
-
- it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348026' do
- Page::Project::Settings::CiVariables.perform do |ci_variable|
- ci_variable.click_edit_ci_variable
- ci_variable.click_ci_variable_delete_button
-
- expect(ci_variable).to have_text('There are no variables yet', wait: 60)
- end
- end
-
- private
-
- def add_ci_variable
- Resource::CiVariable.fabricate_via_browser_ui! do |ci_variable|
- ci_variable.project = project
- ci_variable.key = 'VARIABLE_KEY'
- ci_variable.value = 'some_CI_variable'
- ci_variable.masked = false
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb
index 2ae28d54242..4515353dfc5 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'Pipeline with customizable variable' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
let(:pipeline_job_name) { 'customizable-variable' }
@@ -49,13 +49,8 @@ module QA
Flow::Login.sign_in
project.visit!
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
Page::Project::Pipeline::Index.perform(&:click_run_pipeline_button)
-
- # Sometimes the variables will not be prefilled because of reactive cache so we revisit the page again.
- # TODO: Investigate alternatives to deal with cache implementation
- # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/381233
- page.refresh
end
after do
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 a8ec0a1c835..e2d25e64687 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'Pipeline with protected variable' do
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
let(:protected_value) { Faker::Alphanumeric.alphanumeric(number: 8) }
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb
index 1878292015e..b62ae85436f 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Verify' do
- describe 'Pipeline with prefill variables' do
+ describe 'Pipeline with prefill variables', product_group: :pipeline_security do
let(:prefill_variable_description1) { Faker::Lorem.sentence }
let(:prefill_variable_value1) { Faker::Lorem.word }
let(:prefill_variable_value5) { Faker::Lorem.word }
@@ -52,13 +52,8 @@ module QA
project.visit!
# Navigate to Run Pipeline page
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
Page::Project::Pipeline::Index.perform(&:click_run_pipeline_button)
-
- # Sometimes the variables will not be prefilled because of reactive cache so we revisit the page again.
- # TODO: Investigate alternatives to deal with cache implementation
- # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/381233
- page.refresh
end
it 'shows only variables with description as prefill variables on the run pipeline page',
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb
index 81ccd36c514..15959721935 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Verify', :runner do
- describe 'Pipeline with raw variables in YAML', product_group: :pipeline_authoring do
+ describe 'Pipeline with raw variables in YAML', product_group: :pipeline_security do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
let(:pipeline_job_name) { 'rspec' }
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb
index a5ebd4004d2..12c29ac2363 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'UI defined variable' do
include_context 'variable inheritance test prep'
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb
index f53454b801c..1d354daaa5b 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'UI defined variable' do
include_context 'variable inheritance test prep'
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
deleted file mode 100644
index 0aedbd307bf..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
- describe 'Pipeline creation and processing' do
- let(:executor) { "qa-runner-#{Time.now.to_i}" }
-
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'project-with-pipeline'
- end
- end
-
- let!(:runner) do
- Resource::ProjectRunner.fabricate! do |runner|
- runner.project = project
- runner.name = executor
- runner.tags = [executor]
- end
- end
-
- after do
- [runner, project].each(&:remove_via_api!)
- end
-
- it 'users creates a pipeline which gets processed', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348024' do
- Flow::Login.sign_in
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- test-success:
- tags:
- - #{executor}
- script: echo 'OK'
-
- test-failure:
- tags:
- - #{executor}
- script:
- - echo 'FAILURE'
- - exit 1
-
- test-tags-mismatch:
- tags:
- - invalid
- script: echo 'NOOP'
-
- test-artifacts:
- tags:
- - #{executor}
- script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt
- artifacts:
- paths:
- - my-artifacts/
-
- test-coverage-report:
- tags:
- - #{executor}
- script: mkdir coverage; echo "CONTENTS" > coverage/cobertura.xml
- artifacts:
- reports:
- coverage_report:
- coverage_format: cobertura
- path: coverage/cobertura.xml
- YAML
- }
- ]
- )
- end.project.visit!
-
- Flow::Pipeline.visit_latest_pipeline
-
- aggregate_failures do
- {
- 'test-success': 'passed',
- 'test-failure': 'failed',
- 'test-tags-mismatch': 'pending',
- 'test-artifacts': 'passed',
- 'test-coverage-report': 'passed'
- }.each do |job, status|
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job(job)
- end
-
- Page::Project::Job::Show.perform do |show|
- expect(show).to have_status(status), "Expected job status to be #{status} but got #{show.status_badge} instead."
- show.click_element(:pipeline_path, Page::Project::Pipeline::Show)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_multiple_projects_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_multiple_projects_spec.rb
new file mode 100644
index 00000000000..dc8db7ec387
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_multiple_projects_spec.rb
@@ -0,0 +1,154 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring, feature_flag: {
+ name: 'ci_batch_project_includes_context',
+ scope: :global
+ } do
+ describe 'Include multiple files from multiple projects' do
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
+
+ let(:main_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline'
+ end
+ end
+
+ let(:project1) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'external-project-1'
+ end
+ end
+
+ let(:project2) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'external-project-2'
+ end
+ end
+
+ let!(:runner) do
+ Resource::ProjectRunner.fabricate! do |runner|
+ runner.project = main_project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ def before_do
+ Flow::Login.sign_in
+
+ add_included_files_for(main_project)
+ add_included_files_for(project1)
+ add_included_files_for(project2)
+ add_main_ci_file(main_project)
+
+ main_project.visit!
+ Flow::Pipeline.visit_latest_pipeline(status: 'passed')
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ context 'when FF is on', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396374' do
+ before do
+ Runtime::Feature.enable(:ci_batch_project_includes_context, project: main_project)
+ sleep 60
+
+ before_do
+ end
+
+ it 'runs the pipeline with composed config' do
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ aggregate_failures 'pipeline has all expected jobs' do
+ expect(pipeline).to have_job('test_for_main')
+ expect(pipeline).to have_job("test1_for_#{project1.full_path}")
+ expect(pipeline).to have_job("test1_for_#{project2.full_path}")
+ expect(pipeline).to have_job("test2_for_#{project1.full_path}")
+ expect(pipeline).to have_job("test2_for_#{main_project.full_path}")
+ end
+ end
+ end
+ end
+
+ context 'when FF is off', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/396375' do
+ before do
+ Runtime::Feature.disable(:ci_batch_project_includes_context, project: main_project)
+ sleep 60
+
+ before_do
+ end
+
+ it 'runs the pipeline with composed config' do
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ aggregate_failures 'pipeline has all expected jobs' do
+ expect(pipeline).to have_job('test_for_main')
+ expect(pipeline).to have_job("test1_for_#{project1.full_path}")
+ expect(pipeline).to have_job("test1_for_#{project2.full_path}")
+ expect(pipeline).to have_job("test2_for_#{project1.full_path}")
+ expect(pipeline).to have_job("test2_for_#{main_project.full_path}")
+ end
+ end
+ end
+ end
+
+ private
+
+ def add_included_files_for(project)
+ files = [
+ {
+ file_path: 'file1.yml',
+ content: <<~YAML
+ test1_for_#{project.full_path}:
+ tags: ["#{executor}"]
+ script: echo hello1
+ YAML
+ },
+ {
+ file_path: 'file2.yml',
+ content: <<~YAML
+ test2_for_#{project.full_path}:
+ tags: ["#{executor}"]
+ script: echo hello2
+ YAML
+ }
+ ]
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add files'
+ commit.add_files(files)
+ end
+ end
+
+ def add_main_ci_file(project)
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add config file'
+ commit.add_files([main_ci_file])
+ end
+ end
+
+ def main_ci_file
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ include:
+ - project: #{project1.full_path}
+ file: file1.yml
+ - project: #{project2.full_path}
+ file: file1.yml
+ - project: #{project1.full_path}
+ file: file2.yml
+ - project: #{main_project.full_path}
+ file: file2.yml
+
+ test_for_main:
+ tags: ["#{executor}"]
+ script: echo hello
+ YAML
+ }
+ end
+ end
+ 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
deleted file mode 100644
index 588d22275df..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Verify', :runner, :requires_admin, product_group: :pipeline_insights 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::ProjectRunner.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', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348003' 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
-
- 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 7d1339d2c2d..6295c596dda 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
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
describe 'Pass dotenv variables to downstream via bridge' do
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
let(:upstream_var) { Faker::Alphanumeric.alphanumeric(number: 8) }
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb
index dbe24e2a2b2..745879cf12f 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb
@@ -74,7 +74,7 @@ module QA
show.simulate_pipeline
expect(show.tab_alert_title).to have_content('Simulation completed successfully')
- show.go_to_view_merged_yaml_tab
+ show.go_to_full_configuration_tab
expect(show).to have_source_editor
end
end
@@ -101,7 +101,7 @@ module QA
expect(show.ci_syntax_validate_message).to have_content('CI configuration is invalid')
- show.go_to_view_merged_yaml_tab
+ show.go_to_full_configuration_tab
# TODO: remove this retry when
# https://gitlab.com/gitlab-org/gitlab/-/issues/378536 is resolved
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
index e8ec01577b1..9f43471035f 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
@@ -37,7 +37,7 @@ module QA
before do
Flow::Login.sign_in
project.visit!
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
end
it 'can trigger pipeline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348011' do
diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb
index fba2f22b3e5..016dc9016cd 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb
@@ -1,7 +1,12 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :runner do
+ RSpec.describe 'Verify', :runner, product_group: :runner,
+ quarantine: {
+ only: { job: 'airgapped' },
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/390184',
+ type: :stale
+ } do
describe 'Group runner registration' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb
index d4fee70fbf3..e2bb6c33513 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb
@@ -9,7 +9,7 @@ module QA
# pipeline created (Sidekiq read/write) ->
# runner picks up pipeline (API read/write) ->
# User views pipeline succeeds (Web read)
- RSpec.describe 'Verify', :runner, product_group: :pipeline_insights do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
context 'Endpoint Coverage' do
let!(:project) do
Resource::Project.fabricate_via_api! do |project|
@@ -40,8 +40,7 @@ module QA
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/360837'
) do
# create a CI variable via UI
- Page::Project::Show.perform(&:go_to_ci_cd_settings)
-
+ Page::Project::Menu.perform(&:go_to_ci_cd_settings)
Page::Project::Settings::CiCd.perform do |ci_cd|
ci_cd.expand_ci_variables do |vars|
vars.click_add_variable
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
index b45ccfa5433..ee60483d4de 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_insights do
+ RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
describe 'Code coverage statistics' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
let(:runner) do
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
index ec07116550f..b39475b481d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :skip_live_env, product_group: :container_registry, quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/390090',
- type: :investigating
- } do
+ RSpec.describe 'Package', :orchestrated, :skip_live_env, product_group: :container_registry do
describe 'Self-managed Container Registry' do
include Support::Helpers::MaskToken
@@ -48,7 +45,6 @@ module QA
after do
runner.remove_via_api!
- project.remove_via_api!
end
context "when tls is disabled" do
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
index bf328a2bced..1e076117e4e 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', product_group: :container_registry do
+ RSpec.describe 'Package', :requires_admin, product_group: :container_registry do
describe 'Container Registry Online Garbage Collection', :registry_gc, only: { subdomain: %i[pre] } do
let(:group) { Resource::Group.fabricate_via_api! }
@@ -64,6 +64,8 @@ module QA
end
before do
+ QA::Support::Helpers::ImportSource.enable('git')
+
Flow::Login.sign_in
imported_project
diff --git a/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb
index fe320f10416..8d80e314d71 100644
--- a/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :packages, product_group: :package_registry do
+ RSpec.describe 'Package', :requires_admin, :orchestrated, :packages, product_group: :package_registry do
describe 'Terraform Module Registry' do
include Runtime::Fixtures
@@ -25,6 +25,8 @@ module QA
end
before do
+ QA::Support::Helpers::ImportSource.enable('git')
+
Flow::Login.sign_in
imported_project
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
index 0dce0022b38..d0bae3cfa98 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
@@ -72,7 +72,7 @@ module QA
end
it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348016' do
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
index 39c2121331d..bedd447f6ec 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
@@ -69,7 +69,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
index d6fb52cfea9..c4a1663f36e 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
@@ -83,7 +83,7 @@ module QA
end
it 'uploads a generic package and downloads it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348017' do
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
index f95bcc59db1..6cf6a77ab74 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
@@ -36,6 +36,8 @@ module QA
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: package_project)
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: client_project)
when :ci_job_token
+ package_project_inbound_job_token_disabled
+ client_project_inbound_job_token_disabled
'${CI_JOB_TOKEN}'
when :project_deploy_token
use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: package_project)
@@ -43,10 +45,7 @@ module QA
end
end
- it "pushes and pulls a helm chart", testcase: params[:testcase], quarantine: {
- type: :stale,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391649'
- } do
+ it "pushes and pulls a helm chart", testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
helm_upload_yaml = ERB.new(read_fixture('package_managers/helm', 'helm_upload_package.yaml.erb')).result(binding)
@@ -74,7 +73,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb
index 3fb5c921187..f5dff1b3e0b 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage, :reliable, product_group: :package_registry do
+ RSpec.describe 'Package', :orchestrated, :requires_admin, :packages, :object_storage, :reliable, product_group: :package_registry, feature_flag: { name: 'maven_central_request_forwarding', scope: :global } do
describe 'Maven group level endpoint' do
include Runtime::Fixtures
include Support::Helpers::MaskToken
@@ -41,11 +41,7 @@ module QA
'using a ci job token' => {
authentication_token_type: :ci_job_token,
maven_header_name: 'Job-Token',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347579',
- quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/373189',
- type: :stale
- }
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347579'
}
}
end
@@ -57,6 +53,8 @@ module QA
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: package_project)
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: client_project)
when :ci_job_token
+ package_project_inbound_job_token_disabled
+ client_project_inbound_job_token_disabled
'${CI_JOB_TOKEN}'
when :project_deploy_token
use_ci_variable(name: 'GROUP_DEPLOY_TOKEN', value: group_deploy_token.token, project: package_project)
@@ -64,7 +62,7 @@ module QA
end
end
- it 'pushes and pulls a maven package', testcase: params[:testcase], quarantine: params[:quarantine] do
+ it 'pushes and pulls a maven package', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/group/producer', 'gitlab_ci.yaml.erb')).result(binding)
@@ -94,7 +92,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name)
@@ -223,5 +221,100 @@ module QA
end
end
end
+
+ describe 'Maven request forwarding' do
+ include Runtime::Fixtures
+
+ let(:group_id) { 'com.gitlab.qa' }
+ let(:artifact_id) { "maven-#{SecureRandom.hex(8)}" }
+ let(:package_name) { "#{group_id}/#{artifact_id}".tr('.', '/') }
+ let(:package_version) { '1.3.7' }
+ let(:personal_access_token) { Runtime::Env.personal_access_token }
+ let(:group) { Resource::Group.fabricate_via_api! }
+
+ let(:imported_project) do
+ Resource::ProjectImportedFromURL.fabricate_via_browser_ui! do |project|
+ project.name = "maven_imported_project"
+ project.group = group
+ project.gitlab_repository_path = 'https://gitlab.com/gitlab-org/quality/imported-projects/maven.git'
+ end
+ end
+
+ let(:gitlab_address_with_port) do
+ uri = URI.parse(Runtime::Scenario.gitlab_address)
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
+ end
+
+ let(:package) do
+ Resource::Package.init do |package|
+ package.name = package_name
+ package.project = imported_project
+ end
+ end
+
+ let(:runner) do
+ Resource::ProjectRunner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{imported_project.group.name}"]
+ runner.executor = :docker
+ runner.token = imported_project.group.reload!.runners_token
+ end
+ end
+
+ before do
+ QA::Support::Helpers::ImportSource.enable('git')
+
+ Runtime::Feature.enable(:maven_central_request_forwarding)
+ Flow::Login.sign_in_unless_signed_in
+
+ imported_project
+ runner
+ end
+
+ after do
+ Runtime::Feature.disable(:maven_central_request_forwarding)
+
+ runner.remove_via_api!
+ package.remove_via_api!
+ imported_project.remove_via_api!
+ end
+
+ it(
+ 'uses GitLab as a mirror of the central proxy',
+ :skip_live_env,
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/375988',
+ quarantine: {
+ type: :investigating,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/378221'
+ }
+ ) do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ settings_xml = ERB.new(read_fixture('package_managers/maven/group/consumer/request_forwarding', 'settings.xml.erb')).result(binding)
+ gitlab_ci_yaml = ERB.new(read_fixture('package_managers/maven/group/consumer/request_forwarding', 'gitlab_ci.yaml.erb')).result(binding)
+
+ commit.project = imported_project
+ commit.commit_message = 'Add files'
+ commit.add_files(
+ [
+ { file_path: '.gitlab-ci.yml', content: gitlab_ci_yaml },
+ { file_path: 'settings.xml', content: settings_xml }
+ ])
+ end
+ end
+
+ imported_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)
+ end
+ end
+ end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb
index c69b672a2ec..27bca6c17a2 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Package', :orchestrated, :packages, :object_storage, :reliable,
+ RSpec.describe 'Package', :orchestrated, :requires_admin, :packages, :object_storage, :reliable,
feature_flag: {
name: 'maven_central_request_forwarding',
scope: :global
@@ -134,7 +134,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name)
@@ -190,6 +190,8 @@ module QA
end
before do
+ QA::Support::Helpers::ImportSource.enable('git')
+
Runtime::Feature.enable(:maven_central_request_forwarding)
Flow::Login.sign_in_unless_signed_in
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
index d86ce09c4e1..423304051a2 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
@@ -25,16 +25,15 @@ module QA
when :personal_access_token
"\"#{personal_access_token}\""
when :ci_job_token
+ package_project_inbound_job_token_disabled
+ client_project_inbound_job_token_disabled
'System.getenv("CI_JOB_TOKEN")'
when :project_deploy_token
"\"#{project_deploy_token.token}\""
end
end
- it 'pushes and pulls a maven package via gradle', testcase: params[:testcase], quarantine: {
- type: :stale,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391650'
- } do
+ it 'pushes and pulls a maven package via gradle', testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
gradle_upload_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_upload_package.yaml.erb')).result(binding)
@@ -62,7 +61,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
index 92dee63e37a..4a8b95717d0 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
@@ -153,7 +153,7 @@ module QA
end
project.visit!
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
index 29cdd5b9362..e913df0957d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
@@ -126,7 +126,7 @@ module QA
end
project.visit!
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb
index c2cbec3fbb7..48b9fdec2e9 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb
@@ -50,6 +50,20 @@ module QA
end
end
+ let(:package_project_inbound_job_token_disabled) do
+ Resource::CICDSettings.fabricate_via_api! do |settings|
+ settings.project_path = project.full_path
+ settings.inbound_job_token_scope_enabled = false
+ end
+ end
+
+ let(:client_project_inbound_job_token_disabled) do
+ Resource::CICDSettings.fabricate_via_api! do |settings|
+ settings.project_path = another_project.full_path
+ settings.inbound_job_token_scope_enabled = false
+ end
+ end
+
let!(:runner) do
Resource::GroupRunner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -79,6 +93,8 @@ module QA
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token.token, project: project)
use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token.token, project: another_project)
when :ci_job_token
+ package_project_inbound_job_token_disabled
+ client_project_inbound_job_token_disabled
'${CI_JOB_TOKEN}'
when :group_deploy_token
use_ci_variable(name: 'GROUP_DEPLOY_TOKEN', value: group_deploy_token.token, project: project)
@@ -97,10 +113,7 @@ module QA
end
end
- it 'publishes a nuget package at the project endpoint and installs it from the group endpoint', testcase: params[:testcase], quarantine: {
- type: :stale,
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391648'
- } do
+ it 'publishes a nuget package at the project endpoint and installs it from the group endpoint', testcase: params[:testcase] do
Flow::Login.sign_in
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb
index 038decddd96..ad5835d8c9d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb
@@ -174,7 +174,7 @@ product_group: :package_registry do
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
index 12e9d3e995f..4e072412bd4 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
@@ -92,7 +92,7 @@ module QA
context 'when at the project level' do
it 'publishes and installs a pypi package', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348015' do
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
@@ -112,7 +112,7 @@ module QA
dashboard.go_to_project(project.name)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
index.wait_for_package_replication(package.name)
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
index b80eb3a688e..1af1fc7c231 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
@@ -89,7 +89,7 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ Page::Project::Menu.perform(&:go_to_package_registry)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package.name)
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index 0f6bee951a7..51006dd1e38 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -19,7 +19,6 @@ module QA
resource.project = project
resource.name = runner_name
resource.tags = [runner_name]
- resource.image = 'gitlab/gitlab-runner:alpine-v15.8.3'
end
end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 1e7d0eab365..0a9f30f0529 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Configure',
- only: { subdomain: %i[staging staging-canary] }, product_group: :configure do
+ only: { pipeline: %i[staging staging-canary canary production] }, product_group: :configure do
describe 'Auto DevOps with a Kubernetes Agent' do
let!(:app_project) do
Resource::Project.fabricate_via_api! do |project|
@@ -45,7 +45,7 @@ module QA
app_project.visit!
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ Page::Project::Menu.perform(&:go_to_pipelines)
Page::Project::Pipeline::Index.perform(&:click_run_pipeline_button)
Page::Project::Pipeline::New.perform(&:click_run_pipeline_button)
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb
index 70874e46f27..008d8f808b3 100644
--- a/qa/qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb
+++ b/qa/qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb
@@ -3,8 +3,8 @@
module QA
RSpec.describe 'Monitor', :orchestrated, :smtp, :requires_admin, product_group: :respond do
describe 'Alert' do
- shared_examples 'notification on new alert', :aggregate_failures do
- it 'sends email to user' do
+ shared_examples 'notification on new alert' do
+ it 'sends email to user', :aggregate_failures do
expect { email_subjects }.to eventually_include(alert_email_subject).within(max_duration: 60)
expect(recipient_email_addresses).to include(user.email)
end
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/alert_management/recovery_alert_resolves_correct_alert_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/alert_management/recovery_alert_resolves_correct_alert_spec.rb
new file mode 100644
index 00000000000..af088d2978a
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/8_monitor/alert_management/recovery_alert_resolves_correct_alert_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Monitor', product_group: :respond do
+ describe 'Recovery alert' do
+ shared_examples 'triggers recovery alert' do
+ it 'only resolves the correct alert', :aggregate_failures do
+ Page::Project::Menu.perform(&:go_to_monitor_alerts)
+ Page::Project::Monitor::Alerts::Index.perform do |index|
+ # Open tab is displayed by default
+ expect(index).to have_alert_with_title(unresolve_title)
+ expect(index).to have_no_alert_with_title(resolve_title)
+
+ index.go_to_tab('Resolved')
+ expect(index).to have_alert_with_title(resolve_title)
+ expect(index).to have_no_alert_with_title(unresolve_title)
+ end
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ Flow::AlertSettings.go_to_monitor_settings
+ end
+
+ context(
+ 'when using HTTP endpoint integration',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/393589',
+ quarantine: {
+ only: { pipeline: :nightly },
+ type: :bug,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/395512'
+ }
+ ) do
+ include_context 'sends and resolves test alerts'
+
+ it_behaves_like 'triggers recovery alert'
+ end
+
+ context(
+ 'when using Prometheus integration',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/393590'
+ ) do
+ include_context 'sends and resolves test alerts'
+
+ let(:http) { false }
+
+ it_behaves_like 'triggers recovery alert'
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/incident_management/recovery_alert_closes_correct_incident_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/incident_management/recovery_alert_closes_correct_incident_spec.rb
new file mode 100644
index 00000000000..191da25c57b
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/8_monitor/incident_management/recovery_alert_closes_correct_incident_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Monitor', product_group: :respond, quarantine: {
+ type: :bug,
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/395512'
+ } do
+ describe 'Recovery alert' do
+ shared_examples 'triggers recovery alert' do
+ it 'only closes the correct incident', :aggregate_failures do
+ Page::Project::Menu.perform(&:go_to_monitor_incidents)
+ Page::Project::Monitor::Incidents::Index.perform do |index|
+ # Open tab is displayed by default
+ expect(index).to have_incident(title: unresolve_title),
+ 'Expected to see the unresolved incident in the Open tab'
+ expect(index).to have_no_incident(title: resolve_title),
+ 'Did not expect to see the resolved incident in the Open tab'
+
+ index.go_to_tab('Closed')
+ expect(index).to have_incident(title: resolve_title),
+ 'Expected to see the resolved incident in the Closed tab'
+ expect(index).to have_no_incident(title: unresolve_title),
+ 'Did not expect to see the unresolved incident in the Closed tab'
+ end
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ Flow::AlertSettings.go_to_monitor_settings
+ Flow::AlertSettings.enable_create_incident
+ end
+
+ context(
+ 'when using HTTP endpoint integration',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/393842'
+ ) do
+ include_context 'sends and resolves test alerts'
+
+ it_behaves_like 'triggers recovery alert'
+ end
+
+ context(
+ 'when using Prometheus integration',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/393843'
+ ) do
+ include_context 'sends and resolves test alerts'
+
+ let(:http) { false }
+
+ it_behaves_like 'triggers recovery alert'
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/group_member_access_request_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/group/group_member_access_request_spec.rb
index 3a84646977f..1206898431a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/group_member_access_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/group/group_member_access_request_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :requires_admin, product_group: :organization do
+ RSpec.describe 'Data Stores', :requires_admin, product_group: :tenant_scale do
describe 'Group member access request' do
let!(:admin_api_client) { Runtime::API::Client.as_admin }
@@ -40,7 +40,7 @@ module QA
end
it 'generates a todo item for the group owner',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370132' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370132' do
Page::Dashboard::Todos.perform do |todos|
expect(todos).to have_latest_todo_with_author(
author: user.name,
@@ -64,7 +64,7 @@ module QA
end
it 'adds user to the group',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386792' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386792' do
found_member = group.reload!.find_member(user.username)
expect(found_member).not_to be_nil
@@ -81,7 +81,7 @@ module QA
end
it 'does not add user to the group',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386793' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386793' do
found_member = group.reload!.find_member(user.username)
expect(found_member).to be_nil
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_group_spec.rb
index b2ccacfd142..2f14e2c10da 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_group_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'Subgroup transfer', product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Subgroup transfer', product_group: :tenant_scale do
let(:source_group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "source-group-for-transfer_#{SecureRandom.hex(8)}"
@@ -28,7 +28,7 @@ module QA
end
it 'transfers a subgroup to another group',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347692' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347692' do
Page::Group::Menu.perform(&:click_group_general_settings_item)
Page::Group::Settings::General.perform do |general|
general.transfer_group(sub_group_for_transfer, target_group)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb
index ef05f4cfecf..02e1598d6e7 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'Project transfer between groups', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Project transfer between groups', :reliable, product_group: :tenant_scale do
let(:source_group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "source-group-#{SecureRandom.hex(8)}"
@@ -36,8 +36,8 @@ module QA
end
it 'user transfers a project between groups',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347878' do
- Page::File::Show.perform(&:go_to_general_settings)
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347878' do
+ Page::Project::Menu.perform(&:go_to_general_settings)
Page::Project::Settings::Main.perform(&:expand_advanced_settings)
@@ -45,7 +45,7 @@ module QA
advanced.transfer_project!(project.name, target_group.full_path)
end
- Page::Project::Settings::Main.perform(&:click_project)
+ Page::Project::Menu.perform(&:click_project)
Page::Project::Show.perform do |project|
expect(project).to have_breadcrumb(target_group.path)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/add_project_member_spec.rb
index 50e86b4d555..0beb297ffdb 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/add_project_member_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores', :reliable, product_group: :tenant_scale do
describe 'Add project member' do
it 'user adds project member', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347887' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/create_project_badge_spec.rb
index 0a643d1e33b..87492af089e 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/create_project_badge_spec.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'Create project badge', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Create project badge', :reliable, product_group: :tenant_scale do
let(:badge_name) { "project-badge-#{SecureRandom.hex(8)}" }
let(:expected_badge_link_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}" }
- let(:expected_badge_image_url) { "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}/badges/main/pipeline.svg" }
+ let(:expected_badge_image_url) do
+ "#{Runtime::Scenario.gitlab_address}/#{project.path_with_namespace}/badges/main/pipeline.svg"
+ end
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'badge-test-project'
@@ -18,7 +21,8 @@ module QA
project.visit!
end
- it 'creates project badge successfully', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/350065' do
+ it 'creates project badge successfully',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/350065' do
Resource::ProjectBadge.fabricate! do |badge|
badge.name = badge_name
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/create_project_spec.rb
index c9e90cce84c..2d288ced0ca 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/create_project_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', :smoke, product_group: :organization do
+ RSpec.describe 'Data Stores', :smoke, product_group: :tenant_scale do
describe 'Project' do
shared_examples 'successful project creation' do
it 'creates a new project' do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/dashboard_images_spec.rb
index e609dfb9197..f2136773f59 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/dashboard_images_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', product_group: :organization do
+ RSpec.describe 'Data Stores', product_group: :tenant_scale do
shared_examples 'loads all images' do |admin|
let(:api_client) { Runtime::API::Client.as_admin }
@@ -21,7 +21,7 @@ module QA
Page::Dashboard::Welcome.perform do |welcome|
Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page,
- retry_on_exception: true) do
+ retry_on_exception: true) do
expect(welcome).to have_welcome_title("Welcome to GitLab")
end
# This would be better if it were a visual validation test
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/invite_group_to_project_spec.rb
index 4479f2ebfab..c7501d437eb 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/invite_group_to_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/invite_group_to_project_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'Invite group', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Invite group', :reliable, product_group: :tenant_scale do
shared_examples 'invites group to project' do
it 'verifies group is added and members can access project with correct access level' do
Page::Project::Menu.perform(&:click_members)
@@ -28,7 +28,9 @@ module QA
end
end
- let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
+ let(:user) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
before do
Flow::Login.sign_in
@@ -36,7 +38,8 @@ module QA
project.visit!
end
- context 'to personal namespace project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349223' do
+ context 'with a personal namespace project',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349223' do
let(:group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "group-for-personal-project-#{SecureRandom.hex(8)}"
@@ -52,10 +55,15 @@ module QA
end
end
+ after do
+ project.remove_via_api!
+ group.remove_via_api!
+ end
+
it_behaves_like 'invites group to project'
end
- context 'to group project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349340' do
+ context 'with a group project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349340' do
let(:group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "group-for-group-project-#{SecureRandom.hex(8)}"
@@ -70,6 +78,11 @@ module QA
end
end
+ after do
+ project.remove_via_api!
+ group.remove_via_api!
+ end
+
it_behaves_like 'invites group to project'
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/project_owner_permissions_spec.rb
index 59774ed7c49..2793b0440a4 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/project_owner_permissions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/project_owner_permissions_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'Project owner permissions', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Project owner permissions', :reliable, product_group: :tenant_scale do
let!(:owner) do
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/project/view_project_activity_spec.rb
index 95305b7a4aa..4945ef533a4 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/project/view_project_activity_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'Project activity', :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'Project activity', :reliable, product_group: :tenant_scale do
it 'user creates an event in the activity page upon Git push',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347879' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347879' do
Flow::Login.sign_in
project = Resource::Repository::ProjectPush.fabricate! do |push|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/user/follow_user_activity_spec.rb
index 94b383a746d..c78151b94b7 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/user/follow_user_activity_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'User', :requires_admin, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'User', :requires_admin, product_group: :tenant_scale do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:followed_user_api_client) { Runtime::API::Client.new(:gitlab, user: followed_user) }
@@ -68,7 +68,15 @@ module QA
followed_user_api_client.personal_access_token
end
- it 'can be followed and their activity seen', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347678' do
+ after do
+ project&.api_client = admin_api_client
+ project&.remove_via_api!
+ followed_user&.remove_via_api!
+ following_user&.remove_via_api!
+ end
+
+ it 'can be followed and their activity seen',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347678' do
Flow::Login.sign_in(as: following_user)
page.visit Runtime::Scenario.gitlab_address + "/#{followed_user.username}"
Page::User::Show.perform(&:click_follow_user_link)
@@ -82,7 +90,7 @@ module QA
Page::Main::Menu.perform(&:click_user_profile_link)
Page::User::Show.perform do |show|
- show.click_following_link
+ show.click_following_tab
show.click_user_link(followed_user.username)
aggregate_failures do
@@ -93,13 +101,6 @@ module QA
end
end
end
-
- after do
- project&.api_client = admin_api_client
- project&.remove_via_api!
- followed_user&.remove_via_api!
- following_user&.remove_via_api!
- end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/parent_group_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/user/parent_group_access_termination_spec.rb
index 7caa6677787..7e88f3a9ac3 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/parent_group_access_termination_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/user/parent_group_access_termination_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'User', :requires_admin, :reliable, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'User', :requires_admin, :reliable, product_group: :tenant_scale do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:user) do
@@ -41,7 +41,7 @@ module QA
end
it 'is not allowed to edit the project files',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347866' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347866' do
Flow::Login.sign_in(as: user)
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/user/user_inherited_access_spec.rb
index c57900efe35..78baba403fd 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/user_inherited_access_spec.rb
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/user/user_inherited_access_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
- describe 'User', :requires_admin, product_group: :organization do
+ RSpec.describe 'Data Stores' do
+ describe 'User', :requires_admin, product_group: :tenant_scale do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:parent_group) do
@@ -41,6 +41,10 @@ module QA
parent_group.add_member(parent_group_user)
end
+ after do
+ parent_group_user.remove_via_api!
+ end
+
it(
'is allowed to edit the sub-group project files',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363467'
@@ -58,10 +62,6 @@ module QA
expect(file_form).to have_element(:commit_button)
end
end
-
- after do
- parent_group_user.remove_via_api!
- end
end
context 'when added to sub-group' do
@@ -87,6 +87,10 @@ module QA
sub_group.add_member(sub_group_user)
end
+ after do
+ sub_group_user.remove_via_api!
+ end
+
it(
'is not allowed to edit the parent group project files',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363466'
@@ -102,10 +106,6 @@ module QA
expect(page).to have_text("You can’t edit files directly in this project.")
end
-
- after do
- sub_group_user.remove_via_api!
- end
end
end
end
diff --git a/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb b/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb
index 481a09f601b..5ae90d20351 100644
--- a/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb
+++ b/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb
@@ -4,6 +4,8 @@ module QA
RSpec.shared_context "with github import", :github, :import, :requires_admin, :orchestrated do
include QA::Support::Data::Github
+ let(:import_wait_duration) { 240 }
+
let!(:github_repo) { "#{github_username}/import-test" }
let!(:api_client) { Runtime::API::Client.as_admin }
@@ -26,6 +28,7 @@ module QA
let(:imported_project) do
Resource::ProjectImportedFromGithub.fabricate_via_api! do |project|
project.name = 'imported-project'
+ project.github_repo_id = '466994992'
project.group = group
project.github_personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = github_repo
@@ -52,11 +55,15 @@ module QA
group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
end
+ after do
+ verify_mocks
+ end
+
def expect_project_import_finished_successfully
imported_project.reload! # import the project
status = nil
- Support::Retrier.retry_until(max_duration: 240, sleep_interval: 1, raise_on_failure: false) do
+ Support::Retrier.retry_until(max_duration: import_wait_duration, sleep_interval: 1, raise_on_failure: false) do
status = imported_project.project_import_status[:import_status]
%w[finished failed].include?(status)
end
@@ -74,5 +81,17 @@ module QA
smocker.reset
smocker.register(File.read(File.join(mocks_path, "github.yml")))
end
+
+ # Verify mock session
+ #
+ # @return [void]
+ def verify_mocks
+ return Runtime::Logger.warn("Mock host is not set, skipping verify step") unless smocker_host
+
+ verify_response = smocker.verify
+ return if verify_response.success?
+
+ raise "Mock failures detected:\n#{JSON.pretty_generate(verify_response.failures)}"
+ end
end
end
diff --git a/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb b/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb
index 4bd81ccdf36..bfd0825cf91 100644
--- a/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb
+++ b/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb
@@ -77,7 +77,7 @@ module QA
imported_group.import_details.sum([]) { |details| details[:failures] }
end
- let(:cleanup!) {}
+ let(:cleanup!) {} # rubocop:disable Lint/EmptyBlock
def expect_group_import_finished_successfully
imported_group # trigger import
diff --git a/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb b/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb
index 728907c708f..900245deca3 100644
--- a/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb
+++ b/qa/qa/specs/features/shared_contexts/import/gitlab_project_migration_common.rb
@@ -25,7 +25,6 @@ module QA
end
before do
- Runtime::Feature.enable(:bulk_import_projects) unless Runtime::Feature.enabled?(:bulk_import_projects)
source_project # fabricate source group and project
end
end
diff --git a/qa/qa/specs/features/shared_contexts/packages_registry_shared_context.rb b/qa/qa/specs/features/shared_contexts/packages_registry_shared_context.rb
index a611a801b11..5ab7bb331c0 100644
--- a/qa/qa/specs/features/shared_contexts/packages_registry_shared_context.rb
+++ b/qa/qa/specs/features/shared_contexts/packages_registry_shared_context.rb
@@ -20,6 +20,20 @@ module QA
end
end
+ let(:package_project_inbound_job_token_disabled) do
+ Resource::CICDSettings.fabricate_via_api! do |settings|
+ settings.project_path = package_project.full_path
+ settings.inbound_job_token_scope_enabled = false
+ end
+ end
+
+ let(:client_project_inbound_job_token_disabled) do
+ Resource::CICDSettings.fabricate_via_api! do |settings|
+ settings.project_path = client_project.full_path
+ settings.inbound_job_token_scope_enabled = false
+ end
+ end
+
let(:package) do
Resource::Package.init do |package|
package.name = package_name
diff --git a/qa/qa/specs/features/shared_contexts/sends_and_resolves_test_alerts.rb b/qa/qa/specs/features/shared_contexts/sends_and_resolves_test_alerts.rb
new file mode 100644
index 00000000000..9623bcbb7b5
--- /dev/null
+++ b/qa/qa/specs/features/shared_contexts/sends_and_resolves_test_alerts.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.shared_context 'sends and resolves test alerts' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-for-alerts'
+ project.description = 'Project for alerts'
+ end
+ end
+
+ let(:resolve_title) { Faker::Lorem.sentence }
+ let(:unresolve_title) { Faker::Lorem.sentence }
+ let(:http) { true }
+
+ let(:payload_to_be_resolved) do
+ payload(resolve_title, http)
+ end
+
+ let(:unresolved_payload) do
+ payload(unresolve_title, http)
+ end
+
+ before do
+ http ? Flow::AlertSettings.setup_http_endpoint_integration : Flow::AlertSettings.setup_prometheus_integration
+
+ [payload_to_be_resolved, unresolved_payload].each do |payload|
+ Flow::AlertSettings.send_test_alert(payload: payload)
+ end
+
+ mark_as_resolved(payload_to_be_resolved, http)
+ Flow::AlertSettings.send_test_alert(payload: payload_to_be_resolved)
+ end
+
+ private
+
+ def mark_as_resolved(payload, http)
+ sleep 3 # To ensure create and end time are different
+
+ if http
+ payload[:end_time] = Time.now
+ else
+ payload[:alerts][0][:status] = 'resolved'
+ payload[:alerts][0][:endsAt] = Time.now
+ end
+ end
+
+ def payload(title, http)
+ if http
+ { title: title, description: title }
+ else
+ {
+ version: '4',
+ groupKey: nil,
+ status: 'firing',
+ receiver: '',
+ groupLabels: {},
+ commonLabels: {},
+ commonAnnotations: {},
+ externalURL: '',
+ alerts: [
+ {
+ startsAt: Time.now,
+ generatorURL: Faker::Internet.url,
+ endsAt: nil,
+ status: nil,
+ labels: { gitlab_environment_name: Faker::Lorem.word },
+ annotations: { title: title }
+ }
+ ]
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/helpers/context_selector.rb b/qa/qa/specs/helpers/context_selector.rb
index dfb00cb807b..ab8e9bc3639 100644
--- a/qa/qa/specs/helpers/context_selector.rb
+++ b/qa/qa/specs/helpers/context_selector.rb
@@ -10,7 +10,11 @@ module QA
def except?(*options)
return false if Runtime::Env.ci_job_name.blank? && options.any? { |o| o.is_a?(Hash) && o[:job].present? }
- return false if Runtime::Env.ci_project_name.blank? && options.any? { |o| o.is_a?(Hash) && o[:pipeline].present? }
+
+ return false if Runtime::Env.ci_project_name.blank? && options.any? do |o|
+ o.is_a?(Hash) && o[:pipeline].present?
+ end
+
return false if Runtime::Scenario.attributes[:gitlab_address].blank?
context_matches?(*options)
@@ -22,36 +26,27 @@ module QA
opts = {}
opts[:domain] = '.+'
- opts[:tld] = '.com'
+ opts[:tld] = opts_tld
+ # get uri_tld to decide gitlab or jihulab
uri = URI(Runtime::Scenario.gitlab_address)
+ uri_tld = get_tld(uri.host)
options.each do |option|
- opts[:domain] = production_domain if option == :production
+ opts[:domain] = production_domain(uri_tld) if option == :production
next unless option.is_a?(Hash)
opts.merge!(option)
if option[:pipeline].present?
- return true if Runtime::Env.ci_project_name.blank?
-
- return pipeline_matches?(option[:pipeline])
-
+ return evaluate_pipeline_context(option[:pipeline])
elsif option[:job].present?
- return true if Runtime::Env.ci_job_name.blank?
-
- return job_matches?(option[:job])
-
+ return evaluate_job_context(option[:job])
+ elsif !option[:condition].nil?
+ return evaluate_generic_condition(option[:condition])
elsif option[:subdomain].present?
- opts[:subdomain] = case option[:subdomain]
- when Array
- "(#{option[:subdomain].join("|")})\\."
- when Regexp
- option[:subdomain]
- else
- "(#{option[:subdomain]})\\."
- end
+ opts[:subdomain] = evaluate_subdomain_context(option[:subdomain])
end
end
@@ -60,6 +55,43 @@ module QA
alias_method :dot_com?, :context_matches?
+ private
+
+ def evaluate_pipeline_context(pipeline)
+ return true if Runtime::Env.ci_project_name.blank?
+
+ pipeline_matches?(pipeline)
+ end
+
+ def evaluate_job_context(job)
+ return true if Runtime::Env.ci_job_name.blank?
+
+ job_matches?(job)
+ end
+
+ def evaluate_generic_condition(condition)
+ return condition.call if condition.respond_to?(:call)
+
+ condition
+ end
+
+ def evaluate_subdomain_context(option)
+ case option
+ when Array
+ "(#{option.join('|')})\\."
+ when Regexp
+ option
+ else
+ "(#{option})\\."
+ end
+ end
+
+ def pipeline_matches?(pipeline_to_run_in)
+ Array(pipeline_to_run_in).any? do |pipeline|
+ pipeline.to_s.casecmp?(pipeline_from_project_name(Runtime::Env.ci_project_name))
+ end
+ end
+
def job_matches?(job_patterns)
Array(job_patterns).any? do |job|
pattern = job.is_a?(Regexp) ? job : Regexp.new(job)
@@ -68,16 +100,26 @@ module QA
end
end
- def pipeline_matches?(pipeline_to_run_in)
- Array(pipeline_to_run_in).any? { |pipeline| pipeline.to_s.casecmp?(pipeline_from_project_name(Runtime::Env.ci_project_name)) }
- end
-
def pipeline_from_project_name(project_name)
project_name.to_s.start_with?('gitlab-qa') ? Runtime::Env.default_branch : project_name
end
- def production_domain
- GitlabEdition.jh? ? 'jihulab' : 'gitlab'
+ # Get production domain value based on GitLab edition and URI's top level domain
+ #
+ # @param tld [String] top level domain, e.g. 'hk', 'com'
+ # @return [String] 'gitlab' or 'jihulab'
+ def production_domain(tld)
+ return 'gitlab' unless GitlabEdition.jh?
+ return 'gitlab' if tld == 'hk'
+ return 'jihulab' if tld == 'com'
+ end
+
+ def opts_tld
+ GitlabEdition.jh? ? '(.com|.hk)' : '.com'
+ end
+
+ def get_tld(host)
+ host.split('.').last
end
end
end
diff --git a/qa/qa/specs/spec_helper.rb b/qa/qa/specs/spec_helper.rb
index 1bf189ed6ac..aa274a4e101 100644
--- a/qa/qa/specs/spec_helper.rb
+++ b/qa/qa/specs/spec_helper.rb
@@ -33,7 +33,7 @@ RSpec.configure do |config|
QA::Runtime::Logger.info("Starting test: #{Rainbow(example.full_description).bright}")
QA::Runtime::Example.current = example
- visit(QA::Runtime::Scenario.gitlab_address) if QA::Runtime::Env.remote_mobile_device_name
+ visit(QA::Runtime::Scenario.gitlab_address) if QA::Runtime::Env.mobile_layout?
# Reset fabrication counters tracked in resource base
Thread.current[:api_fabrication] = 0
diff --git a/qa/qa/support/helpers/import_source.rb b/qa/qa/support/helpers/import_source.rb
new file mode 100644
index 00000000000..f25466dc1a0
--- /dev/null
+++ b/qa/qa/support/helpers/import_source.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Helpers
+ module ImportSource
+ def self.enable(new_import_sources)
+ current_import_sources = Runtime::ApplicationSettings.get_application_settings[:import_sources]
+
+ import_sources = current_import_sources | Array(new_import_sources)
+
+ return if (import_sources - current_import_sources).blank?
+
+ Runtime::ApplicationSettings.set_application_settings(import_sources: import_sources)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/json_formatter.rb b/qa/qa/support/json_formatter.rb
index 252ccfe73d3..178b76e1974 100644
--- a/qa/qa/support/json_formatter.rb
+++ b/qa/qa/support/json_formatter.rb
@@ -26,6 +26,10 @@ module QA
class: exception.class.name,
message: exception.message,
message_lines: strip_ansi_codes(notification.message_lines),
+ correlation_id: exception.message[match_data_after(Loglinking::CORRELATION_ID_TITLE)],
+ sentry_url: exception.message[match_data_after(Loglinking::SENTRY_URL_TITLE)],
+ kibana_discover_url: exception.message[match_data_after(Loglinking::KIBANA_DISCOVER_URL_TITLE)],
+ kibana_dashboard_url: exception.message[match_data_after(Loglinking::KIBANA_DASHBOARD_URL_TITLE)],
backtrace: notification.formatted_backtrace
}
end
@@ -70,6 +74,10 @@ module QA
modified = Array(strings).map { |string| string.dup.gsub(/\x1b\[{1,2}[0-9;:?]*m/m, '') }
modified.size == 1 ? modified[0] : modified
end
+
+ def match_data_after(title)
+ /(?<=#{title} ).*/
+ end
end
end
end
diff --git a/qa/qa/support/loglinking.rb b/qa/qa/support/loglinking.rb
index e9202af3965..873390a580b 100644
--- a/qa/qa/support/loglinking.rb
+++ b/qa/qa/support/loglinking.rb
@@ -4,16 +4,22 @@ module QA
module Support
module Loglinking
# Static address variables declared for mapping environment to logging URLs
- STAGING_ADDRESS = 'https://staging.gitlab.com'
- STAGING_REF_ADDRESS = 'https://staging-ref.gitlab.com'
- PRODUCTION_ADDRESS = 'https://gitlab.com'
- PRE_PROD_ADDRESS = 'https://pre.gitlab.com'
+ STAGING_ADDRESS = 'https://staging.gitlab.com'
+ STAGING_REF_ADDRESS = 'https://staging-ref.gitlab.com'
+ PRODUCTION_ADDRESS = 'https://gitlab.com'
+ PRE_PROD_ADDRESS = 'https://pre.gitlab.com'
+
+ # Text titles used for labeling various IDs and URLs
+ CORRELATION_ID_TITLE = 'Correlation Id:'
+ SENTRY_URL_TITLE = 'Sentry Url:'
+ KIBANA_DISCOVER_URL_TITLE = 'Kibana - Discover Url:'
+ KIBANA_DASHBOARD_URL_TITLE = 'Kibana - Dashboard Url:'
class << self
def failure_metadata(correlation_id)
return if correlation_id.blank?
- errors = ["Correlation Id: #{correlation_id}"]
+ errors = ["#{CORRELATION_ID_TITLE} #{correlation_id}"]
env = logging_environment
@@ -24,9 +30,9 @@ module QA
kibana_discover_url = kibana.discover_url
kibana_dashboard_url = kibana.dashboard_url
- errors << "Sentry Url: #{sentry_url}" if sentry_url
- errors << "Kibana - Discover Url: #{kibana_discover_url}" if kibana_discover_url
- errors << "Kibana - Dashboard Url: #{kibana_dashboard_url}" if kibana_dashboard_url
+ errors << "#{SENTRY_URL_TITLE} #{sentry_url}" if sentry_url
+ errors << "#{KIBANA_DISCOVER_URL_TITLE} #{kibana_discover_url}" if kibana_discover_url
+ errors << "#{KIBANA_DASHBOARD_URL_TITLE} #{kibana_dashboard_url}" if kibana_dashboard_url
errors.join("\n")
end
@@ -44,8 +50,6 @@ module QA
:production
when PRE_PROD_ADDRESS
:pre
- else
- nil
end
end
end
diff --git a/qa/qa/support/matchers/have_matcher.rb b/qa/qa/support/matchers/have_matcher.rb
index 734a8890536..a9b365f7e81 100644
--- a/qa/qa/support/matchers/have_matcher.rb
+++ b/qa/qa/support/matchers/have_matcher.rb
@@ -25,6 +25,10 @@ module QA
tag
label
variable
+ system_note
+ alert_with_title
+ incident
+ framework
].each do |predicate|
RSpec::Matchers.define "have_#{predicate}" do |*args, **kwargs|
match do |page_object|
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index 2e97325aff0..ccc5e04d672 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -36,9 +36,7 @@ module QA
def find_element(name, **kwargs)
log("finding :#{name} with args #{kwargs}")
-
- element = super
-
+ element = log_slow_code(name, **kwargs) { super }
log("found :#{name}")
element
@@ -46,9 +44,7 @@ module QA
def all_elements(name, **kwargs)
log("finding all :#{name} with args #{kwargs}")
-
- elements = super
-
+ elements = log_slow_code(name, **kwargs) { super }
log("found #{elements.size} :#{name}") if elements
elements
@@ -88,12 +84,11 @@ module QA
log(msg.join(' '), :info)
log("with args #{kwargs}")
-
- super
+ log_slow_code(name, **kwargs) { super }
end
- def click_via_capybara(method, locator)
- log("clicking via capybara using '#{method}(#{locator})'", :info)
+ def act_via_capybara(method, locator, **kwargs)
+ log("acting via capybara using '#{method}(#{locator})' with args #{kwargs}", :info)
super
end
@@ -113,32 +108,28 @@ module QA
end
def has_element?(name, **kwargs)
- found = super
-
+ found = log_slow_code(name, **kwargs) { super }
log_has_element_or_not('has_element?', name, found, **kwargs)
found
end
def has_no_element?(name, **kwargs)
- found = super
-
+ found = log_slow_code(name, **kwargs) { super }
log_has_element_or_not('has_no_element?', name, found, **kwargs)
found
end
def has_text?(text, **kwargs)
- found = super
-
+ found = log_slow_code(text, **kwargs) { super }
log(%(has_text?('#{text}', wait: #{kwargs[:wait] || Capybara.default_max_wait_time}) returned #{found}))
found
end
def has_no_text?(text, **kwargs)
- found = super
-
+ found = log_slow_code(text, **kwargs) { super }
log(%(has_no_text?('#{text}', wait: #{kwargs[:wait] || Capybara.default_max_wait_time}) returned #{found}))
found
@@ -146,13 +137,11 @@ module QA
def finished_loading?(wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
log('waiting for loading to complete...')
- now = Time.now
-
- loaded = super
-
- log("loading complete after #{Time.now - now} seconds")
+ log_slow_code { super }
+ end
- loaded
+ def wait_for_requests(skip_finished_loading_check: false, skip_resp_code_check: false)
+ log_slow_code { super }
end
def wait_for_animated_element(name)
@@ -209,6 +198,21 @@ module QA
log(msg.compact.join(' '))
end
+
+ # Prints warning log if code duration is slower than threshold
+ # @param [String (frozen)] paramInfo is info relating to the slow element
+ def log_slow_code(param_info = '', **kwargs)
+ starting = kwargs.fetch(:starting_time, Time.now)
+ result = yield
+ ending = kwargs.fetch(:ending_time, Time.now)
+ duration = (ending - starting).round(3)
+ if duration > kwargs.fetch(:log_slow_threshold, 0.5)
+ caller_method_name = caller_locations(1, 1).first.label
+ QA::Runtime::Logger.warn("Potentially Slow Code '#{caller_method_name} #{param_info}' took #{duration}s")
+ end
+
+ result
+ end
end
end
end
diff --git a/qa/qa/support/wait_for_requests.rb b/qa/qa/support/wait_for_requests.rb
index d863ed0491d..2856602629a 100644
--- a/qa/qa/support/wait_for_requests.rb
+++ b/qa/qa/support/wait_for_requests.rb
@@ -16,7 +16,7 @@ module QA
end
def finished_all_ajax_requests?
- requests = %w[window.pendingRequests window.pendingRailsUJSRequests 0]
+ requests = %w[window.pendingRequests window.pendingApolloRequests window.pendingRailsUJSRequests 0]
if Runtime::Env.can_intercept?
requests.unshift('(window.Interceptor && window.Interceptor.activeFetchRequests)')
@@ -26,6 +26,10 @@ module QA
Capybara.page.evaluate_script(script).zero? # rubocop:disable Style/NumericPredicate
end
+ def spinner_exists?
+ Capybara.page.has_css?('.gl-spinner', wait: 2)
+ end
+
def finished_loading?(wait: DEFAULT_MAX_WAIT_TIME)
# The number of selectors should be able to be reduced after
# migration to the new spinner is complete.
diff --git a/qa/qa/tools/test_resource_data_processor.rb b/qa/qa/tools/test_resource_data_processor.rb
index a86c94b4914..3312285ecc4 100644
--- a/qa/qa/tools/test_resource_data_processor.rb
+++ b/qa/qa/tools/test_resource_data_processor.rb
@@ -38,7 +38,7 @@ module QA
api_path: api_path,
fabrication_method: fabrication_method,
fabrication_time: fabrication_time,
- http_method: resource.api_fabrication_http_method,
+ http_method: resource.api_fabrication_http_method || :post,
timestamp: Time.now.to_s
}
end
diff --git a/qa/qa/tools/test_resources_handler.rb b/qa/qa/tools/test_resources_handler.rb
index 2aa8845605e..7f4b8f78618 100644
--- a/qa/qa/tools/test_resources_handler.rb
+++ b/qa/qa/tools/test_resources_handler.rb
@@ -31,6 +31,8 @@ module QA
QA::Resource::CiVariable
QA::Resource::Repository::Commit
QA::Resource::Design
+ QA::Resource::InstanceOauthApplication
+ QA::EE::Resource::ComplianceFramework
QA::EE::Resource::GroupIteration
QA::EE::Resource::Settings::Elasticsearch
QA::EE::Resource::VulnerabilityItem
diff --git a/qa/qa/vendor/github/page/base.rb b/qa/qa/vendor/github/page/base.rb
new file mode 100644
index 00000000000..3b96180afe9
--- /dev/null
+++ b/qa/qa/vendor/github/page/base.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Github
+ module Page
+ class Base
+ include Capybara::DSL
+ include Scenario::Actable
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/github/page/login.rb b/qa/qa/vendor/github/page/login.rb
new file mode 100644
index 00000000000..17a7471e251
--- /dev/null
+++ b/qa/qa/vendor/github/page/login.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+require 'benchmark'
+
+module QA
+ module Vendor
+ module Github
+ module Page
+ class Login < Page::Base
+ def login
+ fill_in 'login', with: QA::Runtime::Env.github_username
+ fill_in 'password', with: QA::Runtime::Env.github_password
+ click_on 'Sign in'
+
+ current_otp = OnePassword::CLI.instance.current_otp
+
+ fill_in 'app_otp', with: current_otp
+
+ if has_text?('Two-factor authentication failed', wait: 2)
+ new_otp = OnePassword::CLI.instance.new_otp(otp)
+
+ fill_in 'app_otp', with: new_otp
+ end
+
+ authorize_app
+ end
+
+ def authorize_app
+ click_on 'Authorize' if has_button?('Authorize')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/one_password/cli.rb b/qa/qa/vendor/one_password/cli.rb
new file mode 100644
index 00000000000..f443ba05492
--- /dev/null
+++ b/qa/qa/vendor/one_password/cli.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'benchmark'
+
+module QA
+ module Vendor
+ module OnePassword
+ class CLI
+ include Singleton
+
+ def initialize
+ @email = QA::Runtime::Env.one_p_email
+ @password = QA::Runtime::Env.one_p_password
+ @secret = QA::Runtime::Env.one_p_secret
+ @github_uuid = QA::Runtime::Env.one_p_github_uuid
+ @address = 'gitlab.1password.com'
+ end
+
+ def new_otp(old_otp = "")
+ # Fetches a new OTP that is not equal to the old OTP
+ new_otp = ""
+ time = Benchmark.realtime do
+ # An otp is valid for 30 seconds so 64 attempts with 0.5 interval are enough to ensure a new OTP is obtained
+ Support::Retrier.retry_until(max_attempts: 64, sleep_interval: 0.5) do
+ new_otp = current_otp
+ new_otp != old_otp
+ end
+ end
+
+ QA::Runtime::Logger.info("Fetched new OTP in: #{time} seconds")
+
+ new_otp
+ end
+
+ def current_otp
+ result = nil
+
+ time = Benchmark.realtime do
+ result = `op item get #{@github_uuid} --otp --session #{session_token}`.chop
+ end
+
+ QA::Runtime::Logger.info("Fetched current OTP in: #{time} seconds")
+
+ result
+ end
+
+ private
+
+ # OP session tokens are valid for 30 minutes. We are caching the session token here and this is fine currently
+ # as we just have one test that is not expected to go over 30 minutes.
+ # But note that if we add more tests that use this class, we might need to add a mechanism to invalidate
+ # the cache after 30 minutes or if the session_token is rejected by op CLI.
+ def session_token
+ @session_token ||= `echo '#{@password}' | op account add --address #{@address} --email #{@email} --secret-key #{@secret} --signin --raw` # rubocop:disable Layout/LineLength
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/smocker/event_payload.rb b/qa/qa/vendor/smocker/event_payload.rb
deleted file mode 100644
index 70998e055ea..00000000000
--- a/qa/qa/vendor/smocker/event_payload.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Vendor
- module Smocker
- class EventPayload
- def initialize(hook_data)
- @hook_data = hook_data
- end
-
- def raw
- @hook_data
- end
-
- def event
- raw[:object_kind]&.to_sym
- end
-
- def event_name
- raw[:event_name]&.to_sym
- end
-
- def project_name
- raw.dig(:project, :name)
- end
-
- def mr?
- event == :merge_request
- end
-
- def issue?
- event == :issue
- end
-
- def note?
- event == :note
- end
-
- def push?
- event == :push
- end
-
- def tag?
- event == :tag_push
- end
-
- def wiki?
- event == :wiki_page
- end
-
- def subgroup_create?
- event_name == :subgroup_create
- end
-
- def subgroup_destroy?
- event_name == :subgroup_destroy
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/smocker/history_response.rb b/qa/qa/vendor/smocker/history_response.rb
index 53d5759ef8b..426bbe024ae 100644
--- a/qa/qa/vendor/smocker/history_response.rb
+++ b/qa/qa/vendor/smocker/history_response.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require_relative './event_payload'
require 'time'
module QA
@@ -23,12 +22,6 @@ module QA
payload[:request]
end
- # @return [EventPayload] the request body as a webhook event
- def as_hook_event
- body = request&.dig(:body)
- EventPayload.new body if body
- end
-
# @return [Time] Time request was recieved
def received
date = request&.dig(:date)
diff --git a/qa/qa/vendor/smocker/smocker_api.rb b/qa/qa/vendor/smocker/smocker_api.rb
index 359d1497825..0434b5dcea4 100644
--- a/qa/qa/vendor/smocker/smocker_api.rb
+++ b/qa/qa/vendor/smocker/smocker_api.rb
@@ -113,6 +113,25 @@ module QA
end
end
+ # Fetch session verify response
+ #
+ # @param [String] session_name
+ # @return [VerifyResponse]
+ def verify(session_name = nil)
+ payload = { session: session_name ? get_session_id(session_name) : nil }
+ response = post("#{admin_url}/sessions/verify", payload)
+
+ VerifyResponse.new(parse_body(response))
+ end
+
+ # Returns a stringfied version of the Smocker history
+ #
+ # @param session_name [String] the session name for the mock
+ # @return [String] stringified event payloads
+ def stringified_history(session_name = nil)
+ history(session_name).map(&:payload).join("\n")
+ end
+
private
attr_reader :host, :public_port, :admin_port, :scheme
diff --git a/qa/qa/vendor/smocker/verify_response.rb b/qa/qa/vendor/smocker/verify_response.rb
new file mode 100644
index 00000000000..916aa204c90
--- /dev/null
+++ b/qa/qa/vendor/smocker/verify_response.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Smocker
+ class VerifyResponse
+ def initialize(payload)
+ @payload = payload
+ end
+
+ # Check if session did not have any errors
+ #
+ # @return [Boolean]
+ def success?
+ payload.dig(:mocks, :verified) && payload.dig(:history, :verified)
+ end
+
+ # Check if all mock definitions have been used
+ #
+ # @return [Boolean]
+ def all_used?
+ payload.dig(:mocks, :all_used)
+ end
+
+ # Fetch failures
+ #
+ # @return [Array]
+ def failures
+ (payload.dig(:mocks, :failures) || []) + (payload.dig(:history, :failures) || [])
+ end
+
+ # Fetch unused mock definitions
+ #
+ # @return [Array]
+ def unused
+ payload.dig(:mocks, :unused)
+ end
+
+ private
+
+ # @return [Hash]
+ attr_reader :payload
+ end
+ end
+ end
+end
diff --git a/qa/spec/fixtures/ff/bulk_import_projects.yml b/qa/spec/fixtures/ff/async_commit_diff_files.yml
index 853389577cf..0cadf592cc1 100644
--- a/qa/spec/fixtures/ff/bulk_import_projects.yml
+++ b/qa/spec/fixtures/ff/async_commit_diff_files.yml
@@ -1,8 +1,8 @@
---
-name: bulk_import_projects
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68873
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339941
-milestone: '14.3'
+name: async_commit_diff_files
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38450
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369439
+milestone: '13.3'
type: development
-group: group::import
+group: group::source code
default_enabled: false
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index 1a82cda2585..646b77a7f84 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -62,6 +62,20 @@ RSpec.describe QA::Support::Page::Logging do
.to output(/finding :element with args {:class=>"active"}/).to_stdout_from_any_process
end
+ it 'logs a warning if find_element is slow' do
+ starting = Time.now
+ ending = starting + 1.4
+ expected_msg = /Potentially Slow Code 'find_element element' took 1.4s/
+
+ # verify logs a warning message to indicate potentially slow code lookups
+ expect { subject.find_element(:element, starting_time: starting, ending_time: ending) }
+ .to output(expected_msg).to_stdout_from_any_process
+
+ # verify it doesn't log a warning message if within allowed limits
+ expect { subject.find_element(:element, starting_time: starting, ending_time: ending, log_slow_threshold: 1.5) }
+ .not_to output(expected_msg).to_stdout_from_any_process
+ end
+
it 'logs click_element' do
expect { subject.click_element(:element) }
.to output(/clicking :element/).to_stdout_from_any_process
@@ -127,8 +141,6 @@ RSpec.describe QA::Support::Page::Logging do
it 'logs finished_loading?' do
expect { subject.finished_loading? }
.to output(/waiting for loading to complete\.\.\./).to_stdout_from_any_process
- expect { subject.finished_loading? }
- .to output(/loading complete after .* seconds$/).to_stdout_from_any_process
end
it 'logs within_element' do
diff --git a/qa/spec/resource/api_fabricator_spec.rb b/qa/spec/resource/api_fabricator_spec.rb
index 337c6772a06..96823ea7ada 100644
--- a/qa/spec/resource/api_fabricator_spec.rb
+++ b/qa/spec/resource/api_fabricator_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe QA::Resource::ApiFabricator do
expect { subject.fabricate_via_api! }.to raise_error do |error|
expect(error.class).to eql(described_class::ResourceFabricationFailedError)
- expect(error.to_s).to eql(<<~ERROR.chomp)
+ expect(error.to_s).to eql(<<~ERROR.strip)
Fabrication of FooBarResource using the API failed (400) with `#{raw_post}`.\n
ERROR
end
diff --git a/qa/spec/resource/project_web_hook_spec.rb b/qa/spec/resource/project_web_hook_spec.rb
new file mode 100644
index 00000000000..bca95124c06
--- /dev/null
+++ b/qa/spec/resource/project_web_hook_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe Resource::ProjectWebHook do
+ let(:smocker_api) { instance_double(Vendor::Smocker::SmockerApi) }
+ let(:smocker_docker) { class_double(Service::DockerRun::Smocker) }
+ let(:history_entries) do
+ [
+ {
+ request: {
+ body: {
+ object_kind: 'tag_push'
+ }
+ }
+ },
+ {
+ request: {
+ body: {
+ object_kind: 'merge_request'
+ }
+ }
+ }
+ ]
+ end
+
+ let(:history_response) { Struct.new(:body).new(history_entries.to_json) }
+
+ it 'configures the project hook events' do
+ setup_mocks
+
+ described_class.setup(pipeline: true, wiki_page: true) do |webhook, _|
+ expect(webhook.pipeline_events).to be(true)
+ expect(webhook.wiki_page_events).to be(true)
+ expect(webhook.push_events).to be(false)
+ end
+ end
+
+ it 'adds an #event method to the smocker object that returns webhook events' do
+ setup_mocks
+
+ # rubocop:disable RSpec/AnyInstanceOf
+ expect_any_instance_of(Vendor::Smocker::SmockerApi).to receive(:get_session_id)
+ .and_return('123')
+ expect_any_instance_of(Vendor::Smocker::SmockerApi).to receive(:get)
+ .with(/history/)
+ .and_return(history_response)
+ # rubocop:enable RSpec/AnyInstanceOf
+
+ described_class.setup do |_, smocker|
+ expect(smocker.events('123')).to include(
+ a_hash_including(object_kind: 'merge_request'),
+ a_hash_including(object_kind: 'tag_push')
+ )
+ end
+ end
+
+ def setup_mocks
+ # rubocop:disable RSpec/AnyInstanceOf
+ expect_any_instance_of(Vendor::Smocker::SmockerApi).to receive(:reset)
+ expect_any_instance_of(Vendor::Smocker::SmockerApi).to receive(:register)
+ # rubocop:enable RSpec/AnyInstanceOf
+
+ expect(Service::DockerRun::Smocker).to receive(:init)
+ .and_yield(Vendor::Smocker::SmockerApi.new(host: 'smocker.net'))
+ allow(subject).to receive(:project)
+ allow(described_class).to receive(:fabricate_via_api!)
+ .and_yield(subject)
+ end
+ end
+end
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index e9c2000681b..afd7146a81a 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -189,14 +189,14 @@ RSpec.describe QA::Runtime::Env do
end
describe '.github_access_token' do
- it 'returns "" if GITHUB_ACCESS_TOKEN is not defined' do
- stub_env('GITHUB_ACCESS_TOKEN', nil)
+ it 'returns "" if QA_GITHUB_ACCESS_TOKEN is not defined' do
+ stub_env('QA_GITHUB_ACCESS_TOKEN', nil)
expect(described_class.github_access_token).to eq('')
end
- it 'returns stripped string if GITHUB_ACCESS_TOKEN is defined' do
- stub_env('GITHUB_ACCESS_TOKEN', ' abc123 ')
+ it 'returns stripped string if QA_GITHUB_ACCESS_TOKEN is defined' do
+ stub_env('QA_GITHUB_ACCESS_TOKEN', ' abc123 ')
expect(described_class.github_access_token).to eq('abc123')
end
end
@@ -229,14 +229,14 @@ RSpec.describe QA::Runtime::Env do
end
describe '.require_github_access_token!' do
- it 'raises ArgumentError if GITHUB_ACCESS_TOKEN is not defined' do
- stub_env('GITHUB_ACCESS_TOKEN', nil)
+ it 'raises ArgumentError if QA_GITHUB_ACCESS_TOKEN is not defined' do
+ stub_env('QA_GITHUB_ACCESS_TOKEN', nil)
expect { described_class.require_github_access_token! }.to raise_error(ArgumentError)
end
- it 'does not raise if GITHUB_ACCESS_TOKEN is defined' do
- stub_env('GITHUB_ACCESS_TOKEN', ' abc123 ')
+ it 'does not raise if QA_GITHUB_ACCESS_TOKEN is defined' do
+ stub_env('QA_GITHUB_ACCESS_TOKEN', ' abc123 ')
expect { described_class.require_github_access_token! }.not_to raise_error
end
@@ -282,9 +282,13 @@ RSpec.describe QA::Runtime::Env do
end
describe 'remote grid credentials' do
- it 'is blank if username is empty' do
+ before do
stub_env('QA_REMOTE_GRID_USERNAME', nil)
+ stub_env('QA_REMOTE_GRID_ACCESS_KEY', nil)
+ stub_env('QA_REMOTE_GRID', nil)
+ end
+ it 'is blank if username is empty' do
expect(described_class.send(:remote_grid_credentials)).to eq('')
end
@@ -300,42 +304,41 @@ RSpec.describe QA::Runtime::Env do
expect(described_class.send(:remote_grid_credentials)).to eq('foo:bar@')
end
- end
- describe '.remote_grid_protocol' do
- it 'defaults protocol to http' do
- stub_env('QA_REMOTE_GRID_PROTOCOL', nil)
- expect(described_class.remote_grid_protocol).to eq('http')
+ describe '.remote_grid_protocol' do
+ it 'defaults protocol to http' do
+ expect(described_class.remote_grid_protocol).to eq('http')
+ end
end
- end
- describe '.remote_grid' do
- it 'is falsey if QA_REMOTE_GRID is not set' do
- expect(described_class.remote_grid).to be_falsey
- end
+ describe '.remote_grid' do
+ it 'is falsey if QA_REMOTE_GRID is not set' do
+ expect(described_class.remote_grid).to be_falsey
+ end
- it 'accepts https protocol' do
- stub_env('QA_REMOTE_GRID', 'localhost:4444')
- stub_env('QA_REMOTE_GRID_PROTOCOL', 'https')
+ it 'accepts https protocol' do
+ stub_env('QA_REMOTE_GRID', 'localhost:4444')
+ stub_env('QA_REMOTE_GRID_PROTOCOL', 'https')
- expect(described_class.remote_grid).to eq('https://localhost:4444/wd/hub')
- end
+ expect(described_class.remote_grid).to eq('https://localhost:4444/wd/hub')
+ end
- context 'with credentials' do
- it 'has a grid of http://user:key@grid/wd/hub' do
- stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
- stub_env('QA_REMOTE_GRID_ACCESS_KEY', 'bar')
- stub_env('QA_REMOTE_GRID', 'localhost:4444')
+ context 'with credentials' do
+ it 'has a grid of http://user:key@grid/wd/hub' do
+ stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
+ stub_env('QA_REMOTE_GRID_ACCESS_KEY', 'bar')
+ stub_env('QA_REMOTE_GRID', 'localhost:4444')
- expect(described_class.remote_grid).to eq('http://foo:bar@localhost:4444/wd/hub')
+ expect(described_class.remote_grid).to eq('http://foo:bar@localhost:4444/wd/hub')
+ end
end
- end
- context 'without credentials' do
- it 'has a grid of http://grid/wd/hub' do
- stub_env('QA_REMOTE_GRID', 'localhost:4444')
+ context 'without credentials' do
+ it 'has a grid of http://grid/wd/hub' do
+ stub_env('QA_REMOTE_GRID', 'localhost:4444')
- expect(described_class.remote_grid).to eq('http://localhost:4444/wd/hub')
+ expect(described_class.remote_grid).to eq('http://localhost:4444/wd/hub')
+ end
end
end
end
diff --git a/qa/spec/specs/helpers/context_selector_spec.rb b/qa/spec/specs/helpers/context_selector_spec.rb
index 7541bb45d82..f6134cc6177 100644
--- a/qa/spec/specs/helpers/context_selector_spec.rb
+++ b/qa/spec/specs/helpers/context_selector_spec.rb
@@ -43,6 +43,7 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
it 'matches multiple subdomains' do
+ allow(GitlabEdition).to receive(:jh?).and_return(false)
QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
aggregate_failures do
@@ -51,13 +52,35 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
end
+ it 'matches multiple subdomains on jh side' do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ QA::Runtime::Scenario.define(:gitlab_address, "https://staging.jihulab.com")
+
+ aggregate_failures do
+ expect(described_class.context_matches?(subdomain: [:release, :staging])).to be_truthy
+ expect(described_class.context_matches?(:production, subdomain: [:release, :staging])).to be_truthy
+ end
+ end
+
it 'matches :production' do
+ allow(GitlabEdition).to receive(:jh?).and_return(false)
QA::Runtime::Scenario.define(:gitlab_address, "https://gitlab.com/")
expect(described_class.context_matches?(:production)).to be_truthy
end
+ it 'matches :production on jh side' do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+
+ QA::Runtime::Scenario.define(:gitlab_address, "https://jihulab.com/")
+ expect(described_class.context_matches?(:production)).to be_truthy
+
+ QA::Runtime::Scenario.define(:gitlab_address, "https://gitlab.hk/")
+ expect(described_class.context_matches?(:production)).to be_truthy
+ end
+
it 'matches domain' do
+ allow(GitlabEdition).to receive(:jh?).and_return(false)
QA::Runtime::Scenario.define(:gitlab_address, 'https://jihulab.com')
aggregate_failures do
@@ -67,6 +90,26 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
end
+ it 'matches domain on jh side' do
+ # To simulate run tests in JH
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://jihulab.com')
+
+ aggregate_failures do
+ expect(described_class.context_matches?(:production)).to be_truthy
+ expect(described_class.context_matches?(domain: 'gitlab')).to be_falsey
+ expect(described_class.context_matches?(domain: 'jihulab')).to be_truthy
+ end
+
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.hk')
+
+ aggregate_failures do
+ expect(described_class.context_matches?(:production)).to be_truthy
+ expect(described_class.context_matches?(domain: 'jihulab')).to be_falsey
+ expect(described_class.context_matches?(domain: 'gitlab')).to be_truthy
+ end
+ end
+
it 'matches tld' do
QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.cn')
@@ -89,6 +132,20 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
end
+ context 'with generic condition context matcher' do
+ it 'matches truthy lambda condition result' do
+ expect(described_class.context_matches?(condition: -> { true })).to be_truthy
+ end
+
+ it 'matches truthy condition result' do
+ expect(described_class.context_matches?(condition: true)).to be_truthy
+ end
+
+ it 'skips falsey condition result' do
+ expect(described_class.context_matches?(condition: false)).to be_falsey
+ end
+ end
+
it 'returns false for mismatching' do
QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
@@ -119,6 +176,7 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
context 'with different environment set' do
before do
+ allow(GitlabEdition).to receive(:jh?).and_return(false)
QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com')
end
@@ -140,6 +198,31 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
end
end
+
+ context 'with different environment set on jh side' do
+ before do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://jihulab.com')
+ end
+
+ it 'does not run against production' do
+ group = describe_successfully 'Runs in staging', :something, only: { subdomain: :staging } do
+ it('runs in staging') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ end
+
+ context 'when excluding contexts' do
+ it 'runs against production' do
+ group = describe_successfully 'Runs in staging', :something, except: { subdomain: :staging } do
+ it('runs in staging') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ end
+ end
+ end
end
it 'runs only in staging' do
@@ -226,6 +309,7 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
context 'production' do
before do
+ allow(GitlabEdition).to receive(:jh?).and_return(false)
QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com/')
end
@@ -260,6 +344,80 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
end
end
+ context 'jh mainland production ' do
+ before do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://jihulab.com/')
+ end
+
+ it 'runs on production' do
+ group = describe_successfully do
+ it('runs on prod', only: :production) {}
+ it('does not run in prod', only: { subdomain: :staging }) {}
+ it('runs in prod and staging', only: { subdomain: /(staging.)?/, domain: 'jihulab' }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:pending)
+ expect(group.examples[2].execution_result.status).to eq(:passed)
+ end
+ end
+
+ context 'when excluding contexts' do
+ it 'skips production' do
+ group = describe_successfully do
+ it('skips prod', except: :production) {}
+ it('runs on prod', except: { subdomain: :staging }) {}
+ it('skips prod and staging', except: { subdomain: /(staging.)?/, domain: 'jihulab' }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ expect(group.examples[2].execution_result.status).to eq(:pending)
+ end
+ end
+ end
+ end
+
+ context 'jh hk production ' do
+ before do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.hk/')
+ end
+
+ it 'runs on production' do
+ group = describe_successfully do
+ it('runs on prod', only: :production) {}
+ it('does not run in prod', only: { subdomain: :staging }) {}
+ it('runs in prod and staging', only: { subdomain: /(staging.)?/, domain: 'gitlab' }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:pending)
+ expect(group.examples[2].execution_result.status).to eq(:passed)
+ end
+ end
+
+ context 'when excluding contexts' do
+ it 'skips production' do
+ group = describe_successfully do
+ it('skips prod', except: :production) {}
+ it('runs on prod', except: { subdomain: :staging }) {}
+ it('skips prod and staging', except: { subdomain: /(staging.)?/, domain: 'gitlab' }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ expect(group.examples[2].execution_result.status).to eq(:pending)
+ end
+ end
+ end
+ end
+
it 'outputs a message for invalid environments' do
group = describe_successfully do
it('will skip', only: :production) {}
diff --git a/qa/spec/specs/helpers/feature_flag_spec.rb b/qa/spec/specs/helpers/feature_flag_spec.rb
index 491fc22f026..e9f64dab587 100644
--- a/qa/spec/specs/helpers/feature_flag_spec.rb
+++ b/qa/spec/specs/helpers/feature_flag_spec.rb
@@ -122,6 +122,10 @@ RSpec.describe QA::Specs::Helpers::FeatureFlag do
end
context 'when run on production' do
+ before do
+ allow(GitlabEdition).to receive(:jh?).and_return(false)
+ end
+
before(:context) do
QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com')
end
@@ -147,6 +151,66 @@ RSpec.describe QA::Specs::Helpers::FeatureFlag do
it_behaves_like 'skips with given feature flag metadata', { name: 'global_ff', scope: :global }
end
+ context 'when run on jh production mainland' do
+ before do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ end
+
+ before(:context) do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://jihulab.com')
+ end
+
+ context 'when no scope is defined' do
+ it_behaves_like 'skips with given feature flag metadata', { name: 'no_scope_ff' }
+
+ context 'for only one test in the example group' do
+ it 'only skips specified test and runs all others' do
+ group = describe_successfully 'Feature flag set for one test' do
+ it('is skipped', feature_flag: { name: 'single_test_ff' }) {}
+ it('passes') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ end
+ end
+ end
+
+ it_behaves_like 'skips with given feature flag metadata', { name: 'actor_ff', scope: :project }
+
+ it_behaves_like 'skips with given feature flag metadata', { name: 'global_ff', scope: :global }
+ end
+
+ context 'when run on jh production hk' do
+ before do
+ allow(GitlabEdition).to receive(:jh?).and_return(true)
+ end
+
+ before(:context) do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.hk')
+ end
+
+ context 'when no scope is defined' do
+ it_behaves_like 'skips with given feature flag metadata', { name: 'no_scope_ff' }
+
+ context 'for only one test in the example group' do
+ it 'only skips specified test and runs all others' do
+ group = describe_successfully 'Feature flag set for one test' do
+ it('is skipped', feature_flag: { name: 'single_test_ff' }) {}
+ it('passes') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ end
+ end
+ end
+
+ it_behaves_like 'skips with given feature flag metadata', { name: 'actor_ff', scope: :project }
+
+ it_behaves_like 'skips with given feature flag metadata', { name: 'global_ff', scope: :global }
+ end
+
context 'when run on pre' do
before(:context) do
QA::Runtime::Scenario.define(:gitlab_address, 'https://pre.gitlab.com')
diff --git a/qa/spec/tools/ci/ff_changes_spec.rb b/qa/spec/tools/ci/ff_changes_spec.rb
index 71ca26867e0..d0bf6de148d 100644
--- a/qa/spec/tools/ci/ff_changes_spec.rb
+++ b/qa/spec/tools/ci/ff_changes_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe QA::Tools::Ci::FfChanges do
let(:mr_diff) do
[
{
- path: "config/feature_flags/development/bulk_import_projects.yml",
+ path: "config/feature_flags/development/async_commit_diff_files.yml",
deleted_file: deleted_file
}
]
@@ -21,12 +21,12 @@ RSpec.describe QA::Tools::Ci::FfChanges do
before do
allow(File).to receive(:read)
.with(File.expand_path("../#{mr_diff.first[:path]}", QA::Runtime::Path.qa_root))
- .and_return(File.read("spec/fixtures/ff/bulk_import_projects.yml"))
+ .and_return(File.read("spec/fixtures/ff/async_commit_diff_files.yml"))
end
context "with changed feature flag" do
it "returns inverse ff state option" do
- expect(ff_changes.fetch).to eq("bulk_import_projects=enabled")
+ expect(ff_changes.fetch).to eq("async_commit_diff_files=enabled")
end
end
@@ -34,7 +34,7 @@ RSpec.describe QA::Tools::Ci::FfChanges do
let(:deleted_file) { true }
it "returns deleted ff state option" do
- expect(ff_changes.fetch).to eq("bulk_import_projects=deleted")
+ expect(ff_changes.fetch).to eq("async_commit_diff_files=deleted")
end
end
end
diff --git a/qa/spec/vendor/smocker_api_spec.rb b/qa/spec/vendor/smocker_api_spec.rb
new file mode 100644
index 00000000000..b54197b8b1f
--- /dev/null
+++ b/qa/spec/vendor/smocker_api_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe Vendor::Smocker::SmockerApi do
+ let(:host) { 'smocker.bar' }
+
+ subject { described_class.new(host: host) }
+
+ it 'retries until the service is ready' do
+ expect(subject).to receive(:get)
+ .and_raise(StandardError)
+ .and_raise(StandardError)
+ .and_return(200)
+
+ expect { subject.wait_for_ready }.not_to raise_error
+ end
+ end
+end
diff --git a/qa/tasks/ci.rake b/qa/tasks/ci.rake
index aaf691de1b5..e5f4acb158b 100644
--- a/qa/tasks/ci.rake
+++ b/qa/tasks/ci.rake
@@ -32,7 +32,7 @@ namespace :ci do
if run_all_label_present
logger.info(" merge request has pipeline:run-all-e2e label, full test suite will be executed")
- append_to_file(env_file, "QA_RUN_ALL_TESTS=true\n")
+ append_to_file(env_file, "QA_RUN_ALL_E2E_LABEL=true\n")
elsif qa_changes.framework_changes? # run all tests when framework changes detected
logger.info(" merge request contains qa framework changes, full test suite will be executed")
append_to_file(env_file, "QA_FRAMEWORK_CHANGES=true\n")
diff --git a/qa/tasks/webdrivers.rake b/qa/tasks/webdrivers.rake
index f4fa3fab555..cd2a36ddf6b 100644
--- a/qa/tasks/webdrivers.rake
+++ b/qa/tasks/webdrivers.rake
@@ -1,4 +1,3 @@
# frozen_string_literal: true
-require 'webdrivers'
load 'webdrivers/Rakefile'