summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/graphql_controller_spec.rb45
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb4
-rw-r--r--spec/factories/merge_requests.rb33
-rw-r--r--spec/factories/suggestions.rb6
-rw-r--r--spec/features/clusters/cluster_detail_page_spec.rb80
-rw-r--r--spec/features/issues/user_uses_quick_actions_spec.rb97
-rw-r--r--spec/features/merge_request/user_uses_quick_actions_spec.rb57
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb2
-rw-r--r--spec/features/milestone_spec.rb28
-rw-r--r--spec/features/projects/artifacts/user_browses_artifacts_spec.rb6
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb2
-rw-r--r--spec/features/snippets/notes_on_personal_snippets_spec.rb2
-rw-r--r--spec/features/snippets/user_creates_snippet_spec.rb2
-rw-r--r--spec/features/tags/master_deletes_tag_spec.rb2
-rw-r--r--spec/features/task_lists_spec.rb8
-rw-r--r--spec/features/users/login_spec.rb2
-rw-r--r--spec/frontend/.eslintrc.yml9
-rw-r--r--spec/frontend/environment.js33
-rw-r--r--spec/frontend/helpers/class_spec_helper.js9
-rw-r--r--spec/frontend/helpers/fixtures.js28
-rw-r--r--spec/frontend/helpers/locale_helper.js11
-rw-r--r--spec/frontend/helpers/scroll_into_view_promise.js28
-rw-r--r--spec/frontend/helpers/set_timeout_promise_helper.js4
-rw-r--r--spec/frontend/helpers/user_mock_data_helper.js14
-rw-r--r--spec/frontend/helpers/vue_component_helper.js18
-rw-r--r--spec/frontend/helpers/vue_resource_helper.js11
-rw-r--r--spec/frontend/helpers/vue_test_utils_helper.js19
-rw-r--r--spec/frontend/helpers/vuex_action_helper.js104
-rw-r--r--spec/frontend/helpers/wait_for_attribute_change.js16
-rw-r--r--spec/frontend/helpers/wait_for_promises.js1
-rw-r--r--spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js (renamed from spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js)6
-rw-r--r--spec/frontend/test_setup.js21
-rw-r--r--spec/helpers/appearances_helper_spec.rb8
-rw-r--r--spec/helpers/auth_helper_spec.rb2
-rw-r--r--spec/helpers/groups_helper_spec.rb2
-rw-r--r--spec/helpers/issuables_helper_spec.rb6
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb2
-rw-r--r--spec/javascripts/activities_spec.js2
-rw-r--r--spec/javascripts/ajax_loading_spinner_spec.js2
-rw-r--r--spec/javascripts/awards_handler_spec.js4
-rw-r--r--spec/javascripts/behaviors/quick_submit_spec.js4
-rw-r--r--spec/javascripts/behaviors/requires_input_spec.js4
-rw-r--r--spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js2
-rw-r--r--spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js4
-rw-r--r--spec/javascripts/blob/blob_file_dropzone_spec.js4
-rw-r--r--spec/javascripts/blob/notebook/index_spec.js4
-rw-r--r--spec/javascripts/blob/pdf/index_spec.js4
-rw-r--r--spec/javascripts/blob/sketch/index_spec.js4
-rw-r--r--spec/javascripts/blob/viewer/index_spec.js4
-rw-r--r--spec/javascripts/boards/components/board_spec.js2
-rw-r--r--spec/javascripts/bootstrap_linked_tabs_spec.js4
-rw-r--r--spec/javascripts/ci_variable_list/ajax_variable_list_spec.js8
-rw-r--r--spec/javascripts/ci_variable_list/ci_variable_list_spec.js16
-rw-r--r--spec/javascripts/ci_variable_list/native_form_variable_list_spec.js4
-rw-r--r--spec/javascripts/clusters/clusters_bundle_spec.js4
-rw-r--r--spec/javascripts/collapsed_sidebar_todo_spec.js2
-rw-r--r--spec/javascripts/create_item_dropdown_spec.js4
-rw-r--r--spec/javascripts/diffs/components/diff_file_header_spec.js3
-rw-r--r--spec/javascripts/diffs/mock_data/diff_discussions.js2
-rw-r--r--spec/javascripts/filtered_search/dropdown_user_spec.js2
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js2
-rw-r--r--spec/javascripts/fixtures/.gitignore1
-rw-r--r--spec/javascripts/fixtures/abuse_reports.rb2
-rw-r--r--spec/javascripts/fixtures/admin_users.rb2
-rw-r--r--spec/javascripts/fixtures/application_settings.rb2
-rw-r--r--spec/javascripts/fixtures/blob.rb2
-rw-r--r--spec/javascripts/fixtures/boards.rb2
-rw-r--r--spec/javascripts/fixtures/branches.rb2
-rw-r--r--spec/javascripts/fixtures/clusters.rb2
-rw-r--r--spec/javascripts/fixtures/commit.rb2
-rw-r--r--spec/javascripts/fixtures/groups.rb4
-rw-r--r--spec/javascripts/fixtures/issues.rb10
-rw-r--r--spec/javascripts/fixtures/jobs.rb2
-rw-r--r--spec/javascripts/fixtures/merge_requests.rb10
-rw-r--r--spec/javascripts/fixtures/pipeline_schedules.rb4
-rw-r--r--spec/javascripts/fixtures/projects.rb10
-rw-r--r--spec/javascripts/fixtures/prometheus_service.rb2
-rw-r--r--spec/javascripts/fixtures/search.rb2
-rw-r--r--spec/javascripts/fixtures/services.rb2
-rw-r--r--spec/javascripts/fixtures/sessions.rb2
-rw-r--r--spec/javascripts/fixtures/snippet.rb2
-rw-r--r--spec/javascripts/fixtures/static/ajax_loading_spinner.html (renamed from spec/javascripts/fixtures/static/ajax_loading_spinner.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/balsamiq_viewer.html (renamed from spec/javascripts/fixtures/static/balsamiq_viewer.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/create_item_dropdown.html (renamed from spec/javascripts/fixtures/static/create_item_dropdown.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/event_filter.html (renamed from spec/javascripts/fixtures/static/event_filter.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/gl_dropdown.html (renamed from spec/javascripts/fixtures/static/gl_dropdown.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/gl_field_errors.html (renamed from spec/javascripts/fixtures/static/gl_field_errors.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/issuable_filter.html (renamed from spec/javascripts/fixtures/static/issuable_filter.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/issue_sidebar_label.html (renamed from spec/javascripts/fixtures/static/issue_sidebar_label.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/line_highlighter.html (renamed from spec/javascripts/fixtures/static/line_highlighter.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/linked_tabs.html (renamed from spec/javascripts/fixtures/static/linked_tabs.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/merge_requests_show.html (renamed from spec/javascripts/fixtures/static/merge_requests_show.html.raw)2
-rw-r--r--spec/javascripts/fixtures/static/mini_dropdown_graph.html (renamed from spec/javascripts/fixtures/static/mini_dropdown_graph.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/notebook_viewer.html (renamed from spec/javascripts/fixtures/static/notebook_viewer.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/oauth_remember_me.html (renamed from spec/javascripts/fixtures/static/oauth_remember_me.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/pdf_viewer.html (renamed from spec/javascripts/fixtures/static/pdf_viewer.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/pipeline_graph.html (renamed from spec/javascripts/fixtures/static/pipeline_graph.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/pipelines.html (renamed from spec/javascripts/fixtures/static/pipelines.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/project_select_combo_button.html (renamed from spec/javascripts/fixtures/static/project_select_combo_button.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/search_autocomplete.html (renamed from spec/javascripts/fixtures/static/search_autocomplete.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/signin_tabs.html (renamed from spec/javascripts/fixtures/static/signin_tabs.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static/sketch_viewer.html (renamed from spec/javascripts/fixtures/static/sketch_viewer.html.raw)0
-rw-r--r--spec/javascripts/fixtures/static_fixtures.rb2
-rw-r--r--spec/javascripts/fixtures/todos.rb2
-rw-r--r--spec/javascripts/fixtures/u2f.rb4
-rw-r--r--spec/javascripts/gl_dropdown_spec.js4
-rw-r--r--spec/javascripts/gl_field_errors_spec.js4
-rw-r--r--spec/javascripts/header_spec.js2
-rw-r--r--spec/javascripts/ide/components/error_message_spec.js2
-rw-r--r--spec/javascripts/ide/stores/actions/file_spec.js74
-rw-r--r--spec/javascripts/integrations/integration_settings_form_spec.js2
-rw-r--r--spec/javascripts/issue_show/components/app_spec.js4
-rw-r--r--spec/javascripts/issue_show/components/description_spec.js4
-rw-r--r--spec/javascripts/issue_spec.js10
-rw-r--r--spec/javascripts/labels_issue_sidebar_spec.js4
-rw-r--r--spec/javascripts/lazy_loader_spec.js6
-rw-r--r--spec/javascripts/line_highlighter_spec.js4
-rw-r--r--spec/javascripts/merge_request_spec.js8
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js6
-rw-r--r--spec/javascripts/mini_pipeline_graph_dropdown_spec.js4
-rw-r--r--spec/javascripts/monitoring/charts/area_spec.js4
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js24
-rw-r--r--spec/javascripts/monitoring/mock_data.js5
-rw-r--r--spec/javascripts/new_branch_spec.js4
-rw-r--r--spec/javascripts/notes/components/note_app_spec.js12
-rw-r--r--spec/javascripts/notes/components/note_form_spec.js18
-rw-r--r--spec/javascripts/notes_spec.js2
-rw-r--r--spec/javascripts/oauth_remember_me_spec.js4
-rw-r--r--spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js2
-rw-r--r--spec/javascripts/pages/admin/users/new/index_spec.js2
-rw-r--r--spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js4
-rw-r--r--spec/javascripts/pipelines/graph/action_component_spec.js17
-rw-r--r--spec/javascripts/pipelines/graph/stage_column_component_spec.js2
-rw-r--r--spec/javascripts/pipelines/stage_spec.js16
-rw-r--r--spec/javascripts/pipelines_spec.js4
-rw-r--r--spec/javascripts/project_select_combo_button_spec.js2
-rw-r--r--spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js44
-rw-r--r--spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js2
-rw-r--r--spec/javascripts/read_more_spec.js2
-rw-r--r--spec/javascripts/right_sidebar_spec.js2
-rw-r--r--spec/javascripts/search_autocomplete_spec.js4
-rw-r--r--spec/javascripts/search_spec.js2
-rw-r--r--spec/javascripts/settings_panels_spec.js4
-rw-r--r--spec/javascripts/shortcuts_spec.js2
-rw-r--r--spec/javascripts/sidebar/assignees_spec.js13
-rw-r--r--spec/javascripts/sidebar/sidebar_assignees_spec.js4
-rw-r--r--spec/javascripts/signin_tabs_memoizer_spec.js2
-rw-r--r--spec/javascripts/todos_spec.js4
-rw-r--r--spec/javascripts/u2f/authenticate_spec.js4
-rw-r--r--spec/javascripts/u2f/register_spec.js4
-rw-r--r--spec/javascripts/user_popovers_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/markdown/field_spec.js8
-rw-r--r--spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js2
-rw-r--r--spec/javascripts/zen_mode_spec.js2
-rw-r--r--spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb47
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb19
-rw-r--r--spec/lib/gitlab/current_settings_spec.rb15
-rw-r--r--spec/lib/gitlab/diff/suggestion_spec.rb88
-rw-r--r--spec/lib/gitlab/diff/suggestions_parser_spec.rb73
-rw-r--r--spec/lib/gitlab/git/pre_receive_error_spec.rb16
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb15
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb10
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb10
-rw-r--r--spec/lib/gitlab/gl_repository/repo_type_spec.rb64
-rw-r--r--spec/lib/gitlab/gl_repository_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml4
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml11
-rw-r--r--spec/lib/gitlab/quick_actions/command_definition_spec.rb30
-rw-r--r--spec/lib/gitlab/quick_actions/dsl_spec.rb26
-rw-r--r--spec/lib/gitlab/repo_path_spec.rb20
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb10
-rw-r--r--spec/lib/gitlab_spec.rb2
-rw-r--r--spec/lib/sentry/client_spec.rb85
-rw-r--r--spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb26
-rw-r--r--spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb24
-rw-r--r--spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb12
-rw-r--r--spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb20
-rw-r--r--spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb12
-rw-r--r--spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb22
-rw-r--r--spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb47
-rw-r--r--spec/models/ability_spec.rb2
-rw-r--r--spec/models/abuse_report_spec.rb2
-rw-r--r--spec/models/active_session_spec.rb2
-rw-r--r--spec/models/appearance_spec.rb2
-rw-r--r--spec/models/application_setting/term_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb2
-rw-r--r--spec/models/award_emoji_spec.rb2
-rw-r--r--spec/models/badge_spec.rb2
-rw-r--r--spec/models/badges/group_badge_spec.rb2
-rw-r--r--spec/models/badges/project_badge_spec.rb2
-rw-r--r--spec/models/blob_spec.rb2
-rw-r--r--spec/models/blob_viewer/base_spec.rb2
-rw-r--r--spec/models/blob_viewer/changelog_spec.rb2
-rw-r--r--spec/models/blob_viewer/composer_json_spec.rb2
-rw-r--r--spec/models/blob_viewer/gemspec_spec.rb2
-rw-r--r--spec/models/blob_viewer/gitlab_ci_yml_spec.rb2
-rw-r--r--spec/models/blob_viewer/license_spec.rb2
-rw-r--r--spec/models/blob_viewer/package_json_spec.rb2
-rw-r--r--spec/models/blob_viewer/podspec_json_spec.rb2
-rw-r--r--spec/models/blob_viewer/podspec_spec.rb2
-rw-r--r--spec/models/blob_viewer/readme_spec.rb2
-rw-r--r--spec/models/blob_viewer/route_map_spec.rb2
-rw-r--r--spec/models/blob_viewer/server_side_spec.rb2
-rw-r--r--spec/models/board_spec.rb2
-rw-r--r--spec/models/broadcast_message_spec.rb2
-rw-r--r--spec/models/chat_name_spec.rb2
-rw-r--r--spec/models/chat_team_spec.rb2
-rw-r--r--spec/models/ci/artifact_blob_spec.rb2
-rw-r--r--spec/models/ci/bridge_spec.rb2
-rw-r--r--spec/models/ci/build_metadata_spec.rb2
-rw-r--r--spec/models/ci/build_runner_session_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb22
-rw-r--r--spec/models/ci/build_trace_chunks/database_spec.rb2
-rw-r--r--spec/models/ci/build_trace_chunks/fog_spec.rb2
-rw-r--r--spec/models/ci/build_trace_chunks/redis_spec.rb2
-rw-r--r--spec/models/ci/build_trace_section_name_spec.rb2
-rw-r--r--spec/models/ci/build_trace_section_spec.rb2
-rw-r--r--spec/models/ci/group_spec.rb2
-rw-r--r--spec/models/ci/group_variable_spec.rb2
-rw-r--r--spec/models/ci/job_artifact_spec.rb2
-rw-r--r--spec/models/ci/legacy_stage_spec.rb2
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb2
-rw-r--r--spec/models/ci/pipeline_schedule_variable_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb46
-rw-r--r--spec/models/ci/pipeline_variable_spec.rb2
-rw-r--r--spec/models/ci/runner_spec.rb2
-rw-r--r--spec/models/ci/stage_spec.rb2
-rw-r--r--spec/models/ci/trigger_request_spec.rb2
-rw-r--r--spec/models/ci/trigger_spec.rb2
-rw-r--r--spec/models/ci/variable_spec.rb2
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb29
-rw-r--r--spec/models/clusters/applications/helm_spec.rb2
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb2
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb2
-rw-r--r--spec/models/clusters/applications/knative_spec.rb4
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb2
-rw-r--r--spec/models/clusters/applications/runner_spec.rb2
-rw-r--r--spec/models/clusters/cluster_spec.rb16
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb4
-rw-r--r--spec/models/clusters/project_spec.rb2
-rw-r--r--spec/models/clusters/providers/gcp_spec.rb2
-rw-r--r--spec/models/commit_collection_spec.rb2
-rw-r--r--spec/models/commit_range_spec.rb2
-rw-r--r--spec/models/commit_spec.rb2
-rw-r--r--spec/models/commit_status_spec.rb2
-rw-r--r--spec/models/compare_spec.rb2
-rw-r--r--spec/models/concerns/access_requestable_spec.rb2
-rw-r--r--spec/models/concerns/avatarable_spec.rb2
-rw-r--r--spec/models/concerns/awardable_spec.rb2
-rw-r--r--spec/models/concerns/batch_destroy_dependent_associations_spec.rb2
-rw-r--r--spec/models/concerns/blocks_json_serialization_spec.rb2
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb2
-rw-r--r--spec/models/concerns/cacheable_attributes_spec.rb2
-rw-r--r--spec/models/concerns/case_sensitivity_spec.rb2
-rw-r--r--spec/models/concerns/chronic_duration_attribute_spec.rb2
-rw-r--r--spec/models/concerns/deployable_spec.rb2
-rw-r--r--spec/models/concerns/deployment_platform_spec.rb2
-rw-r--r--spec/models/concerns/discussion_on_diff_spec.rb2
-rw-r--r--spec/models/concerns/each_batch_spec.rb2
-rw-r--r--spec/models/concerns/editable_spec.rb2
-rw-r--r--spec/models/concerns/expirable_spec.rb2
-rw-r--r--spec/models/concerns/faster_cache_keys_spec.rb2
-rw-r--r--spec/models/concerns/feature_gate_spec.rb2
-rw-r--r--spec/models/concerns/group_descendant_spec.rb2
-rw-r--r--spec/models/concerns/has_status_spec.rb2
-rw-r--r--spec/models/concerns/has_variable_spec.rb2
-rw-r--r--spec/models/concerns/ignorable_column_spec.rb2
-rw-r--r--spec/models/concerns/issuable_spec.rb2
-rw-r--r--spec/models/concerns/loaded_in_group_list_spec.rb2
-rw-r--r--spec/models/concerns/manual_inverse_association_spec.rb2
-rw-r--r--spec/models/concerns/mentionable_spec.rb2
-rw-r--r--spec/models/concerns/milestoneish_spec.rb2
-rw-r--r--spec/models/concerns/noteable_spec.rb2
-rw-r--r--spec/models/concerns/participable_spec.rb2
-rw-r--r--spec/models/concerns/presentable_spec.rb2
-rw-r--r--spec/models/concerns/project_features_compatibility_spec.rb2
-rw-r--r--spec/models/concerns/prometheus_adapter_spec.rb2
-rw-r--r--spec/models/concerns/protected_ref_access_spec.rb2
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb2
-rw-r--r--spec/models/concerns/redactable_spec.rb2
-rw-r--r--spec/models/concerns/redis_cacheable_spec.rb2
-rw-r--r--spec/models/concerns/relative_positioning_spec.rb2
-rw-r--r--spec/models/concerns/resolvable_discussion_spec.rb2
-rw-r--r--spec/models/concerns/resolvable_note_spec.rb2
-rw-r--r--spec/models/concerns/routable_spec.rb2
-rw-r--r--spec/models/concerns/sha_attribute_spec.rb2
-rw-r--r--spec/models/concerns/sortable_spec.rb2
-rw-r--r--spec/models/concerns/spammable_spec.rb2
-rw-r--r--spec/models/concerns/strip_attribute_spec.rb2
-rw-r--r--spec/models/concerns/subscribable_spec.rb2
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb2
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/base_spec.rb2
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb2
-rw-r--r--spec/models/concerns/triggerable_hooks_spec.rb2
-rw-r--r--spec/models/concerns/uniquify_spec.rb2
-rw-r--r--spec/models/container_repository_spec.rb2
-rw-r--r--spec/models/conversational_development_index/metric_spec.rb2
-rw-r--r--spec/models/cycle_analytics/code_spec.rb2
-rw-r--r--spec/models/cycle_analytics/issue_spec.rb2
-rw-r--r--spec/models/cycle_analytics/plan_spec.rb2
-rw-r--r--spec/models/cycle_analytics/production_spec.rb2
-rw-r--r--spec/models/cycle_analytics/review_spec.rb2
-rw-r--r--spec/models/cycle_analytics/staging_spec.rb2
-rw-r--r--spec/models/cycle_analytics/test_spec.rb2
-rw-r--r--spec/models/cycle_analytics_spec.rb2
-rw-r--r--spec/models/deploy_key_spec.rb2
-rw-r--r--spec/models/deploy_keys_project_spec.rb2
-rw-r--r--spec/models/deploy_token_spec.rb2
-rw-r--r--spec/models/deployment_spec.rb2
-rw-r--r--spec/models/diff_discussion_spec.rb2
-rw-r--r--spec/models/diff_note_spec.rb2
-rw-r--r--spec/models/diff_viewer/base_spec.rb2
-rw-r--r--spec/models/diff_viewer/server_side_spec.rb2
-rw-r--r--spec/models/discussion_spec.rb2
-rw-r--r--spec/models/email_spec.rb2
-rw-r--r--spec/models/environment_spec.rb2
-rw-r--r--spec/models/environment_status_spec.rb2
-rw-r--r--spec/models/error_tracking/project_error_tracking_setting_spec.rb28
-rw-r--r--spec/models/event_collection_spec.rb2
-rw-r--r--spec/models/event_spec.rb2
-rw-r--r--spec/models/external_issue_spec.rb2
-rw-r--r--spec/models/fork_network_member_spec.rb2
-rw-r--r--spec/models/fork_network_spec.rb2
-rw-r--r--spec/models/generic_commit_status_spec.rb2
-rw-r--r--spec/models/global_milestone_spec.rb2
-rw-r--r--spec/models/gpg_key_spec.rb2
-rw-r--r--spec/models/gpg_key_subkey_spec.rb2
-rw-r--r--spec/models/gpg_signature_spec.rb2
-rw-r--r--spec/models/group_custom_attribute_spec.rb2
-rw-r--r--spec/models/group_label_spec.rb2
-rw-r--r--spec/models/group_milestone_spec.rb2
-rw-r--r--spec/models/group_spec.rb2
-rw-r--r--spec/models/guest_spec.rb2
-rw-r--r--spec/models/hooks/active_hook_filter_spec.rb2
-rw-r--r--spec/models/hooks/project_hook_spec.rb2
-rw-r--r--spec/models/hooks/service_hook_spec.rb2
-rw-r--r--spec/models/hooks/system_hook_spec.rb2
-rw-r--r--spec/models/hooks/web_hook_log_spec.rb2
-rw-r--r--spec/models/hooks/web_hook_spec.rb2
-rw-r--r--spec/models/identity_spec.rb2
-rw-r--r--spec/models/import_export_upload_spec.rb2
-rw-r--r--spec/models/instance_configuration_spec.rb6
-rw-r--r--spec/models/internal_id_spec.rb2
-rw-r--r--spec/models/issue/metrics_spec.rb2
-rw-r--r--spec/models/issue_collection_spec.rb2
-rw-r--r--spec/models/issue_spec.rb2
-rw-r--r--spec/models/key_spec.rb2
-rw-r--r--spec/models/label_link_spec.rb2
-rw-r--r--spec/models/label_priority_spec.rb2
-rw-r--r--spec/models/label_spec.rb2
-rw-r--r--spec/models/legacy_diff_discussion_spec.rb2
-rw-r--r--spec/models/lfs_download_object_spec.rb2
-rw-r--r--spec/models/lfs_file_lock_spec.rb2
-rw-r--r--spec/models/lfs_object_spec.rb2
-rw-r--r--spec/models/lfs_objects_project_spec.rb2
-rw-r--r--spec/models/license_template_spec.rb15
-rw-r--r--spec/models/list_spec.rb2
-rw-r--r--spec/models/member_spec.rb2
-rw-r--r--spec/models/members/group_member_spec.rb18
-rw-r--r--spec/models/members/project_member_spec.rb2
-rw-r--r--spec/models/merge_request/metrics_spec.rb2
-rw-r--r--spec/models/merge_request_diff_commit_spec.rb2
-rw-r--r--spec/models/merge_request_diff_file_spec.rb2
-rw-r--r--spec/models/merge_request_diff_spec.rb149
-rw-r--r--spec/models/merge_request_spec.rb68
-rw-r--r--spec/models/milestone_spec.rb2
-rw-r--r--spec/models/namespace_spec.rb2
-rw-r--r--spec/models/network/graph_spec.rb2
-rw-r--r--spec/models/note_diff_file_spec.rb2
-rw-r--r--spec/models/note_spec.rb2
-rw-r--r--spec/models/notification_recipient_spec.rb2
-rw-r--r--spec/models/notification_setting_spec.rb2
-rw-r--r--spec/models/pages_domain_spec.rb2
-rw-r--r--spec/models/personal_access_token_spec.rb2
-rw-r--r--spec/models/programming_language_spec.rb2
-rw-r--r--spec/models/project_authorization_spec.rb2
-rw-r--r--spec/models/project_auto_devops_spec.rb2
-rw-r--r--spec/models/project_custom_attribute_spec.rb2
-rw-r--r--spec/models/project_deploy_token_spec.rb2
-rw-r--r--spec/models/project_feature_spec.rb2
-rw-r--r--spec/models/project_group_link_spec.rb2
-rw-r--r--spec/models/project_import_state_spec.rb2
-rw-r--r--spec/models/project_label_spec.rb2
-rw-r--r--spec/models/project_services/asana_service_spec.rb2
-rw-r--r--spec/models/project_services/assembla_service_spec.rb2
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb2
-rw-r--r--spec/models/project_services/bugzilla_service_spec.rb2
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb2
-rw-r--r--spec/models/project_services/campfire_service_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/issue_message_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/merge_message_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/note_message_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/pipeline_message_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/push_message_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/wiki_page_message_spec.rb2
-rw-r--r--spec/models/project_services/chat_notification_service_spec.rb2
-rw-r--r--spec/models/project_services/custom_issue_tracker_service_spec.rb2
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb2
-rw-r--r--spec/models/project_services/emails_on_push_service_spec.rb2
-rw-r--r--spec/models/project_services/external_wiki_service_spec.rb2
-rw-r--r--spec/models/project_services/flowdock_service_spec.rb2
-rw-r--r--spec/models/project_services/gitlab_issue_tracker_service_spec.rb2
-rw-r--r--spec/models/project_services/irker_service_spec.rb2
-rw-r--r--spec/models/project_services/issue_tracker_service_spec.rb2
-rw-r--r--spec/models/project_services/jira_service_spec.rb2
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb2
-rw-r--r--spec/models/project_services/mattermost_service_spec.rb2
-rw-r--r--spec/models/project_services/mattermost_slash_commands_service_spec.rb2
-rw-r--r--spec/models/project_services/microsoft_teams_service_spec.rb2
-rw-r--r--spec/models/project_services/packagist_service_spec.rb2
-rw-r--r--spec/models/project_services/pipelines_email_service_spec.rb2
-rw-r--r--spec/models/project_services/pivotaltracker_service_spec.rb2
-rw-r--r--spec/models/project_services/pushover_service_spec.rb2
-rw-r--r--spec/models/project_services/redmine_service_spec.rb2
-rw-r--r--spec/models/project_services/slack_service_spec.rb2
-rw-r--r--spec/models/project_services/slack_slash_commands_service_spec.rb2
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb2
-rw-r--r--spec/models/project_services/youtrack_service_spec.rb2
-rw-r--r--spec/models/project_snippet_spec.rb2
-rw-r--r--spec/models/project_spec.rb65
-rw-r--r--spec/models/project_statistics_spec.rb2
-rw-r--r--spec/models/project_team_spec.rb2
-rw-r--r--spec/models/project_wiki_spec.rb2
-rw-r--r--spec/models/protectable_dropdown_spec.rb2
-rw-r--r--spec/models/protected_branch/merge_access_level_spec.rb2
-rw-r--r--spec/models/protected_branch/push_access_level_spec.rb2
-rw-r--r--spec/models/protected_branch_spec.rb2
-rw-r--r--spec/models/protected_tag_spec.rb2
-rw-r--r--spec/models/push_event_payload_spec.rb2
-rw-r--r--spec/models/push_event_spec.rb2
-rw-r--r--spec/models/redirect_route_spec.rb2
-rw-r--r--spec/models/release_spec.rb2
-rw-r--r--spec/models/remote_mirror_spec.rb2
-rw-r--r--spec/models/repository_language_spec.rb2
-rw-r--r--spec/models/repository_spec.rb2
-rw-r--r--spec/models/route_spec.rb2
-rw-r--r--spec/models/sent_notification_spec.rb2
-rw-r--r--spec/models/service_spec.rb2
-rw-r--r--spec/models/snippet_blob_spec.rb2
-rw-r--r--spec/models/snippet_spec.rb2
-rw-r--r--spec/models/spam_log_spec.rb2
-rw-r--r--spec/models/ssh_host_key_spec.rb2
-rw-r--r--spec/models/subscription_spec.rb2
-rw-r--r--spec/models/system_note_metadata_spec.rb2
-rw-r--r--spec/models/term_agreement_spec.rb2
-rw-r--r--spec/models/timelog_spec.rb2
-rw-r--r--spec/models/todo_spec.rb2
-rw-r--r--spec/models/tree_spec.rb2
-rw-r--r--spec/models/trending_project_spec.rb2
-rw-r--r--spec/models/upload_spec.rb2
-rw-r--r--spec/models/user_agent_detail_spec.rb2
-rw-r--r--spec/models/user_callout_spec.rb2
-rw-r--r--spec/models/user_custom_attribute_spec.rb2
-rw-r--r--spec/models/user_interacted_project_spec.rb2
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/models/wiki_directory_spec.rb2
-rw-r--r--spec/models/wiki_page_spec.rb2
-rw-r--r--spec/policies/board_policy_spec.rb8
-rw-r--r--spec/policies/group_policy_spec.rb58
-rw-r--r--spec/policies/namespace_policy_spec.rb2
-rw-r--r--spec/policies/project_policy_spec.rb324
-rw-r--r--spec/policies/project_snippet_policy_spec.rb109
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb38
-rw-r--r--spec/presenters/clusters/cluster_presenter_spec.rb16
-rw-r--r--spec/requests/api/branches_spec.rb26
-rw-r--r--spec/requests/api/internal_spec.rb6
-rw-r--r--spec/requests/api/projects_spec.rb10
-rw-r--r--spec/requests/api/suggestions_spec.rb3
-rw-r--r--spec/rubocop/cop/migration/update_column_in_batches_spec.rb18
-rw-r--r--spec/serializers/suggestion_entity_spec.rb4
-rw-r--r--spec/services/error_tracking/list_issues_service_spec.rb24
-rw-r--r--spec/services/issues/create_service_spec.rb14
-rw-r--r--spec/services/issues/update_service_spec.rb10
-rw-r--r--spec/services/merge_requests/create_service_spec.rb48
-rw-r--r--spec/services/merge_requests/ff_merge_service_spec.rb2
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb2
-rw-r--r--spec/services/merge_requests/migrate_external_diffs_service_spec.rb43
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb79
-rw-r--r--spec/services/projects/participants_service_spec.rb53
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb1
-rw-r--r--spec/services/suggestions/apply_service_spec.rb93
-rw-r--r--spec/services/suggestions/create_service_spec.rb73
-rw-r--r--spec/services/suggestions/outdate_service_spec.rb102
-rw-r--r--spec/services/tags/create_service_spec.rb2
-rw-r--r--spec/services/verify_pages_domain_service_spec.rb142
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/api/milestones_shared_examples.rb9
-rw-r--r--spec/support/features/issuable_quick_actions_shared_examples.rb389
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb2
-rw-r--r--spec/support/helpers/license_helper.rb8
-rw-r--r--spec/support/helpers/policy_helpers.rb11
-rw-r--r--spec/support/helpers/stub_worker.rb9
-rw-r--r--spec/support/matchers/issuable_matchers.rb2
-rw-r--r--spec/support/shared_context/policies/project_policy_shared_context.rb88
-rw-r--r--spec/support/shared_contexts/policies/group_policy_shared_context.rb47
-rw-r--r--spec/support/shared_examples/policies/project_policy_shared_examples.rb231
-rw-r--r--spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb110
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb63
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb89
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb88
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb103
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb81
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb83
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb84
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb83
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb95
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb82
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb86
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb82
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb86
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb60
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb81
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb84
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb60
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb98
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb85
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb92
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb120
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb102
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb87
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb86
-rw-r--r--spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb25
-rw-r--r--spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb25
-rw-r--r--spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb4
-rw-r--r--spec/uploaders/object_storage_spec.rb2
-rw-r--r--spec/workers/migrate_external_diffs_worker_spec.rb25
-rw-r--r--spec/workers/schedule_migrate_external_diffs_worker_spec.rb25
540 files changed, 5954 insertions, 1519 deletions
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
new file mode 100644
index 00000000000..c19a752b07b
--- /dev/null
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GraphqlController do
+ before do
+ stub_feature_flags(graphql: true)
+ end
+
+ describe 'POST #execute' do
+ context 'when user is logged in' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'returns 200 when user can access API' do
+ post :execute
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ it 'returns access denied template when user cannot access API' do
+ # User cannot access API in a couple of cases
+ # * When user is internal(like ghost users)
+ # * When user is blocked
+ expect(Ability).to receive(:allowed?).with(user, :access_api, :global).and_return(false)
+
+ post :execute
+
+ expect(response.status).to eq(403)
+ expect(response).to render_template('errors/access_denied')
+ end
+ end
+
+ context 'when user is not logged in' do
+ it 'returns 200' do
+ post :execute
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 79f97aa4170..c8fa93a74ee 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -86,6 +86,10 @@ describe Projects::MergeRequestsController do
end
describe 'as json' do
+ before do
+ expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
+ end
+
context 'with basic serializer param' do
it 'renders basic MR entity as json' do
go(serializer: 'basic', format: :json)
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index a73f330a7a9..abf0e6bccb7 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -46,10 +46,26 @@ FactoryBot.define do
target_branch "improve/awesome"
end
+ trait :merged_last_month do
+ merged
+
+ after(:build) do |merge_request|
+ merge_request.build_metrics.merged_at = 1.month.ago
+ end
+ end
+
trait :closed do
state :closed
end
+ trait :closed_last_month do
+ closed
+
+ after(:build) do |merge_request|
+ merge_request.build_metrics.latest_closed_at = 1.month.ago
+ end
+ end
+
trait :opened do
state :opened
end
@@ -101,9 +117,20 @@ FactoryBot.define do
end
end
+ trait :with_legacy_detached_merge_request_pipeline do
+ after(:create) do |merge_request|
+ merge_request.merge_request_pipelines << create(:ci_pipeline,
+ source: :merge_request_event,
+ merge_request: merge_request,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.source_branch_sha)
+ end
+ end
+
trait :with_detached_merge_request_pipeline do
- after(:build) do |merge_request|
- merge_request.merge_request_pipelines << build(:ci_pipeline,
+ after(:create) do |merge_request|
+ merge_request.merge_request_pipelines << create(:ci_pipeline,
source: :merge_request_event,
merge_request: merge_request,
project: merge_request.source_project,
@@ -119,7 +146,7 @@ FactoryBot.define do
target_sha { target_branch_sha }
end
- after(:build) do |merge_request, evaluator|
+ after(:create) do |merge_request, evaluator|
merge_request.merge_request_pipelines << create(:ci_pipeline,
source: :merge_request_event,
merge_request: merge_request,
diff --git a/spec/factories/suggestions.rb b/spec/factories/suggestions.rb
index 307523cc061..b1427e0211f 100644
--- a/spec/factories/suggestions.rb
+++ b/spec/factories/suggestions.rb
@@ -16,5 +16,11 @@ FactoryBot.define do
applied true
commit_id { RepoHelpers.sample_commit.id }
end
+
+ trait :content_from_repo do
+ after(:build) do |suggestion, evaluator|
+ suggestion.from_content = suggestion.fetch_from_content
+ end
+ end
end
end
diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb
index b9fc52d0dce..d2e46d15730 100644
--- a/spec/features/clusters/cluster_detail_page_spec.rb
+++ b/spec/features/clusters/cluster_detail_page_spec.rb
@@ -53,12 +53,80 @@ describe 'Clusterable > Show page' do
end
end
+ shared_examples 'editing a GCP cluster' do
+ before do
+ clusterable.add_maintainer(current_user)
+ visit cluster_path
+ end
+
+ it 'is not able to edit the name, API url, CA certificate nor token' do
+ within('#js-cluster-details') do
+ cluster_name_field = find('.cluster-name')
+ api_url_field = find('#cluster_platform_kubernetes_attributes_api_url')
+ ca_certificate_field = find('#cluster_platform_kubernetes_attributes_ca_cert')
+ token_field = find('#cluster_platform_kubernetes_attributes_token')
+
+ expect(cluster_name_field).to be_readonly
+ expect(api_url_field).to be_readonly
+ expect(ca_certificate_field).to be_readonly
+ expect(token_field).to be_readonly
+ end
+ end
+
+ it 'displays GKE information' do
+ within('#advanced-settings-section') do
+ expect(page).to have_content('Google Kubernetes Engine')
+ expect(page).to have_content('Manage your Kubernetes cluster by visiting')
+ end
+ end
+ end
+
+ shared_examples 'editing a user-provided cluster' do
+ before do
+ clusterable.add_maintainer(current_user)
+ visit cluster_path
+ end
+
+ it 'is able to edit the name, API url, CA certificate and token' do
+ within('#js-cluster-details') do
+ cluster_name_field = find('#cluster_name')
+ api_url_field = find('#cluster_platform_kubernetes_attributes_api_url')
+ ca_certificate_field = find('#cluster_platform_kubernetes_attributes_ca_cert')
+ token_field = find('#cluster_platform_kubernetes_attributes_token')
+
+ expect(cluster_name_field).not_to be_readonly
+ expect(api_url_field).not_to be_readonly
+ expect(ca_certificate_field).not_to be_readonly
+ expect(token_field).not_to be_readonly
+ end
+ end
+
+ it 'does not display GKE information' do
+ within('#advanced-settings-section') do
+ expect(page).not_to have_content('Google Kubernetes Engine')
+ expect(page).not_to have_content('Manage your Kubernetes cluster by visiting')
+ end
+ end
+ end
+
context 'when clusterable is a project' do
it_behaves_like 'editing domain' do
let(:clusterable) { create(:project) }
let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) }
let(:cluster_path) { project_cluster_path(clusterable, cluster) }
end
+
+ it_behaves_like 'editing a GCP cluster' do
+ let(:clusterable) { create(:project) }
+ let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) }
+ let(:cluster_path) { project_cluster_path(clusterable, cluster) }
+ end
+
+ it_behaves_like 'editing a user-provided cluster' do
+ let(:clusterable) { create(:project) }
+ let(:cluster) { create(:cluster, :provided_by_user, :project, projects: [clusterable]) }
+ let(:cluster_path) { project_cluster_path(clusterable, cluster) }
+ end
end
context 'when clusterable is a group' do
@@ -67,5 +135,17 @@ describe 'Clusterable > Show page' do
let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) }
let(:cluster_path) { group_cluster_path(clusterable, cluster) }
end
+
+ it_behaves_like 'editing a GCP cluster' do
+ let(:clusterable) { create(:group) }
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) }
+ let(:cluster_path) { group_cluster_path(clusterable, cluster) }
+ end
+
+ it_behaves_like 'editing a user-provided cluster' do
+ let(:clusterable) { create(:group) }
+ let(:cluster) { create(:cluster, :provided_by_user, :group, groups: [clusterable]) }
+ let(:cluster_path) { group_cluster_path(clusterable, cluster) }
+ end
end
end
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index b5e7c3954e2..362f8a468ec 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -3,8 +3,41 @@ require 'rails_helper'
describe 'Issues > User uses quick actions', :js do
include Spec::Support::Helpers::Features::NotesHelpers
- it_behaves_like 'issuable record that supports quick actions in its description and notes', :issue do
+ context "issuable common quick actions" do
+ let(:new_url_opts) { {} }
+ let(:maintainer) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let!(:label_bug) { create(:label, project: project, title: 'bug') }
+ let!(:label_feature) { create(:label, project: project, title: 'feature') }
+ let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
let(:issuable) { create(:issue, project: project) }
+ let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])}
+
+ it_behaves_like 'assign quick action', :issue
+ it_behaves_like 'unassign quick action', :issue
+ it_behaves_like 'close quick action', :issue
+ it_behaves_like 'reopen quick action', :issue
+ it_behaves_like 'title quick action', :issue
+ it_behaves_like 'todo quick action', :issue
+ it_behaves_like 'done quick action', :issue
+ it_behaves_like 'subscribe quick action', :issue
+ it_behaves_like 'unsubscribe quick action', :issue
+ it_behaves_like 'lock quick action', :issue
+ it_behaves_like 'unlock quick action', :issue
+ it_behaves_like 'milestone quick action', :issue
+ it_behaves_like 'remove_milestone quick action', :issue
+ it_behaves_like 'label quick action', :issue
+ it_behaves_like 'unlabel quick action', :issue
+ it_behaves_like 'relabel quick action', :issue
+ it_behaves_like 'award quick action', :issue
+ it_behaves_like 'estimate quick action', :issue
+ it_behaves_like 'remove_estimate quick action', :issue
+ it_behaves_like 'spend quick action', :issue
+ it_behaves_like 'remove_time_spent quick action', :issue
+ it_behaves_like 'shrug quick action', :issue
+ it_behaves_like 'tableflip quick action', :issue
+ it_behaves_like 'copy_metadata quick action', :issue
+ it_behaves_like 'issuable time tracker', :issue
end
describe 'issue-only commands' do
@@ -15,37 +48,17 @@ describe 'Issues > User uses quick actions', :js do
project.add_maintainer(user)
sign_in(user)
visit project_issue_path(project, issue)
+ wait_for_all_requests
end
after do
wait_for_requests
end
- describe 'time tracking' do
- let(:issue) { create(:issue, project: project) }
-
- before do
- visit project_issue_path(project, issue)
- end
-
- it_behaves_like 'issuable time tracker'
- end
-
describe 'adding a due date from note' do
let(:issue) { create(:issue, project: project) }
- context 'when the current user can update the due date' do
- it 'does not create a note, and sets the due date accordingly' do
- add_note("/due 2016-08-28")
-
- expect(page).not_to have_content '/due 2016-08-28'
- expect(page).to have_content 'Commands applied'
-
- issue.reload
-
- expect(issue.due_date).to eq Date.new(2016, 8, 28)
- end
- end
+ it_behaves_like 'due quick action available and date can be added'
context 'when the current user cannot update the due date' do
let(:guest) { create(:user) }
@@ -56,35 +69,14 @@ describe 'Issues > User uses quick actions', :js do
visit project_issue_path(project, issue)
end
- it 'does not create a note, and sets the due date accordingly' do
- add_note("/due 2016-08-28")
-
- expect(page).not_to have_content 'Commands applied'
-
- issue.reload
-
- expect(issue.due_date).to be_nil
- end
+ it_behaves_like 'due quick action not available'
end
end
describe 'removing a due date from note' do
let(:issue) { create(:issue, project: project, due_date: Date.new(2016, 8, 28)) }
- context 'when the current user can update the due date' do
- it 'does not create a note, and removes the due date accordingly' do
- expect(issue.due_date).to eq Date.new(2016, 8, 28)
-
- add_note("/remove_due_date")
-
- expect(page).not_to have_content '/remove_due_date'
- expect(page).to have_content 'Commands applied'
-
- issue.reload
-
- expect(issue.due_date).to be_nil
- end
- end
+ it_behaves_like 'remove_due_date action available and due date can be removed'
context 'when the current user cannot update the due date' do
let(:guest) { create(:user) }
@@ -95,15 +87,7 @@ describe 'Issues > User uses quick actions', :js do
visit project_issue_path(project, issue)
end
- it 'does not create a note, and sets the due date accordingly' do
- add_note("/remove_due_date")
-
- expect(page).not_to have_content 'Commands applied'
-
- issue.reload
-
- expect(issue.due_date).to eq Date.new(2016, 8, 28)
- end
+ it_behaves_like 'remove_due_date action not available'
end
end
@@ -200,6 +184,7 @@ describe 'Issues > User uses quick actions', :js do
gitlab_sign_out
sign_in(user)
visit project_issue_path(project, issue)
+ wait_for_requests
end
it 'moves the issue' do
@@ -221,6 +206,7 @@ describe 'Issues > User uses quick actions', :js do
gitlab_sign_out
sign_in(user)
visit project_issue_path(project, issue)
+ wait_for_requests
end
it 'does not move the issue' do
@@ -238,6 +224,7 @@ describe 'Issues > User uses quick actions', :js do
gitlab_sign_out
sign_in(user)
visit project_issue_path(project, issue)
+ wait_for_requests
end
it 'does not move the issue' do
diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb
index b81478a481f..a2b5859bd1e 100644
--- a/spec/features/merge_request/user_uses_quick_actions_spec.rb
+++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb
@@ -9,9 +9,41 @@ describe 'Merge request > User uses quick actions', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
- it_behaves_like 'issuable record that supports quick actions in its description and notes', :merge_request do
+ context "issuable common quick actions" do
+ let!(:new_url_opts) { { merge_request: { source_branch: 'feature', target_branch: 'master' } } }
+ let(:maintainer) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+ let!(:label_bug) { create(:label, project: project, title: 'bug') }
+ let!(:label_feature) { create(:label, project: project, title: 'feature') }
+ let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
let(:issuable) { create(:merge_request, source_project: project) }
- let(:new_url_opts) { { merge_request: { source_branch: 'feature', target_branch: 'master' } } }
+ let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])}
+
+ it_behaves_like 'assign quick action', :merge_request
+ it_behaves_like 'unassign quick action', :merge_request
+ it_behaves_like 'close quick action', :merge_request
+ it_behaves_like 'reopen quick action', :merge_request
+ it_behaves_like 'title quick action', :merge_request
+ it_behaves_like 'todo quick action', :merge_request
+ it_behaves_like 'done quick action', :merge_request
+ it_behaves_like 'subscribe quick action', :merge_request
+ it_behaves_like 'unsubscribe quick action', :merge_request
+ it_behaves_like 'lock quick action', :merge_request
+ it_behaves_like 'unlock quick action', :merge_request
+ it_behaves_like 'milestone quick action', :merge_request
+ it_behaves_like 'remove_milestone quick action', :merge_request
+ it_behaves_like 'label quick action', :merge_request
+ it_behaves_like 'unlabel quick action', :merge_request
+ it_behaves_like 'relabel quick action', :merge_request
+ it_behaves_like 'award quick action', :merge_request
+ it_behaves_like 'estimate quick action', :merge_request
+ it_behaves_like 'remove_estimate quick action', :merge_request
+ it_behaves_like 'spend quick action', :merge_request
+ it_behaves_like 'remove_time_spent quick action', :merge_request
+ it_behaves_like 'shrug quick action', :merge_request
+ it_behaves_like 'tableflip quick action', :merge_request
+ it_behaves_like 'copy_metadata quick action', :merge_request
+ it_behaves_like 'issuable time tracker', :merge_request
end
describe 'merge-request-only commands' do
@@ -24,20 +56,12 @@ describe 'Merge request > User uses quick actions', :js do
project.add_maintainer(user)
end
- describe 'time tracking' do
- before do
- sign_in(user)
- visit project_merge_request_path(project, merge_request)
- end
-
- it_behaves_like 'issuable time tracker'
- end
-
describe 'toggling the WIP prefix in the title from note' do
context 'when the current user can toggle the WIP prefix' do
before do
sign_in(user)
visit project_merge_request_path(project, merge_request)
+ wait_for_requests
end
it 'adds the WIP: prefix to the title' do
@@ -135,11 +159,16 @@ describe 'Merge request > User uses quick actions', :js do
visit project_merge_request_path(project, merge_request)
end
- it 'does not recognize the command nor create a note' do
- add_note('/due 2016-08-28')
+ it_behaves_like 'due quick action not available'
+ end
- expect(page).not_to have_content '/due 2016-08-28'
+ describe 'removing a due date from note' do
+ before do
+ sign_in(user)
+ visit project_merge_request_path(project, merge_request)
end
+
+ it_behaves_like 'remove_due_date action not available'
end
describe '/target_branch command in merge request' do
diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb
index 71022c6bb08..849fab62fc6 100644
--- a/spec/features/merge_request/user_views_open_merge_request_spec.rb
+++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb
@@ -13,7 +13,7 @@ describe 'User views an open merge request' do
end
it 'renders both the title and the description' do
- node = find('.wiki h1 a#user-content-description-header')
+ node = find('.md h1 a#user-content-description-header')
expect(node[:href]).to end_with('#description-header')
# Work around a weird Capybara behavior where calling `parent` on a node
diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb
index 6e349395017..adac59b89ef 100644
--- a/spec/features/milestone_spec.rb
+++ b/spec/features/milestone_spec.rb
@@ -122,4 +122,32 @@ describe 'Milestone' do
expect(page).to have_selector('.popover')
end
end
+
+ describe 'reopen closed milestones' do
+ before do
+ create(:milestone, :closed, project: project)
+ end
+
+ describe 'group milestones page' do
+ it 'reopens the milestone' do
+ visit group_milestones_path(group, { state: 'closed' })
+
+ click_link 'Reopen Milestone'
+
+ expect(page).not_to have_selector('.status-box-closed')
+ expect(page).to have_selector('.status-box-open')
+ end
+ end
+
+ describe 'project milestones page' do
+ it 'reopens the milestone' do
+ visit project_milestones_path(project, { state: 'closed' })
+
+ click_link 'Reopen Milestone'
+
+ expect(page).not_to have_selector('.status-box-closed')
+ expect(page).to have_selector('.status-box-open')
+ end
+ end
+ end
end
diff --git a/spec/features/projects/artifacts/user_browses_artifacts_spec.rb b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb
index 5f630c9ffa4..a1fcd4024c0 100644
--- a/spec/features/projects/artifacts/user_browses_artifacts_spec.rb
+++ b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb
@@ -19,6 +19,12 @@ describe "User browses artifacts" do
visit(browse_project_job_artifacts_path(project, job))
end
+ it "renders a link to the job in the breadcrumbs" do
+ page.within('.js-breadcrumbs-list') do
+ expect(page).to have_link("##{job.id}", href: project_job_path(project, job))
+ end
+ end
+
it "shows artifacts" do
expect(page).not_to have_selector(".build-sidebar")
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index b1a7f167977..efb7b01f5ad 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -136,7 +136,7 @@ describe "User creates wiki page" do
click_button("Create page")
end
- page.within ".wiki" do
+ page.within ".md" do
expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4")
end
end
diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb
index eeacaf5f72a..fc6726985ae 100644
--- a/spec/features/snippets/notes_on_personal_snippets_spec.rb
+++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb
@@ -70,7 +70,7 @@ describe 'Comments on personal snippets', :js do
fill_in 'note[note]', with: 'This is **awesome**!'
find('.js-md-preview-button').click
- page.within('.new-note .md-preview') do
+ page.within('.new-note .md-preview-holder') do
expect(page).to have_content('This is awesome!')
expect(page).to have_selector('strong')
end
diff --git a/spec/features/snippets/user_creates_snippet_spec.rb b/spec/features/snippets/user_creates_snippet_spec.rb
index 879c46d7c4e..1c97d5ec5b4 100644
--- a/spec/features/snippets/user_creates_snippet_spec.rb
+++ b/spec/features/snippets/user_creates_snippet_spec.rb
@@ -37,7 +37,7 @@ describe 'User creates snippet', :js do
dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
find('.js-md-preview-button').click
- page.within('#new_personal_snippet .md-preview') do
+ page.within('#new_personal_snippet .md-preview-holder') do
expect(page).to have_content('My Snippet')
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb
index 8d567e925ef..bdbbe645779 100644
--- a/spec/features/tags/master_deletes_tag_spec.rb
+++ b/spec/features/tags/master_deletes_tag_spec.rb
@@ -37,7 +37,7 @@ describe 'Maintainer deletes tag' do
context 'when pre-receive hook fails', :js do
before do
allow_any_instance_of(Gitlab::GitalyClient::OperationService).to receive(:rm_tag)
- .and_raise(Gitlab::Git::PreReceiveError, 'Do not delete tags')
+ .and_raise(Gitlab::Git::PreReceiveError, 'GitLab: Do not delete tags')
end
it 'shows the error message' do
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 6fe840dccf6..33d9c10f5e8 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -79,7 +79,7 @@ describe 'Task Lists' do
visit_issue(project, issue)
wait_for_requests
- expect(page).to have_selector(".wiki .task-list .task-list-item .task-list-item-checkbox")
+ expect(page).to have_selector(".md .task-list .task-list-item .task-list-item-checkbox")
expect(page).to have_selector('a.btn-close')
end
@@ -87,14 +87,14 @@ describe 'Task Lists' do
visit_issue(project, issue)
wait_for_requests
- expect(page).to have_selector(".wiki .task-list .task-list-item .task-list-item-checkbox")
+ expect(page).to have_selector(".md .task-list .task-list-item .task-list-item-checkbox")
logout(:user)
login_as(user2)
visit current_path
wait_for_requests
- expect(page).to have_selector(".wiki .task-list .task-list-item .task-list-item-checkbox")
+ expect(page).to have_selector(".md .task-list .task-list-item .task-list-item-checkbox")
end
it 'provides a summary on Issues#index' do
@@ -231,7 +231,7 @@ describe 'Task Lists' do
container = '.detail-page-description .description.js-task-list-container'
expect(page).to have_selector(container)
- expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
+ expect(page).to have_selector("#{container} .md .task-list .task-list-item .task-list-item-checkbox")
expect(page).to have_selector("#{container} .js-task-list-field")
expect(page).to have_selector('form.js-issuable-update')
expect(page).to have_selector('a.btn-close')
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 368a814874f..9d5780d29b0 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -447,7 +447,7 @@ describe 'Login' do
'You can leave Group 1 and leave Group 2. '\
'You need to do this '\
'before '\
- "#{(Time.zone.now + 2.days).strftime("%a, %-d %b %Y %H:%M:%S %z")}"
+ "#{(Time.zone.now + 2.days).strftime("%a, %d %b %Y %H:%M:%S %z")}"
)
end
end
diff --git a/spec/frontend/.eslintrc.yml b/spec/frontend/.eslintrc.yml
index 046215e4c93..054dc27cda6 100644
--- a/spec/frontend/.eslintrc.yml
+++ b/spec/frontend/.eslintrc.yml
@@ -2,8 +2,13 @@
env:
jest/globals: true
plugins:
-- jest
+ - jest
settings:
import/resolver:
jest:
- jestConfigFile: "jest.config.js"
+ jestConfigFile: 'jest.config.js'
+globals:
+ getJSONFixture: false
+ loadFixtures: false
+ preloadFixtures: false
+ setFixtures: false
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
new file mode 100644
index 00000000000..1067a53906a
--- /dev/null
+++ b/spec/frontend/environment.js
@@ -0,0 +1,33 @@
+/* eslint-disable import/no-commonjs */
+
+const { ErrorWithStack } = require('jest-util');
+const JSDOMEnvironment = require('jest-environment-jsdom');
+
+class CustomEnvironment extends JSDOMEnvironment {
+ constructor(config, context) {
+ super(config, context);
+
+ Object.assign(context.console, {
+ error(...args) {
+ throw new ErrorWithStack(
+ `Unexpected call of console.error() with:\n\n${args.join(', ')}`,
+ this.error,
+ );
+ },
+
+ warn(...args) {
+ throw new ErrorWithStack(
+ `Unexpected call of console.warn() with:\n\n${args.join(', ')}`,
+ this.warn,
+ );
+ },
+ });
+
+ const { testEnvironmentOptions } = config;
+ this.global.gon = {
+ ee: testEnvironmentOptions.IS_EE,
+ };
+ }
+}
+
+module.exports = CustomEnvironment;
diff --git a/spec/frontend/helpers/class_spec_helper.js b/spec/frontend/helpers/class_spec_helper.js
new file mode 100644
index 00000000000..7a60d33b471
--- /dev/null
+++ b/spec/frontend/helpers/class_spec_helper.js
@@ -0,0 +1,9 @@
+export default class ClassSpecHelper {
+ static itShouldBeAStaticMethod(base, method) {
+ return it('should be a static method', () => {
+ expect(Object.prototype.hasOwnProperty.call(base, method)).toBeTruthy();
+ });
+ }
+}
+
+window.ClassSpecHelper = ClassSpecHelper;
diff --git a/spec/frontend/helpers/fixtures.js b/spec/frontend/helpers/fixtures.js
index f96f27c4d80..f0351aa31c6 100644
--- a/spec/frontend/helpers/fixtures.js
+++ b/spec/frontend/helpers/fixtures.js
@@ -1,24 +1,36 @@
-/* eslint-disable import/prefer-default-export, global-require, import/no-dynamic-require */
-
import fs from 'fs';
import path from 'path';
-// jest-util is part of Jest
-// eslint-disable-next-line import/no-extraneous-dependencies
import { ErrorWithStack } from 'jest-util';
const fixturesBasePath = path.join(process.cwd(), 'spec', 'javascripts', 'fixtures');
-export function getJSONFixture(relativePath, ee = false) {
- const absolutePath = path.join(fixturesBasePath, ee ? 'ee' : '', relativePath);
+export function getFixture(relativePath) {
+ const absolutePath = path.join(fixturesBasePath, relativePath);
if (!fs.existsSync(absolutePath)) {
throw new ErrorWithStack(
`Fixture file ${relativePath} does not exist.
Did you run bin/rake karma:fixtures?`,
- getJSONFixture,
+ getFixture,
);
}
- return require(absolutePath);
+ return fs.readFileSync(absolutePath, 'utf8');
}
+
+export const getJSONFixture = relativePath => JSON.parse(getFixture(relativePath));
+
+export const resetHTMLFixture = () => {
+ document.body.textContent = '';
+};
+
+export const setHTMLFixture = (htmlContent, resetHook = afterEach) => {
+ document.body.outerHTML = htmlContent;
+ resetHook(resetHTMLFixture);
+};
+
+export const loadHTMLFixture = (relativePath, resetHook = afterEach) => {
+ const fileContent = getFixture(relativePath);
+ setHTMLFixture(fileContent, resetHook);
+};
diff --git a/spec/frontend/helpers/locale_helper.js b/spec/frontend/helpers/locale_helper.js
new file mode 100644
index 00000000000..80047b06003
--- /dev/null
+++ b/spec/frontend/helpers/locale_helper.js
@@ -0,0 +1,11 @@
+/* eslint-disable import/prefer-default-export */
+
+export const setLanguage = languageCode => {
+ const htmlElement = document.querySelector('html');
+
+ if (languageCode) {
+ htmlElement.setAttribute('lang', languageCode);
+ } else {
+ htmlElement.removeAttribute('lang');
+ }
+};
diff --git a/spec/frontend/helpers/scroll_into_view_promise.js b/spec/frontend/helpers/scroll_into_view_promise.js
new file mode 100644
index 00000000000..0edea2103da
--- /dev/null
+++ b/spec/frontend/helpers/scroll_into_view_promise.js
@@ -0,0 +1,28 @@
+export default function scrollIntoViewPromise(intersectionTarget, timeout = 100, maxTries = 5) {
+ return new Promise((resolve, reject) => {
+ let intersectionObserver;
+ let retry = 0;
+
+ const intervalId = setInterval(() => {
+ if (retry >= maxTries) {
+ intersectionObserver.disconnect();
+ clearInterval(intervalId);
+ reject(new Error(`Could not scroll target into viewPort within ${timeout * maxTries} ms`));
+ }
+ retry += 1;
+ intersectionTarget.scrollIntoView();
+ }, timeout);
+
+ intersectionObserver = new IntersectionObserver(entries => {
+ if (entries[0].isIntersecting) {
+ intersectionObserver.disconnect();
+ clearInterval(intervalId);
+ resolve();
+ }
+ });
+
+ intersectionObserver.observe(intersectionTarget);
+
+ intersectionTarget.scrollIntoView();
+ });
+}
diff --git a/spec/frontend/helpers/set_timeout_promise_helper.js b/spec/frontend/helpers/set_timeout_promise_helper.js
new file mode 100644
index 00000000000..47087619187
--- /dev/null
+++ b/spec/frontend/helpers/set_timeout_promise_helper.js
@@ -0,0 +1,4 @@
+export default (time = 0) =>
+ new Promise(resolve => {
+ setTimeout(resolve, time);
+ });
diff --git a/spec/frontend/helpers/user_mock_data_helper.js b/spec/frontend/helpers/user_mock_data_helper.js
new file mode 100644
index 00000000000..6999fa1f8a1
--- /dev/null
+++ b/spec/frontend/helpers/user_mock_data_helper.js
@@ -0,0 +1,14 @@
+export default {
+ createNumberRandomUsers(numberUsers) {
+ const users = [];
+ for (let i = 0; i < numberUsers; i += 1) {
+ users.push({
+ avatar: 'https://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ id: i + 1,
+ name: `GitLab User ${i}`,
+ username: `gitlab${i}`,
+ });
+ }
+ return users;
+ },
+};
diff --git a/spec/frontend/helpers/vue_component_helper.js b/spec/frontend/helpers/vue_component_helper.js
new file mode 100644
index 00000000000..e0fe18e5560
--- /dev/null
+++ b/spec/frontend/helpers/vue_component_helper.js
@@ -0,0 +1,18 @@
+/**
+ * Replaces line break with an empty space
+ * @param {*} data
+ */
+export const removeBreakLine = data => data.replace(/\r?\n|\r/g, ' ');
+
+/**
+ * Removes line breaks, spaces and trims the given text
+ * @param {String} str
+ * @returns {String}
+ */
+export const trimText = str =>
+ str
+ .replace(/\r?\n|\r/g, '')
+ .replace(/\s\s+/g, ' ')
+ .trim();
+
+export const removeWhitespace = str => str.replace(/\s\s+/g, ' ');
diff --git a/spec/frontend/helpers/vue_resource_helper.js b/spec/frontend/helpers/vue_resource_helper.js
new file mode 100644
index 00000000000..0f58af09933
--- /dev/null
+++ b/spec/frontend/helpers/vue_resource_helper.js
@@ -0,0 +1,11 @@
+// eslint-disable-next-line import/prefer-default-export
+export const headersInterceptor = (request, next) => {
+ next(response => {
+ const headers = {};
+ response.headers.forEach((value, key) => {
+ headers[key] = value;
+ });
+ // eslint-disable-next-line no-param-reassign
+ response.headers = headers;
+ });
+};
diff --git a/spec/frontend/helpers/vue_test_utils_helper.js b/spec/frontend/helpers/vue_test_utils_helper.js
new file mode 100644
index 00000000000..19e27388eeb
--- /dev/null
+++ b/spec/frontend/helpers/vue_test_utils_helper.js
@@ -0,0 +1,19 @@
+/* eslint-disable import/prefer-default-export */
+
+const vNodeContainsText = (vnode, text) =>
+ (vnode.text && vnode.text.includes(text)) ||
+ (vnode.children && vnode.children.filter(child => vNodeContainsText(child, text)).length);
+
+/**
+ * Determines whether a `shallowMount` Wrapper contains text
+ * within one of it's slots. This will also work on Wrappers
+ * acquired with `find()`, but only if it's parent Wrapper
+ * was shallowMounted.
+ * NOTE: Prefer checking the rendered output of a component
+ * wherever possible using something like `text()` instead.
+ * @param {Wrapper} shallowWrapper - Vue test utils wrapper (shallowMounted)
+ * @param {String} slotName
+ * @param {String} text
+ */
+export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) =>
+ !!shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length;
diff --git a/spec/frontend/helpers/vuex_action_helper.js b/spec/frontend/helpers/vuex_action_helper.js
new file mode 100644
index 00000000000..88652202a8e
--- /dev/null
+++ b/spec/frontend/helpers/vuex_action_helper.js
@@ -0,0 +1,104 @@
+const noop = () => {};
+
+/**
+ * Helper for testing action with expected mutations inspired in
+ * https://vuex.vuejs.org/en/testing.html
+ *
+ * @param {Function} action to be tested
+ * @param {Object} payload will be provided to the action
+ * @param {Object} state will be provided to the action
+ * @param {Array} [expectedMutations=[]] mutations expected to be committed
+ * @param {Array} [expectedActions=[]] actions expected to be dispatched
+ * @param {Function} [done=noop] to be executed after the tests
+ * @return {Promise}
+ *
+ * @example
+ * testAction(
+ * actions.actionName, // action
+ * { }, // mocked payload
+ * state, //state
+ * // expected mutations
+ * [
+ * { type: types.MUTATION}
+ * { type: types.MUTATION_1, payload: jasmine.any(Number)}
+ * ],
+ * // expected actions
+ * [
+ * { type: 'actionName', payload: {param: 'foobar'}},
+ * { type: 'actionName1'}
+ * ]
+ * done,
+ * );
+ *
+ * @example
+ * testAction(
+ * actions.actionName, // action
+ * { }, // mocked payload
+ * state, //state
+ * [ { type: types.MUTATION} ], // expected mutations
+ * [], // expected actions
+ * ).then(done)
+ * .catch(done.fail);
+ */
+export default (
+ action,
+ payload,
+ state,
+ expectedMutations = [],
+ expectedActions = [],
+ done = noop,
+) => {
+ const mutations = [];
+ const actions = [];
+
+ // mock commit
+ const commit = (type, mutationPayload) => {
+ const mutation = { type };
+
+ if (typeof mutationPayload !== 'undefined') {
+ mutation.payload = mutationPayload;
+ }
+
+ mutations.push(mutation);
+ };
+
+ // mock dispatch
+ const dispatch = (type, actionPayload) => {
+ const dispatchedAction = { type };
+
+ if (typeof actionPayload !== 'undefined') {
+ dispatchedAction.payload = actionPayload;
+ }
+
+ actions.push(dispatchedAction);
+ };
+
+ const validateResults = () => {
+ expect({
+ mutations,
+ actions,
+ }).toEqual({
+ mutations: expectedMutations,
+ actions: expectedActions,
+ });
+ done();
+ };
+
+ const result = action(
+ { commit, state, dispatch, rootState: state, rootGetters: state, getters: state },
+ payload,
+ );
+
+ return new Promise(resolve => {
+ setImmediate(resolve);
+ })
+ .then(() => result)
+ .catch(error => {
+ validateResults();
+ throw error;
+ })
+ .then(data => {
+ validateResults();
+ return data;
+ });
+};
diff --git a/spec/frontend/helpers/wait_for_attribute_change.js b/spec/frontend/helpers/wait_for_attribute_change.js
new file mode 100644
index 00000000000..8f22d569222
--- /dev/null
+++ b/spec/frontend/helpers/wait_for_attribute_change.js
@@ -0,0 +1,16 @@
+export default (domElement, attributes, timeout = 1500) =>
+ new Promise((resolve, reject) => {
+ let observer;
+ const timeoutId = setTimeout(() => {
+ observer.disconnect();
+ reject(new Error(`Could not see an attribute update within ${timeout} ms`));
+ }, timeout);
+
+ observer = new MutationObserver(() => {
+ clearTimeout(timeoutId);
+ observer.disconnect();
+ resolve();
+ });
+
+ observer.observe(domElement, { attributes: true, attributeFilter: attributes });
+ });
diff --git a/spec/frontend/helpers/wait_for_promises.js b/spec/frontend/helpers/wait_for_promises.js
new file mode 100644
index 00000000000..1d2b53fc770
--- /dev/null
+++ b/spec/frontend/helpers/wait_for_promises.js
@@ -0,0 +1 @@
+export default () => new Promise(resolve => requestAnimationFrame(resolve));
diff --git a/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
index 23d07056925..1e0bc708c31 100644
--- a/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js
+++ b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
@@ -3,7 +3,7 @@ import '~/lib/utils/text_utility';
import AbuseReports from '~/pages/admin/abuse_reports/abuse_reports';
describe('Abuse Reports', () => {
- const FIXTURE = 'abuse_reports/abuse_reports_list.html.raw';
+ const FIXTURE = 'abuse_reports/abuse_reports_list.html';
const MAX_MESSAGE_LENGTH = 500;
let $messages;
@@ -16,9 +16,9 @@ describe('Abuse Reports', () => {
preloadFixtures(FIXTURE);
- beforeEach(function() {
+ beforeEach(() => {
loadFixtures(FIXTURE);
- this.abuseReports = new AbuseReports();
+ new AbuseReports(); // eslint-disable-line no-new
$messages = $('.abuse-reports .message');
});
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 006fc60ef57..1e3c28e25eb 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import axios from '~/lib/utils/axios_utils';
import { initializeTestTimeout } from './helpers/timeout';
+import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './helpers/fixtures';
// wait for pending setTimeout()s
afterEach(() => {
@@ -22,4 +23,24 @@ beforeEach(done => {
done();
});
+Vue.config.devtools = false;
+Vue.config.productionTip = false;
+
Vue.use(Translate);
+
+// workaround for JSDOM not supporting innerText
+// see https://github.com/jsdom/jsdom/issues/1245
+Object.defineProperty(global.Element.prototype, 'innerText', {
+ get() {
+ return this.textContent;
+ },
+ configurable: true, // make it so that it doesn't blow chunks on re-running tests with things like --watch
+});
+
+// convenience wrapper for migration from Karma
+Object.assign(global, {
+ loadFixtures: loadHTMLFixture,
+ loadJSONFixtures: getJSONFixture,
+ preloadFixtures() {},
+ setFixtures: setHTMLFixture,
+});
diff --git a/spec/helpers/appearances_helper_spec.rb b/spec/helpers/appearances_helper_spec.rb
index 8d717b968dd..a3511e078ce 100644
--- a/spec/helpers/appearances_helper_spec.rb
+++ b/spec/helpers/appearances_helper_spec.rb
@@ -65,12 +65,10 @@ describe AppearancesHelper do
end
describe '#brand_title' do
- it 'returns the default CE title when no appearance is present' do
- allow(helper)
- .to receive(:current_appearance)
- .and_return(nil)
+ it 'returns the default title when no appearance is present' do
+ allow(helper).to receive(:current_appearance).and_return(nil)
- expect(helper.brand_title).to eq('GitLab Community Edition')
+ expect(helper.brand_title).to eq(helper.default_brand_title)
end
end
end
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index 2ba8b3dbf22..aae515def0c 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe AuthHelper do
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 540a8674ec2..91541a16c13 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupsHelper do
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 8b82dea2524..1d1446eaa30 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe IssuablesHelper do
@@ -176,7 +178,7 @@ describe IssuablesHelper do
stub_commonmark_sourcepos_disabled
end
- it 'returns the correct json for an issue' do
+ it 'returns the correct data for an issue' do
issue = create(:issue, author: user, description: 'issue text')
@project = issue.project
@@ -198,7 +200,7 @@ describe IssuablesHelper do
initialDescriptionText: 'issue text',
initialTaskStatus: '0 of 0 tasks completed'
}
- expect(helper.issuable_initial_data(issue)).to eq(expected_data)
+ expect(helper.issuable_initial_data(issue)).to match(hash_including(expected_data))
end
end
end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 885204062fe..193390d2f2c 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MergeRequestsHelper do
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 291eafece94..37c63807c82 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectsHelper do
diff --git a/spec/javascripts/activities_spec.js b/spec/javascripts/activities_spec.js
index 068b8eb65bc..23b6de7e4e0 100644
--- a/spec/javascripts/activities_spec.js
+++ b/spec/javascripts/activities_spec.js
@@ -7,7 +7,7 @@ import Pager from '~/pager';
describe('Activities', () => {
window.gon || (window.gon = {});
- const fixtureTemplate = 'static/event_filter.html.raw';
+ const fixtureTemplate = 'static/event_filter.html';
const filters = [
{
id: 'all',
diff --git a/spec/javascripts/ajax_loading_spinner_spec.js b/spec/javascripts/ajax_loading_spinner_spec.js
index 9389fc94f17..89195a4397f 100644
--- a/spec/javascripts/ajax_loading_spinner_spec.js
+++ b/spec/javascripts/ajax_loading_spinner_spec.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import AjaxLoadingSpinner from '~/ajax_loading_spinner';
describe('Ajax Loading Spinner', () => {
- const fixtureTemplate = 'static/ajax_loading_spinner.html.raw';
+ const fixtureTemplate = 'static/ajax_loading_spinner.html';
preloadFixtures(fixtureTemplate);
beforeEach(() => {
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js
index e5b5707dcef..e10df1b45e7 100644
--- a/spec/javascripts/awards_handler_spec.js
+++ b/spec/javascripts/awards_handler_spec.js
@@ -24,13 +24,13 @@ const lazyAssert = function(done, assertFn) {
describe('AwardsHandler', function() {
const emojiData = getJSONFixture('emojis/emojis.json');
- preloadFixtures('snippets/show.html.raw');
+ preloadFixtures('snippets/show.html');
beforeEach(function(done) {
mock = new MockAdapter(axios);
mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
- loadFixtures('snippets/show.html.raw');
+ loadFixtures('snippets/show.html');
loadAwardsHandler(true)
.then(obj => {
awardsHandler = obj;
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js
index 681463aab66..7af8c984841 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/javascripts/behaviors/quick_submit_spec.js
@@ -4,10 +4,10 @@ import '~/behaviors/quick_submit';
describe('Quick Submit behavior', function() {
const keydownEvent = (options = { keyCode: 13, metaKey: true }) => $.Event('keydown', options);
- preloadFixtures('snippets/show.html.raw');
+ preloadFixtures('snippets/show.html');
beforeEach(() => {
- loadFixtures('snippets/show.html.raw');
+ loadFixtures('snippets/show.html');
$('form').submit(e => {
// Prevent a form submit from moving us off the testing page
e.preventDefault();
diff --git a/spec/javascripts/behaviors/requires_input_spec.js b/spec/javascripts/behaviors/requires_input_spec.js
index 1bde2bb3024..617fe49b059 100644
--- a/spec/javascripts/behaviors/requires_input_spec.js
+++ b/spec/javascripts/behaviors/requires_input_spec.js
@@ -3,10 +3,10 @@ import '~/behaviors/requires_input';
describe('requiresInput', () => {
let submitButton;
- preloadFixtures('branches/new_branch.html.raw');
+ preloadFixtures('branches/new_branch.html');
beforeEach(() => {
- loadFixtures('branches/new_branch.html.raw');
+ loadFixtures('branches/new_branch.html');
submitButton = $('button[type="submit"]');
});
diff --git a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
index 4843a0386b5..5e457a4e823 100644
--- a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -9,7 +9,7 @@ import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
const FORM_SELECTOR = '.js-main-target-form .js-vue-comment-form';
describe('ShortcutsIssuable', function() {
- const fixtureName = 'snippets/show.html.raw';
+ const fixtureName = 'snippets/show.html';
preloadFixtures(fixtureName);
beforeAll(done => {
diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
index 5f027f59fcf..68b4f261617 100644
--- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
+++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
@@ -6,10 +6,10 @@ describe('Balsamiq integration spec', () => {
let endpoint;
let balsamiqViewer;
- preloadFixtures('static/balsamiq_viewer.html.raw');
+ preloadFixtures('static/balsamiq_viewer.html');
beforeEach(() => {
- loadFixtures('static/balsamiq_viewer.html.raw');
+ loadFixtures('static/balsamiq_viewer.html');
container = document.getElementById('js-balsamiq-viewer');
balsamiqViewer = new BalsamiqViewer(container);
diff --git a/spec/javascripts/blob/blob_file_dropzone_spec.js b/spec/javascripts/blob/blob_file_dropzone_spec.js
index 432d8a65b0a..cab06a0a9be 100644
--- a/spec/javascripts/blob/blob_file_dropzone_spec.js
+++ b/spec/javascripts/blob/blob_file_dropzone_spec.js
@@ -2,10 +2,10 @@ import $ from 'jquery';
import BlobFileDropzone from '~/blob/blob_file_dropzone';
describe('BlobFileDropzone', function() {
- preloadFixtures('blob/show.html.raw');
+ preloadFixtures('blob/show.html');
beforeEach(() => {
- loadFixtures('blob/show.html.raw');
+ loadFixtures('blob/show.html');
const form = $('.js-upload-blob-form');
this.blobFileDropzone = new BlobFileDropzone(form, 'POST');
this.dropzone = $('.js-upload-blob-form .dropzone').get(0).dropzone;
diff --git a/spec/javascripts/blob/notebook/index_spec.js b/spec/javascripts/blob/notebook/index_spec.js
index 28d3b2f5ea3..6bb5bac007f 100644
--- a/spec/javascripts/blob/notebook/index_spec.js
+++ b/spec/javascripts/blob/notebook/index_spec.js
@@ -3,10 +3,10 @@ import axios from '~/lib/utils/axios_utils';
import renderNotebook from '~/blob/notebook';
describe('iPython notebook renderer', () => {
- preloadFixtures('static/notebook_viewer.html.raw');
+ preloadFixtures('static/notebook_viewer.html');
beforeEach(() => {
- loadFixtures('static/notebook_viewer.html.raw');
+ loadFixtures('static/notebook_viewer.html');
});
it('shows loading icon', () => {
diff --git a/spec/javascripts/blob/pdf/index_spec.js b/spec/javascripts/blob/pdf/index_spec.js
index be917a0613f..acf87580777 100644
--- a/spec/javascripts/blob/pdf/index_spec.js
+++ b/spec/javascripts/blob/pdf/index_spec.js
@@ -15,10 +15,10 @@ describe('PDF renderer', () => {
}
};
- preloadFixtures('static/pdf_viewer.html.raw');
+ preloadFixtures('static/pdf_viewer.html');
beforeEach(() => {
- loadFixtures('static/pdf_viewer.html.raw');
+ loadFixtures('static/pdf_viewer.html');
viewer = document.getElementById('js-pdf-viewer');
viewer.dataset.endpoint = testPDF;
});
diff --git a/spec/javascripts/blob/sketch/index_spec.js b/spec/javascripts/blob/sketch/index_spec.js
index 2b1e81e9cbc..3d3129e10da 100644
--- a/spec/javascripts/blob/sketch/index_spec.js
+++ b/spec/javascripts/blob/sketch/index_spec.js
@@ -13,10 +13,10 @@ describe('Sketch viewer', () => {
});
};
- preloadFixtures('static/sketch_viewer.html.raw');
+ preloadFixtures('static/sketch_viewer.html');
beforeEach(() => {
- loadFixtures('static/sketch_viewer.html.raw');
+ loadFixtures('static/sketch_viewer.html');
});
describe('with error message', () => {
diff --git a/spec/javascripts/blob/viewer/index_spec.js b/spec/javascripts/blob/viewer/index_spec.js
index 93a942fe8d4..4ac15ca5aa2 100644
--- a/spec/javascripts/blob/viewer/index_spec.js
+++ b/spec/javascripts/blob/viewer/index_spec.js
@@ -9,12 +9,12 @@ describe('Blob viewer', () => {
let blob;
let mock;
- preloadFixtures('snippets/show.html.raw');
+ preloadFixtures('snippets/show.html');
beforeEach(() => {
mock = new MockAdapter(axios);
- loadFixtures('snippets/show.html.raw');
+ loadFixtures('snippets/show.html');
$('#modal-upload-blob').remove();
blob = new BlobViewer();
diff --git a/spec/javascripts/boards/components/board_spec.js b/spec/javascripts/boards/components/board_spec.js
index dee7841c088..6e6b3e6950b 100644
--- a/spec/javascripts/boards/components/board_spec.js
+++ b/spec/javascripts/boards/components/board_spec.js
@@ -9,7 +9,7 @@ describe('Board component', () => {
let el;
beforeEach(done => {
- loadFixtures('boards/show.html.raw');
+ loadFixtures('boards/show.html');
el = document.createElement('div');
document.body.appendChild(el);
diff --git a/spec/javascripts/bootstrap_linked_tabs_spec.js b/spec/javascripts/bootstrap_linked_tabs_spec.js
index c3e3d78ff63..1d21637ceae 100644
--- a/spec/javascripts/bootstrap_linked_tabs_spec.js
+++ b/spec/javascripts/bootstrap_linked_tabs_spec.js
@@ -1,10 +1,10 @@
import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
describe('Linked Tabs', () => {
- preloadFixtures('static/linked_tabs.html.raw');
+ preloadFixtures('static/linked_tabs.html');
beforeEach(() => {
- loadFixtures('static/linked_tabs.html.raw');
+ loadFixtures('static/linked_tabs.html');
});
describe('when is initialized', () => {
diff --git a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
index 1fc0e206d5e..481b1a4d4b0 100644
--- a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
@@ -7,8 +7,8 @@ const VARIABLE_PATCH_ENDPOINT = 'http://test.host/frontend-fixtures/builds-proje
const HIDE_CLASS = 'hide';
describe('AjaxFormVariableList', () => {
- preloadFixtures('projects/ci_cd_settings.html.raw');
- preloadFixtures('projects/ci_cd_settings_with_variables.html.raw');
+ preloadFixtures('projects/ci_cd_settings.html');
+ preloadFixtures('projects/ci_cd_settings_with_variables.html');
let container;
let saveButton;
@@ -18,7 +18,7 @@ describe('AjaxFormVariableList', () => {
let ajaxVariableList;
beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html.raw');
+ loadFixtures('projects/ci_cd_settings.html');
container = document.querySelector('.js-ci-variable-list-section');
mock = new MockAdapter(axios);
@@ -168,7 +168,7 @@ describe('AjaxFormVariableList', () => {
describe('updateRowsWithPersistedVariables', () => {
beforeEach(() => {
- loadFixtures('projects/ci_cd_settings_with_variables.html.raw');
+ loadFixtures('projects/ci_cd_settings_with_variables.html');
container = document.querySelector('.js-ci-variable-list-section');
const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
index bef59b86d0c..70f49469300 100644
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
@@ -5,9 +5,9 @@ import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
const HIDE_CLASS = 'hide';
describe('VariableList', () => {
- preloadFixtures('pipeline_schedules/edit.html.raw');
- preloadFixtures('pipeline_schedules/edit_with_variables.html.raw');
- preloadFixtures('projects/ci_cd_settings.html.raw');
+ preloadFixtures('pipeline_schedules/edit.html');
+ preloadFixtures('pipeline_schedules/edit_with_variables.html');
+ preloadFixtures('projects/ci_cd_settings.html');
let $wrapper;
let variableList;
@@ -15,7 +15,7 @@ describe('VariableList', () => {
describe('with only key/value inputs', () => {
describe('with no variables', () => {
beforeEach(() => {
- loadFixtures('pipeline_schedules/edit.html.raw');
+ loadFixtures('pipeline_schedules/edit.html');
$wrapper = $('.js-ci-variable-list-section');
variableList = new VariableList({
@@ -82,7 +82,7 @@ describe('VariableList', () => {
describe('with persisted variables', () => {
beforeEach(() => {
- loadFixtures('pipeline_schedules/edit_with_variables.html.raw');
+ loadFixtures('pipeline_schedules/edit_with_variables.html');
$wrapper = $('.js-ci-variable-list-section');
variableList = new VariableList({
@@ -115,7 +115,7 @@ describe('VariableList', () => {
describe('with all inputs(key, value, protected)', () => {
beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html.raw');
+ loadFixtures('projects/ci_cd_settings.html');
$wrapper = $('.js-ci-variable-list-section');
$wrapper.find('.js-ci-variable-input-protected').attr('data-default', 'false');
@@ -149,7 +149,7 @@ describe('VariableList', () => {
describe('toggleEnableRow method', () => {
beforeEach(() => {
- loadFixtures('pipeline_schedules/edit_with_variables.html.raw');
+ loadFixtures('pipeline_schedules/edit_with_variables.html');
$wrapper = $('.js-ci-variable-list-section');
variableList = new VariableList({
@@ -198,7 +198,7 @@ describe('VariableList', () => {
describe('hideValues', () => {
beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html.raw');
+ loadFixtures('projects/ci_cd_settings.html');
$wrapper = $('.js-ci-variable-list-section');
variableList = new VariableList({
diff --git a/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js b/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
index 997d0d54d79..4982b68fa81 100644
--- a/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
@@ -2,12 +2,12 @@ import $ from 'jquery';
import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
describe('NativeFormVariableList', () => {
- preloadFixtures('pipeline_schedules/edit.html.raw');
+ preloadFixtures('pipeline_schedules/edit.html');
let $wrapper;
beforeEach(() => {
- loadFixtures('pipeline_schedules/edit.html.raw');
+ loadFixtures('pipeline_schedules/edit.html');
$wrapper = $('.js-ci-variable-list-section');
setupNativeFormVariableList({
diff --git a/spec/javascripts/clusters/clusters_bundle_spec.js b/spec/javascripts/clusters/clusters_bundle_spec.js
index 71f16dc259e..0d3dcc29f22 100644
--- a/spec/javascripts/clusters/clusters_bundle_spec.js
+++ b/spec/javascripts/clusters/clusters_bundle_spec.js
@@ -9,10 +9,10 @@ import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
describe('Clusters', () => {
let cluster;
- preloadFixtures('clusters/show_cluster.html.raw');
+ preloadFixtures('clusters/show_cluster.html');
beforeEach(() => {
- loadFixtures('clusters/show_cluster.html.raw');
+ loadFixtures('clusters/show_cluster.html');
cluster = new Clusters();
});
diff --git a/spec/javascripts/collapsed_sidebar_todo_spec.js b/spec/javascripts/collapsed_sidebar_todo_spec.js
index dc5737558c0..bb90e53e525 100644
--- a/spec/javascripts/collapsed_sidebar_todo_spec.js
+++ b/spec/javascripts/collapsed_sidebar_todo_spec.js
@@ -6,7 +6,7 @@ import Sidebar from '~/right_sidebar';
import timeoutPromise from './helpers/set_timeout_promise_helper';
describe('Issuable right sidebar collapsed todo toggle', () => {
- const fixtureName = 'issues/open-issue.html.raw';
+ const fixtureName = 'issues/open-issue.html';
const jsonFixtureName = 'todos/todos.json';
let mock;
diff --git a/spec/javascripts/create_item_dropdown_spec.js b/spec/javascripts/create_item_dropdown_spec.js
index 9cf72d7c55b..a814952faab 100644
--- a/spec/javascripts/create_item_dropdown_spec.js
+++ b/spec/javascripts/create_item_dropdown_spec.js
@@ -20,7 +20,7 @@ const DROPDOWN_ITEM_DATA = [
];
describe('CreateItemDropdown', () => {
- preloadFixtures('static/create_item_dropdown.html.raw');
+ preloadFixtures('static/create_item_dropdown.html');
let $wrapperEl;
let createItemDropdown;
@@ -44,7 +44,7 @@ describe('CreateItemDropdown', () => {
}
beforeEach(() => {
- loadFixtures('static/create_item_dropdown.html.raw');
+ loadFixtures('static/create_item_dropdown.html');
$wrapperEl = $('.js-create-item-dropdown-fixture-root');
});
diff --git a/spec/javascripts/diffs/components/diff_file_header_spec.js b/spec/javascripts/diffs/components/diff_file_header_spec.js
index 2d10b8383e2..6614069f44d 100644
--- a/spec/javascripts/diffs/components/diff_file_header_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_header_spec.js
@@ -23,9 +23,6 @@ describe('diff_file_header', () => {
});
beforeEach(() => {
- gon.features = {
- expandDiffFullFile: true,
- };
const diffFile = diffDiscussionMock.diff_file;
diffFile.added_lines = 2;
diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js
index fd5dd611383..711ab543411 100644
--- a/spec/javascripts/diffs/mock_data/diff_discussions.js
+++ b/spec/javascripts/diffs/mock_data/diff_discussions.js
@@ -496,7 +496,7 @@ export default {
{
text: 'line',
rich_text:
- '<tr class="line_holder new" id="">\n<td class="diff-line-num new old_line" data-linenumber="1">\n \n</td>\n<td class="diff-line-num new new_line" data-linenumber="1">\n1\n</td>\n<td class="line_content new noteable_line"><span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n</td>\n</tr>\n<tr class="line_holder new" id="">\n<td class="diff-line-num new old_line" data-linenumber="1">\n \n</td>\n<td class="diff-line-num new new_line" data-linenumber="2">\n2\n</td>\n<td class="line_content new noteable_line"><span id="LC2" class="line" lang="plaintext"></span>\n</td>\n</tr>\n',
+ '<tr class="line_holder new" id="">\n<td class="diff-line-num new old_line" data-linenumber="1">\n \n</td>\n<td class="diff-line-num new new_line" data-linenumber="1">\n1\n</td>\n<td class="line_content new"><span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n</td>\n</tr>\n<tr class="line_holder new" id="">\n<td class="diff-line-num new old_line" data-linenumber="1">\n \n</td>\n<td class="diff-line-num new new_line" data-linenumber="2">\n2\n</td>\n<td class="line_content new"><span id="LC2" class="line" lang="plaintext"></span>\n</td>\n</tr>\n',
can_receive_suggestion: true,
line_code: '6f209374f7e565f771b95720abf46024c41d1885_1_1',
type: 'new',
diff --git a/spec/javascripts/filtered_search/dropdown_user_spec.js b/spec/javascripts/filtered_search/dropdown_user_spec.js
index e8fcc8592eb..f764800fff0 100644
--- a/spec/javascripts/filtered_search/dropdown_user_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_user_spec.js
@@ -72,7 +72,7 @@ describe('Dropdown User', () => {
});
describe('hideCurrentUser', () => {
- const fixtureTemplate = 'issues/issue_list.html.raw';
+ const fixtureTemplate = 'issues/issue_list.html';
preloadFixtures(fixtureTemplate);
let dropdown;
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js
index cfd0b96ec43..62d1bd69635 100644
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js
@@ -4,7 +4,7 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Dropdown Utils', () => {
- const issueListFixture = 'issues/issue_list.html.raw';
+ const issueListFixture = 'issues/issue_list.html';
preloadFixtures(issueListFixture);
describe('getEscapedText', () => {
diff --git a/spec/javascripts/fixtures/.gitignore b/spec/javascripts/fixtures/.gitignore
index 0c35cdd778e..2507c8e7263 100644
--- a/spec/javascripts/fixtures/.gitignore
+++ b/spec/javascripts/fixtures/.gitignore
@@ -1,2 +1,3 @@
*.html.raw
+*.html
*.json
diff --git a/spec/javascripts/fixtures/abuse_reports.rb b/spec/javascripts/fixtures/abuse_reports.rb
index 387858cba77..54b6419bcdb 100644
--- a/spec/javascripts/fixtures/abuse_reports.rb
+++ b/spec/javascripts/fixtures/abuse_reports.rb
@@ -18,7 +18,7 @@ describe Admin::AbuseReportsController, '(JavaScript fixtures)', type: :controll
sign_in(admin)
end
- it 'abuse_reports/abuse_reports_list.html.raw' do |example|
+ it 'abuse_reports/abuse_reports_list.html' do |example|
get :index
expect(response).to be_success
diff --git a/spec/javascripts/fixtures/admin_users.rb b/spec/javascripts/fixtures/admin_users.rb
index 9989ac4fff2..76dbdf603da 100644
--- a/spec/javascripts/fixtures/admin_users.rb
+++ b/spec/javascripts/fixtures/admin_users.rb
@@ -17,7 +17,7 @@ describe Admin::UsersController, '(JavaScript fixtures)', type: :controller do
clean_frontend_fixtures('admin/users')
end
- it 'admin/users/new_with_internal_user_regex.html.raw' do |example|
+ it 'admin/users/new_with_internal_user_regex.html' do |example|
stub_application_setting(user_default_external: true)
stub_application_setting(user_default_internal_regex: '^(?:(?!\.ext@).)*$\r?')
diff --git a/spec/javascripts/fixtures/application_settings.rb b/spec/javascripts/fixtures/application_settings.rb
index a9d3043f73d..c535e598e12 100644
--- a/spec/javascripts/fixtures/application_settings.rb
+++ b/spec/javascripts/fixtures/application_settings.rb
@@ -23,7 +23,7 @@ describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', type: :c
remove_repository(project)
end
- it 'application_settings/accounts_and_limit.html.raw' do |example|
+ it 'application_settings/accounts_and_limit.html' do |example|
stub_application_setting(user_default_external: false)
get :show
diff --git a/spec/javascripts/fixtures/blob.rb b/spec/javascripts/fixtures/blob.rb
index cd66d98f92a..db7749bc000 100644
--- a/spec/javascripts/fixtures/blob.rb
+++ b/spec/javascripts/fixtures/blob.rb
@@ -22,7 +22,7 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'blob/show.html.raw' do |example|
+ it 'blob/show.html' do |example|
get(:show, params: {
namespace_id: project.namespace,
project_id: project,
diff --git a/spec/javascripts/fixtures/boards.rb b/spec/javascripts/fixtures/boards.rb
index 1d675e008ba..c4390e89578 100644
--- a/spec/javascripts/fixtures/boards.rb
+++ b/spec/javascripts/fixtures/boards.rb
@@ -17,7 +17,7 @@ describe Projects::BoardsController, '(JavaScript fixtures)', type: :controller
sign_in(admin)
end
- it 'boards/show.html.raw' do |example|
+ it 'boards/show.html' do |example|
get(:index, params: {
namespace_id: project.namespace,
project_id: project
diff --git a/spec/javascripts/fixtures/branches.rb b/spec/javascripts/fixtures/branches.rb
index 3cc713ef90f..5d2d6c7ec0e 100644
--- a/spec/javascripts/fixtures/branches.rb
+++ b/spec/javascripts/fixtures/branches.rb
@@ -21,7 +21,7 @@ describe Projects::BranchesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'branches/new_branch.html.raw' do |example|
+ it 'branches/new_branch.html' do |example|
get :new, params: {
namespace_id: project.namespace.to_param,
project_id: project
diff --git a/spec/javascripts/fixtures/clusters.rb b/spec/javascripts/fixtures/clusters.rb
index 69dbe54ffc2..8ebd8a41366 100644
--- a/spec/javascripts/fixtures/clusters.rb
+++ b/spec/javascripts/fixtures/clusters.rb
@@ -22,7 +22,7 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'clusters/show_cluster.html.raw' do |example|
+ it 'clusters/show_cluster.html' do |example|
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
diff --git a/spec/javascripts/fixtures/commit.rb b/spec/javascripts/fixtures/commit.rb
index 295f13b34a4..ab10f559e4b 100644
--- a/spec/javascripts/fixtures/commit.rb
+++ b/spec/javascripts/fixtures/commit.rb
@@ -19,7 +19,7 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
end
- it 'commit/show.html.raw' do |example|
+ it 'commit/show.html' do |example|
params = {
namespace_id: project.namespace,
project_id: project,
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index 03136f4e661..16e31028b05 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -18,7 +18,7 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
end
describe GroupsController, '(JavaScript fixtures)', type: :controller do
- it 'groups/edit.html.raw' do |example|
+ it 'groups/edit.html' do |example|
get :edit, params: { id: group }
expect(response).to be_success
@@ -27,7 +27,7 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
end
describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'groups/ci_cd_settings.html.raw' do |example|
+ it 'groups/ci_cd_settings.html' do |example|
get :show, params: { group_id: group }
expect(response).to be_success
diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb
index 9b8e90c2a43..645b3aa788a 100644
--- a/spec/javascripts/fixtures/issues.rb
+++ b/spec/javascripts/fixtures/issues.rb
@@ -21,26 +21,26 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
remove_repository(project)
end
- it 'issues/open-issue.html.raw' do |example|
+ it 'issues/open-issue.html' do |example|
render_issue(example.description, create(:issue, project: project))
end
- it 'issues/closed-issue.html.raw' do |example|
+ it 'issues/closed-issue.html' do |example|
render_issue(example.description, create(:closed_issue, project: project))
end
- it 'issues/issue-with-task-list.html.raw' do |example|
+ it 'issues/issue-with-task-list.html' do |example|
issue = create(:issue, project: project, description: '- [ ] Task List Item')
render_issue(example.description, issue)
end
- it 'issues/issue_with_comment.html.raw' do |example|
+ it 'issues/issue_with_comment.html' do |example|
issue = create(:issue, project: project)
create(:note, project: project, noteable: issue, note: '- [ ] Task List Item').save
render_issue(example.description, issue)
end
- it 'issues/issue_list.html.raw' do |example|
+ it 'issues/issue_list.html' do |example|
create(:issue, project: project)
get :index, params: {
diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb
index 433bb690a1c..941235190b5 100644
--- a/spec/javascripts/fixtures/jobs.rb
+++ b/spec/javascripts/fixtures/jobs.rb
@@ -32,7 +32,7 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'builds/build-with-artifacts.html.raw' do |example|
+ it 'builds/build-with-artifacts.html' do |example|
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb
index eb37be87e1d..7df1e5cb512 100644
--- a/spec/javascripts/fixtures/merge_requests.rb
+++ b/spec/javascripts/fixtures/merge_requests.rb
@@ -42,19 +42,19 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
remove_repository(project)
end
- it 'merge_requests/merge_request_of_current_user.html.raw' do |example|
+ it 'merge_requests/merge_request_of_current_user.html' do |example|
merge_request.update(author: admin)
render_merge_request(example.description, merge_request)
end
- it 'merge_requests/merge_request_with_task_list.html.raw' do |example|
+ it 'merge_requests/merge_request_with_task_list.html' do |example|
create(:ci_build, :pending, pipeline: pipeline)
render_merge_request(example.description, merge_request)
end
- it 'merge_requests/merged_merge_request.html.raw' do |example|
+ it 'merge_requests/merged_merge_request.html' do |example|
expect_next_instance_of(MergeRequest) do |merge_request|
allow(merge_request).to receive(:source_branch_exists?).and_return(true)
allow(merge_request).to receive(:can_remove_source_branch?).and_return(true)
@@ -62,13 +62,13 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
render_merge_request(example.description, merged_merge_request)
end
- it 'merge_requests/diff_comment.html.raw' do |example|
+ it 'merge_requests/diff_comment.html' do |example|
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
render_merge_request(example.description, merge_request)
end
- it 'merge_requests/merge_request_with_comment.html.raw' do |example|
+ it 'merge_requests/merge_request_with_comment.html' do |example|
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request, note: '- [ ] Task List Item')
render_merge_request(example.description, merge_request)
end
diff --git a/spec/javascripts/fixtures/pipeline_schedules.rb b/spec/javascripts/fixtures/pipeline_schedules.rb
index 05d79ec8de9..e5176a58273 100644
--- a/spec/javascripts/fixtures/pipeline_schedules.rb
+++ b/spec/javascripts/fixtures/pipeline_schedules.rb
@@ -21,7 +21,7 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
sign_in(admin)
end
- it 'pipeline_schedules/edit.html.raw' do |example|
+ it 'pipeline_schedules/edit.html' do |example|
get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -32,7 +32,7 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
store_frontend_fixture(response, example.description)
end
- it 'pipeline_schedules/edit_with_variables.html.raw' do |example|
+ it 'pipeline_schedules/edit_with_variables.html' do |example|
get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
diff --git a/spec/javascripts/fixtures/projects.rb b/spec/javascripts/fixtures/projects.rb
index 85f02923804..446da83a7f9 100644
--- a/spec/javascripts/fixtures/projects.rb
+++ b/spec/javascripts/fixtures/projects.rb
@@ -28,7 +28,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
end
describe ProjectsController, '(JavaScript fixtures)', type: :controller do
- it 'projects/dashboard.html.raw' do |example|
+ it 'projects/dashboard.html' do |example|
get :show, params: {
namespace_id: project.namespace.to_param,
id: project
@@ -38,7 +38,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
store_frontend_fixture(response, example.description)
end
- it 'projects/overview.html.raw' do |example|
+ it 'projects/overview.html' do |example|
get :show, params: {
namespace_id: project_with_repo.namespace.to_param,
id: project_with_repo
@@ -48,7 +48,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
store_frontend_fixture(response, example.description)
end
- it 'projects/edit.html.raw' do |example|
+ it 'projects/edit.html' do |example|
get :edit, params: {
namespace_id: project.namespace.to_param,
id: project
@@ -60,7 +60,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
end
describe Projects::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'projects/ci_cd_settings.html.raw' do |example|
+ it 'projects/ci_cd_settings.html' do |example|
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project
@@ -70,7 +70,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
store_frontend_fixture(response, example.description)
end
- it 'projects/ci_cd_settings_with_variables.html.raw' do |example|
+ it 'projects/ci_cd_settings_with_variables.html' do |example|
create(:ci_variable, project: project_variable_populated)
create(:ci_variable, project: project_variable_populated)
diff --git a/spec/javascripts/fixtures/prometheus_service.rb b/spec/javascripts/fixtures/prometheus_service.rb
index 746fbfd66dd..29dc95305b7 100644
--- a/spec/javascripts/fixtures/prometheus_service.rb
+++ b/spec/javascripts/fixtures/prometheus_service.rb
@@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'services/prometheus/prometheus_service.html.raw' do |example|
+ it 'services/prometheus/prometheus_service.html' do |example|
get :edit, params: {
namespace_id: namespace,
project_id: project,
diff --git a/spec/javascripts/fixtures/search.rb b/spec/javascripts/fixtures/search.rb
index 703cd3d49fa..5f5b4d4e60d 100644
--- a/spec/javascripts/fixtures/search.rb
+++ b/spec/javascripts/fixtures/search.rb
@@ -9,7 +9,7 @@ describe SearchController, '(JavaScript fixtures)', type: :controller do
clean_frontend_fixtures('search/')
end
- it 'search/show.html.raw' do |example|
+ it 'search/show.html' do |example|
get :show
expect(response).to be_success
diff --git a/spec/javascripts/fixtures/services.rb b/spec/javascripts/fixtures/services.rb
index 6ccd74a07ff..dc7ee484c22 100644
--- a/spec/javascripts/fixtures/services.rb
+++ b/spec/javascripts/fixtures/services.rb
@@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'services/edit_service.html.raw' do |example|
+ it 'services/edit_service.html' do |example|
get :edit, params: {
namespace_id: namespace,
project_id: project,
diff --git a/spec/javascripts/fixtures/sessions.rb b/spec/javascripts/fixtures/sessions.rb
index e90a58e8c54..8656dea696a 100644
--- a/spec/javascripts/fixtures/sessions.rb
+++ b/spec/javascripts/fixtures/sessions.rb
@@ -16,7 +16,7 @@ describe 'Sessions (JavaScript fixtures)' do
set_devise_mapping(context: @request)
end
- it 'sessions/new.html.raw' do |example|
+ it 'sessions/new.html' do |example|
get :new
expect(response).to be_success
diff --git a/spec/javascripts/fixtures/snippet.rb b/spec/javascripts/fixtures/snippet.rb
index bcd6546f3df..ebc5b793166 100644
--- a/spec/javascripts/fixtures/snippet.rb
+++ b/spec/javascripts/fixtures/snippet.rb
@@ -23,7 +23,7 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'snippets/show.html.raw' do |example|
+ it 'snippets/show.html' do |example|
create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item')
get(:show, params: { id: snippet.to_param })
diff --git a/spec/javascripts/fixtures/static/ajax_loading_spinner.html.raw b/spec/javascripts/fixtures/static/ajax_loading_spinner.html
index 0e1ebb32b1c..0e1ebb32b1c 100644
--- a/spec/javascripts/fixtures/static/ajax_loading_spinner.html.raw
+++ b/spec/javascripts/fixtures/static/ajax_loading_spinner.html
diff --git a/spec/javascripts/fixtures/static/balsamiq_viewer.html.raw b/spec/javascripts/fixtures/static/balsamiq_viewer.html
index cdd723d1a84..cdd723d1a84 100644
--- a/spec/javascripts/fixtures/static/balsamiq_viewer.html.raw
+++ b/spec/javascripts/fixtures/static/balsamiq_viewer.html
diff --git a/spec/javascripts/fixtures/static/create_item_dropdown.html.raw b/spec/javascripts/fixtures/static/create_item_dropdown.html
index d2d38370092..d2d38370092 100644
--- a/spec/javascripts/fixtures/static/create_item_dropdown.html.raw
+++ b/spec/javascripts/fixtures/static/create_item_dropdown.html
diff --git a/spec/javascripts/fixtures/static/event_filter.html.raw b/spec/javascripts/fixtures/static/event_filter.html
index 8e9b6fb1b5c..8e9b6fb1b5c 100644
--- a/spec/javascripts/fixtures/static/event_filter.html.raw
+++ b/spec/javascripts/fixtures/static/event_filter.html
diff --git a/spec/javascripts/fixtures/static/gl_dropdown.html.raw b/spec/javascripts/fixtures/static/gl_dropdown.html
index 08f6738414e..08f6738414e 100644
--- a/spec/javascripts/fixtures/static/gl_dropdown.html.raw
+++ b/spec/javascripts/fixtures/static/gl_dropdown.html
diff --git a/spec/javascripts/fixtures/static/gl_field_errors.html.raw b/spec/javascripts/fixtures/static/gl_field_errors.html
index f8470e02b7c..f8470e02b7c 100644
--- a/spec/javascripts/fixtures/static/gl_field_errors.html.raw
+++ b/spec/javascripts/fixtures/static/gl_field_errors.html
diff --git a/spec/javascripts/fixtures/static/issuable_filter.html.raw b/spec/javascripts/fixtures/static/issuable_filter.html
index 06b70fb43f1..06b70fb43f1 100644
--- a/spec/javascripts/fixtures/static/issuable_filter.html.raw
+++ b/spec/javascripts/fixtures/static/issuable_filter.html
diff --git a/spec/javascripts/fixtures/static/issue_sidebar_label.html.raw b/spec/javascripts/fixtures/static/issue_sidebar_label.html
index ec8fb30f219..ec8fb30f219 100644
--- a/spec/javascripts/fixtures/static/issue_sidebar_label.html.raw
+++ b/spec/javascripts/fixtures/static/issue_sidebar_label.html
diff --git a/spec/javascripts/fixtures/static/line_highlighter.html.raw b/spec/javascripts/fixtures/static/line_highlighter.html
index 897a25d6760..897a25d6760 100644
--- a/spec/javascripts/fixtures/static/line_highlighter.html.raw
+++ b/spec/javascripts/fixtures/static/line_highlighter.html
diff --git a/spec/javascripts/fixtures/static/linked_tabs.html.raw b/spec/javascripts/fixtures/static/linked_tabs.html
index c25463bf1db..c25463bf1db 100644
--- a/spec/javascripts/fixtures/static/linked_tabs.html.raw
+++ b/spec/javascripts/fixtures/static/linked_tabs.html
diff --git a/spec/javascripts/fixtures/static/merge_requests_show.html.raw b/spec/javascripts/fixtures/static/merge_requests_show.html
index e219d9462aa..87e36c9f315 100644
--- a/spec/javascripts/fixtures/static/merge_requests_show.html.raw
+++ b/spec/javascripts/fixtures/static/merge_requests_show.html
@@ -1,7 +1,7 @@
<a class="btn-close"></a>
<div class="detail-page-description">
<div class="description js-task-list-container">
-<div class="wiki">
+<div class="md">
<ul class="task-list">
<li class="task-list-item">
<input class="task-list-item-checkbox" type="checkbox">
diff --git a/spec/javascripts/fixtures/static/mini_dropdown_graph.html.raw b/spec/javascripts/fixtures/static/mini_dropdown_graph.html
index cd0b8dec3fc..cd0b8dec3fc 100644
--- a/spec/javascripts/fixtures/static/mini_dropdown_graph.html.raw
+++ b/spec/javascripts/fixtures/static/mini_dropdown_graph.html
diff --git a/spec/javascripts/fixtures/static/notebook_viewer.html.raw b/spec/javascripts/fixtures/static/notebook_viewer.html
index 4bbb7bf1094..4bbb7bf1094 100644
--- a/spec/javascripts/fixtures/static/notebook_viewer.html.raw
+++ b/spec/javascripts/fixtures/static/notebook_viewer.html
diff --git a/spec/javascripts/fixtures/static/oauth_remember_me.html.raw b/spec/javascripts/fixtures/static/oauth_remember_me.html
index 9ba1ffc72fe..9ba1ffc72fe 100644
--- a/spec/javascripts/fixtures/static/oauth_remember_me.html.raw
+++ b/spec/javascripts/fixtures/static/oauth_remember_me.html
diff --git a/spec/javascripts/fixtures/static/pdf_viewer.html.raw b/spec/javascripts/fixtures/static/pdf_viewer.html
index 350d35a262f..350d35a262f 100644
--- a/spec/javascripts/fixtures/static/pdf_viewer.html.raw
+++ b/spec/javascripts/fixtures/static/pdf_viewer.html
diff --git a/spec/javascripts/fixtures/static/pipeline_graph.html.raw b/spec/javascripts/fixtures/static/pipeline_graph.html
index 422372bb7d5..422372bb7d5 100644
--- a/spec/javascripts/fixtures/static/pipeline_graph.html.raw
+++ b/spec/javascripts/fixtures/static/pipeline_graph.html
diff --git a/spec/javascripts/fixtures/static/pipelines.html.raw b/spec/javascripts/fixtures/static/pipelines.html
index 42333f94f2f..42333f94f2f 100644
--- a/spec/javascripts/fixtures/static/pipelines.html.raw
+++ b/spec/javascripts/fixtures/static/pipelines.html
diff --git a/spec/javascripts/fixtures/static/project_select_combo_button.html.raw b/spec/javascripts/fixtures/static/project_select_combo_button.html
index 50c826051c0..50c826051c0 100644
--- a/spec/javascripts/fixtures/static/project_select_combo_button.html.raw
+++ b/spec/javascripts/fixtures/static/project_select_combo_button.html
diff --git a/spec/javascripts/fixtures/static/search_autocomplete.html.raw b/spec/javascripts/fixtures/static/search_autocomplete.html
index 29db9020424..29db9020424 100644
--- a/spec/javascripts/fixtures/static/search_autocomplete.html.raw
+++ b/spec/javascripts/fixtures/static/search_autocomplete.html
diff --git a/spec/javascripts/fixtures/static/signin_tabs.html.raw b/spec/javascripts/fixtures/static/signin_tabs.html
index 7e66ab9394b..7e66ab9394b 100644
--- a/spec/javascripts/fixtures/static/signin_tabs.html.raw
+++ b/spec/javascripts/fixtures/static/signin_tabs.html
diff --git a/spec/javascripts/fixtures/static/sketch_viewer.html.raw b/spec/javascripts/fixtures/static/sketch_viewer.html
index e25e554e568..e25e554e568 100644
--- a/spec/javascripts/fixtures/static/sketch_viewer.html.raw
+++ b/spec/javascripts/fixtures/static/sketch_viewer.html
diff --git a/spec/javascripts/fixtures/static_fixtures.rb b/spec/javascripts/fixtures/static_fixtures.rb
index b5188eeb994..cb4b90cdca5 100644
--- a/spec/javascripts/fixtures/static_fixtures.rb
+++ b/spec/javascripts/fixtures/static_fixtures.rb
@@ -4,7 +4,7 @@ describe ApplicationController, '(Static JavaScript fixtures)', type: :controlle
include JavaScriptFixturesHelpers
Dir.glob('{,ee/}spec/javascripts/fixtures/**/*.haml').map do |file_path|
- it "static/#{file_path.sub(%r{\A(ee/)?spec/javascripts/fixtures/}, '').sub(/\.haml\z/, '.raw')}" do |example|
+ it "static/#{file_path.sub(%r{\A(ee/)?spec/javascripts/fixtures/}, '').sub(/\.haml\z/, '')}" do |example|
store_frontend_fixture(render_template(file_path), example.description)
end
end
diff --git a/spec/javascripts/fixtures/todos.rb b/spec/javascripts/fixtures/todos.rb
index b5f6620873b..6e37a2e5a4c 100644
--- a/spec/javascripts/fixtures/todos.rb
+++ b/spec/javascripts/fixtures/todos.rb
@@ -26,7 +26,7 @@ describe 'Todos (JavaScript fixtures)' do
sign_in(admin)
end
- it 'todos/todos.html.raw' do |example|
+ it 'todos/todos.html' do |example|
get :index
expect(response).to be_success
diff --git a/spec/javascripts/fixtures/u2f.rb b/spec/javascripts/fixtures/u2f.rb
index 5cdbadef639..15866d65a4f 100644
--- a/spec/javascripts/fixtures/u2f.rb
+++ b/spec/javascripts/fixtures/u2f.rb
@@ -18,7 +18,7 @@ context 'U2F' do
set_devise_mapping(context: @request)
end
- it 'u2f/authenticate.html.raw' do |example|
+ it 'u2f/authenticate.html' do |example|
allow(controller).to receive(:find_user).and_return(user)
post :create, params: { user: { login: user.username, password: user.password } }
@@ -36,7 +36,7 @@ context 'U2F' do
allow_any_instance_of(Profiles::TwoFactorAuthsController).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares')
end
- it 'u2f/register.html.raw' do |example|
+ it 'u2f/register.html' do |example|
get :show
expect(response).to be_success
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index 85083653db8..57e31d933ca 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -5,7 +5,7 @@ import GLDropdown from '~/gl_dropdown';
import '~/lib/utils/common_utils';
describe('glDropdown', function describeDropdown() {
- preloadFixtures('static/gl_dropdown.html.raw');
+ preloadFixtures('static/gl_dropdown.html');
loadJSONFixtures('projects.json');
const NON_SELECTABLE_CLASSES =
@@ -64,7 +64,7 @@ describe('glDropdown', function describeDropdown() {
}
beforeEach(() => {
- loadFixtures('static/gl_dropdown.html.raw');
+ loadFixtures('static/gl_dropdown.html');
this.dropdownContainerElement = $('.dropdown.inline');
this.$dropdownMenuElement = $('.dropdown-menu', this.dropdownContainerElement);
this.projectsData = getJSONFixture('projects.json');
diff --git a/spec/javascripts/gl_field_errors_spec.js b/spec/javascripts/gl_field_errors_spec.js
index b463c9afbee..294f219d6fe 100644
--- a/spec/javascripts/gl_field_errors_spec.js
+++ b/spec/javascripts/gl_field_errors_spec.js
@@ -4,10 +4,10 @@ import $ from 'jquery';
import GlFieldErrors from '~/gl_field_errors';
describe('GL Style Field Errors', function() {
- preloadFixtures('static/gl_field_errors.html.raw');
+ preloadFixtures('static/gl_field_errors.html');
beforeEach(function() {
- loadFixtures('static/gl_field_errors.html.raw');
+ loadFixtures('static/gl_field_errors.html');
const $form = $('form.gl-show-field-errors');
this.$form = $form;
diff --git a/spec/javascripts/header_spec.js b/spec/javascripts/header_spec.js
index 2fe34e5a76f..0ddf589f368 100644
--- a/spec/javascripts/header_spec.js
+++ b/spec/javascripts/header_spec.js
@@ -3,7 +3,7 @@ import initTodoToggle from '~/header';
describe('Header', function() {
const todosPendingCount = '.todos-count';
- const fixtureTemplate = 'issues/open-issue.html.raw';
+ const fixtureTemplate = 'issues/open-issue.html';
function isTodosCountHidden() {
return $(todosPendingCount).hasClass('hidden');
diff --git a/spec/javascripts/ide/components/error_message_spec.js b/spec/javascripts/ide/components/error_message_spec.js
index 430e8e2baa3..80d6c7fd564 100644
--- a/spec/javascripts/ide/components/error_message_spec.js
+++ b/spec/javascripts/ide/components/error_message_spec.js
@@ -84,7 +84,7 @@ describe('IDE error message component', () => {
expect(vm.isLoading).toBe(true);
- vm.$nextTick(() => {
+ setTimeout(() => {
expect(vm.isLoading).toBe(false);
done();
diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js
index 7ddc734ff56..1e5b55af4ba 100644
--- a/spec/javascripts/ide/stores/actions/file_spec.js
+++ b/spec/javascripts/ide/stores/actions/file_spec.js
@@ -121,68 +121,48 @@ describe('IDE store file actions', () => {
store._actions.scrollToTab = oldScrollToTab; // eslint-disable-line
});
- it('calls scrollToTab', done => {
- store
- .dispatch('setFileActive', localFile.path)
- .then(() => {
- expect(scrollToTabSpy).toHaveBeenCalled();
-
- done();
- })
- .catch(done.fail);
- });
+ it('calls scrollToTab', () => {
+ const dispatch = jasmine.createSpy();
- it('sets the file active', done => {
- store
- .dispatch('setFileActive', localFile.path)
- .then(() => {
- expect(localFile.active).toBeTruthy();
+ actions.setFileActive(
+ { commit() {}, state: store.state, getters: store.getters, dispatch },
+ localFile.path,
+ );
- done();
- })
- .catch(done.fail);
+ expect(dispatch).toHaveBeenCalledWith('scrollToTab');
});
- it('returns early if file is already active', done => {
- localFile.active = true;
+ it('commits SET_FILE_ACTIVE', () => {
+ const commit = jasmine.createSpy();
- store
- .dispatch('setFileActive', localFile.path)
- .then(() => {
- expect(scrollToTabSpy).not.toHaveBeenCalled();
+ actions.setFileActive(
+ { commit, state: store.state, getters: store.getters, dispatch() {} },
+ localFile.path,
+ );
- done();
- })
- .catch(done.fail);
+ expect(commit).toHaveBeenCalledWith('SET_FILE_ACTIVE', {
+ path: localFile.path,
+ active: true,
+ });
});
- it('sets current active file to not active', done => {
+ it('sets current active file to not active', () => {
const f = file('newActive');
store.state.entries[f.path] = f;
localFile.active = true;
store.state.openFiles.push(localFile);
- store
- .dispatch('setFileActive', f.path)
- .then(() => {
- expect(localFile.active).toBeFalsy();
+ const commit = jasmine.createSpy();
- done();
- })
- .catch(done.fail);
- });
-
- it('resets location.hash for line highlighting', done => {
- window.location.hash = 'test';
-
- store
- .dispatch('setFileActive', localFile.path)
- .then(() => {
- expect(window.location.hash).not.toBe('test');
+ actions.setFileActive(
+ { commit, state: store.state, getters: store.getters, dispatch() {} },
+ f.path,
+ );
- done();
- })
- .catch(done.fail);
+ expect(commit).toHaveBeenCalledWith('SET_FILE_ACTIVE', {
+ path: localFile.path,
+ active: false,
+ });
});
});
diff --git a/spec/javascripts/integrations/integration_settings_form_spec.js b/spec/javascripts/integrations/integration_settings_form_spec.js
index 4f4c9a7b463..069e2cb07b5 100644
--- a/spec/javascripts/integrations/integration_settings_form_spec.js
+++ b/spec/javascripts/integrations/integration_settings_form_spec.js
@@ -4,7 +4,7 @@ import axios from '~/lib/utils/axios_utils';
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
describe('IntegrationSettingsForm', () => {
- const FIXTURE = 'services/edit_service.html.raw';
+ const FIXTURE = 'services/edit_service.html';
preloadFixtures(FIXTURE);
beforeEach(() => {
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
index 0ccf771c7ef..dfc889773c1 100644
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ b/spec/javascripts/issue_show/components/app_spec.js
@@ -75,7 +75,7 @@ describe('Issuable output', () => {
.then(() => {
expect(document.querySelector('title').innerText).toContain('this is a title (#1)');
expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>this is a title</p>');
- expect(vm.$el.querySelector('.wiki').innerHTML).toContain('<p>this is a description!</p>');
+ expect(vm.$el.querySelector('.md').innerHTML).toContain('<p>this is a description!</p>');
expect(vm.$el.querySelector('.js-task-list-field').value).toContain(
'this is a description',
);
@@ -92,7 +92,7 @@ describe('Issuable output', () => {
.then(() => {
expect(document.querySelector('title').innerText).toContain('2 (#1)');
expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>2</p>');
- expect(vm.$el.querySelector('.wiki').innerHTML).toContain('<p>42</p>');
+ expect(vm.$el.querySelector('.md').innerHTML).toContain('<p>42</p>');
expect(vm.$el.querySelector('.js-task-list-field').value).toContain('42');
expect(vm.$el.querySelector('.edited-text')).toBeTruthy();
expect(formatText(vm.$el.querySelector('.edited-text').innerText)).toMatch(
diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js
index 2eeed6770be..7e00fbf2745 100644
--- a/spec/javascripts/issue_show/components/description_spec.js
+++ b/spec/javascripts/issue_show/components/description_spec.js
@@ -43,12 +43,12 @@ describe('Description component', () => {
Vue.nextTick(() => {
expect(
- vm.$el.querySelector('.wiki').classList.contains('issue-realtime-pre-pulse'),
+ vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
).toBeTruthy();
setTimeout(() => {
expect(
- vm.$el.querySelector('.wiki').classList.contains('issue-realtime-trigger-pulse'),
+ vm.$el.querySelector('.md').classList.contains('issue-realtime-trigger-pulse'),
).toBeTruthy();
done();
diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js
index 7be495d1d35..11ab6c38a55 100644
--- a/spec/javascripts/issue_spec.js
+++ b/spec/javascripts/issue_spec.js
@@ -9,9 +9,9 @@ import '~/lib/utils/text_utility';
describe('Issue', function() {
let $boxClosed, $boxOpen, $btn;
- preloadFixtures('issues/closed-issue.html.raw');
- preloadFixtures('issues/issue-with-task-list.html.raw');
- preloadFixtures('issues/open-issue.html.raw');
+ preloadFixtures('issues/closed-issue.html');
+ preloadFixtures('issues/issue-with-task-list.html');
+ preloadFixtures('issues/open-issue.html');
function expectErrorMessage() {
const $flashMessage = $('div.flash-alert');
@@ -105,9 +105,9 @@ describe('Issue', function() {
beforeEach(function() {
if (isIssueInitiallyOpen) {
- loadFixtures('issues/open-issue.html.raw');
+ loadFixtures('issues/open-issue.html');
} else {
- loadFixtures('issues/closed-issue.html.raw');
+ loadFixtures('issues/closed-issue.html');
}
mock = new MockAdapter(axios);
diff --git a/spec/javascripts/labels_issue_sidebar_spec.js b/spec/javascripts/labels_issue_sidebar_spec.js
index e5678ee5379..ccf439aac74 100644
--- a/spec/javascripts/labels_issue_sidebar_spec.js
+++ b/spec/javascripts/labels_issue_sidebar_spec.js
@@ -16,10 +16,10 @@ let saveLabelCount = 0;
let mock;
describe('Issue dropdown sidebar', () => {
- preloadFixtures('static/issue_sidebar_label.html.raw');
+ preloadFixtures('static/issue_sidebar_label.html');
beforeEach(() => {
- loadFixtures('static/issue_sidebar_label.html.raw');
+ loadFixtures('static/issue_sidebar_label.html');
mock = new MockAdapter(axios);
diff --git a/spec/javascripts/lazy_loader_spec.js b/spec/javascripts/lazy_loader_spec.js
index cbdc1644430..f3fb792c62d 100644
--- a/spec/javascripts/lazy_loader_spec.js
+++ b/spec/javascripts/lazy_loader_spec.js
@@ -11,11 +11,11 @@ const execImmediately = callback => {
describe('LazyLoader', function() {
let lazyLoader = null;
- preloadFixtures('issues/issue_with_comment.html.raw');
+ preloadFixtures('issues/issue_with_comment.html');
describe('without IntersectionObserver', () => {
beforeEach(function() {
- loadFixtures('issues/issue_with_comment.html.raw');
+ loadFixtures('issues/issue_with_comment.html');
lazyLoader = new LazyLoader({
observerNode: 'foobar',
@@ -131,7 +131,7 @@ describe('LazyLoader', function() {
describe('with IntersectionObserver', () => {
beforeEach(function() {
- loadFixtures('issues/issue_with_comment.html.raw');
+ loadFixtures('issues/issue_with_comment.html');
lazyLoader = new LazyLoader({
observerNode: 'foobar',
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index 4eea364bd69..a75470b4db8 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -5,7 +5,7 @@ import LineHighlighter from '~/line_highlighter';
describe('LineHighlighter', function() {
var clickLine;
- preloadFixtures('static/line_highlighter.html.raw');
+ preloadFixtures('static/line_highlighter.html');
clickLine = function(number, eventData = {}) {
if ($.isEmptyObject(eventData)) {
return $('#L' + number).click();
@@ -15,7 +15,7 @@ describe('LineHighlighter', function() {
}
};
beforeEach(function() {
- loadFixtures('static/line_highlighter.html.raw');
+ loadFixtures('static/line_highlighter.html');
this['class'] = new LineHighlighter();
this.css = this['class'].highlightLineClass;
return (this.spies = {
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index ab809930804..431798c6ec3 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -11,9 +11,9 @@ describe('MergeRequest', function() {
describe('task lists', function() {
let mock;
- preloadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ preloadFixtures('merge_requests/merge_request_with_task_list.html');
beforeEach(function() {
- loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ loadFixtures('merge_requests/merge_request_with_task_list.html');
spyOn(axios, 'patch').and.callThrough();
mock = new MockAdapter(axios);
@@ -125,7 +125,7 @@ describe('MergeRequest', function() {
describe('hideCloseButton', () => {
describe('merge request of another user', () => {
beforeEach(() => {
- loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ loadFixtures('merge_requests/merge_request_with_task_list.html');
this.el = document.querySelector('.js-issuable-actions');
new MergeRequest(); // eslint-disable-line no-new
MergeRequest.hideCloseButton();
@@ -145,7 +145,7 @@ describe('MergeRequest', function() {
describe('merge request of current_user', () => {
beforeEach(() => {
- loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
+ loadFixtures('merge_requests/merge_request_of_current_user.html');
this.el = document.querySelector('.js-issuable-actions');
MergeRequest.hideCloseButton();
});
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index c8df05eccf5..1295d900de7 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -22,8 +22,8 @@ describe('MergeRequestTabs', function() {
};
preloadFixtures(
- 'merge_requests/merge_request_with_task_list.html.raw',
- 'merge_requests/diff_comment.html.raw',
+ 'merge_requests/merge_request_with_task_list.html',
+ 'merge_requests/diff_comment.html',
);
beforeEach(function() {
@@ -48,7 +48,7 @@ describe('MergeRequestTabs', function() {
var windowTarget = '_blank';
beforeEach(function() {
- loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ loadFixtures('merge_requests/merge_request_with_task_list.html');
tabUrl = $('.commits-tab a').attr('href');
});
diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js
index 092ca9e1dab..aa4a376caf7 100644
--- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js
+++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js
@@ -5,10 +5,10 @@ import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
import timeoutPromise from './helpers/set_timeout_promise_helper';
describe('Mini Pipeline Graph Dropdown', () => {
- preloadFixtures('static/mini_dropdown_graph.html.raw');
+ preloadFixtures('static/mini_dropdown_graph.html');
beforeEach(() => {
- loadFixtures('static/mini_dropdown_graph.html.raw');
+ loadFixtures('static/mini_dropdown_graph.html');
});
describe('When is initialized', () => {
diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js
index fb49290be19..549a7935c0f 100644
--- a/spec/javascripts/monitoring/charts/area_spec.js
+++ b/spec/javascripts/monitoring/charts/area_spec.js
@@ -203,6 +203,10 @@ describe('Area component', () => {
.length,
).toBe(data.length);
});
+
+ it('formats line width correctly', () => {
+ expect(chartData[0].lineStyle.width).toBe(2);
+ });
});
describe('scatterSeries', () => {
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index 6078a0e7872..454777fa912 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -33,6 +33,11 @@ describe('Dashboard', () => {
<div class="layout-page"></div>
`);
+ window.gon = {
+ ...window.gon,
+ ee: false,
+ };
+
mock = new MockAdapter(axios);
DashboardComponent = Vue.extend(Dashboard);
});
@@ -152,6 +157,25 @@ describe('Dashboard', () => {
done();
});
});
+
+ it('hides the dropdown', done => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: {
+ ...propsData,
+ hasMetrics: true,
+ showPanels: false,
+ environmentsEndpoint: '',
+ },
+ });
+
+ Vue.nextTick(() => {
+ const dropdownIsActiveElement = component.$el.querySelectorAll('.environments');
+
+ expect(dropdownIsActiveElement.length).toEqual(0);
+ done();
+ });
+ });
});
describe('when the window resizes', () => {
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index ffc7148fde2..6d4ef960c1a 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -330,6 +330,11 @@ export const metricsGroupsAPIResponse = {
weight: 1,
queries: [
{
+ appearance: {
+ line: {
+ width: 2,
+ },
+ },
query_range:
'avg(rate(container_cpu_usage_seconds_total{%{environment_filter}}[2m])) * 100',
label: 'Core Usage',
diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js
index 1d7b885e64f..4e3140ce4f1 100644
--- a/spec/javascripts/new_branch_spec.js
+++ b/spec/javascripts/new_branch_spec.js
@@ -3,7 +3,7 @@ import NewBranchForm from '~/new_branch_form';
describe('Branch', function() {
describe('create a new branch', function() {
- preloadFixtures('branches/new_branch.html.raw');
+ preloadFixtures('branches/new_branch.html');
function fillNameWith(value) {
$('.js-branch-name')
@@ -16,7 +16,7 @@ describe('Branch', function() {
}
beforeEach(function() {
- loadFixtures('branches/new_branch.html.raw');
+ loadFixtures('branches/new_branch.html');
$('form').on('submit', function(e) {
return e.preventDefault();
});
diff --git a/spec/javascripts/notes/components/note_app_spec.js b/spec/javascripts/notes/components/note_app_spec.js
index d716ece3766..ef876dc2941 100644
--- a/spec/javascripts/notes/components/note_app_spec.js
+++ b/spec/javascripts/notes/components/note_app_spec.js
@@ -192,9 +192,9 @@ describe('note_app', () => {
expect(service.updateNote).toHaveBeenCalled();
// Wait for the requests to finish before destroying
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ setTimeout(() => {
+ done();
+ });
});
});
@@ -227,9 +227,9 @@ describe('note_app', () => {
expect(service.updateNote).toHaveBeenCalled();
// Wait for the requests to finish before destroying
- Vue.nextTick()
- .then(done)
- .catch(done.fail);
+ setTimeout(() => {
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/notes/components/note_form_spec.js b/spec/javascripts/notes/components/note_form_spec.js
index c48f8188105..b632ee6736d 100644
--- a/spec/javascripts/notes/components/note_form_spec.js
+++ b/spec/javascripts/notes/components/note_form_spec.js
@@ -41,8 +41,6 @@ describe('issue_note_form component', () => {
noteBody: 'Magni suscipit eius consectetur enim et ex et commodi.',
noteId: '545',
};
-
- wrapper = createComponentWrapper();
});
afterEach(() => {
@@ -50,6 +48,10 @@ describe('issue_note_form component', () => {
});
describe('noteHash', () => {
+ beforeEach(() => {
+ wrapper = createComponentWrapper();
+ });
+
it('returns note hash string based on `noteId`', () => {
expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`);
});
@@ -71,6 +73,10 @@ describe('issue_note_form component', () => {
});
describe('conflicts editing', () => {
+ beforeEach(() => {
+ wrapper = createComponentWrapper();
+ });
+
it('should show conflict message if note changes outside the component', done => {
wrapper.setProps({
...props,
@@ -100,6 +106,10 @@ describe('issue_note_form component', () => {
});
describe('form', () => {
+ beforeEach(() => {
+ wrapper = createComponentWrapper();
+ });
+
it('should render text area with placeholder', () => {
const textarea = wrapper.find('textarea');
@@ -198,10 +208,6 @@ describe('issue_note_form component', () => {
});
describe('with autosaveKey', () => {
- beforeEach(() => {
- wrapper.destroy();
- });
-
describe('with draft', () => {
beforeEach(done => {
Object.assign(props, {
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index 7c869d4c326..3d2c617e479 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -34,7 +34,7 @@ const htmlEscape = comment => {
describe('Notes', function() {
const FLASH_TYPE_ALERT = 'alert';
const NOTES_POST_PATH = /(.*)\/notes\?html=true$/;
- var fixture = 'snippets/show.html.raw';
+ var fixture = 'snippets/show.html';
preloadFixtures(fixture);
beforeEach(function() {
diff --git a/spec/javascripts/oauth_remember_me_spec.js b/spec/javascripts/oauth_remember_me_spec.js
index 4125706a407..381be82697e 100644
--- a/spec/javascripts/oauth_remember_me_spec.js
+++ b/spec/javascripts/oauth_remember_me_spec.js
@@ -2,10 +2,10 @@ import $ from 'jquery';
import OAuthRememberMe from '~/pages/sessions/new/oauth_remember_me';
describe('OAuthRememberMe', () => {
- preloadFixtures('static/oauth_remember_me.html.raw');
+ preloadFixtures('static/oauth_remember_me.html');
beforeEach(() => {
- loadFixtures('static/oauth_remember_me.html.raw');
+ loadFixtures('static/oauth_remember_me.html');
new OAuthRememberMe({ container: $('#oauth-container') }).bindEvents();
});
diff --git a/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js b/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
index 561bd2c96cb..6a239e307e9 100644
--- a/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
+++ b/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
@@ -5,7 +5,7 @@ import initUserInternalRegexPlaceholder, {
} from '~/pages/admin/application_settings/account_and_limits';
describe('AccountAndLimits', () => {
- const FIXTURE = 'application_settings/accounts_and_limit.html.raw';
+ const FIXTURE = 'application_settings/accounts_and_limit.html';
let $userDefaultExternal;
let $userInternalRegex;
preloadFixtures(FIXTURE);
diff --git a/spec/javascripts/pages/admin/users/new/index_spec.js b/spec/javascripts/pages/admin/users/new/index_spec.js
index 5a849f34bc3..3896323eef7 100644
--- a/spec/javascripts/pages/admin/users/new/index_spec.js
+++ b/spec/javascripts/pages/admin/users/new/index_spec.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import UserInternalRegexHandler from '~/pages/admin/users/new/index';
describe('UserInternalRegexHandler', () => {
- const FIXTURE = 'admin/users/new_with_internal_user_regex.html.raw';
+ const FIXTURE = 'admin/users/new_with_internal_user_regex.html';
let $userExternal;
let $userEmail;
let $warningMessage;
diff --git a/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js b/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
index 7a8227479d4..1809e92e1d9 100644
--- a/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
+++ b/spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js
@@ -2,10 +2,10 @@ import $ from 'jquery';
import preserveUrlFragment from '~/pages/sessions/new/preserve_url_fragment';
describe('preserve_url_fragment', () => {
- preloadFixtures('sessions/new.html.raw');
+ preloadFixtures('sessions/new.html');
beforeEach(() => {
- loadFixtures('sessions/new.html.raw');
+ loadFixtures('sessions/new.html');
});
it('adds the url fragment to all login and sign up form actions', () => {
diff --git a/spec/javascripts/pipelines/graph/action_component_spec.js b/spec/javascripts/pipelines/graph/action_component_spec.js
index 3d2232ff239..95717d659b8 100644
--- a/spec/javascripts/pipelines/graph/action_component_spec.js
+++ b/spec/javascripts/pipelines/graph/action_component_spec.js
@@ -55,13 +55,16 @@ describe('pipeline graph action component', () => {
component.$el.click();
- component
- .$nextTick()
- .then(() => {
- expect(component.$emit).toHaveBeenCalledWith('pipelineActionRequestComplete');
- })
- .then(done)
- .catch(done.fail);
+ setTimeout(() => {
+ component
+ .$nextTick()
+ .then(() => {
+ expect(component.$emit).toHaveBeenCalledWith('pipelineActionRequestComplete');
+ })
+ .catch(done.fail);
+
+ done();
+ }, 0);
});
});
});
diff --git a/spec/javascripts/pipelines/graph/stage_column_component_spec.js b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
index dafb892da43..3240e8e4c1b 100644
--- a/spec/javascripts/pipelines/graph/stage_column_component_spec.js
+++ b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
@@ -55,7 +55,7 @@ describe('stage column component', () => {
id: 4259,
name: '<img src=x onerror=alert(document.domain)>',
status: {
- icon: 'icon_status_success',
+ icon: 'status_success',
label: 'success',
tooltip: '<img src=x onerror=alert(document.domain)>',
},
diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js
index 3c8b8032de8..19ae7860333 100644
--- a/spec/javascripts/pipelines/stage_spec.js
+++ b/spec/javascripts/pipelines/stage_spec.js
@@ -120,13 +120,15 @@ describe('Pipelines stage component', () => {
setTimeout(() => {
component.$el.querySelector('.js-ci-action').click();
- component
- .$nextTick()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
- })
- .then(done)
- .catch(done.fail);
+ setTimeout(() => {
+ component
+ .$nextTick()
+ .then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
+ })
+ .then(done)
+ .catch(done.fail);
+ }, 0);
}, 0);
});
});
diff --git a/spec/javascripts/pipelines_spec.js b/spec/javascripts/pipelines_spec.js
index 6b86f9ea437..6d4d634c575 100644
--- a/spec/javascripts/pipelines_spec.js
+++ b/spec/javascripts/pipelines_spec.js
@@ -1,10 +1,10 @@
import Pipelines from '~/pipelines';
describe('Pipelines', () => {
- preloadFixtures('static/pipeline_graph.html.raw');
+ preloadFixtures('static/pipeline_graph.html');
beforeEach(() => {
- loadFixtures('static/pipeline_graph.html.raw');
+ loadFixtures('static/pipeline_graph.html');
});
it('should be defined', () => {
diff --git a/spec/javascripts/project_select_combo_button_spec.js b/spec/javascripts/project_select_combo_button_spec.js
index 109a5000f5d..dc85292c23e 100644
--- a/spec/javascripts/project_select_combo_button_spec.js
+++ b/spec/javascripts/project_select_combo_button_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import ProjectSelectComboButton from '~/project_select_combo_button';
-const fixturePath = 'static/project_select_combo_button.html.raw';
+const fixturePath = 'static/project_select_combo_button.html';
describe('Project Select Combo Button', function() {
preloadFixtures(fixturePath);
diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js
index 030662b4d90..1eb7cb4bd5b 100644
--- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js
+++ b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js
@@ -53,36 +53,32 @@ describe('GkeProjectIdDropdown', () => {
});
it('returns default toggle text', done =>
- vm
- .$nextTick()
- .then(() => {
- vm.setItem(emptyProjectMock);
+ setTimeout(() => {
+ vm.setItem(emptyProjectMock);
- expect(vm.toggleText).toBe(LABELS.DEFAULT);
- done();
- })
- .catch(done.fail));
+ expect(vm.toggleText).toBe(LABELS.DEFAULT);
+
+ done();
+ }));
it('returns project name if project selected', done =>
- vm
- .$nextTick()
- .then(() => {
- expect(vm.toggleText).toBe(selectedProjectMock.name);
- done();
- })
- .catch(done.fail));
+ setTimeout(() => {
+ vm.isLoading = false;
+
+ expect(vm.toggleText).toBe(selectedProjectMock.name);
+
+ done();
+ }));
it('returns empty toggle text', done =>
- vm
- .$nextTick()
- .then(() => {
- vm.$store.commit(SET_PROJECTS, null);
- vm.setItem(emptyProjectMock);
+ setTimeout(() => {
+ vm.$store.commit(SET_PROJECTS, null);
+ vm.setItem(emptyProjectMock);
- expect(vm.toggleText).toBe(LABELS.EMPTY);
- done();
- })
- .catch(done.fail));
+ expect(vm.toggleText).toBe(LABELS.EMPTY);
+
+ done();
+ }));
});
describe('selectItem', () => {
diff --git a/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js b/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
index 94e2f959d46..dca3e1553b9 100644
--- a/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
@@ -5,7 +5,7 @@ import PANEL_STATE from '~/prometheus_metrics/constants';
import { metrics, missingVarMetrics } from './mock_data';
describe('PrometheusMetrics', () => {
- const FIXTURE = 'services/prometheus/prometheus_service.html.raw';
+ const FIXTURE = 'services/prometheus/prometheus_service.html';
preloadFixtures(FIXTURE);
beforeEach(() => {
diff --git a/spec/javascripts/read_more_spec.js b/spec/javascripts/read_more_spec.js
index b1af0f80a50..d1d01272403 100644
--- a/spec/javascripts/read_more_spec.js
+++ b/spec/javascripts/read_more_spec.js
@@ -1,7 +1,7 @@
import initReadMore from '~/read_more';
describe('Read more click-to-expand functionality', () => {
- const fixtureName = 'projects/overview.html.raw';
+ const fixtureName = 'projects/overview.html';
preloadFixtures(fixtureName);
diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js
index 992e17978c1..9565e3ce546 100644
--- a/spec/javascripts/right_sidebar_spec.js
+++ b/spec/javascripts/right_sidebar_spec.js
@@ -23,7 +23,7 @@ const assertSidebarState = function(state) {
describe('RightSidebar', function() {
describe('fixture tests', () => {
- const fixtureName = 'issues/open-issue.html.raw';
+ const fixtureName = 'issues/open-issue.html';
preloadFixtures(fixtureName);
loadJSONFixtures('todos/todos.json');
let mock;
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index 7a4ca587313..ce7fa7a52ae 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -126,9 +126,9 @@ describe('Search autocomplete dropdown', () => {
expect(list.find(mrsIHaveCreatedLink).text()).toBe("Merge requests I've created");
};
- preloadFixtures('static/search_autocomplete.html.raw');
+ preloadFixtures('static/search_autocomplete.html');
beforeEach(function() {
- loadFixtures('static/search_autocomplete.html.raw');
+ loadFixtures('static/search_autocomplete.html');
window.gon = {};
window.gon.current_user_id = userId;
diff --git a/spec/javascripts/search_spec.js b/spec/javascripts/search_spec.js
index 40bdbac7451..32f60508fa3 100644
--- a/spec/javascripts/search_spec.js
+++ b/spec/javascripts/search_spec.js
@@ -3,7 +3,7 @@ import Api from '~/api';
import Search from '~/pages/search/show/search';
describe('Search', () => {
- const fixturePath = 'search/show.html.raw';
+ const fixturePath = 'search/show.html';
const searchTerm = 'some search';
const fillDropdownInput = dropdownSelector => {
const dropdownElement = document.querySelector(dropdownSelector).parentNode;
diff --git a/spec/javascripts/settings_panels_spec.js b/spec/javascripts/settings_panels_spec.js
index 3b681a9ff28..2c5d91a45bc 100644
--- a/spec/javascripts/settings_panels_spec.js
+++ b/spec/javascripts/settings_panels_spec.js
@@ -2,10 +2,10 @@ import $ from 'jquery';
import initSettingsPanels from '~/settings_panels';
describe('Settings Panels', () => {
- preloadFixtures('groups/edit.html.raw');
+ preloadFixtures('groups/edit.html');
beforeEach(() => {
- loadFixtures('groups/edit.html.raw');
+ loadFixtures('groups/edit.html');
});
describe('initSettingsPane', () => {
diff --git a/spec/javascripts/shortcuts_spec.js b/spec/javascripts/shortcuts_spec.js
index 3ca6ecaa938..df7012bb659 100644
--- a/spec/javascripts/shortcuts_spec.js
+++ b/spec/javascripts/shortcuts_spec.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
describe('Shortcuts', () => {
- const fixtureName = 'snippets/show.html.raw';
+ const fixtureName = 'snippets/show.html';
const createEvent = (type, target) =>
$.Event(type, {
target,
diff --git a/spec/javascripts/sidebar/assignees_spec.js b/spec/javascripts/sidebar/assignees_spec.js
index eced4925489..57b16b12cb0 100644
--- a/spec/javascripts/sidebar/assignees_spec.js
+++ b/spec/javascripts/sidebar/assignees_spec.js
@@ -210,6 +210,19 @@ describe('Assignee component', () => {
expect(component.$el.querySelector('.user-list-more')).toBe(null);
});
+ it('sets tooltip container to body', () => {
+ const users = UsersMockHelper.createNumberRandomUsers(2);
+ component = new AssigneeComponent({
+ propsData: {
+ rootPath: 'http://localhost:3000',
+ users,
+ editable: true,
+ },
+ }).$mount();
+
+ expect(component.$el.querySelector('.user-link').getAttribute('data-container')).toBe('body');
+ });
+
it('Shows the "show-less" assignees label', done => {
const users = UsersMockHelper.createNumberRandomUsers(6);
component = new AssigneeComponent({
diff --git a/spec/javascripts/sidebar/sidebar_assignees_spec.js b/spec/javascripts/sidebar/sidebar_assignees_spec.js
index 3f0f67d71ca..016f5e033a5 100644
--- a/spec/javascripts/sidebar/sidebar_assignees_spec.js
+++ b/spec/javascripts/sidebar/sidebar_assignees_spec.js
@@ -11,12 +11,12 @@ describe('sidebar assignees', () => {
let vm;
let mediator;
let sidebarAssigneesEl;
- preloadFixtures('issues/open-issue.html.raw');
+ preloadFixtures('issues/open-issue.html');
beforeEach(() => {
Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
- loadFixtures('issues/open-issue.html.raw');
+ loadFixtures('issues/open-issue.html');
mediator = new SidebarMediator(Mock.mediator);
spyOn(mediator, 'saveAssignees').and.callThrough();
diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js b/spec/javascripts/signin_tabs_memoizer_spec.js
index 52da6a79939..ef5c774736b 100644
--- a/spec/javascripts/signin_tabs_memoizer_spec.js
+++ b/spec/javascripts/signin_tabs_memoizer_spec.js
@@ -2,7 +2,7 @@ import AccessorUtilities from '~/lib/utils/accessor';
import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer';
describe('SigninTabsMemoizer', () => {
- const fixtureTemplate = 'static/signin_tabs.html.raw';
+ const fixtureTemplate = 'static/signin_tabs.html';
const tabSelector = 'ul.new-session-tabs';
const currentTabKey = 'current_signin_tab';
let memo;
diff --git a/spec/javascripts/todos_spec.js b/spec/javascripts/todos_spec.js
index 69e43274250..802f54f6a7e 100644
--- a/spec/javascripts/todos_spec.js
+++ b/spec/javascripts/todos_spec.js
@@ -3,11 +3,11 @@ import Todos from '~/pages/dashboard/todos/index/todos';
import '~/lib/utils/common_utils';
describe('Todos', () => {
- preloadFixtures('todos/todos.html.raw');
+ preloadFixtures('todos/todos.html');
let todoItem;
beforeEach(() => {
- loadFixtures('todos/todos.html.raw');
+ loadFixtures('todos/todos.html');
todoItem = document.querySelector('.todos-list .todo');
return new Todos();
diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js
index ddb09811dda..8f9cb270729 100644
--- a/spec/javascripts/u2f/authenticate_spec.js
+++ b/spec/javascripts/u2f/authenticate_spec.js
@@ -4,10 +4,10 @@ import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device';
describe('U2FAuthenticate', function() {
- preloadFixtures('u2f/authenticate.html.raw');
+ preloadFixtures('u2f/authenticate.html');
beforeEach(() => {
- loadFixtures('u2f/authenticate.html.raw');
+ loadFixtures('u2f/authenticate.html');
this.u2fDevice = new MockU2FDevice();
this.container = $('#js-authenticate-u2f');
this.component = new U2FAuthenticate(
diff --git a/spec/javascripts/u2f/register_spec.js b/spec/javascripts/u2f/register_spec.js
index 261db3d66d7..a75ceca9f4c 100644
--- a/spec/javascripts/u2f/register_spec.js
+++ b/spec/javascripts/u2f/register_spec.js
@@ -4,10 +4,10 @@ import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device';
describe('U2FRegister', function() {
- preloadFixtures('u2f/register.html.raw');
+ preloadFixtures('u2f/register.html');
beforeEach(done => {
- loadFixtures('u2f/register.html.raw');
+ loadFixtures('u2f/register.html');
this.u2fDevice = new MockU2FDevice();
this.container = $('#js-register-u2f');
this.component = new U2FRegister(this.container, $('#js-register-u2f-templates'), {}, 'token');
diff --git a/spec/javascripts/user_popovers_spec.js b/spec/javascripts/user_popovers_spec.js
index b174a51c1a0..c0d5ee9c446 100644
--- a/spec/javascripts/user_popovers_spec.js
+++ b/spec/javascripts/user_popovers_spec.js
@@ -2,7 +2,7 @@ import initUserPopovers from '~/user_popovers';
import UsersCache from '~/lib/utils/users_cache';
describe('User Popovers', () => {
- const fixtureTemplate = 'merge_requests/diff_comment.html.raw';
+ const fixtureTemplate = 'merge_requests/diff_comment.html';
preloadFixtures(fixtureTemplate);
const selector = '.js-user-link';
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
index 3229ddd5e27..780bed1bf69 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
@@ -120,7 +120,7 @@ describe('MRWidgetFailedToMerge', () => {
it('renders given error', () => {
expect(vm.$el.querySelector('.has-error-message').textContent.trim()).toEqual(
- 'Merge error happened.',
+ 'Merge error happened',
);
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 30659ad16f3..368c997d318 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -415,7 +415,7 @@ describe('ReadyToMerge', () => {
});
beforeEach(() => {
- loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
+ loadFixtures('merge_requests/merge_request_of_current_user.html');
});
it('should call start and stop polling when MR merged', done => {
diff --git a/spec/javascripts/vue_shared/components/markdown/field_spec.js b/spec/javascripts/vue_shared/components/markdown/field_spec.js
index 79e0e756a7a..02d73e1849a 100644
--- a/spec/javascripts/vue_shared/components/markdown/field_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/field_spec.js
@@ -5,7 +5,7 @@ import fieldComponent from '~/vue_shared/components/markdown/field.vue';
function assertMarkdownTabs(isWrite, writeLink, previewLink, vm) {
expect(writeLink.parentNode.classList.contains('active')).toEqual(isWrite);
expect(previewLink.parentNode.classList.contains('active')).toEqual(!isWrite);
- expect(vm.$el.querySelector('.md-preview').style.display).toEqual(isWrite ? 'none' : '');
+ expect(vm.$el.querySelector('.md-preview-holder').style.display).toEqual(isWrite ? 'none' : '');
}
describe('Markdown field component', () => {
@@ -80,7 +80,9 @@ describe('Markdown field component', () => {
previewLink.click();
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.md-preview').textContent.trim()).toContain('Loading…');
+ expect(vm.$el.querySelector('.md-preview-holder').textContent.trim()).toContain(
+ 'Loading…',
+ );
done();
});
@@ -90,7 +92,7 @@ describe('Markdown field component', () => {
previewLink.click();
setTimeout(() => {
- expect(vm.$el.querySelector('.md-preview').innerHTML).toContain(
+ expect(vm.$el.querySelector('.md-preview-holder').innerHTML).toContain(
'<p>markdown preview</p>',
);
diff --git a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
index e8b41e8eeff..852558a83bc 100644
--- a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
@@ -17,7 +17,7 @@ const DEFAULT_PROPS = {
const UserPopover = Vue.extend(userPopover);
describe('User Popover Component', () => {
- const fixtureTemplate = 'merge_requests/diff_comment.html.raw';
+ const fixtureTemplate = 'merge_requests/diff_comment.html';
preloadFixtures(fixtureTemplate);
let vm;
diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js
index e5f1e6ae937..8f662c71c7a 100644
--- a/spec/javascripts/zen_mode_spec.js
+++ b/spec/javascripts/zen_mode_spec.js
@@ -6,7 +6,7 @@ import ZenMode from '~/zen_mode';
describe('ZenMode', () => {
let zen;
let dropzoneForElementSpy;
- const fixtureName = 'snippets/show.html.raw';
+ const fixtureName = 'snippets/show.html';
preloadFixtures(fixtureName);
diff --git a/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb b/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb
new file mode 100644
index 00000000000..4a81a37d341
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Gitlab::BackgroundMigration::PopulateMergeRequestAssigneesTable, :migration, schema: 20190315191339 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:users) { table(:users) }
+
+ let(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
+ let(:user_2) { users.create!(email: 'test2@example.com', projects_limit: 100, username: 'test') }
+ let(:user_3) { users.create!(email: 'test3@example.com', projects_limit: 100, username: 'test') }
+
+ let(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create(namespace_id: namespace.id, name: 'foo') }
+ let(:merge_requests) { table(:merge_requests) }
+ let(:merge_request_assignees) { table(:merge_request_assignees) }
+
+ def create_merge_request(id, params = {})
+ params.merge!(id: id,
+ target_project_id: project.id,
+ target_branch: 'master',
+ source_project_id: project.id,
+ source_branch: 'mr name',
+ title: "mr name#{id}")
+
+ merge_requests.create(params)
+ end
+
+ describe '#perform' do
+ it 'creates merge_request_assignees rows according to merge_requests' do
+ create_merge_request(2, assignee_id: user.id)
+ create_merge_request(3, assignee_id: user_2.id)
+ create_merge_request(4, assignee_id: user_3.id)
+ # Test filtering already migrated row
+ merge_request_assignees.create!(merge_request_id: 2, user_id: user_3.id)
+
+ subject.perform(1, 4)
+
+ rows = merge_request_assignees.order(:id).map { |row| row.attributes.slice('merge_request_id', 'user_id') }
+ existing_rows = [
+ { 'merge_request_id' => 2, 'user_id' => user_3.id }
+ ]
+ created_rows = [
+ { 'merge_request_id' => 3, 'user_id' => user_2.id },
+ { 'merge_request_id' => 4, 'user_id' => user_3.id }
+ ]
+ expected_rows = existing_rows + created_rows
+
+ expect(rows.size).to eq(expected_rows.size)
+ expected_rows.each do |expected_row|
+ expect(rows).to include(expected_row)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index dab0fb51bcc..5181e9c1583 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -48,6 +48,24 @@ describe Gitlab::Ci::Pipeline::Chain::Command do
end
end
+ describe '#merge_request_ref_exists?' do
+ subject { command.merge_request_ref_exists? }
+
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ context 'for existing merge request ref' do
+ let(:origin_ref) { merge_request.ref_path }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'for branch ref' do
+ let(:origin_ref) { merge_request.source_branch }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
describe '#ref' do
subject { command.ref }
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb
index 8ba56d73838..7d750877d09 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb
@@ -10,12 +10,33 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
- project: project, current_user: user, origin_ref: ref)
+ project: project, current_user: user, origin_ref: origin_ref, merge_request: merge_request)
end
let(:step) { described_class.new(pipeline, command) }
let(:ref) { 'master' }
+ let(:origin_ref) { ref }
+ let(:merge_request) { nil }
+
+ shared_context 'detached merge request pipeline' do
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ source_branch: ref,
+ target_project: project,
+ target_branch: 'feature')
+ end
+
+ let(:pipeline) do
+ build(:ci_pipeline,
+ source: :merge_request_event,
+ merge_request: merge_request,
+ project: project)
+ end
+
+ let(:origin_ref) { merge_request.ref_path }
+ end
context 'when users has no ability to run a pipeline' do
before do
@@ -58,6 +79,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do
it { is_expected.to be_truthy }
+ context 'when pipeline is a detached merge request pipeline' do
+ include_context 'detached merge request pipeline'
+
+ it { is_expected.to be_truthy }
+ end
+
context 'when the branch is protected' do
let!(:protected_branch) do
create(:protected_branch, project: project, name: ref)
@@ -65,6 +92,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do
it { is_expected.to be_falsey }
+ context 'when pipeline is a detached merge request pipeline' do
+ include_context 'detached merge request pipeline'
+
+ it { is_expected.to be_falsey }
+ end
+
context 'when developers are allowed to merge' do
let!(:protected_branch) do
create(:protected_branch,
@@ -74,6 +107,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do
end
it { is_expected.to be_truthy }
+
+ context 'when pipeline is a detached merge request pipeline' do
+ include_context 'detached merge request pipeline'
+
+ it { is_expected.to be_truthy }
+ end
end
end
@@ -112,6 +151,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Abilities do
end
it { is_expected.to be_truthy }
+
+ context 'when pipeline is a detached merge request pipeline' do
+ include_context 'detached merge request pipeline'
+
+ it { is_expected.to be_truthy }
+ end
end
context 'when the tag is protected' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
index a7cad423d09..2e8c9d70098 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
@@ -42,6 +42,25 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Repository do
end
end
+ context 'when origin ref is a merge request ref' do
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project, current_user: user, origin_ref: origin_ref, checkout_sha: checkout_sha)
+ end
+
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:origin_ref) { merge_request.ref_path }
+ let(:checkout_sha) { project.repository.commit(merge_request.ref_path).id }
+
+ it 'does not break the chain' do
+ expect(step.break?).to be false
+ end
+
+ it 'does not append pipeline errors' do
+ expect(pipeline.errors).to be_empty
+ end
+ end
+
context 'when ref is ambiguous' do
let(:project) do
create(:project, :repository).tap do |proj|
diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb
index 17d5eae24f5..909dbffa38f 100644
--- a/spec/lib/gitlab/current_settings_spec.rb
+++ b/spec/lib/gitlab/current_settings_spec.rb
@@ -115,9 +115,8 @@ describe Gitlab::CurrentSettings do
shared_examples 'a non-persisted ApplicationSetting object' do
let(:current_settings) { described_class.current_application_settings }
- it 'returns a non-persisted ApplicationSetting object' do
- expect(current_settings).to be_a(ApplicationSetting)
- expect(current_settings).not_to be_persisted
+ it 'returns a FakeApplicationSettings object' do
+ expect(current_settings).to be_a(Gitlab::FakeApplicationSettings)
end
it 'uses the default value from ApplicationSetting.defaults' do
@@ -146,6 +145,16 @@ describe Gitlab::CurrentSettings do
it 'uses the value from the DB attribute if present and not overridden by an accessor' do
expect(current_settings.home_page_url).to eq(db_settings.home_page_url)
end
+
+ context 'when a new column is used before being migrated' do
+ before do
+ allow(ApplicationSetting).to receive(:defaults).and_return({ foo: 'bar' })
+ end
+
+ it 'uses the default value if present' do
+ expect(current_settings.foo).to eq('bar')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/diff/suggestion_spec.rb b/spec/lib/gitlab/diff/suggestion_spec.rb
new file mode 100644
index 00000000000..71fd25df698
--- /dev/null
+++ b/spec/lib/gitlab/diff/suggestion_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Diff::Suggestion do
+ shared_examples 'correct suggestion raw content' do
+ it 'returns correct raw data' do
+ expect(suggestion.to_hash).to include(from_content: expected_lines.join,
+ to_content: "#{text}\n",
+ lines_above: above,
+ lines_below: below)
+ end
+ end
+
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:position) do
+ Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 9,
+ diff_refs: merge_request.diff_refs)
+ end
+ let(:diff_file) do
+ position.diff_file(project.repository)
+ end
+ let(:text) { "# parsed suggestion content\n# with comments" }
+
+ def blob_lines_data(from_line, to_line)
+ diff_file.new_blob_lines_between(from_line, to_line)
+ end
+
+ def blob_data
+ blob = diff_file.new_blob
+ blob.load_all_data!
+ blob.data
+ end
+
+ let(:suggestion) do
+ described_class.new(text, line: line, above: above, below: below, diff_file: diff_file)
+ end
+
+ describe '#to_hash' do
+ context 'when changing content surpasses the top limit' do
+ let(:line) { 4 }
+ let(:above) { 5 }
+ let(:below) { 2 }
+ let(:expected_above) { line - 1 }
+ let(:expected_below) { below }
+ let(:expected_lines) { blob_lines_data(line - expected_above, line + expected_below) }
+
+ it_behaves_like 'correct suggestion raw content'
+ end
+
+ context 'when changing content surpasses the amount of lines in the blob (bottom)' do
+ let(:line) { 5 }
+ let(:above) { 1 }
+ let(:below) { blob_data.lines.size + 10 }
+ let(:expected_below) { below }
+ let(:expected_above) { above }
+ let(:expected_lines) { blob_lines_data(line - expected_above, line + expected_below) }
+
+ it_behaves_like 'correct suggestion raw content'
+ end
+
+ context 'when lines are within blob lines boundary' do
+ let(:line) { 5 }
+ let(:above) { 2 }
+ let(:below) { 3 }
+ let(:expected_below) { below }
+ let(:expected_above) { above }
+ let(:expected_lines) { blob_lines_data(line - expected_above, line + expected_below) }
+
+ it_behaves_like 'correct suggestion raw content'
+ end
+
+ context 'when no extra lines (single-line suggestion)' do
+ let(:line) { 5 }
+ let(:above) { 0 }
+ let(:below) { 0 }
+ let(:expected_below) { below }
+ let(:expected_above) { above }
+ let(:expected_lines) { blob_lines_data(line - expected_above, line + expected_below) }
+
+ it_behaves_like 'correct suggestion raw content'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/suggestions_parser_spec.rb b/spec/lib/gitlab/diff/suggestions_parser_spec.rb
new file mode 100644
index 00000000000..1119ea04995
--- /dev/null
+++ b/spec/lib/gitlab/diff/suggestions_parser_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Diff::SuggestionsParser do
+ describe '.parse' do
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+ let(:position) do
+ Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 9,
+ diff_refs: merge_request.diff_refs)
+ end
+
+ let(:diff_file) do
+ position.diff_file(project.repository)
+ end
+
+ subject do
+ described_class.parse(markdown, project: merge_request.project,
+ position: position)
+ end
+
+ def blob_lines_data(from_line, to_line)
+ diff_file.new_blob_lines_between(from_line, to_line).join
+ end
+
+ context 'single-line suggestions' do
+ let(:markdown) do
+ <<-MARKDOWN.strip_heredoc
+ ```suggestion
+ foo
+ bar
+ ```
+
+ ```
+ nothing
+ ```
+
+ ```suggestion
+ xpto
+ baz
+ ```
+
+ ```thing
+ this is not a suggestion, it's a thing
+ ```
+ MARKDOWN
+ end
+
+ it 'returns a list of Gitlab::Diff::Suggestion' do
+ expect(subject).to all(be_a(Gitlab::Diff::Suggestion))
+ expect(subject.size).to eq(2)
+ end
+
+ it 'parsed suggestion has correct data' do
+ from_line, to_line = position.new_line, position.new_line
+
+ expect(subject.first.to_hash).to include(from_content: blob_lines_data(from_line, to_line),
+ to_content: " foo\n bar\n",
+ lines_above: 0,
+ lines_below: 0)
+
+ expect(subject.second.to_hash).to include(from_content: blob_lines_data(from_line, to_line),
+ to_content: " xpto\n baz\n",
+ lines_above: 0,
+ lines_below: 0)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/pre_receive_error_spec.rb b/spec/lib/gitlab/git/pre_receive_error_spec.rb
index 1b8be62dec6..cb030e38032 100644
--- a/spec/lib/gitlab/git/pre_receive_error_spec.rb
+++ b/spec/lib/gitlab/git/pre_receive_error_spec.rb
@@ -1,9 +1,19 @@
require 'spec_helper'
describe Gitlab::Git::PreReceiveError do
- it 'makes its message HTML-friendly' do
- ex = described_class.new("hello\nworld\n")
+ Gitlab::Git::PreReceiveError::SAFE_MESSAGE_PREFIXES.each do |prefix|
+ context "error messages prefixed with #{prefix}" do
+ it 'accepts only errors lines with the prefix' do
+ ex = described_class.new("#{prefix} Hello,\nworld!")
- expect(ex.message).to eq('hello<br>world<br>')
+ expect(ex.message).to eq('Hello,')
+ end
+
+ it 'makes its message HTML-friendly' do
+ ex = described_class.new("#{prefix} Hello,\n#{prefix} world!\n")
+
+ expect(ex.message).to eq('Hello,<br>world!')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index d7bd757149d..6d6107ca3e7 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -221,6 +221,21 @@ describe Gitlab::GitalyClient::CommitService do
expect(commit).to eq(commit_dbl)
end
end
+
+ context 'when caching of the ref name is enabled' do
+ it 'returns a cached commit' do
+ expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:find_commit).once.and_return(double(commit: commit_dbl))
+
+ commit = nil
+ 2.times do
+ ::Gitlab::GitalyClient.allow_ref_name_caching do
+ commit = described_class.new(repository).find_commit('master')
+ end
+ end
+
+ expect(commit).to eq(commit_dbl)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index b37fe2686b6..7579a6577b9 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -39,7 +39,7 @@ describe Gitlab::GitalyClient::OperationService do
context "when pre_receive_error is present" do
let(:response) do
- Gitaly::UserCreateBranchResponse.new(pre_receive_error: "something failed")
+ Gitaly::UserCreateBranchResponse.new(pre_receive_error: "GitLab: something failed")
end
it "throws a PreReceive exception" do
@@ -80,7 +80,7 @@ describe Gitlab::GitalyClient::OperationService do
context "when pre_receive_error is present" do
let(:response) do
- Gitaly::UserUpdateBranchResponse.new(pre_receive_error: "something failed")
+ Gitaly::UserUpdateBranchResponse.new(pre_receive_error: "GitLab: something failed")
end
it "throws a PreReceive exception" do
@@ -117,7 +117,7 @@ describe Gitlab::GitalyClient::OperationService do
context "when pre_receive_error is present" do
let(:response) do
- Gitaly::UserDeleteBranchResponse.new(pre_receive_error: "something failed")
+ Gitaly::UserDeleteBranchResponse.new(pre_receive_error: "GitLab: something failed")
end
it "throws a PreReceive exception" do
@@ -175,7 +175,7 @@ describe Gitlab::GitalyClient::OperationService do
shared_examples 'cherry pick and revert errors' do
context 'when a pre_receive_error is present' do
- let(:response) { response_class.new(pre_receive_error: "something failed") }
+ let(:response) { response_class.new(pre_receive_error: "GitLab: something failed") }
it 'raises a PreReceiveError' do
expect { subject }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
@@ -313,7 +313,7 @@ describe Gitlab::GitalyClient::OperationService do
end
context 'when a pre_receive_error is present' do
- let(:response) { Gitaly::UserCommitFilesResponse.new(pre_receive_error: "something failed") }
+ let(:response) { Gitaly::UserCommitFilesResponse.new(pre_receive_error: "GitLab: something failed") }
it 'raises a PreReceiveError' do
expect { subject }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 400d426c949..0dab39575b9 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -89,6 +89,16 @@ describe Gitlab::GitalyClient::RefService do
end
end
+ describe '#list_new_blobs' do
+ it 'raises DeadlineExceeded when timeout is too small' do
+ newrev = '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51'
+
+ expect do
+ client.list_new_blobs(newrev, dynamic_timeout: 0.001)
+ end.to raise_error(GRPC::DeadlineExceeded)
+ end
+ end
+
describe '#local_branches' do
it 'sends a find_local_branches message' do
expect_any_instance_of(Gitaly::RefService::Stub)
diff --git a/spec/lib/gitlab/gl_repository/repo_type_spec.rb b/spec/lib/gitlab/gl_repository/repo_type_spec.rb
new file mode 100644
index 00000000000..f06a2448ff7
--- /dev/null
+++ b/spec/lib/gitlab/gl_repository/repo_type_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::GlRepository::RepoType do
+ set(:project) { create(:project) }
+
+ shared_examples 'a repo type' do
+ describe "#identifier_for_subject" do
+ subject { described_class.identifier_for_subject(project) }
+
+ it { is_expected.to eq(expected_identifier) }
+ end
+
+ describe "#fetch_id" do
+ it "finds an id match in the identifier" do
+ expect(described_class.fetch_id(expected_identifier)).to eq(expected_id)
+ end
+
+ it 'does not break on other identifiers' do
+ expect(described_class.fetch_id("wiki-noid")).to eq(nil)
+ end
+ end
+
+ describe "#path_suffix" do
+ subject { described_class.path_suffix }
+
+ it { is_expected.to eq(expected_suffix) }
+ end
+
+ describe "#repository_for" do
+ it "finds the repository for the repo type" do
+ expect(described_class.repository_for(project)).to eq(expected_repository)
+ end
+ end
+ end
+
+ describe Gitlab::GlRepository::PROJECT do
+ it_behaves_like 'a repo type' do
+ let(:expected_identifier) { "project-#{project.id}" }
+ let(:expected_id) { project.id.to_s }
+ let(:expected_suffix) { "" }
+ let(:expected_repository) { project.repository }
+ end
+
+ it "knows its type" do
+ expect(described_class).not_to be_wiki
+ expect(described_class).to be_project
+ end
+ end
+
+ describe Gitlab::GlRepository::WIKI do
+ it_behaves_like 'a repo type' do
+ let(:expected_identifier) { "wiki-#{project.id}" }
+ let(:expected_id) { project.id.to_s }
+ let(:expected_suffix) { ".wiki" }
+ let(:expected_repository) { project.wiki.repository }
+ end
+
+ it "knows its type" do
+ expect(described_class).to be_wiki
+ expect(described_class).not_to be_project
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gl_repository_spec.rb b/spec/lib/gitlab/gl_repository_spec.rb
index 4e09020471b..d4b6c629659 100644
--- a/spec/lib/gitlab/gl_repository_spec.rb
+++ b/spec/lib/gitlab/gl_repository_spec.rb
@@ -5,11 +5,11 @@ describe ::Gitlab::GlRepository do
set(:project) { create(:project, :repository) }
it 'parses a project gl_repository' do
- expect(described_class.parse("project-#{project.id}")).to eq([project, false])
+ expect(described_class.parse("project-#{project.id}")).to eq([project, Gitlab::GlRepository::PROJECT])
end
it 'parses a wiki gl_repository' do
- expect(described_class.parse("wiki-#{project.id}")).to eq([project, true])
+ expect(described_class.parse("wiki-#{project.id}")).to eq([project, Gitlab::GlRepository::WIKI])
end
it 'throws an argument error on an invalid gl_repository' do
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 01da3ea7081..e418516569a 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -100,6 +100,8 @@ merge_requests:
- head_pipeline
- latest_merge_request_diff
- merge_request_pipelines
+- merge_request_assignees
+- suggestions
merge_request_diff:
- merge_request
- merge_request_diff_commits
@@ -351,3 +353,5 @@ resource_label_events:
- label
error_tracking_setting:
- project
+suggestions:
+- note
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ee96e5c4d42..496567b0036 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -608,3 +608,14 @@ ErrorTracking::ProjectErrorTrackingSetting:
- project_id
- project_name
- organization_name
+Suggestion:
+- id
+- note_id
+- relative_order
+- applied
+- commit_id
+- from_content
+- to_content
+- outdated
+- lines_above
+- lines_below
diff --git a/spec/lib/gitlab/quick_actions/command_definition_spec.rb b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
index 136cfb5bcc5..b6e0adbc1c2 100644
--- a/spec/lib/gitlab/quick_actions/command_definition_spec.rb
+++ b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
@@ -69,6 +69,36 @@ describe Gitlab::QuickActions::CommandDefinition do
expect(subject.available?(opts)).to be true
end
end
+
+ context "when the command has types" do
+ before do
+ subject.types = [Issue, Commit]
+ end
+
+ context "when the command target type is allowed" do
+ it "returns true" do
+ opts[:quick_action_target] = Issue.new
+ expect(subject.available?(opts)).to be true
+ end
+ end
+
+ context "when the command target type is not allowed" do
+ it "returns true" do
+ opts[:quick_action_target] = MergeRequest.new
+ expect(subject.available?(opts)).to be false
+ end
+ end
+ end
+
+ context "when the command has no types" do
+ it "any target type is allowed" do
+ opts[:quick_action_target] = Issue.new
+ expect(subject.available?(opts)).to be true
+
+ opts[:quick_action_target] = MergeRequest.new
+ expect(subject.available?(opts)).to be true
+ end
+ end
end
describe "#execute" do
diff --git a/spec/lib/gitlab/quick_actions/dsl_spec.rb b/spec/lib/gitlab/quick_actions/dsl_spec.rb
index fd4df8694ba..185adab1ff6 100644
--- a/spec/lib/gitlab/quick_actions/dsl_spec.rb
+++ b/spec/lib/gitlab/quick_actions/dsl_spec.rb
@@ -48,13 +48,19 @@ describe Gitlab::QuickActions::Dsl do
substitution :something do |text|
"#{text} Some complicated thing you want in here"
end
+
+ desc 'A command with types'
+ types Issue, Commit
+ command :has_types do
+ "Has Issue and Commit types"
+ end
end
end
describe '.command_definitions' do
it 'returns an array with commands definitions' do
no_args_def, explanation_with_aliases_def, dynamic_description_def,
- cc_def, cond_action_def, with_params_parsing_def, substitution_def =
+ cc_def, cond_action_def, with_params_parsing_def, substitution_def, has_types =
DummyClass.command_definitions
expect(no_args_def.name).to eq(:no_args)
@@ -63,6 +69,7 @@ describe Gitlab::QuickActions::Dsl do
expect(no_args_def.explanation).to eq('')
expect(no_args_def.params).to eq([])
expect(no_args_def.condition_block).to be_nil
+ expect(no_args_def.types).to eq([])
expect(no_args_def.action_block).to be_a_kind_of(Proc)
expect(no_args_def.parse_params_block).to be_nil
expect(no_args_def.warning).to eq('')
@@ -73,6 +80,7 @@ describe Gitlab::QuickActions::Dsl do
expect(explanation_with_aliases_def.explanation).to eq('Static explanation')
expect(explanation_with_aliases_def.params).to eq(['The first argument'])
expect(explanation_with_aliases_def.condition_block).to be_nil
+ expect(explanation_with_aliases_def.types).to eq([])
expect(explanation_with_aliases_def.action_block).to be_a_kind_of(Proc)
expect(explanation_with_aliases_def.parse_params_block).to be_nil
expect(explanation_with_aliases_def.warning).to eq('Possible problem!')
@@ -83,6 +91,7 @@ describe Gitlab::QuickActions::Dsl do
expect(dynamic_description_def.explanation).to eq('')
expect(dynamic_description_def.params).to eq(['The first argument', 'The second argument'])
expect(dynamic_description_def.condition_block).to be_nil
+ expect(dynamic_description_def.types).to eq([])
expect(dynamic_description_def.action_block).to be_a_kind_of(Proc)
expect(dynamic_description_def.parse_params_block).to be_nil
expect(dynamic_description_def.warning).to eq('')
@@ -93,6 +102,7 @@ describe Gitlab::QuickActions::Dsl do
expect(cc_def.explanation).to eq('')
expect(cc_def.params).to eq([])
expect(cc_def.condition_block).to be_nil
+ expect(cc_def.types).to eq([])
expect(cc_def.action_block).to be_nil
expect(cc_def.parse_params_block).to be_nil
expect(cc_def.warning).to eq('')
@@ -103,6 +113,7 @@ describe Gitlab::QuickActions::Dsl do
expect(cond_action_def.explanation).to be_a_kind_of(Proc)
expect(cond_action_def.params).to eq([])
expect(cond_action_def.condition_block).to be_a_kind_of(Proc)
+ expect(cond_action_def.types).to eq([])
expect(cond_action_def.action_block).to be_a_kind_of(Proc)
expect(cond_action_def.parse_params_block).to be_nil
expect(cond_action_def.warning).to eq('')
@@ -113,6 +124,7 @@ describe Gitlab::QuickActions::Dsl do
expect(with_params_parsing_def.explanation).to eq('')
expect(with_params_parsing_def.params).to eq([])
expect(with_params_parsing_def.condition_block).to be_nil
+ expect(with_params_parsing_def.types).to eq([])
expect(with_params_parsing_def.action_block).to be_a_kind_of(Proc)
expect(with_params_parsing_def.parse_params_block).to be_a_kind_of(Proc)
expect(with_params_parsing_def.warning).to eq('')
@@ -123,9 +135,21 @@ describe Gitlab::QuickActions::Dsl do
expect(substitution_def.explanation).to eq('')
expect(substitution_def.params).to eq(['<Comment>'])
expect(substitution_def.condition_block).to be_nil
+ expect(substitution_def.types).to eq([])
expect(substitution_def.action_block.call('text')).to eq('text Some complicated thing you want in here')
expect(substitution_def.parse_params_block).to be_nil
expect(substitution_def.warning).to eq('')
+
+ expect(has_types.name).to eq(:has_types)
+ expect(has_types.aliases).to eq([])
+ expect(has_types.description).to eq('A command with types')
+ expect(has_types.explanation).to eq('')
+ expect(has_types.params).to eq([])
+ expect(has_types.condition_block).to be_nil
+ expect(has_types.types).to eq([Issue, Commit])
+ expect(has_types.action_block).to be_a_kind_of(Proc)
+ expect(has_types.parse_params_block).to be_nil
+ expect(has_types.warning).to eq('')
end
end
end
diff --git a/spec/lib/gitlab/repo_path_spec.rb b/spec/lib/gitlab/repo_path_spec.rb
index 13940713dfc..4c7ca4e2b57 100644
--- a/spec/lib/gitlab/repo_path_spec.rb
+++ b/spec/lib/gitlab/repo_path_spec.rb
@@ -6,43 +6,47 @@ describe ::Gitlab::RepoPath do
context 'a repository storage path' do
it 'parses a full repository path' do
- expect(described_class.parse(project.repository.full_path)).to eq([project, false, nil])
+ expect(described_class.parse(project.repository.full_path)).to eq([project, Gitlab::GlRepository::PROJECT, nil])
end
it 'parses a full wiki path' do
- expect(described_class.parse(project.wiki.repository.full_path)).to eq([project, true, nil])
+ expect(described_class.parse(project.wiki.repository.full_path)).to eq([project, Gitlab::GlRepository::WIKI, nil])
end
end
context 'a relative path' do
it 'parses a relative repository path' do
- expect(described_class.parse(project.full_path + '.git')).to eq([project, false, nil])
+ expect(described_class.parse(project.full_path + '.git')).to eq([project, Gitlab::GlRepository::PROJECT, nil])
end
it 'parses a relative wiki path' do
- expect(described_class.parse(project.full_path + '.wiki.git')).to eq([project, true, nil])
+ expect(described_class.parse(project.full_path + '.wiki.git')).to eq([project, Gitlab::GlRepository::WIKI, nil])
end
it 'parses a relative path starting with /' do
- expect(described_class.parse('/' + project.full_path + '.git')).to eq([project, false, nil])
+ expect(described_class.parse('/' + project.full_path + '.git')).to eq([project, Gitlab::GlRepository::PROJECT, nil])
end
context 'of a redirected project' do
let(:redirect) { project.route.create_redirect('foo/bar') }
it 'parses a relative repository path' do
- expect(described_class.parse(redirect.path + '.git')).to eq([project, false, 'foo/bar'])
+ expect(described_class.parse(redirect.path + '.git')).to eq([project, Gitlab::GlRepository::PROJECT, 'foo/bar'])
end
it 'parses a relative wiki path' do
- expect(described_class.parse(redirect.path + '.wiki.git')).to eq([project, true, 'foo/bar.wiki'])
+ expect(described_class.parse(redirect.path + '.wiki.git')).to eq([project, Gitlab::GlRepository::WIKI, 'foo/bar.wiki'])
end
it 'parses a relative path starting with /' do
- expect(described_class.parse('/' + redirect.path + '.git')).to eq([project, false, 'foo/bar'])
+ expect(described_class.parse('/' + redirect.path + '.git')).to eq([project, Gitlab::GlRepository::PROJECT, 'foo/bar'])
end
end
end
+
+ it "returns nil for non existent paths" do
+ expect(described_class.parse("path/non-existent.git")).to eq(nil)
+ end
end
describe '.find_project' do
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 7213eee5675..d88086b01b1 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -250,11 +250,11 @@ describe Gitlab::Workhorse do
}
end
- subject { described_class.git_http_ok(repository, false, user, action) }
+ subject { described_class.git_http_ok(repository, Gitlab::GlRepository::PROJECT, user, action) }
it { expect(subject).to include(params) }
- context 'when is_wiki' do
+ context 'when the repo_type is a wiki' do
let(:params) do
{
GL_ID: "user-#{user.id}",
@@ -264,7 +264,7 @@ describe Gitlab::Workhorse do
}
end
- subject { described_class.git_http_ok(repository, true, user, action) }
+ subject { described_class.git_http_ok(repository, Gitlab::GlRepository::WIKI, user, action) }
it { expect(subject).to include(params) }
end
@@ -304,7 +304,7 @@ describe Gitlab::Workhorse do
end
context 'show_all_refs enabled' do
- subject { described_class.git_http_ok(repository, false, user, action, show_all_refs: true) }
+ subject { described_class.git_http_ok(repository, Gitlab::GlRepository::PROJECT, user, action, show_all_refs: true) }
it { is_expected.to include(ShowAllRefs: true) }
end
@@ -322,7 +322,7 @@ describe Gitlab::Workhorse do
it { expect(subject).to include(gitaly_params) }
context 'show_all_refs enabled' do
- subject { described_class.git_http_ok(repository, false, user, action, show_all_refs: true) }
+ subject { described_class.git_http_ok(repository, Gitlab::GlRepository::PROJECT, user, action, show_all_refs: true) }
it { is_expected.to include(ShowAllRefs: true) }
end
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index 8232715d00e..767b5779a79 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -10,7 +10,7 @@ describe Gitlab do
end
describe '.revision' do
- let(:cmd) { %W[#{described_class.config.git.bin_path} log --pretty=format:%h -n 1] }
+ let(:cmd) { %W[#{described_class.config.git.bin_path} log --pretty=format:%h --abbrev=11 -n 1] }
around do |example|
described_class.instance_variable_set(:@_revision, nil)
diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/sentry/client_spec.rb
index 88e7e2e5ebb..3333f8307ae 100644
--- a/spec/lib/sentry/client_spec.rb
+++ b/spec/lib/sentry/client_spec.rb
@@ -65,7 +65,9 @@ describe Sentry::Client do
let(:issue_status) { 'unresolved' }
let(:limit) { 20 }
- let!(:sentry_api_request) { stub_sentry_request(sentry_url + '/issues/?limit=20&query=is:unresolved', body: issues_sample_response) }
+ let(:sentry_api_response) { issues_sample_response }
+
+ let!(:sentry_api_request) { stub_sentry_request(sentry_url + '/issues/?limit=20&query=is:unresolved', body: sentry_api_response) }
subject { client.list_issues(issue_status: issue_status, limit: limit) }
@@ -74,6 +76,14 @@ describe Sentry::Client do
it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Error
it_behaves_like 'has correct length', 1
+ shared_examples 'has correct external_url' do
+ context 'external_url' do
+ it 'is constructed correctly' do
+ expect(subject[0].external_url).to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project/issues/11')
+ end
+ end
+ end
+
context 'error object created from sentry response' do
using RSpec::Parameterized::TableSyntax
@@ -96,14 +106,10 @@ describe Sentry::Client do
end
with_them do
- it { expect(subject[0].public_send(error_object)).to eq(issues_sample_response[0].dig(*sentry_response)) }
+ it { expect(subject[0].public_send(error_object)).to eq(sentry_api_response[0].dig(*sentry_response)) }
end
- context 'external_url' do
- it 'is constructed correctly' do
- expect(subject[0].external_url).to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project/issues/11')
- end
- end
+ it_behaves_like 'has correct external_url'
end
context 'redirects' do
@@ -135,12 +141,42 @@ describe Sentry::Client do
expect(valid_req_stub).to have_been_requested
end
end
+
+ context 'Older sentry versions where keys are not present' do
+ let(:sentry_api_response) do
+ issues_sample_response[0...1].map do |issue|
+ issue[:project].delete(:id)
+ issue
+ end
+ end
+
+ it_behaves_like 'calls sentry api'
+
+ it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Error
+ it_behaves_like 'has correct length', 1
+
+ it_behaves_like 'has correct external_url'
+ end
+
+ context 'essential keys missing in API response' do
+ let(:sentry_api_response) do
+ issues_sample_response[0...1].map do |issue|
+ issue.except(:id)
+ end
+ end
+
+ it 'raises exception' do
+ expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
+ end
+ end
end
describe '#list_projects' do
let(:sentry_list_projects_url) { 'https://sentrytest.gitlab.com/api/0/projects/' }
- let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: projects_sample_response) }
+ let(:sentry_api_response) { projects_sample_response }
+
+ let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: sentry_api_response) }
subject { client.list_projects }
@@ -149,14 +185,31 @@ describe Sentry::Client do
it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
it_behaves_like 'has correct length', 2
- context 'keys missing in API response' do
- it 'raises exception' do
- projects_sample_response[0].delete(:slug)
+ context 'essential keys missing in API response' do
+ let(:sentry_api_response) do
+ projects_sample_response[0...1].map do |project|
+ project.except(:slug)
+ end
+ end
- stub_sentry_request(sentry_list_projects_url, body: projects_sample_response)
+ it 'raises exception' do
+ expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "slug"')
+ end
+ end
- expect { subject }.to raise_error(Sentry::Client::SentryError, 'Sentry API response is missing keys. key not found: "slug"')
+ context 'optional keys missing in sentry response' do
+ let(:sentry_api_response) do
+ projects_sample_response[0...1].map do |project|
+ project[:organization].delete(:id)
+ project.delete(:id)
+ project.except(:status)
+ end
end
+
+ it_behaves_like 'calls sentry api'
+
+ it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
+ it_behaves_like 'has correct length', 1
end
context 'error object created from sentry response' do
@@ -173,7 +226,11 @@ describe Sentry::Client do
end
with_them do
- it { expect(subject[0].public_send(sentry_project_object)).to eq(projects_sample_response[0].dig(*sentry_response)) }
+ it do
+ expect(subject[0].public_send(sentry_project_object)).to(
+ eq(sentry_api_response[0].dig(*sentry_response))
+ )
+ end
end
end
diff --git a/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb b/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb
index b2d8f476bb2..a1f243651b5 100644
--- a/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb
@@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20181219145520_migrate_cluster_co
describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
+ include StubWorker
context 'when there are jobs in the queue' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'gcp_cluster:cluster_platform_configure').perform_async('Something', [1])
- stubbed_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_platform_configure').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1])
described_class.new.up
@@ -19,12 +20,12 @@ describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do
it 'does not affect other queues under the same namespace' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'gcp_cluster:cluster_install_app').perform_async('Something', [1])
- stubbed_worker(queue: 'gcp_cluster:cluster_provision').perform_async('Something', [1])
- stubbed_worker(queue: 'gcp_cluster:cluster_wait_for_app_installation').perform_async('Something', [1])
- stubbed_worker(queue: 'gcp_cluster:wait_for_cluster_creation').perform_async('Something', [1])
- stubbed_worker(queue: 'gcp_cluster:cluster_wait_for_ingress_ip_address').perform_async('Something', [1])
- stubbed_worker(queue: 'gcp_cluster:cluster_project_configure').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_install_app').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_provision').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_wait_for_app_installation').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:wait_for_cluster_creation').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_wait_for_ingress_ip_address').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_project_configure').perform_async('Something', [1])
described_class.new.up
@@ -39,7 +40,7 @@ describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do
it 'correctly migrates queue when migrating down' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1])
+ stub_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1])
described_class.new.down
@@ -58,11 +59,4 @@ describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do
expect { described_class.new.down }.not_to raise_error
end
end
-
- def stubbed_worker(queue:)
- Class.new do
- include Sidekiq::Worker
- sidekiq_options queue: queue
- end
- end
end
diff --git a/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb b/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb
index c18ae3b76d3..66555118a43 100644
--- a/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_create_trace_artifact_sidekiq_queue_spec.rb
@@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20180306074045_migrate_create_tra
describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
+ include StubWorker
context 'when there are jobs in the queues' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'pipeline_default:create_trace_artifact').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:create_trace_artifact').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1])
described_class.new.up
@@ -19,11 +20,11 @@ describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do
it 'does not affect other queues under the same namespace' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1])
described_class.new.up
@@ -37,7 +38,7 @@ describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do
it 'correctly migrates queue when migrating down' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_background:archive_trace').perform_async('Something', [1])
described_class.new.down
@@ -56,11 +57,4 @@ describe MigrateCreateTraceArtifactSidekiqQueue, :sidekiq, :redis do
expect { described_class.new.down }.not_to raise_error
end
end
-
- def stubbed_worker(queue:)
- Class.new do
- include Sidekiq::Worker
- sidekiq_options queue: queue
- end
- end
end
diff --git a/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb b/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb
index 1ee6c440cf4..6ce04805e5d 100644
--- a/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_object_storage_upload_sidekiq_queue_spec.rb
@@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20180603190921_migrate_object_sto
describe MigrateObjectStorageUploadSidekiqQueue, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
+ include StubWorker
context 'when there are jobs in the queue' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'object_storage_upload').perform_async('Something', [1])
- stubbed_worker(queue: 'object_storage:object_storage_background_move').perform_async('Something', [1])
+ stub_worker(queue: 'object_storage_upload').perform_async('Something', [1])
+ stub_worker(queue: 'object_storage:object_storage_background_move').perform_async('Something', [1])
described_class.new.up
@@ -23,11 +24,4 @@ describe MigrateObjectStorageUploadSidekiqQueue, :sidekiq, :redis do
expect { described_class.new.up }.not_to raise_error
end
end
-
- def stubbed_worker(queue:)
- Class.new do
- include Sidekiq::Worker
- sidekiq_options queue: queue
- end
- end
end
diff --git a/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb b/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb
index e02bcd2f4da..e38044ccceb 100644
--- a/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb
+++ b/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb
@@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20170822101017_migrate_pipeline_s
describe MigratePipelineSidekiqQueues, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
+ include StubWorker
context 'when there are jobs in the queues' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: :pipeline).perform_async('Something', [1])
- stubbed_worker(queue: :build).perform_async('Something', [1])
+ stub_worker(queue: :pipeline).perform_async('Something', [1])
+ stub_worker(queue: :build).perform_async('Something', [1])
described_class.new.up
@@ -20,10 +21,10 @@ describe MigratePipelineSidekiqQueues, :sidekiq, :redis do
it 'correctly migrates queue when migrating down' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: :pipeline_default).perform_async('Class', [1])
- stubbed_worker(queue: :pipeline_processing).perform_async('Class', [2])
- stubbed_worker(queue: :pipeline_hooks).perform_async('Class', [3])
- stubbed_worker(queue: :pipeline_cache).perform_async('Class', [4])
+ stub_worker(queue: :pipeline_default).perform_async('Class', [1])
+ stub_worker(queue: :pipeline_processing).perform_async('Class', [2])
+ stub_worker(queue: :pipeline_hooks).perform_async('Class', [3])
+ stub_worker(queue: :pipeline_cache).perform_async('Class', [4])
described_class.new.down
@@ -45,11 +46,4 @@ describe MigratePipelineSidekiqQueues, :sidekiq, :redis do
expect { described_class.new.down }.not_to raise_error
end
end
-
- def stubbed_worker(queue:)
- Class.new do
- include Sidekiq::Worker
- sidekiq_options queue: queue
- end
- end
end
diff --git a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
index f8cf76cb339..94de208e53e 100644
--- a/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb
@@ -3,11 +3,12 @@ require Rails.root.join('db', 'post_migrate', '20190124200344_migrate_storage_mi
describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
+ include StubWorker
context 'when there are jobs in the queues' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: :storage_migrator).perform_async(1, 5)
+ stub_worker(queue: :storage_migrator).perform_async(1, 5)
described_class.new.up
@@ -18,7 +19,7 @@ describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do
it 'correctly migrates queue when migrating down' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: :'hashed_storage:hashed_storage_migrator').perform_async(1, 5)
+ stub_worker(queue: :'hashed_storage:hashed_storage_migrator').perform_async(1, 5)
described_class.new.down
@@ -37,11 +38,4 @@ describe MigrateStorageMigratorSidekiqQueue, :sidekiq, :redis do
expect { described_class.new.down }.not_to raise_error
end
end
-
- def stubbed_worker(queue:)
- Class.new do
- include Sidekiq::Worker
- sidekiq_options queue: queue
- end
- end
end
diff --git a/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb b/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb
index 5e3b20ab4a8..976f3ce07d7 100644
--- a/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb
+++ b/spec/migrations/migrate_update_head_pipeline_for_merge_request_sidekiq_queue_spec.rb
@@ -3,12 +3,13 @@ require Rails.root.join('db', 'post_migrate', '20180307012445_migrate_update_hea
describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis do
include Gitlab::Database::MigrationHelpers
+ include StubWorker
context 'when there are jobs in the queues' do
it 'correctly migrates queue when migrating up' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:update_head_pipeline_for_merge_request').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1])
described_class.new.up
@@ -19,10 +20,10 @@ describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis
it 'does not affect other queues under the same namespace' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1])
- stubbed_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:build_coverage').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:build_trace_sections').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:pipeline_metrics').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_default:pipeline_notification').perform_async('Something', [1])
described_class.new.up
@@ -35,7 +36,7 @@ describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis
it 'correctly migrates queue when migrating down' do
Sidekiq::Testing.disable! do
- stubbed_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1])
+ stub_worker(queue: 'pipeline_processing:update_head_pipeline_for_merge_request').perform_async('Something', [1])
described_class.new.down
@@ -54,11 +55,4 @@ describe MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue, :sidekiq, :redis
expect { described_class.new.down }.not_to raise_error
end
end
-
- def stubbed_worker(queue:)
- Class.new do
- include Sidekiq::Worker
- sidekiq_options queue: queue
- end
- end
end
diff --git a/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb b/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
new file mode 100644
index 00000000000..e397fbb7138
--- /dev/null
+++ b/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190322132835_schedule_populate_merge_request_assignees_table.rb')
+
+describe SchedulePopulateMergeRequestAssigneesTable, :migration, :sidekiq do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create(namespace_id: namespace.id, name: 'foo') }
+ let(:merge_requests) { table(:merge_requests) }
+
+ def create_merge_request(id)
+ params = {
+ id: id,
+ target_project_id: project.id,
+ target_branch: 'master',
+ source_project_id: project.id,
+ source_branch: 'mr name',
+ title: "mr name#{id}"
+ }
+
+ merge_requests.create!(params)
+ end
+
+ it 'correctly schedules background migrations' do
+ create_merge_request(1)
+ create_merge_request(2)
+ create_merge_request(3)
+
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(8.minutes, 1, 2)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(16.minutes, 3, 3)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index eee80e9bad7..d9d60e02a97 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ability do
diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb
index f49a61062c1..a5f8e999d5d 100644
--- a/spec/models/abuse_report_spec.rb
+++ b/spec/models/abuse_report_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe AbuseReport do
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb
index e128fe8a4b7..b523f393ece 100644
--- a/spec/models/active_session_spec.rb
+++ b/spec/models/active_session_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb
index 3e95aa2b5dd..209d138f956 100644
--- a/spec/models/appearance_spec.rb
+++ b/spec/models/appearance_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Appearance do
diff --git a/spec/models/application_setting/term_spec.rb b/spec/models/application_setting/term_spec.rb
index aa49594f4d1..dd263335b81 100644
--- a/spec/models/application_setting/term_spec.rb
+++ b/spec/models/application_setting/term_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ApplicationSetting::Term do
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 314f0728b8e..c5579dafb4a 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ApplicationSetting do
diff --git a/spec/models/award_emoji_spec.rb b/spec/models/award_emoji_spec.rb
index 3f52091698c..8452ac69734 100644
--- a/spec/models/award_emoji_spec.rb
+++ b/spec/models/award_emoji_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe AwardEmoji do
diff --git a/spec/models/badge_spec.rb b/spec/models/badge_spec.rb
index 33dc19e3432..314d7d1e9f4 100644
--- a/spec/models/badge_spec.rb
+++ b/spec/models/badge_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Badge do
diff --git a/spec/models/badges/group_badge_spec.rb b/spec/models/badges/group_badge_spec.rb
index ed7f83d0489..c297bc957ea 100644
--- a/spec/models/badges/group_badge_spec.rb
+++ b/spec/models/badges/group_badge_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupBadge do
diff --git a/spec/models/badges/project_badge_spec.rb b/spec/models/badges/project_badge_spec.rb
index 0e1a8159cb6..e683d110252 100644
--- a/spec/models/badges/project_badge_spec.rb
+++ b/spec/models/badges/project_badge_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectBadge do
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index 05cf242e84d..d0e1688cce3 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -1,4 +1,6 @@
# encoding: utf-8
+# frozen_string_literal: true
+
require 'rails_helper'
describe Blob do
diff --git a/spec/models/blob_viewer/base_spec.rb b/spec/models/blob_viewer/base_spec.rb
index 7ba28f72215..39c7a34f052 100644
--- a/spec/models/blob_viewer/base_spec.rb
+++ b/spec/models/blob_viewer/base_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::Base do
diff --git a/spec/models/blob_viewer/changelog_spec.rb b/spec/models/blob_viewer/changelog_spec.rb
index db41eca0fc8..0fcc94182af 100644
--- a/spec/models/blob_viewer/changelog_spec.rb
+++ b/spec/models/blob_viewer/changelog_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::Changelog do
diff --git a/spec/models/blob_viewer/composer_json_spec.rb b/spec/models/blob_viewer/composer_json_spec.rb
index 85b0d9668a0..eda34779679 100644
--- a/spec/models/blob_viewer/composer_json_spec.rb
+++ b/spec/models/blob_viewer/composer_json_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::ComposerJson do
diff --git a/spec/models/blob_viewer/gemspec_spec.rb b/spec/models/blob_viewer/gemspec_spec.rb
index d8c4490637f..b6cc82c03ba 100644
--- a/spec/models/blob_viewer/gemspec_spec.rb
+++ b/spec/models/blob_viewer/gemspec_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::Gemspec do
diff --git a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
index 16bf947b493..db405ceb4f1 100644
--- a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
+++ b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::GitlabCiYml do
diff --git a/spec/models/blob_viewer/license_spec.rb b/spec/models/blob_viewer/license_spec.rb
index 222ed166ee0..e02bfae3829 100644
--- a/spec/models/blob_viewer/license_spec.rb
+++ b/spec/models/blob_viewer/license_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::License do
diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb
index fbaa8d47a71..b317278f3c8 100644
--- a/spec/models/blob_viewer/package_json_spec.rb
+++ b/spec/models/blob_viewer/package_json_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::PackageJson do
diff --git a/spec/models/blob_viewer/podspec_json_spec.rb b/spec/models/blob_viewer/podspec_json_spec.rb
index 9a23877b23f..7f1fb8666fd 100644
--- a/spec/models/blob_viewer/podspec_json_spec.rb
+++ b/spec/models/blob_viewer/podspec_json_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::PodspecJson do
diff --git a/spec/models/blob_viewer/podspec_spec.rb b/spec/models/blob_viewer/podspec_spec.rb
index 02d06ea24d6..527ae79d766 100644
--- a/spec/models/blob_viewer/podspec_spec.rb
+++ b/spec/models/blob_viewer/podspec_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::Podspec do
diff --git a/spec/models/blob_viewer/readme_spec.rb b/spec/models/blob_viewer/readme_spec.rb
index 8d11d58cfca..958927bddb4 100644
--- a/spec/models/blob_viewer/readme_spec.rb
+++ b/spec/models/blob_viewer/readme_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::Readme do
diff --git a/spec/models/blob_viewer/route_map_spec.rb b/spec/models/blob_viewer/route_map_spec.rb
index c13662427b0..f7ce873c9d1 100644
--- a/spec/models/blob_viewer/route_map_spec.rb
+++ b/spec/models/blob_viewer/route_map_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::RouteMap do
diff --git a/spec/models/blob_viewer/server_side_spec.rb b/spec/models/blob_viewer/server_side_spec.rb
index 63790486200..f95305abe78 100644
--- a/spec/models/blob_viewer/server_side_spec.rb
+++ b/spec/models/blob_viewer/server_side_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BlobViewer::ServerSide do
diff --git a/spec/models/board_spec.rb b/spec/models/board_spec.rb
index 12d29540137..54452faa0e1 100644
--- a/spec/models/board_spec.rb
+++ b/spec/models/board_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Board do
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index 30ca07d5d2c..3ab013ddc0e 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BroadcastMessage do
diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb
index 504bc710b25..82991937644 100644
--- a/spec/models/chat_name_spec.rb
+++ b/spec/models/chat_name_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatName do
diff --git a/spec/models/chat_team_spec.rb b/spec/models/chat_team_spec.rb
index 70a9a206faa..76beb3d506b 100644
--- a/spec/models/chat_team_spec.rb
+++ b/spec/models/chat_team_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatTeam do
diff --git a/spec/models/ci/artifact_blob_spec.rb b/spec/models/ci/artifact_blob_spec.rb
index 0014bbcf9f5..f63816fd92a 100644
--- a/spec/models/ci/artifact_blob_spec.rb
+++ b/spec/models/ci/artifact_blob_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::ArtifactBlob do
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index b5ec8991720..aacfbe3f180 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Bridge do
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index 016a5899eef..917a65ddf21 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildMetadata do
diff --git a/spec/models/ci/build_runner_session_spec.rb b/spec/models/ci/build_runner_session_spec.rb
index 35622366829..a52c10019e6 100644
--- a/spec/models/ci/build_runner_session_spec.rb
+++ b/spec/models/ci/build_runner_session_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildRunnerSession, model: true do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 7500e6ae5b1..2c41dfa65cd 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Build do
@@ -24,6 +26,8 @@ describe Ci::Build do
it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(:trace) }
it { is_expected.to delegate_method(:merge_request_event?).to(:pipeline) }
+ it { is_expected.to delegate_method(:merge_request_ref?).to(:pipeline) }
+ it { is_expected.to delegate_method(:legacy_detached_merge_request_pipeline?).to(:pipeline) }
it { is_expected.to be_a(ArtifactMigratable) }
@@ -3626,6 +3630,24 @@ describe Ci::Build do
it { is_expected.to be_falsey }
end
end
+
+ context 'when refspecs feature is required by build' do
+ before do
+ allow(build).to receive(:merge_request_ref?) { true }
+ end
+
+ context 'when runner provides given feature' do
+ let(:runner_features) { { refspecs: true } }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when runner does not provide given feature' do
+ let(:runner_features) { {} }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
describe '#deployment_status' do
diff --git a/spec/models/ci/build_trace_chunks/database_spec.rb b/spec/models/ci/build_trace_chunks/database_spec.rb
index d8fc9d57e95..eb94d7dae38 100644
--- a/spec/models/ci/build_trace_chunks/database_spec.rb
+++ b/spec/models/ci/build_trace_chunks/database_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildTraceChunks::Database do
diff --git a/spec/models/ci/build_trace_chunks/fog_spec.rb b/spec/models/ci/build_trace_chunks/fog_spec.rb
index 8f49190af13..b8d78bcd069 100644
--- a/spec/models/ci/build_trace_chunks/fog_spec.rb
+++ b/spec/models/ci/build_trace_chunks/fog_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildTraceChunks::Fog do
diff --git a/spec/models/ci/build_trace_chunks/redis_spec.rb b/spec/models/ci/build_trace_chunks/redis_spec.rb
index 9da1e6a95ee..6cff33d24fa 100644
--- a/spec/models/ci/build_trace_chunks/redis_spec.rb
+++ b/spec/models/ci/build_trace_chunks/redis_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildTraceChunks::Redis, :clean_gitlab_redis_shared_state do
diff --git a/spec/models/ci/build_trace_section_name_spec.rb b/spec/models/ci/build_trace_section_name_spec.rb
index 386ee6880cb..11e2d27ff79 100644
--- a/spec/models/ci/build_trace_section_name_spec.rb
+++ b/spec/models/ci/build_trace_section_name_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildTraceSectionName, model: true do
diff --git a/spec/models/ci/build_trace_section_spec.rb b/spec/models/ci/build_trace_section_spec.rb
index 541a9a36fb8..5bd3a953ec0 100644
--- a/spec/models/ci/build_trace_section_spec.rb
+++ b/spec/models/ci/build_trace_section_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::BuildTraceSection, model: true do
diff --git a/spec/models/ci/group_spec.rb b/spec/models/ci/group_spec.rb
index 838fa63cb1f..36c65d92840 100644
--- a/spec/models/ci/group_spec.rb
+++ b/spec/models/ci/group_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Group do
diff --git a/spec/models/ci/group_variable_spec.rb b/spec/models/ci/group_variable_spec.rb
index 21d96bf3454..b3999765e5f 100644
--- a/spec/models/ci/group_variable_spec.rb
+++ b/spec/models/ci/group_variable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::GroupVariable do
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index c68ba02b8de..d7abd54eec1 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::JobArtifact do
diff --git a/spec/models/ci/legacy_stage_spec.rb b/spec/models/ci/legacy_stage_spec.rb
index 0c33c1466b7..be0307518eb 100644
--- a/spec/models/ci/legacy_stage_spec.rb
+++ b/spec/models/ci/legacy_stage_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::LegacyStage do
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 8ee15f0e734..81913f4a3b6 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::PipelineSchedule do
diff --git a/spec/models/ci/pipeline_schedule_variable_spec.rb b/spec/models/ci/pipeline_schedule_variable_spec.rb
index dc8427f28bc..3c9379ecb0d 100644
--- a/spec/models/ci/pipeline_schedule_variable_spec.rb
+++ b/spec/models/ci/pipeline_schedule_variable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::PipelineScheduleVariable do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 5b8097621e0..e76cf376ed1 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Pipeline, :mailer do
@@ -362,6 +364,42 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '#merge_request_ref?' do
+ subject { pipeline.merge_request_ref? }
+
+ it 'calls MergeRequest#merge_request_ref?' do
+ expect(MergeRequest).to receive(:merge_request_ref?).with(pipeline.ref)
+
+ subject
+ end
+ end
+
+ describe '#legacy_detached_merge_request_pipeline?' do
+ subject { pipeline.legacy_detached_merge_request_pipeline? }
+
+ set(:merge_request) { create(:merge_request) }
+ let(:ref) { 'feature' }
+ let(:target_sha) { nil }
+
+ let(:pipeline) do
+ build(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: ref, target_sha: target_sha)
+ end
+
+ it { is_expected.to be_truthy }
+
+ context 'when pipeline ref is a merge request ref' do
+ let(:ref) { 'refs/merge-requests/1/head' }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'when target sha is set' do
+ let(:target_sha) { 'target-sha' }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe '#matches_sha_or_source_sha?' do
subject { pipeline.matches_sha_or_source_sha?(sample_sha) }
@@ -1460,6 +1498,14 @@ describe Ci::Pipeline, :mailer do
end
end
+ context 'with a branch name as the ref' do
+ it 'looks up commit with the full ref name' do
+ expect(pipeline.project).to receive(:commit).with('refs/heads/master').and_call_original
+
+ expect(pipeline).to be_latest
+ end
+ end
+
context 'with not latest sha' do
before do
pipeline.update(
diff --git a/spec/models/ci/pipeline_variable_spec.rb b/spec/models/ci/pipeline_variable_spec.rb
index 03d09cb31d6..2ecb688299a 100644
--- a/spec/models/ci/pipeline_variable_spec.rb
+++ b/spec/models/ci/pipeline_variable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::PipelineVariable do
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index eb2daed7f32..b3ab63925dd 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Runner do
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 3228c400155..661958390e2 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Stage, :models do
diff --git a/spec/models/ci/trigger_request_spec.rb b/spec/models/ci/trigger_request_spec.rb
index 7dcf3528f73..d04349bec92 100644
--- a/spec/models/ci/trigger_request_spec.rb
+++ b/spec/models/ci/trigger_request_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::TriggerRequest do
diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb
index d4b72205203..fde8375f2a5 100644
--- a/spec/models/ci/trigger_spec.rb
+++ b/spec/models/ci/trigger_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Trigger do
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index 02c07a2bd83..d2df6b3344e 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Ci::Variable do
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index cf5cbf8ec5c..af7eadfc74c 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::CertManager do
@@ -9,7 +11,27 @@ describe Clusters::Applications::CertManager do
include_examples 'cluster application initial status specs'
describe '#install_command' do
- let(:cluster_issuer_file) { { "cluster_issuer.yaml": "---\napiVersion: certmanager.k8s.io/v1alpha1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-prod\nspec:\n acme:\n server: https://acme-v02.api.letsencrypt.org/directory\n email: admin@example.com\n privateKeySecretRef:\n name: letsencrypt-prod\n http01: {}\n" } }
+ let(:cert_email) { 'admin@example.com' }
+
+ let(:cluster_issuer_file) do
+ file_contents = <<~EOF
+ ---
+ apiVersion: certmanager.k8s.io/v1alpha1
+ kind: ClusterIssuer
+ metadata:
+ name: letsencrypt-prod
+ spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: #{cert_email}
+ privateKeySecretRef:
+ name: letsencrypt-prod
+ http01: {}
+ EOF
+
+ { "cluster_issuer.yaml": file_contents }
+ end
+
subject { cert_manager.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
@@ -24,9 +46,10 @@ describe Clusters::Applications::CertManager do
end
context 'for a specific user' do
+ let(:cert_email) { 'abc@xyz.com' }
+
before do
- cert_manager.email = 'abc@xyz.com'
- cluster_issuer_file[:'cluster_issuer.yaml'].gsub! 'admin@example.com', 'abc@xyz.com'
+ cert_manager.email = cert_email
end
it 'should use his/her email to register issuer with certificate provider' do
diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb
index f16eff92167..f97d126d918 100644
--- a/spec/models/clusters/applications/helm_spec.rb
+++ b/spec/models/clusters/applications/helm_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::Helm do
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index a40fa988287..09e60b9a206 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::Ingress do
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index 2967c4076c6..5970a1959b5 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::Jupyter do
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index bf425a2617c..25493689fbc 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::Knative do
@@ -107,7 +109,7 @@ describe Clusters::Applications::Knative do
subject { knative.install_command }
it 'should be initialized with latest version' do
- expect(subject.version).to eq('0.2.2')
+ expect(subject.version).to eq('0.3.0')
end
it_behaves_like 'a command'
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index 81708b0c2ed..82a502addd4 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::Prometheus do
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 3ce8aa1c7bc..7e2f5835279 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Clusters::Applications::Runner do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index acbcdc7d170..fabd2806d9a 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -620,4 +620,20 @@ describe Clusters::Cluster do
end
end
end
+
+ describe '#provided_by_user?' do
+ subject { cluster.provided_by_user? }
+
+ context 'with a GCP provider' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'with an user provider' do
+ let(:cluster) { create(:cluster, :provided_by_user) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index af65530e663..14bec17a2bd 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching do
@@ -15,7 +17,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to delegate_method(:project).to(:cluster) }
it { is_expected.to delegate_method(:enabled?).to(:cluster) }
- it { is_expected.to delegate_method(:managed?).to(:cluster) }
+ it { is_expected.to delegate_method(:provided_by_user?).to(:cluster) }
it { is_expected.to delegate_method(:kubernetes_namespace).to(:cluster) }
it_behaves_like 'having unique enum values'
diff --git a/spec/models/clusters/project_spec.rb b/spec/models/clusters/project_spec.rb
index 82ef5a23c18..2f017e69251 100644
--- a/spec/models/clusters/project_spec.rb
+++ b/spec/models/clusters/project_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Clusters::Project do
diff --git a/spec/models/clusters/providers/gcp_spec.rb b/spec/models/clusters/providers/gcp_spec.rb
index 5012e6f15c6..785db4febe0 100644
--- a/spec/models/clusters/providers/gcp_spec.rb
+++ b/spec/models/clusters/providers/gcp_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Clusters::Providers::Gcp do
diff --git a/spec/models/commit_collection_spec.rb b/spec/models/commit_collection_spec.rb
index 30c504ebea8..8a7fcb39fe2 100644
--- a/spec/models/commit_collection_spec.rb
+++ b/spec/models/commit_collection_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CommitCollection do
diff --git a/spec/models/commit_range_spec.rb b/spec/models/commit_range_spec.rb
index f2efcd9d0e9..b96ca89c893 100644
--- a/spec/models/commit_range_spec.rb
+++ b/spec/models/commit_range_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CommitRange do
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 9d4e18534ae..14f4b4d692f 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Commit do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index e2b7f5c6ee2..ca2f9e36c98 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CommitStatus do
diff --git a/spec/models/compare_spec.rb b/spec/models/compare_spec.rb
index 0bc3ee014e6..43c3580bed2 100644
--- a/spec/models/compare_spec.rb
+++ b/spec/models/compare_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Compare do
diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb
index 04d6cfa2c02..de2bc3a387b 100644
--- a/spec/models/concerns/access_requestable_spec.rb
+++ b/spec/models/concerns/access_requestable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe AccessRequestable do
diff --git a/spec/models/concerns/avatarable_spec.rb b/spec/models/concerns/avatarable_spec.rb
index 1ea7f2b9985..c750be6b75c 100644
--- a/spec/models/concerns/avatarable_spec.rb
+++ b/spec/models/concerns/avatarable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Avatarable do
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
index 5713106418d..9e7106281ee 100644
--- a/spec/models/concerns/awardable_spec.rb
+++ b/spec/models/concerns/awardable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Awardable do
diff --git a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
index e5392fe0462..1fe90d3cc9a 100644
--- a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
+++ b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BatchDestroyDependentAssociations do
diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb
index 5906b588d0e..e8657c45a93 100644
--- a/spec/models/concerns/blocks_json_serialization_spec.rb
+++ b/spec/models/concerns/blocks_json_serialization_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe BlocksJsonSerialization do
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index 7d555f15e39..78637ff10c6 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CacheMarkdownField do
diff --git a/spec/models/concerns/cacheable_attributes_spec.rb b/spec/models/concerns/cacheable_attributes_spec.rb
index 43a544cfe26..394fac52aa7 100644
--- a/spec/models/concerns/cacheable_attributes_spec.rb
+++ b/spec/models/concerns/cacheable_attributes_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CacheableAttributes do
diff --git a/spec/models/concerns/case_sensitivity_spec.rb b/spec/models/concerns/case_sensitivity_spec.rb
index 1bf6c9b3404..d6d41a25eac 100644
--- a/spec/models/concerns/case_sensitivity_spec.rb
+++ b/spec/models/concerns/case_sensitivity_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CaseSensitivity do
diff --git a/spec/models/concerns/chronic_duration_attribute_spec.rb b/spec/models/concerns/chronic_duration_attribute_spec.rb
index 51221e07ca3..e41d75568f7 100644
--- a/spec/models/concerns/chronic_duration_attribute_spec.rb
+++ b/spec/models/concerns/chronic_duration_attribute_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
shared_examples 'ChronicDurationAttribute reader' do
diff --git a/spec/models/concerns/deployable_spec.rb b/spec/models/concerns/deployable_spec.rb
index 6951be903fe..42bed9434f5 100644
--- a/spec/models/concerns/deployable_spec.rb
+++ b/spec/models/concerns/deployable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Deployable do
diff --git a/spec/models/concerns/deployment_platform_spec.rb b/spec/models/concerns/deployment_platform_spec.rb
index 19ab4382b53..0e34d8fccf3 100644
--- a/spec/models/concerns/deployment_platform_spec.rb
+++ b/spec/models/concerns/deployment_platform_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe DeploymentPlatform do
diff --git a/spec/models/concerns/discussion_on_diff_spec.rb b/spec/models/concerns/discussion_on_diff_spec.rb
index 64bf04071e8..baddca47dfa 100644
--- a/spec/models/concerns/discussion_on_diff_spec.rb
+++ b/spec/models/concerns/discussion_on_diff_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DiscussionOnDiff do
diff --git a/spec/models/concerns/each_batch_spec.rb b/spec/models/concerns/each_batch_spec.rb
index 17224c09693..c4cf8e80f7a 100644
--- a/spec/models/concerns/each_batch_spec.rb
+++ b/spec/models/concerns/each_batch_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe EachBatch do
diff --git a/spec/models/concerns/editable_spec.rb b/spec/models/concerns/editable_spec.rb
index 49a9a8ebcbc..4a4a3ca5687 100644
--- a/spec/models/concerns/editable_spec.rb
+++ b/spec/models/concerns/editable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Editable do
diff --git a/spec/models/concerns/expirable_spec.rb b/spec/models/concerns/expirable_spec.rb
index f7b436f32e6..f4f5eab5b86 100644
--- a/spec/models/concerns/expirable_spec.rb
+++ b/spec/models/concerns/expirable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Expirable do
diff --git a/spec/models/concerns/faster_cache_keys_spec.rb b/spec/models/concerns/faster_cache_keys_spec.rb
index 8d3f94267fa..7830acbae3d 100644
--- a/spec/models/concerns/faster_cache_keys_spec.rb
+++ b/spec/models/concerns/faster_cache_keys_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe FasterCacheKeys do
diff --git a/spec/models/concerns/feature_gate_spec.rb b/spec/models/concerns/feature_gate_spec.rb
index 3f601243245..276d3d9e1d5 100644
--- a/spec/models/concerns/feature_gate_spec.rb
+++ b/spec/models/concerns/feature_gate_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe FeatureGate do
diff --git a/spec/models/concerns/group_descendant_spec.rb b/spec/models/concerns/group_descendant_spec.rb
index 28352d8c961..194caac3fce 100644
--- a/spec/models/concerns/group_descendant_spec.rb
+++ b/spec/models/concerns/group_descendant_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupDescendant, :nested_groups do
diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb
index e8b1eba67cc..a217dc42537 100644
--- a/spec/models/concerns/has_status_spec.rb
+++ b/spec/models/concerns/has_status_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe HasStatus do
diff --git a/spec/models/concerns/has_variable_spec.rb b/spec/models/concerns/has_variable_spec.rb
index bff96e12ffa..2bb21d7934e 100644
--- a/spec/models/concerns/has_variable_spec.rb
+++ b/spec/models/concerns/has_variable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe HasVariable do
diff --git a/spec/models/concerns/ignorable_column_spec.rb b/spec/models/concerns/ignorable_column_spec.rb
index b70f2331a0e..6b82825d2cc 100644
--- a/spec/models/concerns/ignorable_column_spec.rb
+++ b/spec/models/concerns/ignorable_column_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe IgnorableColumn do
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 72c6161424b..259ac6852a8 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Issuable do
diff --git a/spec/models/concerns/loaded_in_group_list_spec.rb b/spec/models/concerns/loaded_in_group_list_spec.rb
index 7a279547a3a..7c97b580779 100644
--- a/spec/models/concerns/loaded_in_group_list_spec.rb
+++ b/spec/models/concerns/loaded_in_group_list_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LoadedInGroupList do
diff --git a/spec/models/concerns/manual_inverse_association_spec.rb b/spec/models/concerns/manual_inverse_association_spec.rb
index ff4a04ea573..ee32e3b165b 100644
--- a/spec/models/concerns/manual_inverse_association_spec.rb
+++ b/spec/models/concerns/manual_inverse_association_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ManualInverseAssociation do
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index a9b237fa9ea..f31e3e8821d 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Mentionable do
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 81ca5b638fe..22d4b2cc517 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Milestone, 'Milestoneish' do
diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb
index 485a6e165a1..ee613b199ad 100644
--- a/spec/models/concerns/noteable_spec.rb
+++ b/spec/models/concerns/noteable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Noteable do
diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb
index 431f1482615..3d5937c4fc6 100644
--- a/spec/models/concerns/participable_spec.rb
+++ b/spec/models/concerns/participable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Participable do
diff --git a/spec/models/concerns/presentable_spec.rb b/spec/models/concerns/presentable_spec.rb
index 941647a79fb..9db868dd348 100644
--- a/spec/models/concerns/presentable_spec.rb
+++ b/spec/models/concerns/presentable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Presentable do
diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb
index 9041690023f..5aa43b58217 100644
--- a/spec/models/concerns/project_features_compatibility_spec.rb
+++ b/spec/models/concerns/project_features_compatibility_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectFeaturesCompatibility do
diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb
index f4b9c57e71a..7148261b1e4 100644
--- a/spec/models/concerns/prometheus_adapter_spec.rb
+++ b/spec/models/concerns/prometheus_adapter_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/concerns/protected_ref_access_spec.rb b/spec/models/concerns/protected_ref_access_spec.rb
index ce602337647..94798f0590d 100644
--- a/spec/models/concerns/protected_ref_access_spec.rb
+++ b/spec/models/concerns/protected_ref_access_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProtectedRefAccess do
diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb
index 03ae45e6b17..32e13d5abed 100644
--- a/spec/models/concerns/reactive_caching_spec.rb
+++ b/spec/models/concerns/reactive_caching_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ReactiveCaching, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/concerns/redactable_spec.rb b/spec/models/concerns/redactable_spec.rb
index 7feeaa54069..57c7d2cb767 100644
--- a/spec/models/concerns/redactable_spec.rb
+++ b/spec/models/concerns/redactable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Redactable do
diff --git a/spec/models/concerns/redis_cacheable_spec.rb b/spec/models/concerns/redis_cacheable_spec.rb
index 23c6c6233e9..a9dca27f258 100644
--- a/spec/models/concerns/redis_cacheable_spec.rb
+++ b/spec/models/concerns/redis_cacheable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe RedisCacheable do
diff --git a/spec/models/concerns/relative_positioning_spec.rb b/spec/models/concerns/relative_positioning_spec.rb
index ac8da30b6c9..d0ae45f7871 100644
--- a/spec/models/concerns/relative_positioning_spec.rb
+++ b/spec/models/concerns/relative_positioning_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe RelativePositioning do
diff --git a/spec/models/concerns/resolvable_discussion_spec.rb b/spec/models/concerns/resolvable_discussion_spec.rb
index 97b046b0f21..9ea01ca9002 100644
--- a/spec/models/concerns/resolvable_discussion_spec.rb
+++ b/spec/models/concerns/resolvable_discussion_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Discussion, ResolvableDiscussion do
diff --git a/spec/models/concerns/resolvable_note_spec.rb b/spec/models/concerns/resolvable_note_spec.rb
index fcb5250278e..4f46252a044 100644
--- a/spec/models/concerns/resolvable_note_spec.rb
+++ b/spec/models/concerns/resolvable_note_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Note, ResolvableNote do
diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb
index 565266321d3..1fb0dd5030c 100644
--- a/spec/models/concerns/routable_spec.rb
+++ b/spec/models/concerns/routable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Group, 'Routable' do
diff --git a/spec/models/concerns/sha_attribute_spec.rb b/spec/models/concerns/sha_attribute_spec.rb
index 0d3beb6a6e3..a4a81ae126d 100644
--- a/spec/models/concerns/sha_attribute_spec.rb
+++ b/spec/models/concerns/sha_attribute_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ShaAttribute do
diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb
index 0a9d2021a19..184f7986a6f 100644
--- a/spec/models/concerns/sortable_spec.rb
+++ b/spec/models/concerns/sortable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Sortable do
diff --git a/spec/models/concerns/spammable_spec.rb b/spec/models/concerns/spammable_spec.rb
index e698207166c..650d49e41a1 100644
--- a/spec/models/concerns/spammable_spec.rb
+++ b/spec/models/concerns/spammable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Spammable do
diff --git a/spec/models/concerns/strip_attribute_spec.rb b/spec/models/concerns/strip_attribute_spec.rb
index 8c945686b66..5c0d1042e06 100644
--- a/spec/models/concerns/strip_attribute_spec.rb
+++ b/spec/models/concerns/strip_attribute_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe StripAttribute do
diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb
index 45dfb136aea..2f88adf08dd 100644
--- a/spec/models/concerns/subscribable_spec.rb
+++ b/spec/models/concerns/subscribable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Subscribable, 'Subscribable' do
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 40cb4eef60a..51e28974ae0 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
shared_examples 'TokenAuthenticatable' do
diff --git a/spec/models/concerns/token_authenticatable_strategies/base_spec.rb b/spec/models/concerns/token_authenticatable_strategies/base_spec.rb
index 2a0182b4294..7332da309d5 100644
--- a/spec/models/concerns/token_authenticatable_strategies/base_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/base_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe TokenAuthenticatableStrategies::Base do
diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
index ca38f86c5ab..70f41981b3b 100644
--- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe TokenAuthenticatableStrategies::Encrypted do
diff --git a/spec/models/concerns/triggerable_hooks_spec.rb b/spec/models/concerns/triggerable_hooks_spec.rb
index 265abd6bd72..f28e5f56411 100644
--- a/spec/models/concerns/triggerable_hooks_spec.rb
+++ b/spec/models/concerns/triggerable_hooks_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe TriggerableHooks do
diff --git a/spec/models/concerns/uniquify_spec.rb b/spec/models/concerns/uniquify_spec.rb
index 6cd2de6dcce..9ba35702ba6 100644
--- a/spec/models/concerns/uniquify_spec.rb
+++ b/spec/models/concerns/uniquify_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Uniquify do
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index e46945e301e..013112d1d51 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ContainerRepository do
diff --git a/spec/models/conversational_development_index/metric_spec.rb b/spec/models/conversational_development_index/metric_spec.rb
index b3193619503..60b1a860dfd 100644
--- a/spec/models/conversational_development_index/metric_spec.rb
+++ b/spec/models/conversational_development_index/metric_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe ConversationalDevelopmentIndex::Metric do
diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb
index 6a6b58fb52b..b22a0340015 100644
--- a/spec/models/cycle_analytics/code_spec.rb
+++ b/spec/models/cycle_analytics/code_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#code' do
diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb
index 45f1b4fe8a3..07d60be091a 100644
--- a/spec/models/cycle_analytics/issue_spec.rb
+++ b/spec/models/cycle_analytics/issue_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#issue' do
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
index d366e2b723a..3d22a284264 100644
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ b/spec/models/cycle_analytics/plan_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#plan' do
diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb
index 156eb96cfce..383727cd8f7 100644
--- a/spec/models/cycle_analytics/production_spec.rb
+++ b/spec/models/cycle_analytics/production_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#production' do
diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb
index 0aedfb49cb5..1af5f9cc1f4 100644
--- a/spec/models/cycle_analytics/review_spec.rb
+++ b/spec/models/cycle_analytics/review_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#review' do
diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb
index 0cbda50c688..8375944f03c 100644
--- a/spec/models/cycle_analytics/staging_spec.rb
+++ b/spec/models/cycle_analytics/staging_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#staging' do
diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb
index e58b8fdff58..b78258df564 100644
--- a/spec/models/cycle_analytics/test_spec.rb
+++ b/spec/models/cycle_analytics/test_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'CycleAnalytics#test' do
diff --git a/spec/models/cycle_analytics_spec.rb b/spec/models/cycle_analytics_spec.rb
index 0fe24870f02..5d8b5b573cf 100644
--- a/spec/models/cycle_analytics_spec.rb
+++ b/spec/models/cycle_analytics_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CycleAnalytics do
diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb
index 41440c6d288..ec6cfb6b826 100644
--- a/spec/models/deploy_key_spec.rb
+++ b/spec/models/deploy_key_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DeployKey, :mailer do
diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb
index fca3090ff4a..c137444763b 100644
--- a/spec/models/deploy_keys_project_spec.rb
+++ b/spec/models/deploy_keys_project_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DeployKeysProject do
diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb
index 3435f93c999..05320703e25 100644
--- a/spec/models/deploy_token_spec.rb
+++ b/spec/models/deploy_token_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DeployToken do
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 5fce9504334..d9170d5fa07 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Deployment do
diff --git a/spec/models/diff_discussion_spec.rb b/spec/models/diff_discussion_spec.rb
index 50b19000799..cfeb4382927 100644
--- a/spec/models/diff_discussion_spec.rb
+++ b/spec/models/diff_discussion_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DiffDiscussion do
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index 67e5f4f7e41..fa19cb47a0d 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DiffNote do
diff --git a/spec/models/diff_viewer/base_spec.rb b/spec/models/diff_viewer/base_spec.rb
index f4efe5a7b3a..b8bdeb781dc 100644
--- a/spec/models/diff_viewer/base_spec.rb
+++ b/spec/models/diff_viewer/base_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DiffViewer::Base do
diff --git a/spec/models/diff_viewer/server_side_spec.rb b/spec/models/diff_viewer/server_side_spec.rb
index 86b14b6ebf3..27de0584b8a 100644
--- a/spec/models/diff_viewer/server_side_spec.rb
+++ b/spec/models/diff_viewer/server_side_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DiffViewer::ServerSide do
diff --git a/spec/models/discussion_spec.rb b/spec/models/discussion_spec.rb
index a46f7ed6507..0d02165787a 100644
--- a/spec/models/discussion_spec.rb
+++ b/spec/models/discussion_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Discussion do
diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb
index 47eb0717c0c..cae88f39660 100644
--- a/spec/models/email_spec.rb
+++ b/spec/models/email_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Email do
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index ab1b306e597..448ed35cb1e 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Environment do
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index 2576a9aba06..c503c35305f 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe EnvironmentStatus do
diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
index cbde13a2c7a..21e381d9fb7 100644
--- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb
+++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
@@ -167,7 +167,7 @@ describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
- context 'when sentry client raises exception' do
+ context 'when sentry client raises Sentry::Client::Error' do
let(:sentry_client) { spy(:sentry_client) }
before do
@@ -179,7 +179,31 @@ describe ErrorTracking::ProjectErrorTrackingSetting do
end
it 'returns error' do
- expect(result).to eq(error: 'error message')
+ expect(result).to eq(
+ error: 'error message',
+ error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE
+ )
+ expect(subject).to have_received(:sentry_client)
+ expect(sentry_client).to have_received(:list_issues)
+ end
+ end
+
+ context 'when sentry client raises Sentry::Client::MissingKeysError' do
+ let(:sentry_client) { spy(:sentry_client) }
+
+ before do
+ synchronous_reactive_cache(subject)
+
+ allow(subject).to receive(:sentry_client).and_return(sentry_client)
+ allow(sentry_client).to receive(:list_issues).with(opts)
+ .and_raise(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
+ end
+
+ it 'returns error' do
+ expect(result).to eq(
+ error: 'Sentry API response is missing keys. key not found: "id"',
+ error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS
+ )
expect(subject).to have_received(:sentry_client)
expect(sentry_client).to have_received(:list_issues)
end
diff --git a/spec/models/event_collection_spec.rb b/spec/models/event_collection_spec.rb
index 6078f429bdc..efe511042c3 100644
--- a/spec/models/event_collection_spec.rb
+++ b/spec/models/event_collection_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe EventCollection do
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index ce4f8ee4705..d192fe70506 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Event do
diff --git a/spec/models/external_issue_spec.rb b/spec/models/external_issue_spec.rb
index 83ba22caa03..9d064d458f0 100644
--- a/spec/models/external_issue_spec.rb
+++ b/spec/models/external_issue_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ExternalIssue do
diff --git a/spec/models/fork_network_member_spec.rb b/spec/models/fork_network_member_spec.rb
index 60d04562e6c..eab758248de 100644
--- a/spec/models/fork_network_member_spec.rb
+++ b/spec/models/fork_network_member_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ForkNetworkMember do
diff --git a/spec/models/fork_network_spec.rb b/spec/models/fork_network_spec.rb
index a43baf1820a..5ec0f8d6b02 100644
--- a/spec/models/fork_network_spec.rb
+++ b/spec/models/fork_network_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ForkNetwork do
diff --git a/spec/models/generic_commit_status_spec.rb b/spec/models/generic_commit_status_spec.rb
index a3e68d2e646..c851810ffb3 100644
--- a/spec/models/generic_commit_status_spec.rb
+++ b/spec/models/generic_commit_status_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GenericCommitStatus do
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index f93904065c7..9d901d01a52 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GlobalMilestone do
diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb
index 58a1d2e4ea2..479b39cd139 100644
--- a/spec/models/gpg_key_spec.rb
+++ b/spec/models/gpg_key_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe GpgKey do
diff --git a/spec/models/gpg_key_subkey_spec.rb b/spec/models/gpg_key_subkey_spec.rb
index 3c86837f47f..51d2f9cb9ac 100644
--- a/spec/models/gpg_key_subkey_spec.rb
+++ b/spec/models/gpg_key_subkey_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe GpgKeySubkey do
diff --git a/spec/models/gpg_signature_spec.rb b/spec/models/gpg_signature_spec.rb
index e90319c39b1..47c343edf0e 100644
--- a/spec/models/gpg_signature_spec.rb
+++ b/spec/models/gpg_signature_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe GpgSignature do
diff --git a/spec/models/group_custom_attribute_spec.rb b/spec/models/group_custom_attribute_spec.rb
index 7ecb2022567..7d60c74b62b 100644
--- a/spec/models/group_custom_attribute_spec.rb
+++ b/spec/models/group_custom_attribute_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupCustomAttribute do
diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb
index d0fc1eaa3ec..a3a5c631c3d 100644
--- a/spec/models/group_label_spec.rb
+++ b/spec/models/group_label_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupLabel do
diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb
index fcc33cd95fe..01856870fe0 100644
--- a/spec/models/group_milestone_spec.rb
+++ b/spec/models/group_milestone_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupMilestone do
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 16624ce47d0..2c6abddca17 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Group do
diff --git a/spec/models/guest_spec.rb b/spec/models/guest_spec.rb
index fc30f3056e5..93862e98172 100644
--- a/spec/models/guest_spec.rb
+++ b/spec/models/guest_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Guest do
diff --git a/spec/models/hooks/active_hook_filter_spec.rb b/spec/models/hooks/active_hook_filter_spec.rb
index df7edda2213..1249c793f7f 100644
--- a/spec/models/hooks/active_hook_filter_spec.rb
+++ b/spec/models/hooks/active_hook_filter_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ActiveHookFilter do
diff --git a/spec/models/hooks/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb
index 5dd31b1b5de..a945f0d1516 100644
--- a/spec/models/hooks/project_hook_spec.rb
+++ b/spec/models/hooks/project_hook_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectHook do
diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb
index e32eaafc13f..936c2fbad27 100644
--- a/spec/models/hooks/service_hook_spec.rb
+++ b/spec/models/hooks/service_hook_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ServiceHook do
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index edd1cb455af..e0d4d2e4858 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe SystemHook do
diff --git a/spec/models/hooks/web_hook_log_spec.rb b/spec/models/hooks/web_hook_log_spec.rb
index 744a6ccae8b..f812149c9be 100644
--- a/spec/models/hooks/web_hook_log_spec.rb
+++ b/spec/models/hooks/web_hook_log_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe WebHookLog do
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index a308ac6e33a..fe08dc4f5e6 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe WebHook do
diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb
index e1a7a59dfd1..74ddc2d6284 100644
--- a/spec/models/identity_spec.rb
+++ b/spec/models/identity_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Identity do
diff --git a/spec/models/import_export_upload_spec.rb b/spec/models/import_export_upload_spec.rb
index 58af84b8a08..18a714f4d98 100644
--- a/spec/models/import_export_upload_spec.rb
+++ b/spec/models/import_export_upload_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ImportExportUpload do
diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb
index cb3d6c7cda2..e65f97df3c3 100644
--- a/spec/models/instance_configuration_spec.rb
+++ b/spec/models/instance_configuration_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe InstanceConfiguration do
@@ -30,8 +32,8 @@ describe InstanceConfiguration do
end
def stub_pub_file(exist: true)
- path = 'spec/fixtures/ssh_host_example_key.pub'
- path << 'random' unless exist
+ path = exist ? 'spec/fixtures/ssh_host_example_key.pub' : 'spec/fixtures/ssh_host_example_key.pub.random'
+
allow(subject).to receive(:ssh_algorithm_file).and_return(Rails.root.join(path))
end
end
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index d32f163f05b..ff2382838ae 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe InternalId do
diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb
index b7291eebe64..07858fe8a70 100644
--- a/spec/models/issue/metrics_spec.rb
+++ b/spec/models/issue/metrics_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Issue::Metrics do
diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb
index 580a98193af..7fc635f100f 100644
--- a/spec/models/issue_collection_spec.rb
+++ b/spec/models/issue_collection_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe IssueCollection do
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 6101df2e099..892dd053e39 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Issue do
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 06d26ef89f1..a0b6eff88d5 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Key, :mailer do
diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb
index e2b49bc2de7..b160e72e759 100644
--- a/spec/models/label_link_spec.rb
+++ b/spec/models/label_link_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LabelLink do
diff --git a/spec/models/label_priority_spec.rb b/spec/models/label_priority_spec.rb
index 9dcb0f06b20..1a93468290f 100644
--- a/spec/models/label_priority_spec.rb
+++ b/spec/models/label_priority_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LabelPriority do
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index 3fc6c06b7fa..5174c590a10 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Label do
diff --git a/spec/models/legacy_diff_discussion_spec.rb b/spec/models/legacy_diff_discussion_spec.rb
index dae97b69c84..49ea319fbd1 100644
--- a/spec/models/legacy_diff_discussion_spec.rb
+++ b/spec/models/legacy_diff_discussion_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LegacyDiffDiscussion do
diff --git a/spec/models/lfs_download_object_spec.rb b/spec/models/lfs_download_object_spec.rb
index 88838b127d2..effd8b08124 100644
--- a/spec/models/lfs_download_object_spec.rb
+++ b/spec/models/lfs_download_object_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe LfsDownloadObject do
diff --git a/spec/models/lfs_file_lock_spec.rb b/spec/models/lfs_file_lock_spec.rb
index 41ca1578b94..aa64d66944b 100644
--- a/spec/models/lfs_file_lock_spec.rb
+++ b/spec/models/lfs_file_lock_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe LfsFileLock do
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index 3f929710862..3d4d4b7d795 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LfsObject do
diff --git a/spec/models/lfs_objects_project_spec.rb b/spec/models/lfs_objects_project_spec.rb
index 0a3180f43e8..3e86ee38566 100644
--- a/spec/models/lfs_objects_project_spec.rb
+++ b/spec/models/lfs_objects_project_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LfsObjectsProject do
diff --git a/spec/models/license_template_spec.rb b/spec/models/license_template_spec.rb
index dd912eefac1..7037277e580 100644
--- a/spec/models/license_template_spec.rb
+++ b/spec/models/license_template_spec.rb
@@ -1,16 +1,19 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe LicenseTemplate do
describe '#content' do
it 'calls a proc exactly once if provided' do
- lazy = build_template(-> { 'bar' })
- content = lazy.content
+ content_proc = -> { 'bar' }
+ expect(content_proc).to receive(:call).once.and_call_original
+
+ lazy = build_template(content_proc)
- expect(content).to eq('bar')
- expect(content.object_id).to eq(lazy.content.object_id)
+ expect(lazy.content).to eq('bar')
- content.replace('foo')
- expect(lazy.content).to eq('foo')
+ # Subsequent calls should not call proc again
+ expect(lazy.content).to eq('bar')
end
it 'returns a string if provided' do
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index a51580f8292..18d4549977c 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe List do
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 188beac1582..c68c3ce2abe 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Member do
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index a3451c67bd8..f227abd3dae 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -1,6 +1,24 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GroupMember do
+ describe '.count_users_by_group_id' do
+ it 'counts users by group ID' do
+ user_1 = create(:user)
+ user_2 = create(:user)
+ group_1 = create(:group)
+ group_2 = create(:group)
+
+ group_1.add_owner(user_1)
+ group_1.add_owner(user_2)
+ group_2.add_owner(user_1)
+
+ expect(described_class.count_users_by_group_id).to eq(group_1.id => 2,
+ group_2.id => 1)
+ end
+ end
+
describe '.access_level_roles' do
it 'returns Gitlab::Access.options_with_owner' do
expect(described_class.access_level_roles).to eq(Gitlab::Access.options_with_owner)
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 36bfff2c339..497764b6825 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectMember do
diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb
index 02ff7839739..49573af0fed 100644
--- a/spec/models/merge_request/metrics_spec.rb
+++ b/spec/models/merge_request/metrics_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MergeRequest::Metrics do
diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb
index 10487190a44..ab2aadf7d88 100644
--- a/spec/models/merge_request_diff_commit_spec.rb
+++ b/spec/models/merge_request_diff_commit_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe MergeRequestDiffCommit do
diff --git a/spec/models/merge_request_diff_file_spec.rb b/spec/models/merge_request_diff_file_spec.rb
index faa47660a74..66957c24fdc 100644
--- a/spec/models/merge_request_diff_file_spec.rb
+++ b/spec/models/merge_request_diff_file_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe MergeRequestDiffFile do
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 53f5307ea0b..a53add67066 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MergeRequestDiff do
@@ -51,7 +53,104 @@ describe MergeRequestDiff do
end
end
- describe '#latest' do
+ describe '.ids_for_external_storage_migration' do
+ set(:merge_request) { create(:merge_request) }
+ set(:outdated) { merge_request.merge_request_diff }
+ set(:latest) { merge_request.create_merge_request_diff }
+
+ set(:closed_mr) { create(:merge_request, :closed_last_month) }
+ let(:closed) { closed_mr.merge_request_diff }
+
+ set(:merged_mr) { create(:merge_request, :merged_last_month) }
+ let(:merged) { merged_mr.merge_request_diff }
+
+ set(:recently_closed_mr) { create(:merge_request, :closed) }
+ let(:closed_recently) { recently_closed_mr.merge_request_diff }
+
+ set(:recently_merged_mr) { create(:merge_request, :merged) }
+ let(:merged_recently) { recently_merged_mr.merge_request_diff }
+
+ before do
+ merge_request.update!(latest_merge_request_diff: latest)
+ end
+
+ subject { described_class.ids_for_external_storage_migration(limit: 1000) }
+
+ context 'external diffs are disabled' do
+ before do
+ stub_external_diffs_setting(enabled: false)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'external diffs are misconfigured' do
+ before do
+ stub_external_diffs_setting(enabled: true, when: 'every second tuesday')
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'external diffs are enabled unconditionally' do
+ before do
+ stub_external_diffs_setting(enabled: true)
+ end
+
+ it { is_expected.to contain_exactly(outdated.id, latest.id, closed.id, merged.id, closed_recently.id, merged_recently.id) }
+ end
+
+ context 'external diffs are enabled for outdated diffs' do
+ before do
+ stub_external_diffs_setting(enabled: true, when: 'outdated')
+ end
+
+ it 'returns records for outdated merge request versions' do
+ is_expected.to contain_exactly(outdated.id, closed.id, merged.id)
+ end
+ end
+
+ context 'with limit' do
+ it 'respects the limit' do
+ stub_external_diffs_setting(enabled: true)
+
+ expect(described_class.ids_for_external_storage_migration(limit: 3).count).to eq(3)
+ end
+ end
+ end
+
+ describe '#migrate_files_to_external_storage!' do
+ let(:diff) { create(:merge_request).merge_request_diff }
+
+ it 'converts from in-database to external storage' do
+ expect(diff).not_to be_stored_externally
+
+ stub_external_diffs_setting(enabled: true)
+ expect(diff).to receive(:save!)
+
+ diff.migrate_files_to_external_storage!
+
+ expect(diff).to be_stored_externally
+ end
+
+ it 'does nothing with an external diff' do
+ stub_external_diffs_setting(enabled: true)
+
+ expect(diff).to be_stored_externally
+ expect(diff).not_to receive(:save!)
+
+ diff.migrate_files_to_external_storage!
+ end
+
+ it 'does nothing if external diffs are disabled' do
+ expect(diff).not_to be_stored_externally
+ expect(diff).not_to receive(:save!)
+
+ diff.migrate_files_to_external_storage!
+ end
+ end
+
+ describe '#latest?' do
let!(:mr) { create(:merge_request, :with_diffs) }
let!(:first_diff) { mr.merge_request_diff }
let!(:last_diff) { mr.create_merge_request_diff }
@@ -222,12 +321,56 @@ describe MergeRequestDiff do
include_examples 'merge request diffs'
end
- describe 'external diffs configured' do
+ describe 'external diffs always enabled' do
before do
- stub_external_diffs_setting(enabled: true)
+ stub_external_diffs_setting(enabled: true, when: 'always')
+ end
+
+ include_examples 'merge request diffs'
+ end
+
+ describe 'exernal diffs enabled for outdated diffs' do
+ before do
+ stub_external_diffs_setting(enabled: true, when: 'outdated')
end
include_examples 'merge request diffs'
+
+ it 'stores up-to-date diffs in the database' do
+ expect(diff).not_to be_stored_externally
+ end
+
+ it 'stores diffs for recently closed MRs in the database' do
+ mr = create(:merge_request, :closed)
+
+ expect(mr.merge_request_diff).not_to be_stored_externally
+ end
+
+ it 'stores diffs for recently merged MRs in the database' do
+ mr = create(:merge_request, :merged)
+
+ expect(mr.merge_request_diff).not_to be_stored_externally
+ end
+
+ it 'stores diffs for old MR versions in external storage' do
+ old_diff = diff
+ merge_request.create_merge_request_diff
+ old_diff.migrate_files_to_external_storage!
+
+ expect(old_diff).to be_stored_externally
+ end
+
+ it 'stores diffs for old closed MRs in external storage' do
+ mr = create(:merge_request, :closed_last_month)
+
+ expect(mr.merge_request_diff).to be_stored_externally
+ end
+
+ it 'stores diffs for old merged MRs in external storage' do
+ mr = create(:merge_request, :merged_last_month)
+
+ expect(mr.merge_request_diff).to be_stored_externally
+ end
end
describe '#commit_shas' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 2bcc8a77224..4b3a77e6bc2 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MergeRequest do
@@ -179,6 +181,31 @@ describe MergeRequest do
expect(MergeRequest::Metrics.count).to eq(1)
end
end
+
+ describe '#refresh_merge_request_assignees' do
+ set(:user) { create(:user) }
+
+ it 'creates merge request assignees relation upon MR creation' do
+ merge_request = create(:merge_request, assignee: nil)
+
+ expect(merge_request.merge_request_assignees).to be_empty
+
+ expect { merge_request.update!(assignee: user) }
+ .to change { merge_request.reload.merge_request_assignees.count }
+ .from(0).to(1)
+ end
+
+ it 'updates merge request assignees relation upon MR assignee change' do
+ another_user = create(:user)
+ merge_request = create(:merge_request, assignee: user)
+
+ expect { merge_request.update!(assignee: another_user) }
+ .to change { merge_request.reload.merge_request_assignees.first.assignee }
+ .from(user).to(another_user)
+
+ expect(merge_request.merge_request_assignees.count).to eq(1)
+ end
+ end
end
describe 'respond to' do
@@ -2687,14 +2714,21 @@ describe MergeRequest do
end
describe '#has_commits?' do
- before do
+ it 'returns true when merge request diff has commits' do
allow(subject.merge_request_diff).to receive(:commits_count)
.and_return(2)
- end
- it 'returns true when merge request diff has commits' do
expect(subject.has_commits?).to be_truthy
end
+
+ context 'when commits_count is nil' do
+ it 'returns false' do
+ allow(subject.merge_request_diff).to receive(:commits_count)
+ .and_return(nil)
+
+ expect(subject.has_commits?).to be_falsey
+ end
+ end
end
describe '#has_no_commits?' do
@@ -3090,4 +3124,32 @@ describe MergeRequest do
end
end
end
+
+ describe '.merge_request_ref?' do
+ subject { described_class.merge_request_ref?(ref) }
+
+ context 'when ref is ref name of a branch' do
+ let(:ref) { 'feature' }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when ref is HEAD ref path of a branch' do
+ let(:ref) { 'refs/heads/feature' }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when ref is HEAD ref path of a merge request' do
+ let(:ref) { 'refs/merge-requests/1/head' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when ref is merge ref path of a merge request' do
+ let(:ref) { 'refs/merge-requests/1/merge' }
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 717d4ae4ec0..b82368318f2 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Milestone do
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index aadc298ae0b..62e7dd3231b 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Namespace do
diff --git a/spec/models/network/graph_spec.rb b/spec/models/network/graph_spec.rb
index c364dd6643b..d1a2bedf542 100644
--- a/spec/models/network/graph_spec.rb
+++ b/spec/models/network/graph_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Network::Graph do
diff --git a/spec/models/note_diff_file_spec.rb b/spec/models/note_diff_file_spec.rb
index 591c1a89748..99eeac8d778 100644
--- a/spec/models/note_diff_file_spec.rb
+++ b/spec/models/note_diff_file_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe NoteDiffFile do
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index eb6f6ff5faf..7a1ab20186a 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Note do
diff --git a/spec/models/notification_recipient_spec.rb b/spec/models/notification_recipient_spec.rb
index 13fe47799ed..3710f2be287 100644
--- a/spec/models/notification_recipient_spec.rb
+++ b/spec/models/notification_recipient_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe NotificationRecipient do
diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb
index c8ab564e3bc..85128456918 100644
--- a/spec/models/notification_setting_spec.rb
+++ b/spec/models/notification_setting_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe NotificationSetting do
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 4b85c5e8720..142ddebbbf8 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PagesDomain do
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index c82ab9c9e62..e0e1101ffc6 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PersonalAccessToken do
diff --git a/spec/models/programming_language_spec.rb b/spec/models/programming_language_spec.rb
index 99cd358f863..b327d360461 100644
--- a/spec/models/programming_language_spec.rb
+++ b/spec/models/programming_language_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProgrammingLanguage do
diff --git a/spec/models/project_authorization_spec.rb b/spec/models/project_authorization_spec.rb
index c289ee0859a..6f06fe4e55a 100644
--- a/spec/models/project_authorization_spec.rb
+++ b/spec/models/project_authorization_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectAuthorization do
diff --git a/spec/models/project_auto_devops_spec.rb b/spec/models/project_auto_devops_spec.rb
index 7ff64c76e37..8ad28ce68cc 100644
--- a/spec/models/project_auto_devops_spec.rb
+++ b/spec/models/project_auto_devops_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectAutoDevops do
diff --git a/spec/models/project_custom_attribute_spec.rb b/spec/models/project_custom_attribute_spec.rb
index 669de5506bc..80638676b49 100644
--- a/spec/models/project_custom_attribute_spec.rb
+++ b/spec/models/project_custom_attribute_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectCustomAttribute do
diff --git a/spec/models/project_deploy_token_spec.rb b/spec/models/project_deploy_token_spec.rb
index 9e2e40c2e8f..2a5fefc1ab0 100644
--- a/spec/models/project_deploy_token_spec.rb
+++ b/spec/models/project_deploy_token_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe ProjectDeployToken, type: :model do
diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb
index fee7d65c217..50c9d5968ac 100644
--- a/spec/models/project_feature_spec.rb
+++ b/spec/models/project_feature_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectFeature do
diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb
index 5bea21427d4..dad5506900b 100644
--- a/spec/models/project_group_link_spec.rb
+++ b/spec/models/project_group_link_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectGroupLink do
diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb
index e3b2d971419..472bf8f9713 100644
--- a/spec/models/project_import_state_spec.rb
+++ b/spec/models/project_import_state_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe ProjectImportState, type: :model do
diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb
index 689d4e505e5..330aab9f856 100644
--- a/spec/models/project_label_spec.rb
+++ b/spec/models/project_label_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectLabel do
diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb
index e66109fd98f..18e839bcc64 100644
--- a/spec/models/project_services/asana_service_spec.rb
+++ b/spec/models/project_services/asana_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe AsanaService do
diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb
index 5cb6d63659e..7742e33e901 100644
--- a/spec/models/project_services/assembla_service_spec.rb
+++ b/spec/models/project_services/assembla_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe AssemblaService do
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index b880d90d28f..08c510f09df 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BambooService, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb
index 43f7bcb1a19..6818db48fee 100644
--- a/spec/models/project_services/bugzilla_service_spec.rb
+++ b/spec/models/project_services/bugzilla_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BugzillaService do
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
index 1615a93a4ca..091d4d8f695 100644
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ b/spec/models/project_services/buildkite_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe BuildkiteService, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb
index ed8347edffd..bf4c52fc7ab 100644
--- a/spec/models/project_services/campfire_service_spec.rb
+++ b/spec/models/project_services/campfire_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CampfireService do
diff --git a/spec/models/project_services/chat_message/issue_message_spec.rb b/spec/models/project_services/chat_message/issue_message_spec.rb
index f7a35fdc88a..d3adc62c38e 100644
--- a/spec/models/project_services/chat_message/issue_message_spec.rb
+++ b/spec/models/project_services/chat_message/issue_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatMessage::IssueMessage do
diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb
index 7997b5bb6b9..b56eb19dd55 100644
--- a/spec/models/project_services/chat_message/merge_message_spec.rb
+++ b/spec/models/project_services/chat_message/merge_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatMessage::MergeMessage do
diff --git a/spec/models/project_services/chat_message/note_message_spec.rb b/spec/models/project_services/chat_message/note_message_spec.rb
index 5abbd7bec18..5e7987dc0f6 100644
--- a/spec/models/project_services/chat_message/note_message_spec.rb
+++ b/spec/models/project_services/chat_message/note_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatMessage::NoteMessage do
diff --git a/spec/models/project_services/chat_message/pipeline_message_spec.rb b/spec/models/project_services/chat_message/pipeline_message_spec.rb
index 0ff20400999..8f9fa310ad4 100644
--- a/spec/models/project_services/chat_message/pipeline_message_spec.rb
+++ b/spec/models/project_services/chat_message/pipeline_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatMessage::PipelineMessage do
diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb
index 973d6bdb2a0..a89645a3ea8 100644
--- a/spec/models/project_services/chat_message/push_message_spec.rb
+++ b/spec/models/project_services/chat_message/push_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatMessage::PushMessage do
diff --git a/spec/models/project_services/chat_message/wiki_page_message_spec.rb b/spec/models/project_services/chat_message/wiki_page_message_spec.rb
index 7efcba9bcfd..c3db516f253 100644
--- a/spec/models/project_services/chat_message/wiki_page_message_spec.rb
+++ b/spec/models/project_services/chat_message/wiki_page_message_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatMessage::WikiPageMessage do
diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb
index 46713df77da..6f4ddd223f6 100644
--- a/spec/models/project_services/chat_notification_service_spec.rb
+++ b/spec/models/project_services/chat_notification_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ChatNotificationService do
diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb
index 7e1b1a4f2af..f0e7551693d 100644
--- a/spec/models/project_services/custom_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe CustomIssueTrackerService do
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
index 26597d9b83c..22df19d943f 100644
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ b/spec/models/project_services/drone_ci_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe DroneCiService, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/project_services/emails_on_push_service_spec.rb b/spec/models/project_services/emails_on_push_service_spec.rb
index d9b7010e5e5..0a58eb367e3 100644
--- a/spec/models/project_services/emails_on_push_service_spec.rb
+++ b/spec/models/project_services/emails_on_push_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe EmailsOnPushService do
diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb
index 62fd97b038b..bdd8605436f 100644
--- a/spec/models/project_services/external_wiki_service_spec.rb
+++ b/spec/models/project_services/external_wiki_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ExternalWikiService do
diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb
index fabcb142858..c1ebe69ee66 100644
--- a/spec/models/project_services/flowdock_service_spec.rb
+++ b/spec/models/project_services/flowdock_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe FlowdockService do
diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
index 3237b660a16..11f96c03d46 100644
--- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe GitlabIssueTrackerService do
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
index cb9ca76fc3f..2e1f6964692 100644
--- a/spec/models/project_services/irker_service_spec.rb
+++ b/spec/models/project_services/irker_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'socket'
require 'json'
diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/project_services/issue_tracker_service_spec.rb
index e6a1752576b..2fc4d69c2db 100644
--- a/spec/models/project_services/issue_tracker_service_spec.rb
+++ b/spec/models/project_services/issue_tracker_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe IssueTrackerService do
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 5428fcb1271..4a7eee1fbf3 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe JiraService do
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 56e587262ef..7bf093b71e7 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe KubernetesService, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/project_services/mattermost_service_spec.rb b/spec/models/project_services/mattermost_service_spec.rb
index 10c62ca55a7..6261c70f266 100644
--- a/spec/models/project_services/mattermost_service_spec.rb
+++ b/spec/models/project_services/mattermost_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MattermostService do
diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
index 1983e0cc967..87e482059f2 100644
--- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb
+++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MattermostSlashCommandsService do
diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb
index 3351c6280b4..521d5265753 100644
--- a/spec/models/project_services/microsoft_teams_service_spec.rb
+++ b/spec/models/project_services/microsoft_teams_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe MicrosoftTeamsService do
diff --git a/spec/models/project_services/packagist_service_spec.rb b/spec/models/project_services/packagist_service_spec.rb
index 6acee311700..53f18a1bdd9 100644
--- a/spec/models/project_services/packagist_service_spec.rb
+++ b/spec/models/project_services/packagist_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PackagistService do
diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb
index 75ae2207910..ca17e7453b8 100644
--- a/spec/models/project_services/pipelines_email_service_spec.rb
+++ b/spec/models/project_services/pipelines_email_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PipelinesEmailService, :mailer do
diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb
index f7d2372eca2..de2c8790405 100644
--- a/spec/models/project_services/pivotaltracker_service_spec.rb
+++ b/spec/models/project_services/pivotaltracker_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PivotaltrackerService do
diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb
index 54b8c658ff6..d2a45f48705 100644
--- a/spec/models/project_services/pushover_service_spec.rb
+++ b/spec/models/project_services/pushover_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PushoverService do
diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb
index 2ac14eab5e1..ac570ac27e1 100644
--- a/spec/models/project_services/redmine_service_spec.rb
+++ b/spec/models/project_services/redmine_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe RedmineService do
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
index 13cf4d1915e..01f580c5d01 100644
--- a/spec/models/project_services/slack_service_spec.rb
+++ b/spec/models/project_services/slack_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SlackService do
diff --git a/spec/models/project_services/slack_slash_commands_service_spec.rb b/spec/models/project_services/slack_slash_commands_service_spec.rb
index 5c4bce90ace..8c57907d064 100644
--- a/spec/models/project_services/slack_slash_commands_service_spec.rb
+++ b/spec/models/project_services/slack_slash_commands_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SlackSlashCommandsService do
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 64b4efca43a..96dccae733b 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe TeamcityService, :use_clean_rails_memory_store_caching do
diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb
index 9524b526a46..bf9d892f66c 100644
--- a/spec/models/project_services/youtrack_service_spec.rb
+++ b/spec/models/project_services/youtrack_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe YoutrackService do
diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb
index 1b439bcfad1..e87b4f41f4d 100644
--- a/spec/models/project_snippet_spec.rb
+++ b/spec/models/project_snippet_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProjectSnippet do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 1ea54eeb4f7..2158d3cf3e6 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Project do
@@ -2710,7 +2712,7 @@ describe Project do
end
describe '#any_lfs_file_locks?', :request_store do
- set(:project) { create(:project) }
+ let!(:project) { create(:project) }
it 'returns false when there are no LFS file locks' do
expect(project.any_lfs_file_locks?).to be_falsey
@@ -3148,6 +3150,53 @@ describe Project do
expect(projects).to eq([public_project])
end
end
+
+ context 'with requested visibility levels' do
+ set(:internal_project) { create(:project, :internal, :repository) }
+ set(:private_project_2) { create(:project, :private) }
+
+ context 'with admin user' do
+ set(:admin) { create(:admin) }
+
+ it 'returns all projects' do
+ projects = described_class.all.public_or_visible_to_user(admin, [])
+
+ expect(projects).to match_array([public_project, private_project, private_project_2, internal_project])
+ end
+
+ it 'returns all public and private projects' do
+ projects = described_class.all.public_or_visible_to_user(admin, [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::PRIVATE])
+
+ expect(projects).to match_array([public_project, private_project, private_project_2])
+ end
+
+ it 'returns all private projects' do
+ projects = described_class.all.public_or_visible_to_user(admin, [Gitlab::VisibilityLevel::PRIVATE])
+
+ expect(projects).to match_array([private_project, private_project_2])
+ end
+ end
+
+ context 'with regular user' do
+ it 'returns authorized projects' do
+ projects = described_class.all.public_or_visible_to_user(user, [])
+
+ expect(projects).to match_array([public_project, private_project, internal_project])
+ end
+
+ it "returns user's public and private projects" do
+ projects = described_class.all.public_or_visible_to_user(user, [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::PRIVATE])
+
+ expect(projects).to match_array([public_project, private_project])
+ end
+
+ it 'returns one private project' do
+ projects = described_class.all.public_or_visible_to_user(user, [Gitlab::VisibilityLevel::PRIVATE])
+
+ expect(projects).to eq([private_project])
+ end
+ end
+ end
end
describe '.with_feature_available_for_user' do
@@ -3428,7 +3477,7 @@ describe Project do
end
it 'schedules HashedStorage::ProjectMigrateWorker with delayed start when the project repo is in use' do
- Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: false)).increase
+ Gitlab::ReferenceCounter.new(Gitlab::GlRepository::PROJECT.identifier_for_subject(project)).increase
expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_in)
@@ -3436,7 +3485,7 @@ describe Project do
end
it 'schedules HashedStorage::ProjectMigrateWorker with delayed start when the wiki repo is in use' do
- Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: true)).increase
+ Gitlab::ReferenceCounter.new(Gitlab::GlRepository::WIKI.identifier_for_subject(project)).increase
expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_in)
@@ -3569,16 +3618,6 @@ describe Project do
end
end
- describe '#gl_repository' do
- let(:project) { create(:project) }
-
- it 'delegates to Gitlab::GlRepository.gl_repository' do
- expect(Gitlab::GlRepository).to receive(:gl_repository).with(project, true)
-
- project.gl_repository(is_wiki: true)
- end
- end
-
describe '#has_ci?' do
set(:project) { create(:project) }
let(:repository) { double }
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index 64c39f09e33..c670b6aac56 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe ProjectStatistics do
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index 3537dead5d1..a2d4fad9292 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe ProjectTeam do
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 7be8d67ba9e..7ea67f31534 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -1,4 +1,6 @@
# coding: utf-8
+# frozen_string_literal: true
+
require "spec_helper"
describe ProjectWiki do
diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb
index d4433a88a15..aca3df9fdde 100644
--- a/spec/models/protectable_dropdown_spec.rb
+++ b/spec/models/protectable_dropdown_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProtectableDropdown do
diff --git a/spec/models/protected_branch/merge_access_level_spec.rb b/spec/models/protected_branch/merge_access_level_spec.rb
index 612e4a0e332..39dd586b157 100644
--- a/spec/models/protected_branch/merge_access_level_spec.rb
+++ b/spec/models/protected_branch/merge_access_level_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProtectedBranch::MergeAccessLevel do
diff --git a/spec/models/protected_branch/push_access_level_spec.rb b/spec/models/protected_branch/push_access_level_spec.rb
index 9ccdc22fd41..628c8d29ecd 100644
--- a/spec/models/protected_branch/push_access_level_spec.rb
+++ b/spec/models/protected_branch/push_access_level_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProtectedBranch::PushAccessLevel do
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index dafe7646366..267434a4148 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProtectedBranch do
diff --git a/spec/models/protected_tag_spec.rb b/spec/models/protected_tag_spec.rb
index e5a0f6ec23f..79120d17d39 100644
--- a/spec/models/protected_tag_spec.rb
+++ b/spec/models/protected_tag_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe ProtectedTag do
diff --git a/spec/models/push_event_payload_spec.rb b/spec/models/push_event_payload_spec.rb
index 69a4922b6fd..6b59ee5ee57 100644
--- a/spec/models/push_event_payload_spec.rb
+++ b/spec/models/push_event_payload_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PushEventPayload do
diff --git a/spec/models/push_event_spec.rb b/spec/models/push_event_spec.rb
index bfe7a30b96a..f86500f91cd 100644
--- a/spec/models/push_event_spec.rb
+++ b/spec/models/push_event_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PushEvent do
diff --git a/spec/models/redirect_route_spec.rb b/spec/models/redirect_route_spec.rb
index 106ae59af29..6ecb5c31c7e 100644
--- a/spec/models/redirect_route_spec.rb
+++ b/spec/models/redirect_route_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe RedirectRoute do
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 157c96c1f65..b4b32c95dee 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe Release do
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index c06e9a08ab4..0478094034a 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe RemoteMirror, :mailer do
diff --git a/spec/models/repository_language_spec.rb b/spec/models/repository_language_spec.rb
index e2e4beb512f..13a4cd1e7cf 100644
--- a/spec/models/repository_language_spec.rb
+++ b/spec/models/repository_language_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe RepositoryLanguage do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 6599b4e765a..2578208659a 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Repository do
diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb
index 48799781b87..20289afbeb5 100644
--- a/spec/models/route_spec.rb
+++ b/spec/models/route_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Route do
diff --git a/spec/models/sent_notification_spec.rb b/spec/models/sent_notification_spec.rb
index 6c35ed8f649..09be90b82ed 100644
--- a/spec/models/sent_notification_spec.rb
+++ b/spec/models/sent_notification_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SentNotification do
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 25eecb3f909..2f025038bab 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Service do
diff --git a/spec/models/snippet_blob_spec.rb b/spec/models/snippet_blob_spec.rb
index 7c71c458fcc..88441e39d45 100644
--- a/spec/models/snippet_blob_spec.rb
+++ b/spec/models/snippet_blob_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SnippetBlob do
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 664dc3fa145..3524cdae3b8 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Snippet do
diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb
index 90a2caaeb88..e9ea234f75d 100644
--- a/spec/models/spam_log_spec.rb
+++ b/spec/models/spam_log_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SpamLog do
diff --git a/spec/models/ssh_host_key_spec.rb b/spec/models/ssh_host_key_spec.rb
index 4c677569561..a17cd8ba345 100644
--- a/spec/models/ssh_host_key_spec.rb
+++ b/spec/models/ssh_host_key_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SshHostKey do
diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb
index 9e4c2620d82..41bd48810b2 100644
--- a/spec/models/subscription_spec.rb
+++ b/spec/models/subscription_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Subscription do
diff --git a/spec/models/system_note_metadata_spec.rb b/spec/models/system_note_metadata_spec.rb
index 1e3f587e460..bcd3c03f947 100644
--- a/spec/models/system_note_metadata_spec.rb
+++ b/spec/models/system_note_metadata_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe SystemNoteMetadata do
diff --git a/spec/models/term_agreement_spec.rb b/spec/models/term_agreement_spec.rb
index 950dfa09a6a..42a48048b67 100644
--- a/spec/models/term_agreement_spec.rb
+++ b/spec/models/term_agreement_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe TermAgreement do
diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb
index a0c93c531ea..9d69a0ab148 100644
--- a/spec/models/timelog_spec.rb
+++ b/spec/models/timelog_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
RSpec.describe Timelog do
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index 3682e21ca40..b5bf294790a 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Todo do
diff --git a/spec/models/tree_spec.rb b/spec/models/tree_spec.rb
index 6bdb62a0864..c2d5dfdf9c4 100644
--- a/spec/models/tree_spec.rb
+++ b/spec/models/tree_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Tree do
diff --git a/spec/models/trending_project_spec.rb b/spec/models/trending_project_spec.rb
index 3b5e7ca0d39..619fc8e7d38 100644
--- a/spec/models/trending_project_spec.rb
+++ b/spec/models/trending_project_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe TrendingProject do
diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb
index 5a0df9fbbb0..02702cb2497 100644
--- a/spec/models/upload_spec.rb
+++ b/spec/models/upload_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe Upload do
diff --git a/spec/models/user_agent_detail_spec.rb b/spec/models/user_agent_detail_spec.rb
index b4669f8c1c2..f191d245045 100644
--- a/spec/models/user_agent_detail_spec.rb
+++ b/spec/models/user_agent_detail_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe UserAgentDetail do
diff --git a/spec/models/user_callout_spec.rb b/spec/models/user_callout_spec.rb
index d54355afe12..b87f6f03d6f 100644
--- a/spec/models/user_callout_spec.rb
+++ b/spec/models/user_callout_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe UserCallout do
diff --git a/spec/models/user_custom_attribute_spec.rb b/spec/models/user_custom_attribute_spec.rb
index 37fc3cb64f0..d0981b2d771 100644
--- a/spec/models/user_custom_attribute_spec.rb
+++ b/spec/models/user_custom_attribute_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe UserCustomAttribute do
diff --git a/spec/models/user_interacted_project_spec.rb b/spec/models/user_interacted_project_spec.rb
index cb4bb3372d4..47d919c1d12 100644
--- a/spec/models/user_interacted_project_spec.rb
+++ b/spec/models/user_interacted_project_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe UserInteractedProject do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 1be29d039a7..b7e36748fa2 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe User do
diff --git a/spec/models/wiki_directory_spec.rb b/spec/models/wiki_directory_spec.rb
index fb8575cfe2b..5fbcccf897e 100644
--- a/spec/models/wiki_directory_spec.rb
+++ b/spec/models/wiki_directory_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
RSpec.describe WikiDirectory do
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index cba22b2cc4e..e68da67818a 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe WikiPage do
diff --git a/spec/policies/board_policy_spec.rb b/spec/policies/board_policy_spec.rb
index 4b76d65ef69..52c23951e37 100644
--- a/spec/policies/board_policy_spec.rb
+++ b/spec/policies/board_policy_spec.rb
@@ -17,14 +17,6 @@ describe BoardPolicy do
]
end
- def expect_allowed(*permissions)
- permissions.each { |p| is_expected.to be_allowed(p) }
- end
-
- def expect_disallowed(*permissions)
- permissions.each { |p| is_expected.not_to be_allowed(p) }
- end
-
context 'group board' do
subject { described_class.new(user, group_board) }
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 92bdaa8b8b8..dc98baca6dc 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -1,63 +1,7 @@
require 'spec_helper'
describe GroupPolicy do
- let(:guest) { create(:user) }
- let(:reporter) { create(:user) }
- let(:developer) { create(:user) }
- let(:maintainer) { create(:user) }
- let(:owner) { create(:user) }
- let(:admin) { create(:admin) }
- let(:group) { create(:group, :private) }
-
- let(:guest_permissions) do
- [:read_label, :read_group, :upload_file, :read_namespace, :read_group_activity,
- :read_group_issues, :read_group_boards, :read_group_labels, :read_group_milestones,
- :read_group_merge_requests]
- end
-
- let(:reporter_permissions) { [:admin_label] }
-
- let(:developer_permissions) { [:admin_milestone] }
-
- let(:maintainer_permissions) do
- [
- :create_projects,
- :read_cluster,
- :create_cluster,
- :update_cluster,
- :admin_cluster,
- :add_cluster
- ]
- end
-
- let(:owner_permissions) do
- [
- :admin_group,
- :admin_namespace,
- :admin_group_member,
- :change_visibility_level,
- :set_note_created_at,
- (Gitlab::Database.postgresql? ? :create_subgroup : nil)
- ].compact
- end
-
- before do
- group.add_guest(guest)
- group.add_reporter(reporter)
- group.add_developer(developer)
- group.add_maintainer(maintainer)
- group.add_owner(owner)
- end
-
- subject { described_class.new(current_user, group) }
-
- def expect_allowed(*permissions)
- permissions.each { |p| is_expected.to be_allowed(p) }
- end
-
- def expect_disallowed(*permissions)
- permissions.each { |p| is_expected.not_to be_allowed(p) }
- end
+ include_context 'GroupPolicy context'
context 'with no user' do
let(:group) { create(:group, :public) }
diff --git a/spec/policies/namespace_policy_spec.rb b/spec/policies/namespace_policy_spec.rb
index 1fdf95ad716..99fa8b1fe44 100644
--- a/spec/policies/namespace_policy_spec.rb
+++ b/spec/policies/namespace_policy_spec.rb
@@ -30,7 +30,7 @@ describe NamespacePolicy do
context 'user who has exceeded project limit' do
let(:owner) { create(:user, projects_limit: 0) }
- it { is_expected.not_to be_allowed(:create_projects) }
+ it { is_expected.to be_disallowed(:create_projects) }
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 772d1fbee2b..726ccba8807 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -1,96 +1,7 @@
require 'spec_helper'
describe ProjectPolicy do
- set(:guest) { create(:user) }
- set(:reporter) { create(:user) }
- set(:developer) { create(:user) }
- set(:maintainer) { create(:user) }
- set(:owner) { create(:user) }
- set(:admin) { create(:admin) }
- let(:project) { create(:project, :public, namespace: owner.namespace) }
-
- let(:base_guest_permissions) do
- %i[
- read_project read_board read_list read_wiki read_issue
- read_project_for_iids read_issue_iid read_label
- read_milestone read_project_snippet read_project_member read_note
- create_project create_issue create_note upload_file create_merge_request_in
- award_emoji read_release
- ]
- end
-
- let(:base_reporter_permissions) do
- %i[
- download_code fork_project create_project_snippet update_issue
- admin_issue admin_label admin_list read_commit_status read_build
- read_container_image read_pipeline read_environment read_deployment
- read_merge_request download_wiki_code read_sentry_issue
- ]
- end
-
- let(:team_member_reporter_permissions) do
- %i[build_download_code build_read_container_image]
- end
-
- let(:developer_permissions) do
- %i[
- admin_milestone admin_merge_request update_merge_request create_commit_status
- update_commit_status create_build update_build create_pipeline
- update_pipeline create_merge_request_from create_wiki push_code
- resolve_note create_container_image update_container_image
- create_environment create_deployment create_release update_release
- ]
- end
-
- let(:base_maintainer_permissions) do
- %i[
- push_to_delete_protected_branch update_project_snippet update_environment
- update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
- admin_commit_status admin_build admin_container_image
- admin_pipeline admin_environment admin_deployment destroy_release add_cluster
- daily_statistics
- ]
- end
-
- let(:public_permissions) do
- %i[
- download_code fork_project read_commit_status read_pipeline
- read_container_image build_download_code build_read_container_image
- download_wiki_code read_release
- ]
- end
-
- let(:owner_permissions) do
- %i[
- change_namespace change_visibility_level rename_project remove_project
- archive_project remove_fork_project destroy_merge_request destroy_issue
- set_issue_iid set_issue_created_at set_note_created_at
- ]
- end
-
- # Used in EE specs
- let(:additional_guest_permissions) { [] }
- let(:additional_reporter_permissions) { [] }
- let(:additional_maintainer_permissions) { [] }
-
- let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
- let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
- let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
-
- before do
- project.add_guest(guest)
- project.add_maintainer(maintainer)
- project.add_developer(developer)
- project.add_reporter(reporter)
- end
-
- def expect_allowed(*permissions)
- permissions.each { |p| is_expected.to be_allowed(p) }
- end
-
- def expect_disallowed(*permissions)
- permissions.each { |p| is_expected.not_to be_allowed(p) }
- end
+ include_context 'ProjectPolicy context'
it 'does not include the read_issue permission when the issue author is not a member of the private project' do
project = create(:project, :private)
@@ -140,7 +51,7 @@ describe ProjectPolicy do
end
it 'disables boards and lists permissions' do
- expect_disallowed :read_board, :create_board, :update_board, :admin_board
+ expect_disallowed :read_board, :create_board, :update_board
expect_disallowed :read_list, :create_list, :update_list, :admin_list
end
@@ -237,237 +148,6 @@ describe ProjectPolicy do
end
end
- shared_examples 'archived project policies' do
- let(:feature_write_abilities) do
- described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature|
- described_class.create_update_admin_destroy(feature)
- end
- end
-
- let(:other_write_abilities) do
- %i[
- create_merge_request_in
- create_merge_request_from
- push_to_delete_protected_branch
- push_code
- request_access
- upload_file
- resolve_note
- award_emoji
- ]
- end
-
- context 'when the project is archived' do
- before do
- project.archived = true
- end
-
- it 'disables write actions on all relevant project features' do
- expect_disallowed(*feature_write_abilities)
- end
-
- it 'disables some other important write actions' do
- expect_disallowed(*other_write_abilities)
- end
-
- it 'does not disable other abilities' do
- expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities))
- end
- end
- end
-
- shared_examples 'project policies as anonymous' do
- context 'abilities for public projects' do
- context 'when a project has pending invites' do
- let(:group) { create(:group, :public) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] }
- let(:anonymous_permissions) { guest_permissions - user_permissions }
-
- subject { described_class.new(nil, project) }
-
- before do
- create(:group_member, :invited, group: group)
- end
-
- it 'does not grant owner access' do
- expect_allowed(*anonymous_permissions)
- expect_disallowed(*user_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { anonymous_permissions }
- end
- end
- end
-
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(nil, project) }
-
- it { is_expected.to be_banned }
- end
- end
-
- shared_examples 'project policies as guest' do
- subject { described_class.new(guest, project) }
-
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
- let(:reporter_public_build_permissions) do
- reporter_permissions - [:read_build, :read_pipeline]
- end
-
- it do
- expect_allowed(*guest_permissions)
- expect_disallowed(*reporter_public_build_permissions)
- expect_disallowed(*team_member_reporter_permissions)
- expect_disallowed(*developer_permissions)
- expect_disallowed(*maintainer_permissions)
- expect_disallowed(*owner_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { guest_permissions }
- end
-
- context 'public builds enabled' do
- it do
- expect_allowed(*guest_permissions)
- expect_allowed(:read_build, :read_pipeline)
- end
- end
-
- context 'when public builds disabled' do
- before do
- project.update(public_builds: false)
- end
-
- it do
- expect_allowed(*guest_permissions)
- expect_disallowed(:read_build, :read_pipeline)
- end
- end
-
- context 'when builds are disabled' do
- before do
- project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
- end
-
- it do
- expect_disallowed(:read_build)
- expect_allowed(:read_pipeline)
- end
- end
- end
- end
-
- shared_examples 'project policies as reporter' do
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(reporter, project) }
-
- it do
- expect_allowed(*guest_permissions)
- expect_allowed(*reporter_permissions)
- expect_allowed(*team_member_reporter_permissions)
- expect_disallowed(*developer_permissions)
- expect_disallowed(*maintainer_permissions)
- expect_disallowed(*owner_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { reporter_permissions }
- end
- end
- end
-
- shared_examples 'project policies as developer' do
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(developer, project) }
-
- it do
- expect_allowed(*guest_permissions)
- expect_allowed(*reporter_permissions)
- expect_allowed(*team_member_reporter_permissions)
- expect_allowed(*developer_permissions)
- expect_disallowed(*maintainer_permissions)
- expect_disallowed(*owner_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { developer_permissions }
- end
- end
- end
-
- shared_examples 'project policies as maintainer' do
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(maintainer, project) }
-
- it do
- expect_allowed(*guest_permissions)
- expect_allowed(*reporter_permissions)
- expect_allowed(*team_member_reporter_permissions)
- expect_allowed(*developer_permissions)
- expect_allowed(*maintainer_permissions)
- expect_disallowed(*owner_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { maintainer_permissions }
- end
- end
- end
-
- shared_examples 'project policies as owner' do
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(owner, project) }
-
- it do
- expect_allowed(*guest_permissions)
- expect_allowed(*reporter_permissions)
- expect_allowed(*team_member_reporter_permissions)
- expect_allowed(*developer_permissions)
- expect_allowed(*maintainer_permissions)
- expect_allowed(*owner_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { owner_permissions }
- end
- end
- end
-
- shared_examples 'project policies as admin' do
- context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(admin, project) }
-
- it do
- expect_allowed(*guest_permissions)
- expect_allowed(*reporter_permissions)
- expect_disallowed(*team_member_reporter_permissions)
- expect_allowed(*developer_permissions)
- expect_allowed(*maintainer_permissions)
- expect_allowed(*owner_permissions)
- end
-
- it_behaves_like 'archived project policies' do
- let(:regular_abilities) { owner_permissions }
- end
- end
- end
-
it_behaves_like 'project policies as anonymous'
it_behaves_like 'project policies as guest'
it_behaves_like 'project policies as reporter'
diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb
index d6329e84579..2e9ef1e89fd 100644
--- a/spec/policies/project_snippet_policy_spec.rb
+++ b/spec/policies/project_snippet_policy_spec.rb
@@ -5,7 +5,7 @@ describe ProjectSnippetPolicy do
let(:regular_user) { create(:user) }
let(:external_user) { create(:user, :external) }
let(:project) { create(:project, :public) }
-
+ let(:snippet) { create(:project_snippet, snippet_visibility, project: project) }
let(:author_permissions) do
[
:update_project_snippet,
@@ -13,23 +13,13 @@ describe ProjectSnippetPolicy do
]
end
- def abilities(user, snippet_visibility)
- snippet = create(:project_snippet, snippet_visibility, project: project)
-
- described_class.new(user, snippet)
- end
-
- def expect_allowed(*permissions)
- permissions.each { |p| is_expected.to be_allowed(p) }
- end
-
- def expect_disallowed(*permissions)
- permissions.each { |p| is_expected.not_to be_allowed(p) }
- end
+ subject { described_class.new(current_user, snippet) }
context 'public snippet' do
+ let(:snippet_visibility) { :public }
+
context 'no user' do
- subject { abilities(nil, :public) }
+ let(:current_user) { nil }
it do
expect_allowed(:read_project_snippet)
@@ -38,7 +28,7 @@ describe ProjectSnippetPolicy do
end
context 'regular user' do
- subject { abilities(regular_user, :public) }
+ let(:current_user) { regular_user }
it do
expect_allowed(:read_project_snippet, :create_note)
@@ -47,7 +37,7 @@ describe ProjectSnippetPolicy do
end
context 'external user' do
- subject { abilities(external_user, :public) }
+ let(:current_user) { external_user }
it do
expect_allowed(:read_project_snippet, :create_note)
@@ -57,8 +47,10 @@ describe ProjectSnippetPolicy do
end
context 'internal snippet' do
+ let(:snippet_visibility) { :internal }
+
context 'no user' do
- subject { abilities(nil, :internal) }
+ let(:current_user) { nil }
it do
expect_disallowed(:read_project_snippet)
@@ -67,7 +59,7 @@ describe ProjectSnippetPolicy do
end
context 'regular user' do
- subject { abilities(regular_user, :internal) }
+ let(:current_user) { regular_user }
it do
expect_allowed(:read_project_snippet, :create_note)
@@ -76,31 +68,31 @@ describe ProjectSnippetPolicy do
end
context 'external user' do
- subject { abilities(external_user, :internal) }
+ let(:current_user) { external_user }
it do
expect_disallowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
- end
- context 'project team member external user' do
- subject { abilities(external_user, :internal) }
-
- before do
- project.add_developer(external_user)
- end
+ context 'project team member' do
+ before do
+ project.add_developer(external_user)
+ end
- it do
- expect_allowed(:read_project_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ it do
+ expect_allowed(:read_project_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
end
end
end
context 'private snippet' do
+ let(:snippet_visibility) { :private }
+
context 'no user' do
- subject { abilities(nil, :private) }
+ let(:current_user) { nil }
it do
expect_disallowed(:read_project_snippet)
@@ -109,53 +101,52 @@ describe ProjectSnippetPolicy do
end
context 'regular user' do
- subject { abilities(regular_user, :private) }
+ let(:current_user) { regular_user }
it do
expect_disallowed(:read_project_snippet, :create_note)
expect_disallowed(*author_permissions)
end
- end
-
- context 'snippet author' do
- let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) }
- subject { described_class.new(regular_user, snippet) }
+ context 'snippet author' do
+ let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) }
- it do
- expect_allowed(:read_project_snippet, :create_note)
- expect_allowed(*author_permissions)
+ it do
+ expect_allowed(:read_project_snippet, :create_note)
+ expect_allowed(*author_permissions)
+ end
end
- end
- context 'project team member normal user' do
- subject { abilities(regular_user, :private) }
-
- before do
- project.add_developer(regular_user)
- end
+ context 'project team member normal user' do
+ before do
+ project.add_developer(regular_user)
+ end
- it do
- expect_allowed(:read_project_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ it do
+ expect_allowed(:read_project_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
end
end
- context 'project team member external user' do
- subject { abilities(external_user, :private) }
+ context 'external user' do
+ context 'project team member' do
+ let(:current_user) { external_user }
- before do
- project.add_developer(external_user)
- end
+ before do
+ project.add_developer(external_user)
+ end
- it do
- expect_allowed(:read_project_snippet, :create_note)
- expect_disallowed(*author_permissions)
+ it do
+ expect_allowed(:read_project_snippet, :create_note)
+ expect_disallowed(*author_permissions)
+ end
end
end
context 'admin user' do
- subject { abilities(create(:admin), :private) }
+ let(:snippet_visibility) { :private }
+ let(:current_user) { create(:admin) }
it do
expect_allowed(:read_project_snippet, :create_note)
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index f50bcf54b46..ad6cb012d0b 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -136,6 +136,24 @@ describe Ci::BuildRunnerPresenter do
is_expected.to eq(1)
end
end
+
+ context 'when pipeline is detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
+ let(:pipeline) { merge_request.all_pipelines.first }
+ let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) }
+
+ it 'returns the default git depth for pipelines for merge requests' do
+ is_expected.to eq(described_class::DEFAULT_GIT_DEPTH_MERGE_REQUEST)
+ end
+
+ context 'when pipeline is legacy detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) }
+
+ it 'behaves as branch pipeline' do
+ is_expected.to eq(0)
+ end
+ end
+ end
end
describe '#refspecs' do
@@ -165,5 +183,25 @@ describe Ci::BuildRunnerPresenter do
end
end
end
+
+ context 'when pipeline is detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
+ let(:pipeline) { merge_request.all_pipelines.first }
+ let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) }
+
+ it 'returns the correct refspecs' do
+ is_expected
+ .to contain_exactly('+refs/merge-requests/1/head:refs/merge-requests/1/head')
+ end
+
+ context 'when pipeline is legacy detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) }
+
+ it 'returns the correct refspecs' do
+ is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
+ '+refs/heads/*:refs/remotes/origin/*')
+ end
+ end
+ end
end
end
diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb
index 754ba0a594c..a9d786bc872 100644
--- a/spec/presenters/clusters/cluster_presenter_spec.rb
+++ b/spec/presenters/clusters/cluster_presenter_spec.rb
@@ -228,4 +228,20 @@ describe Clusters::ClusterPresenter do
it { is_expected.to eq(group_cluster_path(group, cluster)) }
end
end
+
+ describe '#read_only_kubernetes_platform_fields?' do
+ subject { described_class.new(cluster).read_only_kubernetes_platform_fields? }
+
+ context 'with a user-provided cluster' do
+ let(:cluster) { build_stubbed(:cluster, :provided_by_user) }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'with a GCP-provided cluster' do
+ let(:cluster) { build_stubbed(:cluster, :provided_by_gcp) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index b38cd66986f..8b503777443 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -20,9 +20,9 @@ describe API::Branches do
let(:route) { "/projects/#{project_id}/repository/branches" }
shared_examples_for 'repository branches' do
- RSpec::Matchers.define :has_merged_branch_names_count do |expected|
+ RSpec::Matchers.define :has_up_to_merged_branch_names_count do |expected|
match do |actual|
- actual[:merged_branch_names].count == expected
+ expected >= actual[:merged_branch_names].count
end
end
@@ -36,10 +36,30 @@ describe API::Branches do
expect(branch_names).to match_array(project.repository.branch_names)
end
+ def check_merge_status(json_response)
+ merged, unmerged = json_response.partition { |branch| branch['merged'] }
+ merged_branches = merged.map { |branch| branch['name'] }
+ unmerged_branches = unmerged.map { |branch| branch['name'] }
+ expect(Set.new(merged_branches)).to eq(project.repository.merged_branch_names(merged_branches + unmerged_branches))
+ expect(project.repository.merged_branch_names(unmerged_branches)).to be_empty
+ end
+
it 'determines only a limited number of merged branch names' do
- expect(API::Entities::Branch).to receive(:represent).with(anything, has_merged_branch_names_count(2))
+ expect(API::Entities::Branch).to receive(:represent).with(anything, has_up_to_merged_branch_names_count(2)).and_call_original
get api(route, current_user), params: { per_page: 2 }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ check_merge_status(json_response)
+ end
+
+ it 'merge status matches reality on paginated input' do
+ get api(route, current_user), params: { per_page: 20, page: 2 }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ check_merge_status(json_response)
end
context 'when repository is disabled' do
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index b184c92824a..537194b8e11 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -321,7 +321,7 @@ describe API::Internal do
end
context 'with env passed as a JSON' do
- let(:gl_repository) { project.gl_repository(is_wiki: true) }
+ let(:gl_repository) { Gitlab::GlRepository::WIKI.identifier_for_subject(project) }
it 'sets env in RequestStore' do
obj_dir_relative = './objects'
@@ -975,9 +975,9 @@ describe API::Internal do
def gl_repository_for(project_or_wiki)
case project_or_wiki
when ProjectWiki
- project_or_wiki.project.gl_repository(is_wiki: true)
+ Gitlab::GlRepository::WIKI.identifier_for_subject(project_or_wiki.project)
when Project
- project_or_wiki.gl_repository(is_wiki: false)
+ Gitlab::GlRepository::PROJECT.identifier_for_subject(project_or_wiki)
else
nil
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 60d9d7fed13..4c3c088b307 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1183,6 +1183,16 @@ describe API::Projects do
expect(response).to have_gitlab_http_status(200)
expect(json_response).to include 'statistics'
end
+
+ it "includes statistics also when repository is disabled" do
+ project.add_developer(user)
+ project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
+
+ get api("/projects/#{project.id}", user), params: { statistics: true }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to include 'statistics'
+ end
end
it "includes import_error if user can admin project" do
diff --git a/spec/requests/api/suggestions_spec.rb b/spec/requests/api/suggestions_spec.rb
index 3c2842e5725..5b07e598b8d 100644
--- a/spec/requests/api/suggestions_spec.rb
+++ b/spec/requests/api/suggestions_spec.rb
@@ -42,8 +42,7 @@ describe API::Suggestions do
expect(response).to have_gitlab_http_status(200)
expect(json_response)
- .to include('id', 'from_original_line', 'to_original_line',
- 'from_line', 'to_line', 'appliable', 'applied',
+ .to include('id', 'from_line', 'to_line', 'appliable', 'applied',
'from_content', 'to_content')
end
end
diff --git a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
index 1c8ab0ad5d2..cba01400d85 100644
--- a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
+++ b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
@@ -93,4 +93,22 @@ describe RuboCop::Cop::Migration::UpdateColumnInBatches do
it_behaves_like 'a migration file with no spec file'
it_behaves_like 'a migration file with a spec file'
end
+
+ context 'EE migrations' do
+ let(:spec_filepath) { tmp_rails_root.join('ee', 'spec', 'migrations', 'my_super_migration_spec.rb') }
+
+ context 'in a migration' do
+ let(:migration_filepath) { tmp_rails_root.join('ee', 'db', 'migrate', '20121220064453_my_super_migration.rb') }
+
+ it_behaves_like 'a migration file with no spec file'
+ it_behaves_like 'a migration file with a spec file'
+ end
+
+ context 'in a post migration' do
+ let(:migration_filepath) { tmp_rails_root.join('ee', 'db', 'post_migrate', '20121220064453_my_super_migration.rb') }
+
+ it_behaves_like 'a migration file with no spec file'
+ it_behaves_like 'a migration file with a spec file'
+ end
+ end
end
diff --git a/spec/serializers/suggestion_entity_spec.rb b/spec/serializers/suggestion_entity_spec.rb
index 047571f161c..d38fc2b132b 100644
--- a/spec/serializers/suggestion_entity_spec.rb
+++ b/spec/serializers/suggestion_entity_spec.rb
@@ -13,8 +13,8 @@ describe SuggestionEntity do
subject { entity.as_json }
it 'exposes correct attributes' do
- expect(subject).to include(:id, :from_original_line, :to_original_line, :from_line,
- :to_line, :appliable, :applied, :from_content, :to_content)
+ expect(subject).to include(:id, :from_line, :to_line, :appliable,
+ :applied, :from_content, :to_content)
end
it 'exposes current user abilities' do
diff --git a/spec/services/error_tracking/list_issues_service_spec.rb b/spec/services/error_tracking/list_issues_service_spec.rb
index 9d4fc62f923..3a8f3069911 100644
--- a/spec/services/error_tracking/list_issues_service_spec.rb
+++ b/spec/services/error_tracking/list_issues_service_spec.rb
@@ -53,7 +53,10 @@ describe ErrorTracking::ListIssuesService do
before do
allow(error_tracking_setting)
.to receive(:list_sentry_issues)
- .and_return(error: 'Sentry response status code: 401')
+ .and_return(
+ error: 'Sentry response status code: 401',
+ error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE
+ )
end
it 'returns the error' do
@@ -64,6 +67,25 @@ describe ErrorTracking::ListIssuesService do
)
end
end
+
+ context 'when list_sentry_issues returns error with http_status' do
+ before do
+ allow(error_tracking_setting)
+ .to receive(:list_sentry_issues)
+ .and_return(
+ error: 'Sentry API response is missing keys. key not found: "id"',
+ error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS
+ )
+ end
+
+ it 'returns the error with correct http_status' do
+ expect(result).to eq(
+ status: :error,
+ http_status: :internal_server_error,
+ message: 'Sentry API response is missing keys. key not found: "id"'
+ )
+ end
+ end
end
context 'with unauthorized user' do
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 715b1168bfb..d50412b6d2c 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -138,6 +138,20 @@ describe Issues::CreateService do
end
end
+ context 'when duplicate label titles are given' do
+ let(:label) { create(:label, project: project) }
+
+ let(:opts) do
+ { title: 'Title',
+ description: 'Description',
+ labels: [label.title, label.title] }
+ end
+
+ it 'assigns the label once' do
+ expect(issue.labels).to contain_exactly(label)
+ end
+ end
+
it 'executes issue hooks when issue is not confidential' do
opts = { title: 'Title', description: 'Description', confidential: false }
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index f1684209729..1c8a4b608d5 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -592,6 +592,16 @@ describe Issues::UpdateService, :mailer do
expect(result.label_ids).not_to include(label.id)
end
end
+
+ context 'when duplicate label titles are given' do
+ let(:params) do
+ { labels: [label3.title, label3.title] }
+ end
+
+ it 'assigns the label once' do
+ expect(result.labels).to contain_exactly(label3)
+ end
+ end
end
context 'updating asssignee_id' do
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index a04a4d5fc36..55e7b46248b 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -173,7 +173,7 @@ describe MergeRequests::CreateService do
end
end
- describe 'Merge request pipelines' do
+ describe 'Pipelines for merge requests' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
@@ -189,12 +189,46 @@ describe MergeRequests::CreateService do
}
end
- it 'creates a merge request pipeline and sets it as a head pipeline' do
+ it 'creates a detached merge request pipeline and sets it as a head pipeline' do
expect(merge_request).to be_persisted
merge_request.reload
expect(merge_request.merge_request_pipelines.count).to eq(1)
- expect(merge_request.actual_head_pipeline).to be_merge_request_event
+ expect(merge_request.actual_head_pipeline).to be_detached_merge_request_pipeline
+ end
+
+ context 'when merge request is submitted from forked project' do
+ let(:target_project) { fork_project(project, nil, repository: true) }
+
+ let(:opts) do
+ {
+ title: 'Awesome merge_request',
+ source_branch: 'feature',
+ target_branch: 'master',
+ target_project_id: target_project.id
+ }
+ end
+
+ before do
+ target_project.add_developer(assignee)
+ target_project.add_maintainer(user)
+ end
+
+ it 'create legacy detached merge request pipeline for fork merge request' do
+ expect(merge_request.actual_head_pipeline)
+ .to be_legacy_detached_merge_request_pipeline
+ end
+ end
+
+ context 'when ci_use_merge_request_ref feature flag is false' do
+ before do
+ stub_feature_flags(ci_use_merge_request_ref: false)
+ end
+
+ it 'create legacy detached merge request pipeline for non-fork merge request' do
+ expect(merge_request.actual_head_pipeline)
+ .to be_legacy_detached_merge_request_pipeline
+ end
end
context 'when there are no commits between source branch and target branch' do
@@ -207,7 +241,7 @@ describe MergeRequests::CreateService do
}
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(merge_request).to be_persisted
merge_request.reload
@@ -225,7 +259,7 @@ describe MergeRequests::CreateService do
merge_request
end
- it 'sets the latest merge request pipeline as the head pipeline' do
+ it 'sets the latest detached merge request pipeline as the head pipeline' do
expect(merge_request.actual_head_pipeline).to be_merge_request_event
end
end
@@ -235,7 +269,7 @@ describe MergeRequests::CreateService do
stub_feature_flags(ci_merge_request_pipeline: false)
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(merge_request).to be_persisted
merge_request.reload
@@ -254,7 +288,7 @@ describe MergeRequests::CreateService do
}
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(merge_request).to be_persisted
merge_request.reload
diff --git a/spec/services/merge_requests/ff_merge_service_spec.rb b/spec/services/merge_requests/ff_merge_service_spec.rb
index fe673de46aa..1430e12a07e 100644
--- a/spec/services/merge_requests/ff_merge_service_spec.rb
+++ b/spec/services/merge_requests/ff_merge_service_spec.rb
@@ -72,7 +72,7 @@ describe MergeRequests::FfMergeService do
it 'logs and saves error if there is an PreReceiveError exception' do
error_message = 'error message'
- allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, error_message)
+ allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, "GitLab: #{error_message}")
allow(service).to receive(:execute_hooks)
service.execute(merge_request)
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index ede79b87bcc..887ec17171e 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -239,7 +239,7 @@ describe MergeRequests::MergeService do
it 'logs and saves error if there is an PreReceiveError exception' do
error_message = 'error message'
- allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, error_message)
+ allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, "GitLab: #{error_message}")
allow(service).to receive(:execute_hooks)
service.execute(merge_request)
diff --git a/spec/services/merge_requests/migrate_external_diffs_service_spec.rb b/spec/services/merge_requests/migrate_external_diffs_service_spec.rb
new file mode 100644
index 00000000000..40ac747e66f
--- /dev/null
+++ b/spec/services/merge_requests/migrate_external_diffs_service_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequests::MigrateExternalDiffsService do
+ let(:merge_request) { create(:merge_request) }
+ let(:diff) { merge_request.merge_request_diff }
+
+ describe '.enqueue!', :sidekiq do
+ around do |example|
+ Sidekiq::Testing.fake! { example.run }
+ end
+
+ it 'enqueues nothing if external diffs are disabled' do
+ expect(diff).not_to be_stored_externally
+
+ expect { described_class.enqueue! }
+ .not_to change { MigrateExternalDiffsWorker.jobs.count }
+ end
+
+ it 'enqueues eligible in-database diffs if external diffs are enabled' do
+ expect(diff).not_to be_stored_externally
+
+ stub_external_diffs_setting(enabled: true)
+
+ expect { described_class.enqueue! }
+ .to change { MigrateExternalDiffsWorker.jobs.count }
+ .by(1)
+ end
+ end
+
+ describe '#execute' do
+ it 'migrates an in-database diff to the external store' do
+ expect(diff).not_to be_stored_externally
+
+ stub_external_diffs_setting(enabled: true)
+
+ described_class.new(diff).execute
+
+ expect(diff).to be_stored_externally
+ end
+ end
+end
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 43ceb1dcbee..25cbac6d7ee 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -97,6 +97,15 @@ describe MergeRequests::RefreshService do
}
end
+ it 'outdates MR suggestions' do
+ expect_next_instance_of(Suggestions::OutdateService) do |service|
+ expect(service).to receive(:execute).with(@merge_request).and_call_original
+ expect(service).to receive(:execute).with(@another_merge_request).and_call_original
+ end
+
+ refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
+ end
+
context 'when source branch ref does not exists' do
before do
DeleteBranchService.new(@project, @user).execute(@merge_request.source_branch)
@@ -132,7 +141,7 @@ describe MergeRequests::RefreshService do
end
end
- describe 'Merge request pipelines' do
+ describe 'Pipelines for merge requests' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
@@ -150,7 +159,7 @@ describe MergeRequests::RefreshService do
}
end
- it 'create merge request pipeline with commits' do
+ it 'create detached merge request pipeline with commits' do
expect { subject }
.to change { @merge_request.merge_request_pipelines.count }.by(1)
.and change { @fork_merge_request.merge_request_pipelines.count }.by(1)
@@ -161,7 +170,34 @@ describe MergeRequests::RefreshService do
expect(@another_merge_request.has_commits?).to be_falsy
end
- context "when branch pipeline was created before a merge request pipline has been created" do
+ it 'create detached merge request pipeline for non-fork merge request' do
+ subject
+
+ expect(@merge_request.merge_request_pipelines.first)
+ .to be_detached_merge_request_pipeline
+ end
+
+ it 'create legacy detached merge request pipeline for fork merge request' do
+ subject
+
+ expect(@fork_merge_request.merge_request_pipelines.first)
+ .to be_legacy_detached_merge_request_pipeline
+ end
+
+ context 'when ci_use_merge_request_ref feature flag is false' do
+ before do
+ stub_feature_flags(ci_use_merge_request_ref: false)
+ end
+
+ it 'create legacy detached merge request pipeline for non-fork merge request' do
+ subject
+
+ expect(@merge_request.merge_request_pipelines.first)
+ .to be_legacy_detached_merge_request_pipeline
+ end
+ end
+
+ context "when branch pipeline was created before a detaced merge request pipeline has been created" do
before do
create(:ci_pipeline, project: @merge_request.source_project,
sha: @merge_request.diff_head_sha,
@@ -171,7 +207,7 @@ describe MergeRequests::RefreshService do
subject
end
- it 'sets the latest merge request pipeline as a head pipeline' do
+ it 'sets the latest detached merge request pipeline as a head pipeline' do
@merge_request.reload
expect(@merge_request.actual_head_pipeline).to be_merge_request_event
end
@@ -184,7 +220,7 @@ describe MergeRequests::RefreshService do
end
context "when MergeRequestUpdateWorker is retried by an exception" do
- it 'does not re-create a duplicate merge request pipeline' do
+ it 'does not re-create a duplicate detached merge request pipeline' do
expect do
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master')
end.to change { @merge_request.merge_request_pipelines.count }.by(1)
@@ -200,7 +236,7 @@ describe MergeRequests::RefreshService do
stub_feature_flags(ci_merge_request_pipeline: false)
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect { subject }
.not_to change { @merge_request.merge_request_pipelines.count }
end
@@ -217,7 +253,7 @@ describe MergeRequests::RefreshService do
}
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect { subject }
.not_to change { @merge_request.merge_request_pipelines.count }
end
@@ -329,14 +365,16 @@ describe MergeRequests::RefreshService do
context 'push to fork repo source branch' do
let(:refresh_service) { service.new(@fork_project, @user) }
- context 'open fork merge request' do
- before do
- allow(refresh_service).to receive(:execute_hooks)
- refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
- reload_mrs
- end
+ def refresh
+ allow(refresh_service).to receive(:execute_hooks)
+ refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
+ reload_mrs
+ end
+ context 'open fork merge request' do
it 'executes hooks with update action' do
+ refresh
+
expect(refresh_service).to have_received(:execute_hooks)
.with(@fork_merge_request, 'update', old_rev: @oldrev)
@@ -347,21 +385,30 @@ describe MergeRequests::RefreshService do
expect(@build_failed_todo).to be_pending
expect(@fork_build_failed_todo).to be_pending
end
+
+ it 'outdates opened forked MR suggestions' do
+ expect_next_instance_of(Suggestions::OutdateService) do |service|
+ expect(service).to receive(:execute).with(@fork_merge_request).and_call_original
+ end
+
+ refresh
+ end
end
context 'closed fork merge request' do
before do
@fork_merge_request.close!
- allow(refresh_service).to receive(:execute_hooks)
- refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
- reload_mrs
end
it 'do not execute hooks with update action' do
+ refresh
+
expect(refresh_service).not_to have_received(:execute_hooks)
end
it 'updates merge request to closed state' do
+ refresh
+
expect(@merge_request.notes).to be_empty
expect(@merge_request).to be_open
expect(@fork_merge_request.notes).to be_empty
diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb
index 6040f9100f8..4b6d0c51363 100644
--- a/spec/services/projects/participants_service_spec.rb
+++ b/spec/services/projects/participants_service_spec.rb
@@ -2,29 +2,56 @@ require 'spec_helper'
describe Projects::ParticipantsService do
describe '#groups' do
+ set(:user) { create(:user) }
+ set(:project) { create(:project, :public) }
+ let(:service) { described_class.new(project, user) }
+
+ it 'avoids N+1 queries' do
+ group_1 = create(:group)
+ group_1.add_owner(user)
+
+ service.groups # Run general application warmup queries
+ control_count = ActiveRecord::QueryRecorder.new { service.groups }.count
+
+ group_2 = create(:group)
+ group_2.add_owner(user)
+
+ expect { service.groups }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'returns correct user counts for groups' do
+ group_1 = create(:group)
+ group_1.add_owner(user)
+ group_1.add_owner(create(:user))
+
+ group_2 = create(:group)
+ group_2.add_owner(user)
+ create(:group_member, :access_request, group: group_2, user: create(:user))
+
+ expect(service.groups).to contain_exactly(
+ a_hash_including(name: group_1.full_name, count: 2),
+ a_hash_including(name: group_2.full_name, count: 1)
+ )
+ end
+
describe 'avatar_url' do
- let(:project) { create(:project, :public) }
let(:group) { create(:group, avatar: fixture_file_upload('spec/fixtures/dk.png')) }
- let(:user) { create(:user) }
- let!(:group_member) { create(:group_member, group: group, user: user) }
- it 'should return an url for the avatar' do
- participants = described_class.new(project, user)
- groups = participants.groups
+ before do
+ group.add_owner(user)
+ end
- expect(groups.size).to eq 1
- expect(groups.first[:avatar_url]).to eq("/uploads/-/system/group/avatar/#{group.id}/dk.png")
+ it 'should return an url for the avatar' do
+ expect(service.groups.size).to eq 1
+ expect(service.groups.first[:avatar_url]).to eq("/uploads/-/system/group/avatar/#{group.id}/dk.png")
end
it 'should return an url for the avatar with relative url' do
stub_config_setting(relative_url_root: '/gitlab')
stub_config_setting(url: Settings.send(:build_gitlab_url))
- participants = described_class.new(project, user)
- groups = participants.groups
-
- expect(groups.size).to eq 1
- expect(groups.first[:avatar_url]).to eq("/gitlab/uploads/-/system/group/avatar/#{group.id}/dk.png")
+ expect(service.groups.size).to eq 1
+ expect(service.groups.first[:avatar_url]).to eq("/gitlab/uploads/-/system/group/avatar/#{group.id}/dk.png")
end
end
end
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index ea33d156c8a..8b0f9c8ade2 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -15,6 +15,7 @@ describe QuickActions::InterpretService do
let(:service) { described_class.new(project, developer) }
before do
+ stub_licensed_features(multiple_issue_assignees: false)
project.add_developer(developer)
end
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index fe85b5c9065..80b5dcac6c7 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -5,6 +5,41 @@ require 'spec_helper'
describe Suggestions::ApplyService do
include ProjectForksHelper
+ shared_examples 'successfully creates commit and updates suggestion' do
+ def apply(suggestion)
+ result = subject.execute(suggestion)
+ expect(result[:status]).to eq(:success)
+ end
+
+ it 'updates the file with the new contents' do
+ apply(suggestion)
+
+ blob = project.repository.blob_at_branch(merge_request.source_branch,
+ position.new_path)
+
+ expect(blob.data).to eq(expected_content)
+ end
+
+ it 'updates suggestion applied and commit_id columns' do
+ expect { apply(suggestion) }
+ .to change(suggestion, :applied)
+ .from(false).to(true)
+ .and change(suggestion, :commit_id)
+ .from(nil)
+ end
+
+ it 'created commit has users email and name' do
+ apply(suggestion)
+
+ commit = project.repository.commit
+
+ expect(user.commit_email).not_to eq(user.email)
+ expect(commit.author_email).to eq(user.commit_email)
+ expect(commit.committer_email).to eq(user.commit_email)
+ expect(commit.author_name).to eq(user.name)
+ end
+ end
+
let(:project) { create(:project, :repository) }
let(:user) { create(:user, :commit_email) }
@@ -17,9 +52,8 @@ describe Suggestions::ApplyService do
end
let(:suggestion) do
- create(:suggestion, note: diff_note,
- from_content: " raise RuntimeError, \"System commands must be given as an array of strings\"\n",
- to_content: " raise RuntimeError, 'Explosion'\n # explosion?\n")
+ create(:suggestion, :content_from_repo, note: diff_note,
+ to_content: " raise RuntimeError, 'Explosion'\n # explosion?\n")
end
subject { described_class.new(user) }
@@ -84,39 +118,7 @@ describe Suggestions::ApplyService do
project.add_maintainer(user)
end
- it 'updates the file with the new contents' do
- subject.execute(suggestion)
-
- blob = project.repository.blob_at_branch(merge_request.source_branch,
- position.new_path)
-
- expect(blob.data).to eq(expected_content)
- end
-
- it 'returns success status' do
- result = subject.execute(suggestion)
-
- expect(result[:status]).to eq(:success)
- end
-
- it 'updates suggestion applied and commit_id columns' do
- expect { subject.execute(suggestion) }
- .to change(suggestion, :applied)
- .from(false).to(true)
- .and change(suggestion, :commit_id)
- .from(nil)
- end
-
- it 'created commit has users email and name' do
- subject.execute(suggestion)
-
- commit = project.repository.commit
-
- expect(user.commit_email).not_to eq(user.email)
- expect(commit.author_email).to eq(user.commit_email)
- expect(commit.committer_email).to eq(user.commit_email)
- expect(commit.author_name).to eq(user.name)
- end
+ it_behaves_like 'successfully creates commit and updates suggestion'
context 'when it fails to apply because the file was changed' do
it 'returns error message' do
@@ -212,11 +214,13 @@ describe Suggestions::ApplyService do
end
def apply_suggestion(suggestion)
- suggestion.note.reload
+ suggestion.reload
merge_request.reload
merge_request.clear_memoized_shas
result = subject.execute(suggestion)
+ expect(result[:status]).to eq(:success)
+
refresh = MergeRequests::RefreshService.new(project, user)
refresh.execute(merge_request.diff_head_sha,
suggestion.commit_id,
@@ -241,7 +245,7 @@ describe Suggestions::ApplyService do
suggestion_2_changes = { old_line: 24,
new_line: 31,
- from_content: " @cmd_output << stderr.read\n",
+ from_content: " @cmd_output << stderr.read\n",
to_content: "# v2 change\n",
path: path }
@@ -368,7 +372,18 @@ describe Suggestions::ApplyService do
result = subject.execute(suggestion)
- expect(result).to eq(message: 'The file was not found',
+ expect(result).to eq(message: 'Suggestion is not appliable',
+ status: :error)
+ end
+ end
+
+ context 'suggestion is eligible to be outdated' do
+ it 'returns error message' do
+ expect(suggestion).to receive(:outdated?) { true }
+
+ result = subject.execute(suggestion)
+
+ expect(result).to eq(message: 'Suggestion is not appliable',
status: :error)
end
end
diff --git a/spec/services/suggestions/create_service_spec.rb b/spec/services/suggestions/create_service_spec.rb
index 1b4b15b8eaa..ce4990a34a4 100644
--- a/spec/services/suggestions/create_service_spec.rb
+++ b/spec/services/suggestions/create_service_spec.rb
@@ -40,6 +40,14 @@ describe Suggestions::CreateService do
```thing
this is not a suggestion, it's a thing
```
+
+ ```suggestion:-3+2
+ # multi-line suggestion 1
+ ```
+
+ ```suggestion:-5
+ # multi-line suggestion 1
+ ```
MARKDOWN
end
@@ -54,7 +62,7 @@ describe Suggestions::CreateService do
end
it 'does not try to parse suggestions' do
- expect(Banzai::SuggestionsParser).not_to receive(:parse)
+ expect(Gitlab::Diff::SuggestionsParser).not_to receive(:parse)
subject.execute
end
@@ -71,7 +79,7 @@ describe Suggestions::CreateService do
it 'does not try to parse suggestions' do
allow(note).to receive(:on_text?) { false }
- expect(Banzai::SuggestionsParser).not_to receive(:parse)
+ expect(Gitlab::Diff::SuggestionsParser).not_to receive(:parse)
subject.execute
end
@@ -87,7 +95,9 @@ describe Suggestions::CreateService do
end
it 'creates no suggestion when diff file is not found' do
- expect(note).to receive(:latest_diff_file) { nil }
+ expect_next_instance_of(DiffNote) do |diff_note|
+ expect(diff_note).to receive(:latest_diff_file).twice { nil }
+ end
expect { subject.execute }.not_to change(Suggestion, :count)
end
@@ -101,43 +111,44 @@ describe Suggestions::CreateService do
note: markdown)
end
- context 'single line suggestions' do
- it 'persists suggestion records' do
- expect { subject.execute }
- .to change { note.suggestions.count }
- .from(0)
- .to(2)
- end
+ let(:expected_suggestions) do
+ Gitlab::Diff::SuggestionsParser.parse(markdown,
+ project: note.project,
+ position: note.position)
+ end
- it 'persists original from_content lines and suggested lines' do
- subject.execute
+ it 'persists suggestion records' do
+ expect { subject.execute }.to change { note.suggestions.count }
+ .from(0).to(expected_suggestions.size)
+ end
- suggestions = note.suggestions.order(:relative_order)
+ it 'persists suggestions data correctly' do
+ subject.execute
- suggestion_1 = suggestions.first
- suggestion_2 = suggestions.last
+ suggestions = note.suggestions.order(:relative_order)
- expect(suggestion_1).to have_attributes(from_content: " vars = {\n",
- to_content: " foo\n bar\n")
+ suggestions.zip(expected_suggestions) do |suggestion, expected_suggestion|
+ expected_data = expected_suggestion.to_hash
- expect(suggestion_2).to have_attributes(from_content: " vars = {\n",
- to_content: " xpto\n baz\n")
+ expect(suggestion.from_content).to eq(expected_data[:from_content])
+ expect(suggestion.to_content).to eq(expected_data[:to_content])
+ expect(suggestion.lines_above).to eq(expected_data[:lines_above])
+ expect(suggestion.lines_below).to eq(expected_data[:lines_below])
end
+ end
- context 'outdated position note' do
- let!(:outdated_diff) { merge_request.merge_request_diff }
- let!(:latest_diff) { merge_request.create_merge_request_diff }
- let(:outdated_position) { build_position(diff_refs: outdated_diff.diff_refs) }
- let(:position) { build_position(diff_refs: latest_diff.diff_refs) }
+ context 'outdated position note' do
+ let!(:outdated_diff) { merge_request.merge_request_diff }
+ let!(:latest_diff) { merge_request.create_merge_request_diff }
+ let(:outdated_position) { build_position(diff_refs: outdated_diff.diff_refs) }
+ let(:position) { build_position(diff_refs: latest_diff.diff_refs) }
- it 'uses the correct position when creating the suggestion' do
- expect(note.position)
- .to receive(:diff_file)
- .with(project_with_repo.repository)
- .and_call_original
+ it 'uses the correct position when creating the suggestion' do
+ expect(Gitlab::Diff::SuggestionsParser).to receive(:parse)
+ .with(note.note, project: note.project, position: note.position)
+ .and_call_original
- subject.execute
- end
+ subject.execute
end
end
end
diff --git a/spec/services/suggestions/outdate_service_spec.rb b/spec/services/suggestions/outdate_service_spec.rb
new file mode 100644
index 00000000000..bcc627013d8
--- /dev/null
+++ b/spec/services/suggestions/outdate_service_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Suggestions::OutdateService do
+ describe '#execute' do
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.target_project }
+ let(:user) { merge_request.author }
+ let(:file_path) { 'files/ruby/popen.rb' }
+ let(:branch_name) { project.default_branch }
+ let(:diff_file) { suggestion.diff_file }
+ let(:position) { build_position(file_path, comment_line) }
+ let(:note) do
+ create(:diff_note_on_merge_request, noteable: merge_request,
+ position: position,
+ project: project)
+ end
+
+ def build_position(path, line)
+ Gitlab::Diff::Position.new(old_path: path,
+ new_path: path,
+ old_line: nil,
+ new_line: line,
+ diff_refs: merge_request.diff_refs)
+ end
+
+ def commit_changes(file_path, new_content)
+ params = {
+ file_path: file_path,
+ commit_message: "Update File",
+ file_content: new_content,
+ start_project: project,
+ start_branch: project.default_branch,
+ branch_name: branch_name
+ }
+
+ Files::UpdateService.new(project, user, params).execute
+ end
+
+ def update_file_line(diff_file, change_line, content)
+ new_lines = diff_file.new_blob.data.lines
+ new_lines[change_line..change_line] = content
+ result = commit_changes(diff_file.file_path, new_lines.join)
+ newrev = result[:result]
+
+ expect(result[:status]).to eq(:success)
+ expect(newrev).to be_present
+
+ # Ensure all memoized data is cleared in order
+ # to generate the new merge_request_diff.
+ MergeRequest.find(merge_request.id).reload_diff(user)
+
+ note.reload
+ end
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ subject { described_class.new.execute(merge_request) }
+
+ context 'when there is a change within multi-line suggestion range' do
+ let(:comment_line) { 9 }
+ let(:lines_above) { 8 } # suggesting to change lines 1..9
+ let(:change_line) { 2 } # line 2 is within the range
+ let!(:suggestion) do
+ create(:suggestion, :content_from_repo, note: note, lines_above: lines_above)
+ end
+
+ it 'updates the outdatable suggestion record' do
+ update_file_line(diff_file, change_line, "# foo\nbar\n")
+
+ # Make sure note is still active
+ expect(note.active?).to be(true)
+
+ expect { subject }.to change { suggestion.reload.outdated }
+ .from(false).to(true)
+ end
+ end
+
+ context 'when there is no change within multi-line suggestion range' do
+ let(:comment_line) { 9 }
+ let(:lines_above) { 3 } # suggesting to change lines 6..9
+ let(:change_line) { 2 } # line 2 is not within the range
+ let!(:suggestion) do
+ create(:suggestion, :content_from_repo, note: note, lines_above: lines_above)
+ end
+
+ subject { described_class.new.execute(merge_request) }
+
+ it 'does not outdates suggestion record' do
+ update_file_line(diff_file, change_line, "# foo\nbar\n")
+
+ # Make sure note is still active
+ expect(note.active?).to be(true)
+
+ expect { subject }.not_to change { suggestion.reload.outdated }.from(false)
+ end
+ end
+ end
+end
diff --git a/spec/services/tags/create_service_spec.rb b/spec/services/tags/create_service_spec.rb
index 0cbe57352be..e112cdc8881 100644
--- a/spec/services/tags/create_service_spec.rb
+++ b/spec/services/tags/create_service_spec.rb
@@ -41,7 +41,7 @@ describe Tags::CreateService do
it 'returns an error' do
expect(repository).to receive(:add_tag)
.with(user, 'v1.1.0', 'master', 'Foo')
- .and_raise(Gitlab::Git::PreReceiveError, 'something went wrong')
+ .and_raise(Gitlab::Git::PreReceiveError, 'GitLab: something went wrong')
response = service.execute('v1.1.0', 'master', 'Foo')
diff --git a/spec/services/verify_pages_domain_service_spec.rb b/spec/services/verify_pages_domain_service_spec.rb
index d974cc0226f..ddf9d2b4917 100644
--- a/spec/services/verify_pages_domain_service_spec.rb
+++ b/spec/services/verify_pages_domain_service_spec.rb
@@ -9,88 +9,130 @@ describe VerifyPagesDomainService do
subject(:service) { described_class.new(domain) }
describe '#execute' do
- context 'verification code recognition (verified domain)' do
- where(:domain_sym, :code_sym) do
- :domain | :verification_code
- :domain | :keyed_verification_code
+ where(:domain_sym, :code_sym) do
+ :domain | :verification_code
+ :domain | :keyed_verification_code
- :verification_domain | :verification_code
- :verification_domain | :keyed_verification_code
- end
-
- with_them do
- set(:domain) { create(:pages_domain) }
+ :verification_domain | :verification_code
+ :verification_domain | :keyed_verification_code
+ end
- let(:domain_name) { domain.send(domain_sym) }
- let(:verification_code) { domain.send(code_sym) }
+ with_them do
+ let(:domain_name) { domain.send(domain_sym) }
+ let(:verification_code) { domain.send(code_sym) }
+ shared_examples 'verifies and enables the domain' do
it 'verifies and enables the domain' do
- stub_resolver(domain_name => ['something else', verification_code])
-
expect(service.execute).to eq(status: :success)
+
expect(domain).to be_verified
expect(domain).to be_enabled
end
+ end
- it 'verifies and enables when the code is contained partway through a TXT record' do
- stub_resolver(domain_name => "something #{verification_code} else")
+ shared_examples 'successful enablement and verification' do
+ context 'when txt record contains verification code' do
+ before do
+ stub_resolver(domain_name => ['something else', verification_code])
+ end
- expect(service.execute).to eq(status: :success)
- expect(domain).to be_verified
- expect(domain).to be_enabled
+ include_examples 'verifies and enables the domain'
end
- it 'does not verify when the code is not present' do
- stub_resolver(domain_name => 'something else')
-
- expect(service.execute).to eq(error_status)
+ context 'when txt record contains verification code with other text' do
+ before do
+ stub_resolver(domain_name => "something #{verification_code} else")
+ end
- expect(domain).not_to be_verified
- expect(domain).to be_enabled
+ include_examples 'verifies and enables the domain'
end
end
- context 'verified domain' do
- set(:domain) { create(:pages_domain) }
+ context 'when domain is disabled(or new)' do
+ let(:domain) { create(:pages_domain, :disabled) }
- it 'unverifies (but does not disable) when the right code is not present' do
- stub_resolver(domain.domain => 'something else')
+ include_examples 'successful enablement and verification'
- expect(service.execute).to eq(error_status)
- expect(domain).not_to be_verified
- expect(domain).to be_enabled
+ shared_examples 'unverifies and disables domain' do
+ it 'unverifies and disables domain' do
+ expect(service.execute).to eq(error_status)
+
+ expect(domain).not_to be_verified
+ expect(domain).not_to be_enabled
+ end
end
- it 'unverifies (but does not disable) when no records are present' do
- stub_resolver
+ context 'when txt record does not contain verification code' do
+ before do
+ stub_resolver(domain_name => 'something else')
+ end
- expect(service.execute).to eq(error_status)
- expect(domain).not_to be_verified
- expect(domain).to be_enabled
+ include_examples 'unverifies and disables domain'
+ end
+
+ context 'when no txt records are present' do
+ before do
+ stub_resolver
+ end
+
+ include_examples 'unverifies and disables domain'
end
end
- context 'expired domain' do
- set(:domain) { create(:pages_domain, :expired) }
+ context 'when domain is verified' do
+ let(:domain) { create(:pages_domain) }
- it 'verifies and enables when the right code is present' do
- stub_resolver(domain.domain => domain.keyed_verification_code)
+ include_examples 'successful enablement and verification'
- expect(service.execute).to eq(status: :success)
+ context 'when txt record does not contain verification code' do
+ before do
+ stub_resolver(domain_name => 'something else')
+ end
- expect(domain).to be_verified
- expect(domain).to be_enabled
+ it 'unverifies but does not disable domain' do
+ expect(service.execute).to eq(error_status)
+ expect(domain).not_to be_verified
+ expect(domain).to be_enabled
+ end
end
- it 'disables when the right code is not present' do
- error_status[:message] += '. It is now disabled.'
+ context 'when no txt records are present' do
+ before do
+ stub_resolver
+ end
- stub_resolver
+ it 'unverifies but does not disable domain' do
+ expect(service.execute).to eq(error_status)
+ expect(domain).not_to be_verified
+ expect(domain).to be_enabled
+ end
+ end
+ end
- expect(service.execute).to eq(error_status)
+ context 'when domain is expired' do
+ let(:domain) { create(:pages_domain, :expired) }
- expect(domain).not_to be_verified
- expect(domain).not_to be_enabled
+ context 'when the right code is present' do
+ before do
+ stub_resolver(domain_name => domain.keyed_verification_code)
+ end
+
+ include_examples 'verifies and enables the domain'
+ end
+
+ context 'when the right code is not present' do
+ before do
+ stub_resolver
+ end
+
+ it 'disables domain' do
+ error_status[:message] += '. It is now disabled.'
+
+ expect(service.execute).to eq(error_status)
+
+ expect(domain).not_to be_verified
+ expect(domain).not_to be_enabled
+ end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e8d7b18bf04..60db3e1bc46 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -66,6 +66,7 @@ RSpec.configure do |config|
metadata[:type] = match[1].singularize.to_sym if match
end
+ config.include LicenseHelpers
config.include ActiveJob::TestHelper
config.include ActiveSupport::Testing::TimeHelpers
config.include CycleAnalyticsHelpers
@@ -96,6 +97,7 @@ RSpec.configure do |config|
config.include MigrationsHelpers, :migration
config.include RedisHelpers
config.include Rails.application.routes.url_helpers, type: :routing
+ config.include PolicyHelpers, type: :policy
if ENV['CI']
# This includes the first try, i.e. tests will be run 4 times before failing.
diff --git a/spec/support/api/milestones_shared_examples.rb b/spec/support/api/milestones_shared_examples.rb
index 5f709831ce1..63b719be03e 100644
--- a/spec/support/api/milestones_shared_examples.rb
+++ b/spec/support/api/milestones_shared_examples.rb
@@ -72,6 +72,15 @@ shared_examples_for 'group and project milestones' do |route_definition|
expect(json_response.first['id']).to eq closed_milestone.id
end
+ it 'returns a milestone by title' do
+ get api(route, user), params: { title: 'version2' }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['title']).to eq milestone.title
+ expect(json_response.first['id']).to eq milestone.id
+ end
+
it 'returns a milestone by searching for title' do
get api(route, user), params: { search: 'version2' }
diff --git a/spec/support/features/issuable_quick_actions_shared_examples.rb b/spec/support/features/issuable_quick_actions_shared_examples.rb
deleted file mode 100644
index 2a883ce1074..00000000000
--- a/spec/support/features/issuable_quick_actions_shared_examples.rb
+++ /dev/null
@@ -1,389 +0,0 @@
-# Specifications for behavior common to all objects with executable attributes.
-# It takes a `issuable_type`, and expect an `issuable`.
-
-shared_examples 'issuable record that supports quick actions in its description and notes' do |issuable_type|
- include Spec::Support::Helpers::Features::NotesHelpers
-
- let(:maintainer) { create(:user) }
- let(:project) do
- case issuable_type
- when :merge_request
- create(:project, :public, :repository)
- when :issue
- create(:project, :public)
- end
- end
- let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
- let!(:label_bug) { create(:label, project: project, title: 'bug') }
- let!(:label_feature) { create(:label, project: project, title: 'feature') }
- let(:new_url_opts) { {} }
-
- before do
- project.add_maintainer(maintainer)
-
- gitlab_sign_in(maintainer)
- end
-
- after do
- # Ensure all outstanding Ajax requests are complete to avoid database deadlocks
- wait_for_requests
- end
-
- describe "new #{issuable_type}", :js do
- context 'with commands in the description' do
- it "creates the #{issuable_type} and interpret commands accordingly" do
- case issuable_type
- when :merge_request
- visit public_send("namespace_project_new_merge_request_path", project.namespace, project, new_url_opts)
- when :issue
- visit public_send("new_namespace_project_issue_path", project.namespace, project, new_url_opts)
- end
- fill_in "#{issuable_type}_title", with: 'bug 345'
- fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug\n/milestone %\"ASAP\""
- click_button "Submit #{issuable_type}".humanize
-
- issuable = project.public_send(issuable_type.to_s.pluralize).first
-
- expect(issuable.description).to eq "bug description"
- expect(issuable.labels).to eq [label_bug]
- expect(issuable.milestone).to eq milestone
- expect(page).to have_content 'bug 345'
- expect(page).to have_content 'bug description'
- end
- end
- end
-
- describe "note on #{issuable_type}", :js do
- before do
- visit public_send("project_#{issuable_type}_path", project, issuable)
- end
-
- context 'with a note containing commands' do
- it 'creates a note without the commands and interpret the commands accordingly' do
- assignee = create(:user, username: 'bob')
- add_note("Awesome!\n\n/assign @bob\n\n/label ~bug\n\n/milestone %\"ASAP\"")
-
- expect(page).to have_content 'Awesome!'
- expect(page).not_to have_content '/assign @bob'
- expect(page).not_to have_content '/label ~bug'
- expect(page).not_to have_content '/milestone %"ASAP"'
-
- wait_for_requests
- issuable.reload
- note = issuable.notes.user.first
-
- expect(note.note).to eq "Awesome!"
- expect(issuable.assignees).to eq [assignee]
- expect(issuable.labels).to eq [label_bug]
- expect(issuable.milestone).to eq milestone
- end
-
- it 'removes the quick action from note and explains it in the preview' do
- preview_note("Awesome!\n\n/close")
-
- expect(page).to have_content 'Awesome!'
- expect(page).not_to have_content '/close'
- issuable_name = issuable.is_a?(Issue) ? 'issue' : 'merge request'
- expect(page).to have_content "Closes this #{issuable_name}."
- end
- end
-
- context 'with a note containing only commands' do
- it 'does not create a note but interpret the commands accordingly' do
- assignee = create(:user, username: 'bob')
- add_note("/assign @bob\n\n/label ~bug\n\n/milestone %\"ASAP\"")
-
- expect(page).not_to have_content '/assign @bob'
- expect(page).not_to have_content '/label ~bug'
- expect(page).not_to have_content '/milestone %"ASAP"'
- expect(page).to have_content 'Commands applied'
-
- issuable.reload
-
- expect(issuable.notes.user).to be_empty
- expect(issuable.assignees).to eq [assignee]
- expect(issuable.labels).to eq [label_bug]
- expect(issuable.milestone).to eq milestone
- end
- end
-
- context "with a note closing the #{issuable_type}" do
- before do
- expect(issuable).to be_open
- end
-
- context "when current user can close #{issuable_type}" do
- it "closes the #{issuable_type}" do
- add_note("/close")
-
- expect(page).not_to have_content '/close'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.reload).to be_closed
- end
- end
-
- context "when current user cannot close #{issuable_type}" do
- before do
- guest = create(:user)
- project.add_guest(guest)
-
- gitlab_sign_out
- gitlab_sign_in(guest)
- visit public_send("project_#{issuable_type}_path", project, issuable)
- end
-
- it "does not close the #{issuable_type}" do
- add_note("/close")
-
- expect(page).not_to have_content 'Commands applied'
-
- expect(issuable).to be_open
- end
- end
- end
-
- context "with a note reopening the #{issuable_type}" do
- before do
- issuable.close
- expect(issuable).to be_closed
- end
-
- context "when current user can reopen #{issuable_type}" do
- it "reopens the #{issuable_type}" do
- add_note("/reopen")
-
- expect(page).not_to have_content '/reopen'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.reload).to be_open
- end
- end
-
- context "when current user cannot reopen #{issuable_type}" do
- before do
- guest = create(:user)
- project.add_guest(guest)
-
- gitlab_sign_out
- gitlab_sign_in(guest)
- visit public_send("project_#{issuable_type}_path", project, issuable)
- end
-
- it "does not reopen the #{issuable_type}" do
- add_note("/reopen")
-
- expect(page).not_to have_content 'Commands applied'
-
- expect(issuable).to be_closed
- end
- end
- end
-
- context "with a note changing the #{issuable_type}'s title" do
- context "when current user can change title of #{issuable_type}" do
- it "reopens the #{issuable_type}" do
- add_note("/title Awesome new title")
-
- expect(page).not_to have_content '/title'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.reload.title).to eq 'Awesome new title'
- end
- end
-
- context "when current user cannot change title of #{issuable_type}" do
- before do
- guest = create(:user)
- project.add_guest(guest)
-
- gitlab_sign_out
- gitlab_sign_in(guest)
- visit public_send("project_#{issuable_type}_path", project, issuable)
- end
-
- it "does not change the #{issuable_type} title" do
- add_note("/title Awesome new title")
-
- expect(page).not_to have_content 'Commands applied'
-
- expect(issuable.reload.title).not_to eq 'Awesome new title'
- end
- end
- end
-
- context "with a note marking the #{issuable_type} as todo" do
- it "creates a new todo for the #{issuable_type}" do
- add_note("/todo")
-
- expect(page).not_to have_content '/todo'
- expect(page).to have_content 'Commands applied'
-
- todos = TodosFinder.new(maintainer).execute
- todo = todos.first
-
- expect(todos.size).to eq 1
- expect(todo).to be_pending
- expect(todo.target).to eq issuable
- expect(todo.author).to eq maintainer
- expect(todo.user).to eq maintainer
- end
- end
-
- context "with a note marking the #{issuable_type} as done" do
- before do
- TodoService.new.mark_todo(issuable, maintainer)
- end
-
- it "creates a new todo for the #{issuable_type}" do
- todos = TodosFinder.new(maintainer).execute
- todo = todos.first
-
- expect(todos.size).to eq 1
- expect(todos.first).to be_pending
- expect(todo.target).to eq issuable
- expect(todo.author).to eq maintainer
- expect(todo.user).to eq maintainer
-
- add_note("/done")
-
- expect(page).not_to have_content '/done'
- expect(page).to have_content 'Commands applied'
-
- expect(todo.reload).to be_done
- end
- end
-
- context "with a note subscribing to the #{issuable_type}" do
- it "creates a new todo for the #{issuable_type}" do
- expect(issuable.subscribed?(maintainer, project)).to be_falsy
-
- add_note("/subscribe")
-
- expect(page).not_to have_content '/subscribe'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.subscribed?(maintainer, project)).to be_truthy
- end
- end
-
- context "with a note unsubscribing to the #{issuable_type} as done" do
- before do
- issuable.subscribe(maintainer, project)
- end
-
- it "creates a new todo for the #{issuable_type}" do
- expect(issuable.subscribed?(maintainer, project)).to be_truthy
-
- add_note("/unsubscribe")
-
- expect(page).not_to have_content '/unsubscribe'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.subscribed?(maintainer, project)).to be_falsy
- end
- end
-
- context "with a note assigning the #{issuable_type} to the current user" do
- it "assigns the #{issuable_type} to the current user" do
- add_note("/assign me")
-
- expect(page).not_to have_content '/assign me'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.reload.assignees).to eq [maintainer]
- end
- end
-
- context "with a note locking the #{issuable_type} discussion" do
- before do
- issuable.update(discussion_locked: false)
- expect(issuable).not_to be_discussion_locked
- end
-
- context "when current user can lock #{issuable_type} discussion" do
- it "locks the #{issuable_type} discussion" do
- add_note("/lock")
-
- expect(page).not_to have_content '/lock'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.reload).to be_discussion_locked
- end
- end
-
- context "when current user cannot lock #{issuable_type}" do
- before do
- guest = create(:user)
- project.add_guest(guest)
-
- gitlab_sign_out
- sign_in(guest)
- visit public_send("project_#{issuable_type}_path", project, issuable)
- end
-
- it "does not lock the #{issuable_type} discussion" do
- add_note("/lock")
-
- expect(page).not_to have_content 'Commands applied'
-
- expect(issuable).not_to be_discussion_locked
- end
- end
- end
-
- context "with a note unlocking the #{issuable_type} discussion" do
- before do
- issuable.update(discussion_locked: true)
- expect(issuable).to be_discussion_locked
- end
-
- context "when current user can unlock #{issuable_type} discussion" do
- it "unlocks the #{issuable_type} discussion" do
- add_note("/unlock")
-
- expect(page).not_to have_content '/unlock'
- expect(page).to have_content 'Commands applied'
-
- expect(issuable.reload).not_to be_discussion_locked
- end
- end
-
- context "when current user cannot unlock #{issuable_type}" do
- before do
- guest = create(:user)
- project.add_guest(guest)
-
- gitlab_sign_out
- sign_in(guest)
- visit public_send("project_#{issuable_type}_path", project, issuable)
- end
-
- it "does not unlock the #{issuable_type} discussion" do
- add_note("/unlock")
-
- expect(page).not_to have_content 'Commands applied'
-
- expect(issuable).to be_discussion_locked
- end
- end
- end
- end
-
- describe "preview of note on #{issuable_type}", :js do
- it 'removes quick actions from note and explains them' do
- create(:user, username: 'bob')
-
- visit public_send("project_#{issuable_type}_path", project, issuable)
-
- page.within('.js-main-target-form') do
- fill_in 'note[note]', with: "Awesome!\n/assign @bob "
- click_on 'Preview'
-
- expect(page).to have_content 'Awesome!'
- expect(page).not_to have_content '/assign @bob'
- expect(page).to have_content 'Assigns @bob.'
- end
- end
- end
-end
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index cceb179d53e..9cae8f934db 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -24,7 +24,7 @@ module JavaScriptFixturesHelpers
#
def clean_frontend_fixtures(directory_name)
full_directory_name = File.expand_path(directory_name, fixture_root_path)
- Dir[File.expand_path('*.html.raw', full_directory_name)].each do |file_name|
+ Dir[File.expand_path('*.html', full_directory_name)].each do |file_name|
FileUtils.rm(file_name)
end
end
diff --git a/spec/support/helpers/license_helper.rb b/spec/support/helpers/license_helper.rb
new file mode 100644
index 00000000000..4aaad55a8ef
--- /dev/null
+++ b/spec/support/helpers/license_helper.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+# Placeholder module for EE implementation needed for CE specs to be run in EE codebase
+module LicenseHelpers
+ def stub_licensed_features(features)
+ # do nothing
+ end
+end
diff --git a/spec/support/helpers/policy_helpers.rb b/spec/support/helpers/policy_helpers.rb
new file mode 100644
index 00000000000..3d780eb5fb1
--- /dev/null
+++ b/spec/support/helpers/policy_helpers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module PolicyHelpers
+ def expect_allowed(*permissions)
+ permissions.each { |p| is_expected.to be_allowed(p) }
+ end
+
+ def expect_disallowed(*permissions)
+ permissions.each { |p| is_expected.not_to be_allowed(p) }
+ end
+end
diff --git a/spec/support/helpers/stub_worker.rb b/spec/support/helpers/stub_worker.rb
new file mode 100644
index 00000000000..58b7ee93dff
--- /dev/null
+++ b/spec/support/helpers/stub_worker.rb
@@ -0,0 +1,9 @@
+# Inspired by https://github.com/ljkbennett/stub_env/blob/master/lib/stub_env/helpers.rb
+module StubWorker
+ def stub_worker(queue:)
+ Class.new do
+ include Sidekiq::Worker
+ sidekiq_options queue: queue
+ end
+ end
+end
diff --git a/spec/support/matchers/issuable_matchers.rb b/spec/support/matchers/issuable_matchers.rb
index f5d9a97051a..62f510b0fbd 100644
--- a/spec/support/matchers/issuable_matchers.rb
+++ b/spec/support/matchers/issuable_matchers.rb
@@ -1,4 +1,4 @@
-RSpec::Matchers.define :have_header_with_correct_id_and_link do |level, text, id, parent = ".wiki"|
+RSpec::Matchers.define :have_header_with_correct_id_and_link do |level, text, id, parent = ".md"|
match do |actual|
node = find("#{parent} h#{level} a#user-content-#{id}")
diff --git a/spec/support/shared_context/policies/project_policy_shared_context.rb b/spec/support/shared_context/policies/project_policy_shared_context.rb
new file mode 100644
index 00000000000..8bcd26ec0cd
--- /dev/null
+++ b/spec/support/shared_context/policies/project_policy_shared_context.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'ProjectPolicy context' do
+ set(:guest) { create(:user) }
+ set(:reporter) { create(:user) }
+ set(:developer) { create(:user) }
+ set(:maintainer) { create(:user) }
+ set(:owner) { create(:user) }
+ set(:admin) { create(:admin) }
+ let(:project) { create(:project, :public, namespace: owner.namespace) }
+
+ let(:base_guest_permissions) do
+ %i[
+ read_project read_board read_list read_wiki read_issue
+ read_project_for_iids read_issue_iid read_label
+ read_milestone read_project_snippet read_project_member read_note
+ create_project create_issue create_note upload_file create_merge_request_in
+ award_emoji read_release
+ ]
+ end
+
+ let(:base_reporter_permissions) do
+ %i[
+ download_code fork_project create_project_snippet update_issue
+ admin_issue admin_label admin_list read_commit_status read_build
+ read_container_image read_pipeline read_environment read_deployment
+ read_merge_request download_wiki_code read_sentry_issue
+ ]
+ end
+
+ let(:team_member_reporter_permissions) do
+ %i[build_download_code build_read_container_image]
+ end
+
+ let(:developer_permissions) do
+ %i[
+ admin_milestone admin_merge_request update_merge_request create_commit_status
+ update_commit_status create_build update_build create_pipeline
+ update_pipeline create_merge_request_from create_wiki push_code
+ resolve_note create_container_image update_container_image
+ create_environment create_deployment create_release update_release
+ ]
+ end
+
+ let(:base_maintainer_permissions) do
+ %i[
+ push_to_delete_protected_branch update_project_snippet update_environment
+ update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
+ admin_commit_status admin_build admin_container_image
+ admin_pipeline admin_environment admin_deployment destroy_release add_cluster
+ daily_statistics
+ ]
+ end
+
+ let(:public_permissions) do
+ %i[
+ download_code fork_project read_commit_status read_pipeline
+ read_container_image build_download_code build_read_container_image
+ download_wiki_code read_release
+ ]
+ end
+
+ let(:base_owner_permissions) do
+ %i[
+ change_namespace change_visibility_level rename_project remove_project
+ archive_project remove_fork_project destroy_merge_request destroy_issue
+ set_issue_iid set_issue_created_at set_note_created_at
+ ]
+ end
+
+ # Used in EE specs
+ let(:additional_guest_permissions) { [] }
+ let(:additional_reporter_permissions) { [] }
+ let(:additional_maintainer_permissions) { [] }
+ let(:additional_owner_permissions) { [] }
+
+ let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
+ let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
+ let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
+ let(:owner_permissions) { base_owner_permissions + additional_owner_permissions }
+
+ before do
+ project.add_guest(guest)
+ project.add_maintainer(maintainer)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ end
+end
diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
new file mode 100644
index 00000000000..b4808ac0068
--- /dev/null
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'GroupPolicy context' do
+ let(:guest) { create(:user) }
+ let(:reporter) { create(:user) }
+ let(:developer) { create(:user) }
+ let(:maintainer) { create(:user) }
+ let(:owner) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:group) { create(:group, :private) }
+
+ let(:guest_permissions) do
+ %i[
+ read_label read_group upload_file read_namespace read_group_activity
+ read_group_issues read_group_boards read_group_labels read_group_milestones
+ read_group_merge_requests
+ ]
+ end
+ let(:reporter_permissions) { [:admin_label] }
+ let(:developer_permissions) { [:admin_milestone] }
+ let(:maintainer_permissions) do
+ %i[
+ create_projects
+ read_cluster create_cluster update_cluster admin_cluster add_cluster
+ ]
+ end
+ let(:owner_permissions) do
+ [
+ :admin_group,
+ :admin_namespace,
+ :admin_group_member,
+ :change_visibility_level,
+ :set_note_created_at,
+ (Gitlab::Database.postgresql? ? :create_subgroup : nil)
+ ].compact
+ end
+
+ before do
+ group.add_guest(guest)
+ group.add_reporter(reporter)
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ group.add_owner(owner)
+ end
+
+ subject { described_class.new(current_user, group) }
+end
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
new file mode 100644
index 00000000000..7a71e2ee370
--- /dev/null
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -0,0 +1,231 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'archived project policies' do
+ let(:feature_write_abilities) do
+ described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature|
+ described_class.create_update_admin_destroy(feature)
+ end + additional_reporter_permissions + additional_maintainer_permissions
+ end
+
+ let(:other_write_abilities) do
+ %i[
+ create_merge_request_in
+ create_merge_request_from
+ push_to_delete_protected_branch
+ push_code
+ request_access
+ upload_file
+ resolve_note
+ award_emoji
+ ]
+ end
+
+ context 'when the project is archived' do
+ before do
+ project.archived = true
+ end
+
+ it 'disables write actions on all relevant project features' do
+ expect_disallowed(*feature_write_abilities)
+ end
+
+ it 'disables some other important write actions' do
+ expect_disallowed(*other_write_abilities)
+ end
+
+ it 'does not disable other abilities' do
+ expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities))
+ end
+ end
+end
+
+RSpec.shared_examples 'project policies as anonymous' do
+ context 'abilities for public projects' do
+ context 'when a project has pending invites' do
+ let(:group) { create(:group, :public) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] }
+ let(:anonymous_permissions) { guest_permissions - user_permissions }
+
+ subject { described_class.new(nil, project) }
+
+ before do
+ create(:group_member, :invited, group: group)
+ end
+
+ it 'does not grant owner access' do
+ expect_allowed(*anonymous_permissions)
+ expect_disallowed(*user_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { anonymous_permissions }
+ end
+ end
+ end
+
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+
+ subject { described_class.new(nil, project) }
+
+ it { is_expected.to be_banned }
+ end
+end
+
+RSpec.shared_examples 'project policies as guest' do
+ subject { described_class.new(guest, project) }
+
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+ let(:reporter_public_build_permissions) do
+ reporter_permissions - [:read_build, :read_pipeline]
+ end
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_disallowed(*reporter_public_build_permissions)
+ expect_disallowed(*team_member_reporter_permissions)
+ expect_disallowed(*developer_permissions)
+ expect_disallowed(*maintainer_permissions)
+ expect_disallowed(*owner_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { guest_permissions }
+ end
+
+ context 'public builds enabled' do
+ it do
+ expect_allowed(*guest_permissions)
+ expect_allowed(:read_build, :read_pipeline)
+ end
+ end
+
+ context 'when public builds disabled' do
+ before do
+ project.update(public_builds: false)
+ end
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_disallowed(:read_build, :read_pipeline)
+ end
+ end
+
+ context 'when builds are disabled' do
+ before do
+ project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
+ end
+
+ it do
+ expect_disallowed(:read_build)
+ expect_allowed(:read_pipeline)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'project policies as reporter' do
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+
+ subject { described_class.new(reporter, project) }
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_allowed(*reporter_permissions)
+ expect_allowed(*team_member_reporter_permissions)
+ expect_disallowed(*developer_permissions)
+ expect_disallowed(*maintainer_permissions)
+ expect_disallowed(*owner_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { reporter_permissions }
+ end
+ end
+end
+
+RSpec.shared_examples 'project policies as developer' do
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+ subject { described_class.new(developer, project) }
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_allowed(*reporter_permissions)
+ expect_allowed(*team_member_reporter_permissions)
+ expect_allowed(*developer_permissions)
+ expect_disallowed(*maintainer_permissions)
+ expect_disallowed(*owner_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { developer_permissions }
+ end
+ end
+end
+
+RSpec.shared_examples 'project policies as maintainer' do
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+
+ subject { described_class.new(maintainer, project) }
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_allowed(*reporter_permissions)
+ expect_allowed(*team_member_reporter_permissions)
+ expect_allowed(*developer_permissions)
+ expect_allowed(*maintainer_permissions)
+ expect_disallowed(*owner_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { maintainer_permissions }
+ end
+ end
+end
+
+RSpec.shared_examples 'project policies as owner' do
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+
+ subject { described_class.new(owner, project) }
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_allowed(*reporter_permissions)
+ expect_allowed(*team_member_reporter_permissions)
+ expect_allowed(*developer_permissions)
+ expect_allowed(*maintainer_permissions)
+ expect_allowed(*owner_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { owner_permissions }
+ end
+ end
+end
+
+RSpec.shared_examples 'project policies as admin' do
+ context 'abilities for non-public projects' do
+ let(:project) { create(:project, namespace: owner.namespace) }
+
+ subject { described_class.new(admin, project) }
+
+ it do
+ expect_allowed(*guest_permissions)
+ expect_allowed(*reporter_permissions)
+ expect_disallowed(*team_member_reporter_permissions)
+ expect_allowed(*developer_permissions)
+ expect_allowed(*maintainer_permissions)
+ expect_allowed(*owner_permissions)
+ end
+
+ it_behaves_like 'archived project policies' do
+ let(:regular_abilities) { owner_permissions }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..4604d867507
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/commit/tag_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'tag quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..d97da6be192
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/assign_quick_action_shared_examples.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+shared_examples 'assign quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets assign quick action accordingly" do
+ assignee = create(:user, username: 'bob')
+
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/assign @bob"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable.assignees).to eq [assignee]
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+
+ it "creates the #{issuable_type} and interprets assign quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/assign me"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable.assignees).to eq [maintainer]
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the assign quick action accordingly' do
+ assignee = create(:user, username: 'bob')
+ add_note("Awesome!\n\n/assign @bob")
+
+ expect(page).to have_content 'Awesome!'
+ expect(page).not_to have_content '/assign @bob'
+
+ wait_for_requests
+ issuable.reload
+ note = issuable.notes.user.first
+
+ expect(note.note).to eq 'Awesome!'
+ expect(issuable.assignees).to eq [assignee]
+ end
+
+ it "assigns the #{issuable_type} to the current user" do
+ add_note("/assign me")
+
+ expect(page).not_to have_content '/assign me'
+ expect(page).to have_content 'Commands applied'
+
+ expect(issuable.reload.assignees).to eq [maintainer]
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains assign quick action to bob' do
+ create(:user, username: 'bob')
+
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ page.within('.js-main-target-form') do
+ fill_in 'note[note]', with: "Awesome!\n/assign @bob "
+ click_on 'Preview'
+
+ expect(page).not_to have_content '/assign @bob'
+ expect(page).to have_content 'Awesome!'
+ expect(page).to have_content 'Assigns @bob.'
+ end
+ end
+
+ it 'explains assign quick action to me' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ page.within('.js-main-target-form') do
+ fill_in 'note[note]', with: "Awesome!\n/assign me"
+ click_on 'Preview'
+
+ expect(page).not_to have_content '/assign me'
+ expect(page).to have_content 'Awesome!'
+ expect(page).to have_content "Assigns @#{maintainer.username}."
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..74cbfa3f4b4
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/award_quick_action_shared_examples.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+shared_examples 'award quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets award quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/award :100:"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.award_emoji).to eq []
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ expect(issuable.award_emoji).to eq []
+ end
+
+ it 'creates the note and interprets the award quick action accordingly' do
+ add_note("/award :100:")
+
+ wait_for_requests
+ expect(page).not_to have_content '/award'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.award_emoji.last.name).to eq('100')
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains label quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/award :100:')
+
+ expect(page).not_to have_content '/award'
+ expect(page).to have_selector "gl-emoji[data-name='100']"
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..e0d0b790a0e
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+shared_examples 'close quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets close quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/close"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ expect(issuable).to be_opened
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the close quick action accordingly' do
+ add_note("this is done, close\n\n/close")
+
+ wait_for_requests
+ expect(page).not_to have_content '/close'
+ expect(page).to have_content 'this is done, close'
+
+ issuable.reload
+ note = issuable.notes.user.first
+
+ expect(note.note).to eq 'this is done, close'
+ expect(issuable).to be_closed
+ end
+
+ context "when current user cannot close #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ end
+
+ it "does not close the #{issuable_type}" do
+ add_note('/close')
+
+ expect(page).not_to have_content 'Commands applied'
+ expect(issuable).to be_open
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains close quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ page.within('.js-main-target-form') do
+ fill_in 'note[note]', with: "this is done, close\n/close"
+ click_on 'Preview'
+
+ expect(page).not_to have_content '/close'
+ expect(page).to have_content 'this is done, close'
+ expect(page).to have_content "Closes this #{issuable_type.to_s.humanize.downcase}."
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..1e1e3c7bc95
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/copy_metadata_quick_action_shared_examples.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+shared_examples 'copy_metadata quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets copy_metadata quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/copy_metadata #{source_issuable.to_reference(project)}"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).last
+
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ issuable.reload
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable.milestone).to eq milestone
+ expect(issuable.labels).to match_array([label_bug, label_feature])
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets copy_metadata quick action accordingly' do
+ add_note("/copy_metadata #{source_issuable.to_reference(project)}")
+
+ wait_for_requests
+ expect(page).not_to have_content '/copy_metadata'
+ expect(page).to have_content 'Commands applied'
+ issuable.reload
+ expect(issuable.milestone).to eq milestone
+ expect(issuable.labels).to match_array([label_bug, label_feature])
+ end
+
+ context "when current user cannot copy_metadata" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not copy_metadata' do
+ add_note("/copy_metadata #{source_issuable.to_reference(project)}")
+
+ wait_for_requests
+ expect(page).not_to have_content '/copy_metadata'
+ expect(page).not_to have_content 'Commands applied'
+ issuable.reload
+ expect(issuable.milestone).not_to eq milestone
+ expect(issuable.labels).to eq []
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains copy_metadata quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note("/copy_metadata #{source_issuable.to_reference(project)}")
+
+ expect(page).not_to have_content '/copy_metadata'
+ expect(page).to have_content "Copy labels and milestone from #{source_issuable.to_reference(project)}."
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..8a72bbc13bf
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/done_quick_action_shared_examples.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+shared_examples 'done quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets done quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/done"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+
+ todos = TodosFinder.new(maintainer).execute
+ expect(todos.size).to eq 0
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ TodoService.new.mark_todo(issuable, maintainer)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the done quick action accordingly' do
+ todos = TodosFinder.new(maintainer).execute
+ todo = todos.first
+ expect(todo.reload).to be_pending
+
+ expect(todos.size).to eq 1
+ expect(todo.target).to eq issuable
+ expect(todo.author).to eq maintainer
+ expect(todo.user).to eq maintainer
+
+ add_note('/done')
+
+ wait_for_requests
+ expect(page).not_to have_content '/done'
+ expect(page).to have_content 'Commands applied'
+ expect(todo.reload).to be_done
+ end
+
+ context "when current user cannot mark #{issuable_type} todo as done" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not set the #{issuable_type} todo as done" do
+ todos = TodosFinder.new(maintainer).execute
+ todo = todos.first
+ expect(todo.reload).to be_pending
+
+ expect(todos.size).to eq 1
+ expect(todo.target).to eq issuable
+ expect(todo.author).to eq maintainer
+ expect(todo.user).to eq maintainer
+
+ add_note('/done')
+
+ expect(page).not_to have_content 'Commands applied'
+ expect(todo.reload).to be_pending
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains done quick action' do
+ TodoService.new.mark_todo(issuable, maintainer)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/done')
+
+ expect(page).not_to have_content '/done'
+ expect(page).to have_content "Marks todo as done."
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..648755d7e55
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/estimate_quick_action_shared_examples.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+shared_examples 'estimate quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets estimate quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/estimate 1d 2h 3m"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.time_estimate).to eq 36180
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the estimate quick action accordingly' do
+ add_note("/estimate 1d 2h 3m")
+
+ wait_for_requests
+ expect(page).not_to have_content '/estimate'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.time_estimate).to eq 36180
+ end
+
+ context "when current user cannot set estimate to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not set estimate' do
+ add_note("/estimate ~bug ~feature")
+
+ wait_for_requests
+ expect(page).not_to have_content '/estimate'
+ expect(issuable.reload.time_estimate).to eq 0
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains estimate quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/estimate 1d 2h 3m')
+
+ expect(page).not_to have_content '/estimate'
+ expect(page).to have_content 'Sets time estimate to 1d 2h 3m.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..9066e382b70
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/label_quick_action_shared_examples.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+shared_examples 'label quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets label quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug ~feature"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.labels).to match_array([label_bug, label_feature])
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ expect(issuable.labels).to eq []
+ end
+
+ it 'creates the note and interprets the label quick action accordingly' do
+ add_note("/label ~bug ~feature")
+
+ wait_for_requests
+ expect(page).not_to have_content '/label'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.labels).to match_array([label_bug, label_feature])
+ end
+
+ context "when current user cannot set label to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not set label' do
+ add_note("/label ~bug ~feature")
+
+ wait_for_requests
+ expect(page).not_to have_content '/label'
+ expect(issuable.labels).to eq []
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains label quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/label ~bug ~feature')
+
+ expect(page).not_to have_content '/label'
+ expect(page).to have_content 'Adds bug feature labels.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..d3197f2a459
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/lock_quick_action_shared_examples.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+shared_examples 'lock quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets lock quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/lock"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable).not_to be_discussion_locked
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ issuable.update(discussion_locked: false)
+ expect(issuable).not_to be_discussion_locked
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the lock quick action accordingly' do
+ add_note('/lock')
+
+ wait_for_requests
+ expect(page).not_to have_content '/lock'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload).to be_discussion_locked
+ end
+
+ context "when current user cannot lock to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not lock the #{issuable_type}" do
+ add_note('/lock')
+
+ wait_for_requests
+ expect(page).not_to have_content '/lock'
+ expect(issuable).not_to be_discussion_locked
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains lock quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/lock')
+
+ expect(page).not_to have_content '/lock'
+ expect(page).to have_content "Locks the discussion"
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..7f16ce93b6a
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/milestone_quick_action_shared_examples.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+shared_examples 'milestone quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets milestone quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/milestone %\"ASAP\""
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.milestone).to eq milestone
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ expect(issuable.milestone).to be_nil
+ end
+
+ it 'creates the note and interprets the milestone quick action accordingly' do
+ add_note("/milestone %\"ASAP\"")
+
+ wait_for_requests
+ expect(page).not_to have_content '/milestone'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.milestone).to eq milestone
+ end
+
+ context "when current user cannot set milestone to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not set milestone' do
+ add_note('/milestone')
+
+ wait_for_requests
+ expect(page).not_to have_content '/milestone'
+ expect(issuable.reload.milestone).to be_nil
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains milestone quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note("/milestone %\"ASAP\"")
+
+ expect(page).not_to have_content '/milestone'
+ expect(page).to have_content 'Sets the milestone to %ASAP'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..643ae77516a
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/relabel_quick_action_shared_examples.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+shared_examples 'relabel quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets relabel quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug /relabel ~feature"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.labels).to eq [label_bug, label_feature]
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ issuable.update(labels: [label_bug])
+ end
+
+ it 'creates the note and interprets the relabel quick action accordingly' do
+ add_note('/relabel ~feature')
+
+ wait_for_requests
+ expect(page).not_to have_content '/relabel'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.labels).to match_array([label_feature])
+ end
+
+ it 'creates the note and interprets the relabel quick action with empty param' do
+ add_note('/relabel')
+
+ wait_for_requests
+ expect(page).not_to have_content '/relabel'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.labels).to match_array([label_bug])
+ end
+
+ context "when current user cannot relabel to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not relabel' do
+ add_note('/relabel ~feature')
+
+ wait_for_requests
+ expect(page).not_to have_content '/relabel'
+ expect(issuable.labels).to match_array([label_bug])
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ before do
+ issuable.update(labels: [label_bug])
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ end
+
+ it 'explains relabel all quick action' do
+ preview_note('/relabel ~feature')
+
+ expect(page).not_to have_content '/relabel'
+ expect(page).to have_content 'Replaces all labels with feature label.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..24f6f8d5bf4
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/remove_estimate_quick_action_shared_examples.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+shared_examples 'remove_estimate quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets estimate quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/remove_estimate"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.time_estimate).to eq 0
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ issuable.update_attribute(:time_estimate, 36180)
+ end
+
+ it 'creates the note and interprets the remove_estimate quick action accordingly' do
+ add_note("/remove_estimate")
+
+ wait_for_requests
+ expect(page).not_to have_content '/remove_estimate'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.time_estimate).to eq 0
+ end
+
+ context "when current user cannot remove_estimate" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not remove_estimate' do
+ add_note('/remove_estimate')
+
+ wait_for_requests
+ expect(page).not_to have_content '/remove_estimate'
+ expect(issuable.reload.time_estimate).to eq 36180
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains remove_estimate quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/remove_estimate')
+
+ expect(page).not_to have_content '/remove_estimate'
+ expect(page).to have_content 'Removes time estimate.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..edd92d5cdbc
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/remove_milestone_quick_action_shared_examples.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+shared_examples 'remove_milestone quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets remove_milestone quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/remove_milestone"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.milestone).to be_nil
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ issuable.update(milestone: milestone)
+ expect(issuable.milestone).to eq(milestone)
+ end
+
+ it 'creates the note and interprets the remove_milestone quick action accordingly' do
+ add_note("/remove_milestone")
+
+ wait_for_requests
+ expect(page).not_to have_content '/remove_milestone'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.milestone).to be_nil
+ end
+
+ context "when current user cannot remove milestone to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not remove milestone' do
+ add_note('/remove_milestone')
+
+ wait_for_requests
+ expect(page).not_to have_content '/remove_milestone'
+ expect(issuable.reload.milestone).to eq(milestone)
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains remove_milestone quick action' do
+ issuable.update(milestone: milestone)
+ expect(issuable.milestone).to eq(milestone)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note("/remove_milestone")
+
+ expect(page).not_to have_content '/remove_milestone'
+ expect(page).to have_content 'Removes %ASAP milestone.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..6d5894b2318
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/remove_time_spent_quick_action_shared_examples.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+shared_examples 'remove_time_spent quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets remove_time_spent quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/remove_time_spent"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.total_time_spent).to eq 0
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ issuable.update!(spend_time: { duration: 36180, user_id: maintainer.id })
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the remove_time_spent quick action accordingly' do
+ add_note("/remove_time_spent")
+
+ wait_for_requests
+ expect(page).not_to have_content '/remove_time_spent'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.total_time_spent).to eq 0
+ end
+
+ context "when current user cannot set remove_time_spent time" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not set remove_time_spent time' do
+ add_note("/remove_time_spent")
+
+ wait_for_requests
+ expect(page).not_to have_content '/remove_time_spent'
+ expect(issuable.reload.total_time_spent).to eq 36180
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains remove_time_spent quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/remove_time_spent')
+
+ expect(page).not_to have_content '/remove_time_spent'
+ expect(page).to have_content 'Removes spent time.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..af173e93bb5
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/reopen_quick_action_shared_examples.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+shared_examples 'reopen quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets reopen quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/reopen"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ issuable.close
+ expect(issuable).to be_closed
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the reopen quick action accordingly' do
+ add_note('/reopen')
+
+ wait_for_requests
+ expect(page).not_to have_content '/reopen'
+ expect(page).to have_content 'Commands applied'
+
+ issuable.reload
+ expect(issuable).to be_opened
+ end
+
+ context "when current user cannot reopen #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not reopen the #{issuable_type}" do
+ add_note('/reopen')
+
+ expect(page).not_to have_content 'Commands applied'
+ expect(issuable).to be_closed
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains reopen quick action' do
+ issuable.close
+ expect(issuable).to be_closed
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/reopen')
+
+ expect(page).not_to have_content '/reopen'
+ expect(page).to have_content "Reopens this #{issuable_type.to_s.humanize.downcase}."
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..0a526808585
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+shared_examples 'shrug quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets shrug quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/shrug oops"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq "bug description\noops ¯\\_(ツ)_/¯"
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content "bug description\noops ¯\\_(ツ)_/¯"
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets shrug quick action accordingly' do
+ add_note("/shrug oops")
+
+ wait_for_requests
+ expect(page).not_to have_content '/shrug oops'
+ expect(page).to have_content "oops ¯\\_(ツ)_/¯"
+ expect(issuable.notes.last.note).to eq "oops ¯\\_(ツ)_/¯"
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains shrug quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/shrug oops')
+
+ expect(page).not_to have_content '/shrug'
+ expect(page).to have_content "oops ¯\\_(ツ)_/¯"
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..97b4885eba0
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/spend_quick_action_shared_examples.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+shared_examples 'spend quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets spend quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/spend 1d 2h 3m"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.total_time_spent).to eq 36180
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the spend quick action accordingly' do
+ add_note("/spend 1d 2h 3m")
+
+ wait_for_requests
+ expect(page).not_to have_content '/spend'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.total_time_spent).to eq 36180
+ end
+
+ context "when current user cannot set spend time" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not set spend time' do
+ add_note("/spend 1s 2h 3m")
+
+ wait_for_requests
+ expect(page).not_to have_content '/spend'
+ expect(issuable.reload.total_time_spent).to eq 0
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains spend quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/spend 1d 2h 3m')
+
+ expect(page).not_to have_content '/spend'
+ expect(page).to have_content 'Adds 1d 2h 3m spent time.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..15aefd511a5
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/subscribe_quick_action_shared_examples.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+shared_examples 'subscribe quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets subscribe quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/subscribe"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.subscribed?(maintainer, project)).to be_truthy
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ expect(issuable.subscribed?(maintainer, project)).to be_falsy
+ end
+
+ it 'creates the note and interprets the subscribe quick action accordingly' do
+ add_note('/subscribe')
+
+ wait_for_requests
+ expect(page).not_to have_content '/subscribe'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.subscribed?(maintainer, project)).to be_truthy
+ end
+
+ context "when current user cannot subscribe to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not subscribe to the #{issuable_type}" do
+ add_note('/subscribe')
+
+ wait_for_requests
+ expect(page).not_to have_content '/subscribe'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.subscribed?(maintainer, project)).to be_falsy
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains subscribe quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/subscribe')
+
+ expect(page).not_to have_content '/subscribe'
+ expect(page).to have_content "Subscribes to this #{issuable_type.to_s.humanize.downcase}"
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..ef831e39872
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+shared_examples 'tableflip quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets tableflip quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/tableflip oops"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq "bug description\noops (╯°□°)╯︵ ┻━┻"
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content "bug description\noops (╯°□°)╯︵ ┻━┻"
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets tableflip quick action accordingly' do
+ add_note("/tableflip oops")
+
+ wait_for_requests
+ expect(page).not_to have_content '/tableflip oops'
+ expect(page).to have_content "oops (╯°□°)╯︵ ┻━┻"
+ expect(issuable.notes.last.note).to eq "oops (╯°□°)╯︵ ┻━┻"
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains tableflip quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/tableflip oops')
+
+ expect(page).not_to have_content '/tableflip'
+ expect(page).to have_content "oops (╯°□°)╯︵ ┻━┻"
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..ed904c8d539
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/time_tracking_quick_action_shared_examples.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+shared_examples 'issuable time tracker' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ after do
+ wait_for_requests
+ end
+
+ it 'renders the sidebar component empty state' do
+ page.within '.time-tracking-no-tracking-pane' do
+ expect(page).to have_content 'No estimate or time spent'
+ end
+ end
+
+ it 'updates the sidebar component when estimate is added' do
+ submit_time('/estimate 3w 1d 1h')
+
+ wait_for_requests
+ page.within '.time-tracking-estimate-only-pane' do
+ expect(page).to have_content '3w 1d 1h'
+ end
+ end
+
+ it 'updates the sidebar component when spent is added' do
+ submit_time('/spend 3w 1d 1h')
+
+ wait_for_requests
+ page.within '.time-tracking-spend-only-pane' do
+ expect(page).to have_content '3w 1d 1h'
+ end
+ end
+
+ it 'shows the comparison when estimate and spent are added' do
+ submit_time('/estimate 3w 1d 1h')
+ submit_time('/spend 3w 1d 1h')
+
+ wait_for_requests
+ page.within '.time-tracking-comparison-pane' do
+ expect(page).to have_content '3w 1d 1h'
+ end
+ end
+
+ it 'updates the sidebar component when estimate is removed' do
+ submit_time('/estimate 3w 1d 1h')
+ submit_time('/remove_estimate')
+
+ page.within '.time-tracking-component-wrap' do
+ expect(page).to have_content 'No estimate or time spent'
+ end
+ end
+
+ it 'updates the sidebar component when spent is removed' do
+ submit_time('/spend 3w 1d 1h')
+ submit_time('/remove_time_spent')
+
+ page.within '.time-tracking-component-wrap' do
+ expect(page).to have_content 'No estimate or time spent'
+ end
+ end
+
+ it 'shows the help state when icon is clicked' do
+ page.within '.time-tracking-component-wrap' do
+ find('.help-button').click
+ expect(page).to have_content 'Track time with quick actions'
+ expect(page).to have_content 'Learn more'
+ end
+ end
+
+ it 'hides the help state when close icon is clicked' do
+ page.within '.time-tracking-component-wrap' do
+ find('.help-button').click
+ find('.close-help-button').click
+
+ expect(page).not_to have_content 'Track time with quick actions'
+ expect(page).not_to have_content 'Learn more'
+ end
+ end
+
+ it 'displays the correct help url' do
+ page.within '.time-tracking-component-wrap' do
+ find('.help-button').click
+
+ expect(find_link('Learn more')[:href]).to have_content('/help/workflow/time_tracking.md')
+ end
+ end
+end
+
+def submit_time(quick_action)
+ fill_in 'note[note]', with: quick_action
+ find('.js-comment-submit-button').click
+ wait_for_requests
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..93a69093dde
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/title_quick_action_shared_examples.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+shared_examples 'title quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets title quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/title new title"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(issuable.title).to eq 'bug 345'
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the title quick action accordingly' do
+ add_note('/title New title')
+
+ wait_for_requests
+ expect(page).not_to have_content '/title new title'
+ expect(page).to have_content 'Commands applied'
+ expect(page).to have_content 'New title'
+
+ issuable.reload
+ expect(issuable.title).to eq 'New title'
+ end
+
+ context "when current user cannot set title #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not set title to the #{issuable_type}" do
+ add_note('/title New title')
+
+ expect(page).not_to have_content 'Commands applied'
+ expect(issuable.title).not_to eq 'New title'
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains title quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/title New title')
+ wait_for_requests
+
+ expect(page).not_to have_content '/title New title'
+ expect(page).to have_content 'Changes the title to "New title".'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..cccc28127ce
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/todo_quick_action_shared_examples.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+shared_examples 'todo quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets todo quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/todo"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+
+ todos = TodosFinder.new(maintainer).execute
+ expect(todos.size).to eq 0
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the todo quick action accordingly' do
+ add_note('/todo')
+
+ wait_for_requests
+ expect(page).not_to have_content '/todo'
+ expect(page).to have_content 'Commands applied'
+
+ todos = TodosFinder.new(maintainer).execute
+ todo = todos.first
+
+ expect(todos.size).to eq 1
+ expect(todo).to be_pending
+ expect(todo.target).to eq issuable
+ expect(todo.author).to eq maintainer
+ expect(todo.user).to eq maintainer
+ end
+
+ context "when current user cannot add todo #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not add todo the #{issuable_type}" do
+ add_note('/todo')
+
+ expect(page).not_to have_content 'Commands applied'
+ todos = TodosFinder.new(maintainer).execute
+ expect(todos.size).to eq 0
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains todo quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/todo')
+
+ expect(page).not_to have_content '/todo'
+ expect(page).to have_content "Adds a todo."
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..0b1a52bc860
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/unassign_quick_action_shared_examples.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+shared_examples 'unassign quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets unassign quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/unassign @bob"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable.assignees).to eq []
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+
+ it "creates the #{issuable_type} and interprets unassign quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/unassign me"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable.assignees).to eq []
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the unassign quick action accordingly' do
+ assignee = create(:user, username: 'bob')
+ issuable.update(assignee_ids: [assignee.id])
+ expect(issuable.assignees).to eq [assignee]
+
+ add_note("Awesome!\n\n/unassign @bob")
+
+ expect(page).to have_content 'Awesome!'
+ expect(page).not_to have_content '/unassign @bob'
+
+ wait_for_requests
+ issuable.reload
+ note = issuable.notes.user.first
+
+ expect(note.note).to eq 'Awesome!'
+ expect(issuable.assignees).to eq []
+ end
+
+ it "unassigns the #{issuable_type} from current user" do
+ issuable.update(assignee_ids: [maintainer.id])
+ expect(issuable.reload.assignees).to eq [maintainer]
+ expect(issuable.assignees).to eq [maintainer]
+
+ add_note("/unassign me")
+
+ expect(page).not_to have_content '/unassign me'
+ expect(page).to have_content 'Commands applied'
+
+ expect(issuable.reload.assignees).to eq []
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains unassign quick action: from bob' do
+ assignee = create(:user, username: 'bob')
+ issuable.update(assignee_ids: [assignee.id])
+ expect(issuable.assignees).to eq [assignee]
+
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ page.within('.js-main-target-form') do
+ fill_in 'note[note]', with: "Awesome!\n/unassign @bob "
+ click_on 'Preview'
+
+ expect(page).not_to have_content '/unassign @bob'
+ expect(page).to have_content 'Awesome!'
+ expect(page).to have_content 'Removes assignee @bob.'
+ end
+ end
+
+ it 'explains unassign quick action: from me' do
+ issuable.update(assignee_ids: [maintainer.id])
+ expect(issuable.assignees).to eq [maintainer]
+
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ page.within('.js-main-target-form') do
+ fill_in 'note[note]', with: "Awesome!\n/unassign me"
+ click_on 'Preview'
+
+ expect(page).not_to have_content '/unassign me'
+ expect(page).to have_content 'Awesome!'
+ expect(page).to have_content "Removes assignee @#{maintainer.username}."
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..1a1ee05841f
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/unlabel_quick_action_shared_examples.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+shared_examples 'unlabel quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets unlabel quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug /unlabel"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.labels).to eq [label_bug]
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ issuable.update(labels: [label_bug, label_feature])
+ end
+
+ it 'creates the note and interprets the unlabel all quick action accordingly' do
+ add_note("/unlabel")
+
+ wait_for_requests
+ expect(page).not_to have_content '/unlabel'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.labels).to eq []
+ end
+
+ it 'creates the note and interprets the unlabel some quick action accordingly' do
+ add_note("/unlabel ~bug")
+
+ wait_for_requests
+ expect(page).not_to have_content '/unlabel'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload.labels).to match_array([label_feature])
+ end
+
+ context "when current user cannot unlabel to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'does not unlabel' do
+ add_note("/unlabel")
+
+ wait_for_requests
+ expect(page).not_to have_content '/unlabel'
+ expect(issuable.labels).to match_array([label_bug, label_feature])
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ before do
+ issuable.update(labels: [label_bug, label_feature])
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ end
+
+ it 'explains unlabel all quick action' do
+ preview_note('/unlabel')
+
+ expect(page).not_to have_content '/unlabel'
+ expect(page).to have_content 'Removes all labels.'
+ end
+
+ it 'explains unlabel some quick action' do
+ preview_note('/unlabel ~bug')
+
+ expect(page).not_to have_content '/unlabel'
+ expect(page).to have_content 'Removes bug label.'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..998ff99b32e
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/unlock_quick_action_shared_examples.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+shared_examples 'unlock quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets unlock quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/unlock"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable).not_to be_discussion_locked
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ issuable.update(discussion_locked: true)
+ expect(issuable).to be_discussion_locked
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it 'creates the note and interprets the unlock quick action accordingly' do
+ add_note('/unlock')
+
+ wait_for_requests
+ expect(page).not_to have_content '/unlock'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.reload).not_to be_discussion_locked
+ end
+
+ context "when current user cannot unlock to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not lock the #{issuable_type}" do
+ add_note('/unlock')
+
+ wait_for_requests
+ expect(page).not_to have_content '/unlock'
+ expect(issuable).to be_discussion_locked
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains unlock quick action' do
+ issuable.update(discussion_locked: true)
+ expect(issuable).to be_discussion_locked
+
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+
+ preview_note('/unlock')
+
+ expect(page).not_to have_content '/unlock'
+ expect(page).to have_content 'Unlocks the discussion'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..bd92f133889
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issuable/unsubscribe_quick_action_shared_examples.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+shared_examples 'unsubscribe quick action' do |issuable_type|
+ before do
+ project.add_maintainer(maintainer)
+ gitlab_sign_in(maintainer)
+ end
+
+ context "new #{issuable_type}", :js do
+ before do
+ case issuable_type
+ when :merge_request
+ visit public_send('namespace_project_new_merge_request_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ when :issue
+ visit public_send('new_namespace_project_issue_path', project.namespace, project, new_url_opts)
+ wait_for_all_requests
+ end
+ end
+
+ it "creates the #{issuable_type} and interprets unsubscribe quick action accordingly" do
+ fill_in "#{issuable_type}_title", with: 'bug 345'
+ fill_in "#{issuable_type}_description", with: "bug description\n/unsubscribe"
+ click_button "Submit #{issuable_type}".humanize
+
+ issuable = project.public_send(issuable_type.to_s.pluralize).first
+
+ expect(issuable.description).to eq 'bug description'
+ expect(issuable).to be_opened
+ expect(page).to have_content 'bug 345'
+ expect(page).to have_content 'bug description'
+ expect(issuable.subscribed?(maintainer, project)).to be_truthy
+ end
+ end
+
+ context "post note to existing #{issuable_type}" do
+ before do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ issuable.subscribe(maintainer, project)
+ expect(issuable.subscribed?(maintainer, project)).to be_truthy
+ end
+
+ it 'creates the note and interprets the unsubscribe quick action accordingly' do
+ add_note('/unsubscribe')
+
+ wait_for_requests
+ expect(page).not_to have_content '/unsubscribe'
+ expect(page).to have_content 'Commands applied'
+ expect(issuable.subscribed?(maintainer, project)).to be_falsey
+ end
+
+ context "when current user cannot unsubscribe to #{issuable_type}" do
+ before do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ gitlab_sign_out
+ gitlab_sign_in(guest)
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ wait_for_all_requests
+ end
+
+ it "does not unsubscribe to the #{issuable_type}" do
+ add_note('/unsubscribe')
+
+ wait_for_requests
+ expect(page).not_to have_content '/unsubscribe'
+ expect(issuable.subscribed?(maintainer, project)).to be_truthy
+ end
+ end
+ end
+
+ context "preview of note on #{issuable_type}", :js do
+ it 'explains unsubscribe quick action' do
+ visit public_send("project_#{issuable_type}_path", project, issuable)
+ issuable.subscribe(maintainer, project)
+ expect(issuable.subscribed?(maintainer, project)).to be_truthy
+
+ preview_note('/unsubscribe')
+
+ expect(page).not_to have_content '/unsubscribe'
+ expect(page).to have_content "Unsubscribes from this #{issuable_type.to_s.humanize.downcase}."
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..6edd20bb024
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/board_move_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'board_move quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..c68e5aee842
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/confidential_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'confidential quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..5bfc3bb222f
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'create_merge_request quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..db3ecccc339
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+shared_examples 'due quick action not available' do
+ it 'does not set the due date' do
+ add_note('/due 2016-08-28')
+
+ expect(page).not_to have_content 'Commands applied'
+ expect(page).not_to have_content '/due 2016-08-28'
+ end
+end
+
+shared_examples 'due quick action available and date can be added' do
+ it 'sets the due date accordingly' do
+ add_note('/due 2016-08-28')
+
+ expect(page).not_to have_content '/due 2016-08-28'
+ expect(page).to have_content 'Commands applied'
+
+ visit project_issue_path(project, issue)
+
+ page.within '.due_date' do
+ expect(page).to have_content 'Aug 28, 2016'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..24576fe0021
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/duplicate_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'duplicate quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..953e67b0423
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'move quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..5904164fcfc
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+shared_examples 'remove_due_date action not available' do
+ it 'does not remove the due date' do
+ add_note("/remove_due_date")
+
+ expect(page).not_to have_content 'Commands applied'
+ expect(page).not_to have_content '/remove_due_date'
+ end
+end
+
+shared_examples 'remove_due_date action available and due date can be removed' do
+ it 'removes the due date accordingly' do
+ add_note('/remove_due_date')
+
+ expect(page).not_to have_content '/remove_due_date'
+ expect(page).to have_content 'Commands applied'
+
+ visit project_issue_path(project, issue)
+
+ page.within '.due_date' do
+ expect(page).to have_content 'No due date'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..31d88183f0d
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'merge quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..ccb4a85325b
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/merge_request/target_branch_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'target_branch quick action' do
+end
diff --git a/spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb
new file mode 100644
index 00000000000..6abb12b41b2
--- /dev/null
+++ b/spec/support/shared_examples/quick_actions/merge_request/wip_quick_action_shared_examples.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+shared_examples 'wip quick action' do
+end
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 533e9d87ea6..9ce9a353913 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -375,7 +375,7 @@ describe ObjectStorage do
describe '#fog_public' do
subject { uploader.fog_public }
- it { is_expected.to eq(false) }
+ it { is_expected.to eq(nil) }
end
describe '.workhorse_authorize' do
diff --git a/spec/workers/migrate_external_diffs_worker_spec.rb b/spec/workers/migrate_external_diffs_worker_spec.rb
new file mode 100644
index 00000000000..88d48cad14b
--- /dev/null
+++ b/spec/workers/migrate_external_diffs_worker_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MigrateExternalDiffsWorker do
+ let(:worker) { described_class.new }
+ let(:diff) { create(:merge_request).merge_request_diff }
+
+ describe '#perform' do
+ it 'migrates the listed diff' do
+ expect_next_instance_of(MergeRequests::MigrateExternalDiffsService) do |instance|
+ expect(instance.diff).to eq(diff)
+ expect(instance).to receive(:execute)
+ end
+
+ worker.perform(diff.id)
+ end
+
+ it 'does nothing if the diff is missing' do
+ diff.destroy
+
+ worker.perform(diff.id)
+ end
+ end
+end
diff --git a/spec/workers/schedule_migrate_external_diffs_worker_spec.rb b/spec/workers/schedule_migrate_external_diffs_worker_spec.rb
new file mode 100644
index 00000000000..9d6fecc9f4e
--- /dev/null
+++ b/spec/workers/schedule_migrate_external_diffs_worker_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ScheduleMigrateExternalDiffsWorker do
+ include ExclusiveLeaseHelpers
+
+ let(:worker) { described_class.new }
+
+ describe '#perform' do
+ it 'triggers a scan for diffs to migrate' do
+ expect(MergeRequests::MigrateExternalDiffsService).to receive(:enqueue!)
+
+ worker.perform
+ end
+
+ it 'will not run if the lease is already taken' do
+ stub_exclusive_lease_taken('schedule_migrate_external_diffs_worker', timeout: 2.hours)
+
+ expect(MergeRequests::MigrateExternalDiffsService).not_to receive(:enqueue!)
+
+ worker.perform
+ end
+ end
+end