diff options
161 files changed, 1121 insertions, 294 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f832b88b821..9c6b84d3931 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,7 +67,7 @@ variables: RAILS_ENV: "test" NODE_ENV: "test" BUNDLE_WITHOUT: "production:development" - BUNDLE_INSTALL_FLAGS: "--jobs=$(nproc) --retry=3 --quiet" + BUNDLE_INSTALL_FLAGS: "--jobs=$(nproc) --retry=3" BUNDLE_FROZEN: "true" # we override the max_old_space_size to prevent OOM errors NODE_OPTIONS: --max_old_space_size=3584 diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index a214959deab..bb6ebaa42d5 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -1801,6 +1801,10 @@ when: never - <<: *if-default-branch-or-tag changes: *code-backstage-qa-patterns + - <<: *if-dot-com-gitlab-org-merge-request + changes: [".gitlab/ci/setup.gitlab-ci.yml"] + when: manual + allow_failure: true .setup:rules:dont-interrupt-me: rules: diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml index 437b02e4819..4f3111de2bf 100644 --- a/.gitlab/ci/setup.gitlab-ci.yml +++ b/.gitlab/ci/setup.gitlab-ci.yml @@ -3,16 +3,20 @@ cache gems: extends: - .default-retry - - .rails-cache + - .ruby-cache - .default-before_script - .setup:rules:cache-gems - stage: test - needs: ["setup-test-env"] + stage: prepare + needs: [] variables: - BUNDLE_INSTALL_FLAGS: --with=production --with=development --with=test --jobs=2 --path=vendor --retry=3 --quiet + BUNDLE_WITHOUT: "" + BUNDLE_WITH: "production:development:test" SETUP_DB: "false" script: - - bundle package --all --all-platforms + - echo -e "\e[0Ksection_start:`date +%s`:bundle-package[collapsed=true]\r\e[0KPackaging gems" + - bundle config set cache_all true + - run_timed_command "bundle package --all-platforms" + - echo -e "\e[0Ksection_end:`date +%s`:bundle-package\r\e[0K" artifacts: paths: - vendor/cache diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue index 4c2f55fd174..679c8caffdb 100644 --- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue +++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue @@ -69,14 +69,18 @@ export default { </script> <template> <div> - <div v-if="!isLocalStorageAvailable" ref="localStorageNote" class="dropdown-info-note"> + <div + v-if="!isLocalStorageAvailable" + data-testid="local-storage-note" + class="dropdown-info-note" + > {{ __('This feature requires local storage to be enabled') }} </div> <ul v-else-if="hasItems"> <li v-for="(item, index) in processedItems" - ref="dropdownItem" :key="`processed-items-${index}`" + data-testid="dropdown-item" > <button type="button" @@ -100,7 +104,7 @@ export default { <li class="divider"></li> <li> <button - ref="clearButton" + data-testid="clear-button" type="button" class="filtered-search-history-clear-button" @click="onRequestClearRecentSearches($event)" @@ -109,7 +113,7 @@ export default { </button> </li> </ul> - <div v-else ref="dropdownNote" class="dropdown-info-note"> + <div v-else data-testid="dropdown-note" class="dropdown-info-note"> {{ __("You don't have any recent searches") }} </div> </div> diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue index 1da0b88c9e9..c0bfcf9c4a9 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue @@ -58,7 +58,7 @@ export default { <template> <div class="frequent-items-list-container"> - <ul ref="frequentItemsList" class="list-unstyled"> + <ul data-testid="frequent-items-list" class="list-unstyled"> <li v-if="isListEmpty" :class="{ 'section-failure': isFetchFailed }" diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue index 9fb69a3cae3..33ab1d5cd7f 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue @@ -79,16 +79,19 @@ export default { :project-name="itemName" aria-hidden="true" /> - <div ref="frequentItemsItemMetadataContainer" class="frequent-items-item-metadata-container"> + <div + data-testid="frequent-items-item-metadata-container" + class="frequent-items-item-metadata-container" + > <div - ref="frequentItemsItemTitle" v-safe-html="highlightedItemName" + data-testid="frequent-items-item-title" :title="itemName" class="frequent-items-item-title" ></div> <div v-if="namespace" - ref="frequentItemsItemNamespace" + data-testid="frequent-items-item-namespace" :title="namespace" class="frequent-items-item-namespace" > diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 07d786ab060..8ed67c26f19 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -65,7 +65,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController add_pagination_headers(tokens) end - ::API::Entities::PersonalAccessTokenWithDetails.represent(tokens) + ::PersonalAccessTokenSerializer.new.represent(tokens) end def add_pagination_headers(relation) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 7474485a09b..5a212e9a152 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -220,7 +220,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def context_commits # Get commits from repository # or from cache if already merged - commits = ContextCommitsFinder.new(project, @merge_request, { search: params[:search], limit: params[:limit], offset: params[:offset] }).execute + commits = ContextCommitsFinder.new(project, @merge_request, { + search: params[:search], + author: params[:author], + committed_before: convert_date_to_epoch(params[:committed_before]), + committed_after: convert_date_to_epoch(params[:committed_after]), + limit: params[:limit] + }).execute render json: CommitEntity.represent(commits, { type: :full, request: merge_request }) end @@ -553,6 +559,11 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params) end + + def convert_date_to_epoch(date) + Date.strptime(date, "%Y-%m-%d")&.to_time&.to_i if date + rescue Date::Error, TypeError + end end Projects::MergeRequestsController.prepend_mod_with('Projects::MergeRequestsController') diff --git a/app/finders/context_commits_finder.rb b/app/finders/context_commits_finder.rb index d623854ada4..4a45817cc61 100644 --- a/app/finders/context_commits_finder.rb +++ b/app/finders/context_commits_finder.rb @@ -5,8 +5,10 @@ class ContextCommitsFinder @project = project @merge_request = merge_request @search = params[:search] + @author = params[:author] + @committed_before = params[:committed_before] + @committed_after = params[:committed_after] @limit = (params[:limit] || 40).to_i - @offset = (params[:offset] || 0).to_i end def execute @@ -16,13 +18,13 @@ class ContextCommitsFinder private - attr_reader :project, :merge_request, :search, :limit, :offset + attr_reader :project, :merge_request, :search, :author, :committed_before, :committed_after, :limit def init_collection if search.present? search_commits else - project.repository.commits(merge_request.target_branch, { limit: limit, offset: offset }) + project.repository.commits(merge_request.target_branch, { limit: limit }) end end @@ -41,7 +43,8 @@ class ContextCommitsFinder commits = [commit_by_sha] if commit_by_sha end else - commits = project.repository.find_commits_by_message(search, merge_request.target_branch, nil, 20) + commits = project.repository.list_commits_by(search, merge_request.target_branch, + author: author, before: committed_before, after: committed_after, limit: limit) end commits diff --git a/app/finders/groups/accepting_group_transfers_finder.rb b/app/finders/groups/accepting_group_transfers_finder.rb index 03f5e492d27..df67f940d20 100644 --- a/app/finders/groups/accepting_group_transfers_finder.rb +++ b/app/finders/groups/accepting_group_transfers_finder.rb @@ -2,6 +2,8 @@ module Groups class AcceptingGroupTransfersFinder < Base + include Gitlab::Utils::StrongMemoize + def initialize(current_user, group_to_be_transferred, params = {}) @current_user = current_user @group_to_be_transferred = group_to_be_transferred @@ -11,7 +13,12 @@ module Groups def execute return Group.none unless can_transfer_group? - items = find_groups + items = if Feature.enabled?(:include_groups_from_group_shares_in_group_transfer_locations) + find_all_groups + else + find_groups + end + items = by_search(items) sort(items) @@ -29,11 +36,30 @@ module Groups ).execute.without_order end + def find_all_groups + ::Namespace.from_union( + [ + find_groups, + groups_originating_from_group_shares_with_owner_access + ] + ) + end + + def groups_originating_from_group_shares_with_owner_access + GroupGroupLink + .with_owner_access + .groups_accessible_via( + current_user.owned_groups.select(:id) + ).id_not_in(exclude_groups) + end + def exclude_groups - exclude_groups = group_to_be_transferred.self_and_descendants.pluck_primary_key - exclude_groups << group_to_be_transferred.parent_id if group_to_be_transferred.parent_id + strong_memoize(:exclude_groups) do + exclude_groups = group_to_be_transferred.self_and_descendants.pluck_primary_key + exclude_groups << group_to_be_transferred.parent_id if group_to_be_transferred.parent_id - exclude_groups + exclude_groups + end end def can_transfer_group? diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index ef01ef4697f..eb17770ab62 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -977,6 +977,11 @@ module Ci end # With multi-project and parent-child pipelines + def self_and_downstreams + object_hierarchy.base_and_descendants + end + + # With multi-project and parent-child pipelines def upstream_and_all_downstreams object_hierarchy.all_objects end @@ -1012,7 +1017,12 @@ module Ci # Follow the upstream pipeline relationships, regardless of multi-project or # parent-child, and return the top-level ancestor. def upstream_root - object_hierarchy.base_and_ancestors(hierarchy_order: :desc).first + @upstream_root ||= object_hierarchy.base_and_ancestors(hierarchy_order: :desc).first + end + + # Applies to all parent-child and multi-project pipelines + def complete_hierarchy_count + upstream_root.self_and_downstreams.count end def bridge_triggered? diff --git a/app/models/ci/pipeline_artifact.rb b/app/models/ci/pipeline_artifact.rb index 4954463a37a..6d22a875aab 100644 --- a/app/models/ci/pipeline_artifact.rb +++ b/app/models/ci/pipeline_artifact.rb @@ -53,7 +53,7 @@ module Ci find_by(file_type: file_type) end - def create_or_replace_for_pipeline!(pipeline:, file_type:, file:, size:) + def create_or_replace_for_pipeline!(pipeline:, file_type:, file:, size:, locked: :unknown) transaction do pipeline.pipeline_artifacts.find_by_file_type(file_type)&.destroy! @@ -63,7 +63,8 @@ module Ci size: size, file: file, file_format: REPORT_TYPES[file_type], - expire_at: EXPIRATION_DATE.from_now + expire_at: EXPIRATION_DATE.from_now, + locked: locked ) end rescue ActiveRecord::ActiveRecordError => err diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 60a9eade5a5..28d9edcc135 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -348,6 +348,12 @@ module Ci end end + def owner_project + return unless project_type? + + runner_projects.order(:id).first.project + end + def belongs_to_one_project? runner_projects.count == 1 end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index d8ca68eb2a5..7df0525fa35 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -319,11 +319,7 @@ class CommitStatus < Ci::ApplicationRecord end def stage_name - if Feature.enabled?(:ci_read_stage_records, project) - ci_stage&.name - else - stage - end + ci_stage&.name end private diff --git a/app/models/group_group_link.rb b/app/models/group_group_link.rb index 8dd245a6ab5..7005c8593bd 100644 --- a/app/models/group_group_link.rb +++ b/app/models/group_group_link.rb @@ -19,6 +19,10 @@ class GroupGroupLink < ApplicationRecord where(group_access: [Gitlab::Access::OWNER, Gitlab::Access::MAINTAINER]) end + scope :with_owner_access, -> do + where(group_access: [Gitlab::Access::OWNER]) + end + scope :groups_accessible_via, -> (shared_with_group_ids) do links = where(shared_with_group_id: shared_with_group_ids) # a group share also gives you access to the descendants of the group being shared, diff --git a/app/models/repository.rb b/app/models/repository.rb index 63fbb86544c..5aa9267b00e 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -194,6 +194,18 @@ class Repository CommitCollection.new(container, commits, ref) end + def list_commits_by(query, ref, author: nil, before: nil, after: nil, limit: 1000) + return [] unless exists? + return [] unless has_visible_content? + return [] unless query.present? && ref.present? + + commits = raw_repository.list_commits_by( + query, ref, author: author, before: before, after: after, limit: limit).map do |c| + commit(c) + end + CommitCollection.new(container, commits, ref) + end + def find_branch(name) raw_repository.find_branch(name) end diff --git a/app/serializers/access_token_entity_base.rb b/app/serializers/access_token_entity_base.rb new file mode 100644 index 00000000000..db22dbf1302 --- /dev/null +++ b/app/serializers/access_token_entity_base.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# rubocop: disable Gitlab/NamespacedClass +class AccessTokenEntityBase < API::Entities::PersonalAccessToken + expose :expired?, as: :expired + expose :expires_soon?, as: :expires_soon +end +# rubocop: enable Gitlab/NamespacedClass diff --git a/app/serializers/group_access_token_entity.rb b/app/serializers/group_access_token_entity.rb index 76dc3999a61..ab1fbb8ab46 100644 --- a/app/serializers/group_access_token_entity.rb +++ b/app/serializers/group_access_token_entity.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # rubocop: disable Gitlab/NamespacedClass -class GroupAccessTokenEntity < API::Entities::PersonalAccessToken +class GroupAccessTokenEntity < AccessTokenEntityBase include Gitlab::Routing expose :revoke_path do |token, options| diff --git a/app/serializers/impersonation_access_token_entity.rb b/app/serializers/impersonation_access_token_entity.rb index 9c59ed58bd8..b4ed62a890d 100644 --- a/app/serializers/impersonation_access_token_entity.rb +++ b/app/serializers/impersonation_access_token_entity.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # rubocop: disable Gitlab/NamespacedClass -class ImpersonationAccessTokenEntity < API::Entities::PersonalAccessToken +class ImpersonationAccessTokenEntity < AccessTokenEntityBase include Gitlab::Routing expose :revoke_path do |token, _options| diff --git a/app/serializers/personal_access_token_entity.rb b/app/serializers/personal_access_token_entity.rb index acd06fecd12..49dcdf12a6f 100644 --- a/app/serializers/personal_access_token_entity.rb +++ b/app/serializers/personal_access_token_entity.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # rubocop: disable Gitlab/NamespacedClass -class PersonalAccessTokenEntity < API::Entities::PersonalAccessToken +class PersonalAccessTokenEntity < AccessTokenEntityBase include Gitlab::Routing expose :revoke_path do |token, options| diff --git a/app/serializers/project_access_token_entity.rb b/app/serializers/project_access_token_entity.rb index 695a5122348..52bb7b05d4e 100644 --- a/app/serializers/project_access_token_entity.rb +++ b/app/serializers/project_access_token_entity.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # rubocop: disable Gitlab/NamespacedClass -class ProjectAccessTokenEntity < API::Entities::PersonalAccessToken +class ProjectAccessTokenEntity < AccessTokenEntityBase include Gitlab::Routing expose :revoke_path do |token, options| diff --git a/app/services/ci/pipeline_artifacts/coverage_report_service.rb b/app/services/ci/pipeline_artifacts/coverage_report_service.rb index c11a8f7a0fd..99877603554 100644 --- a/app/services/ci/pipeline_artifacts/coverage_report_service.rb +++ b/app/services/ci/pipeline_artifacts/coverage_report_service.rb @@ -27,12 +27,18 @@ module Ci end def pipeline_artifact_params - { + attributes = { pipeline: pipeline, file_type: :code_coverage, file: carrierwave_file, size: carrierwave_file['tempfile'].size } + + if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project) + attributes[:locked] = pipeline.locked + end + + attributes end def carrierwave_file diff --git a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb index d6865efac9f..aeb68a75f88 100644 --- a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb +++ b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb @@ -13,21 +13,31 @@ module Ci return if pipeline.has_codequality_mr_diff_report? return unless new_errors_introduced? + pipeline.pipeline_artifacts.create!(**artifact_attributes) + end + + private + + attr_reader :pipeline + + def artifact_attributes file = build_carrierwave_file! - pipeline.pipeline_artifacts.create!( + attributes = { project_id: pipeline.project_id, file_type: :code_quality_mr_diff, file_format: Ci::PipelineArtifact::REPORT_TYPES.fetch(:code_quality_mr_diff), size: file["tempfile"].size, file: file, expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now - ) - end + } - private + if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project) + attributes[:locked] = pipeline.locked + end - attr_reader :pipeline + attributes + end def merge_requests strong_memoize(:merge_requests) do diff --git a/app/services/ci/runners/set_runner_associated_projects_service.rb b/app/services/ci/runners/set_runner_associated_projects_service.rb new file mode 100644 index 00000000000..759bd2ffb16 --- /dev/null +++ b/app/services/ci/runners/set_runner_associated_projects_service.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +module Ci + module Runners + class SetRunnerAssociatedProjectsService + # @param [Ci::Runner] runner: the project runner to assign/unassign projects from + # @param [User] current_user: the user performing the operation + # @param [Array<Integer>] project_ids: the IDs of the associated projects to assign the runner to + def initialize(runner:, current_user:, project_ids:) + @runner = runner + @current_user = current_user + @project_ids = project_ids + end + + def execute + unless current_user&.can?(:assign_runner, runner) + return ServiceResponse.error(message: 'user not allowed to assign runner', http_status: :forbidden) + end + + set_associated_projects + end + + private + + def set_associated_projects + new_project_ids = [runner.owner_project.id] + project_ids + + response = ServiceResponse.success + runner.transaction do + # rubocop:disable CodeReuse/ActiveRecord + current_project_ids = runner.projects.ids + # rubocop:enable CodeReuse/ActiveRecord + + unless associate_new_projects(new_project_ids, current_project_ids) + response = ServiceResponse.error(message: 'failed to assign projects to runner') + raise ActiveRecord::Rollback, response.errors + end + + unless disassociate_old_projects(new_project_ids, current_project_ids) + response = ServiceResponse.error(message: 'failed to destroy runner project') + raise ActiveRecord::Rollback, response.errors + end + end + + response + end + + def associate_new_projects(new_project_ids, current_project_ids) + missing_projects = Project.id_in(new_project_ids - current_project_ids) + missing_projects.each do |project| + return false unless runner.assign_to(project, current_user) + end + + true + end + + def disassociate_old_projects(new_project_ids, current_project_ids) + Ci::RunnerProject + .destroy_by(project_id: current_project_ids - new_project_ids) + .all?(&:destroyed?) + end + + attr_reader :runner, :current_user, :project_ids + end + end +end + +Ci::Runners::SetRunnerAssociatedProjectsService.prepend_mod diff --git a/app/services/ci/unlock_artifacts_service.rb b/app/services/ci/unlock_artifacts_service.rb index 30da31ba8ec..1fee31da4fc 100644 --- a/app/services/ci/unlock_artifacts_service.rb +++ b/app/services/ci/unlock_artifacts_service.rb @@ -7,9 +7,12 @@ module Ci def execute(ci_ref, before_pipeline = nil) results = { unlocked_pipelines: 0, - unlocked_job_artifacts: 0 + unlocked_job_artifacts: 0, + unlocked_pipeline_artifacts: 0 } + unlock_pipeline_artifacts_enabled = ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, ci_ref.project) + if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, ci_ref.project) loop do unlocked_pipelines = [] @@ -18,6 +21,10 @@ module Ci ::Ci::Pipeline.transaction do unlocked_pipelines = unlock_pipelines(ci_ref, before_pipeline) unlocked_job_artifacts = unlock_job_artifacts(unlocked_pipelines) + + if unlock_pipeline_artifacts_enabled + results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines) + end end break if unlocked_pipelines.empty? @@ -100,6 +107,14 @@ module Ci ) end + # rubocop:disable CodeReuse/ActiveRecord + def unlock_pipeline_artifacts(pipelines) + return 0 if pipelines.empty? + + ::Ci::PipelineArtifact.where(pipeline_id: pipelines.rows.flatten).update_all(locked: :unlocked) + end + # rubocop:enable CodeReuse/ActiveRecord + def unlock_pipelines(ci_ref, before_pipeline) ::Ci::Pipeline.connection.exec_query(unlock_pipelines_query(ci_ref, before_pipeline)) end diff --git a/app/services/concerns/ci/downstream_pipeline_helpers.rb b/app/services/concerns/ci/downstream_pipeline_helpers.rb index 557bfe2534b..26d7eb97151 100644 --- a/app/services/concerns/ci/downstream_pipeline_helpers.rb +++ b/app/services/concerns/ci/downstream_pipeline_helpers.rb @@ -5,7 +5,6 @@ module Ci def log_downstream_pipeline_creation(downstream_pipeline) return unless downstream_pipeline&.persisted? - hierarchy_size = downstream_pipeline.upstream_and_all_downstreams.count root_pipeline = downstream_pipeline.upstream_root ::Gitlab::AppLogger.info( @@ -14,7 +13,7 @@ module Ci root_pipeline_id: root_pipeline.id, downstream_pipeline_id: downstream_pipeline.id, downstream_pipeline_relationship: downstream_pipeline.parent_pipeline? ? :parent_child : :multi_project, - hierarchy_size: hierarchy_size, + hierarchy_size: downstream_pipeline.complete_hierarchy_count, root_pipeline_plan: root_pipeline.project.actual_plan_name, root_pipeline_namespace_path: root_pipeline.project.namespace.full_path, root_pipeline_project_path: root_pipeline.project.full_path diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index 5205d34baae..533d0052fb8 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -234,6 +234,7 @@ module MergeRequests end # Add comment about pushing new commits to merge requests and send nofitication emails + # def notify_about_push(merge_request) return unless @commits.present? diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index d64089ea58a..79fc1a64790 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -8,16 +8,15 @@ %h1.page-title.gl-font-size-h-display = s_('TagsPage|New Tag') -%hr = form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "common-note-form tag-form js-quick-submit js-requires-input" do .form-group.row - = label_tag :tag_name, nil, class: 'col-form-label col-sm-2' - .col-sm-10 + .col-sm-12 + = label_tag :tag_name, nil = text_field_tag :tag_name, params[:tag_name], required: true, autofocus: true, class: 'form-control', data: { qa_selector: "tag_name_field" } .form-group.row - = label_tag :ref, 'Create from', class: 'col-form-label col-sm-2' - .col-sm-10.create-from + .col-sm-12.create-from + = label_tag :ref, 'Create from' .dropdown = hidden_field_tag :ref, default_ref = button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide js-branch-select monospace', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do @@ -27,15 +26,14 @@ .form-text.text-muted = s_('TagsPage|Existing branch name, tag, or commit SHA') .form-group.row - = label_tag :message, nil, class: 'col-form-label col-sm-2' - .col-sm-10 + .col-sm-12 + = label_tag :message, nil = text_area_tag :message, @message, required: false, class: 'form-control', rows: 5, data: { qa_selector: "tag_message_field" } .form-text.text-muted = tag_description_help_text - %hr .form-group.row - = label_tag :release_description, s_('TagsPage|Release notes'), class: 'col-form-label col-sm-2' - .col-sm-10 + .col-sm-12 + = label_tag :release_description, s_('TagsPage|Release notes'), class: 'gl-mb-0' .form-text.mb-3 - link_start = '<a href="%{url}" rel="noopener noreferrer" target="_blank">'.html_safe - releases_page_path = project_releases_path(@project) @@ -49,7 +47,7 @@ = render layout: 'shared/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do = render 'shared/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here…'), current_text: @release_description, qa_selector: 'release_notes_field' = render 'shared/notes/hints' - .form-actions.gl-display-flex + .gl-display-flex = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'gl-mr-3', data: { qa_selector: "create_tag_button" }, type: 'submit' }) do = s_('TagsPage|Create tag') = render Pajamas::ButtonComponent.new(href: project_tags_path(@project)) do diff --git a/config/feature_flags/development/ci_read_stage_records.yml b/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml index 2a7e6ecf5ad..ffcd5352751 100644 --- a/config/feature_flags/development/ci_read_stage_records.yml +++ b/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml @@ -1,8 +1,8 @@ --- -name: ci_read_stage_records -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94941 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371486 +name: ci_update_unlocked_pipeline_artifacts +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97228 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372835 milestone: '15.4' type: development -group: group::pipeline execution +group: group::pipeline insights default_enabled: false diff --git a/config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml b/config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml new file mode 100644 index 00000000000..f92a6b2b1b0 --- /dev/null +++ b/config/feature_flags/development/include_groups_from_group_shares_in_group_transfer_locations.yml @@ -0,0 +1,8 @@ +--- +name: include_groups_from_group_shares_in_group_transfer_locations +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96347 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/371961 +milestone: '15.4' +type: development +group: group::workspace +default_enabled: false diff --git a/db/post_migrate/20220906074449_schedule_disable_legacy_open_source_license_for_projects_less_than_one_mb.rb b/db/post_migrate/20220906074449_schedule_disable_legacy_open_source_license_for_projects_less_than_one_mb.rb new file mode 100644 index 00000000000..ee48ace13e0 --- /dev/null +++ b/db/post_migrate/20220906074449_schedule_disable_legacy_open_source_license_for_projects_less_than_one_mb.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class ScheduleDisableLegacyOpenSourceLicenseForProjectsLessThanOneMb < Gitlab::Database::Migration[2.0] + MIGRATION = 'DisableLegacyOpenSourceLicenseForProjectsLessThanOneMb' + INTERVAL = 2.minutes + BATCH_SIZE = 4_000 + MAX_BATCH_SIZE = 50_000 + SUB_BATCH_SIZE = 250 + + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main + + def up + return unless Gitlab.com? + + queue_batched_background_migration( + MIGRATION, + :project_settings, + :project_id, + job_interval: INTERVAL, + batch_size: BATCH_SIZE, + max_batch_size: MAX_BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + return unless Gitlab.com? + + delete_batched_background_migration(MIGRATION, :project_settings, :project_id, []) + end +end diff --git a/db/schema_migrations/20220906074449 b/db/schema_migrations/20220906074449 new file mode 100644 index 00000000000..df657642eb3 --- /dev/null +++ b/db/schema_migrations/20220906074449 @@ -0,0 +1 @@ +fc34cdbddc61ee9c23b790101f911d21892cf2ace34e3615b920817374c803f9
\ No newline at end of file diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md index 94c12f80fda..4b75141ac43 100644 --- a/doc/development/documentation/styleguide/word_list.md +++ b/doc/development/documentation/styleguide/word_list.md @@ -147,6 +147,18 @@ Do not use **and so on**. Instead, be more specific. For details, see Use [**section**](#section) instead of **area**. The only exception is [the Admin Area](#admin-area). +## as + +Do not use **as** to mean **because**. + +Use: + +- Because none of the endpoints return an ID... + +Instead of: + +- As none of the endpoints return an ID... + ## associate Do not use **associate** when describing adding issues to epics, or users to issues, merge requests, @@ -619,6 +631,10 @@ Instead of: - Buy a license. - Purchase a license. +## limitations + +Do not use **limitations**. Use **known issues** instead. + ## log in, log on Do not use **log in** or **log on**. Use [sign in](#sign-in) instead. If the user interface has **Log in**, you can use it. diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md index ade0277efa8..f238678b662 100644 --- a/doc/user/project/merge_requests/cherry_pick_changes.md +++ b/doc/user/project/merge_requests/cherry_pick_changes.md @@ -20,6 +20,32 @@ NOTE: Support for tracking commits cherry-picked from the command line is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/202215). +## Cherry-pick example + +In this example of cherry-picking, a Git repository has two branches: `develop` and `main`. + +```mermaid +gitGraph + commit id: "A" + branch develop + commit id:"B" + checkout main + commit id:"C" + checkout develop + commit id:"D" + checkout main + commit id:"E" + cherry-pick id:"B" + commit id:"G" + checkout develop + commit id:"H" +``` + +The example shows a cherry-pick of commit `B` from the `develop` branch, which is added +after commit `E` in the `main` branch. + +Commit `G` is added after the cherry-pick. + ## Cherry-pick all changes from a merge request After a merge request is merged, you can cherry-pick all changes introduced diff --git a/lib/api/entities/personal_access_token_with_details.rb b/lib/api/entities/personal_access_token_with_details.rb deleted file mode 100644 index 5654bd4a1e1..00000000000 --- a/lib/api/entities/personal_access_token_with_details.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module API - module Entities - class PersonalAccessTokenWithDetails < Entities::PersonalAccessToken - expose :expired?, as: :expired - expose :expires_soon?, as: :expires_soon - expose :revoke_path do |token| - Gitlab::Routing.url_helpers.revoke_profile_personal_access_token_path(token) - end - end - end -end diff --git a/lib/gitlab/background_migration/disable_legacy_open_source_license_for_projects_less_than_one_mb.rb b/lib/gitlab/background_migration/disable_legacy_open_source_license_for_projects_less_than_one_mb.rb new file mode 100644 index 00000000000..6e4d5d8ddcb --- /dev/null +++ b/lib/gitlab/background_migration/disable_legacy_open_source_license_for_projects_less_than_one_mb.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # Set `project_settings.legacy_open_source_license_available` to false for projects less than 1 MB + class DisableLegacyOpenSourceLicenseForProjectsLessThanOneMb < ::Gitlab::BackgroundMigration::BatchedMigrationJob + scope_to ->(relation) { relation.where(legacy_open_source_license_available: true) } + + def perform + each_sub_batch(operation_name: :disable_legacy_open_source_license_for_projects_less_than_one_mb) do |sub_batch| + updates = { legacy_open_source_license_available: false, updated_at: Time.current } + + sub_batch + .joins('INNER JOIN project_statistics ON project_statistics.project_id = project_settings.project_id') + .where('project_statistics.repository_size < ?', 1.megabyte) + .update_all(updates) + end + end + end + end +end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index d26834089b4..a68218f84b7 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1056,6 +1056,24 @@ module Gitlab end end + def list_commits_by(query, ref, author: nil, before: nil, after: nil, limit: 1000) + params = { + author: author, + ignore_case: true, + commit_message_patterns: query, + before: before, + after: after, + reverse: false, + pagination_params: { limit: limit } + } + + wrapped_gitaly_errors do + gitaly_commit_client + .list_commits([ref], params) + .map { |c| commit(c) } + end + end + def list_last_commits_for_tree(sha, path, offset: 0, limit: 25, literal_pathspec: false) wrapped_gitaly_errors do gitaly_commit_client.list_last_commits_for_tree(sha, path, offset: offset, limit: limit, literal_pathspec: literal_pathspec) diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index d76a1131160..312d1dddff1 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -251,14 +251,23 @@ module Gitlab consume_commits_response(response) end - def list_commits(revisions, reverse: false, pagination_params: nil) + def list_commits(revisions, params = {}) request = Gitaly::ListCommitsRequest.new( repository: @gitaly_repo, revisions: Array.wrap(revisions), - reverse: reverse, - pagination_params: pagination_params + reverse: !!params[:reverse], + ignore_case: params[:ignore_case], + pagination_params: params[:pagination_params] ) + if params[:commit_message_patterns] + request.commit_message_patterns += Array.wrap(params[:commit_message_patterns]) + end + + request.author = encode_binary(params[:author]) if params[:author] + request.before = GitalyClient.timestamp(params[:before]) if params[:before] + request.after = GitalyClient.timestamp(params[:after]) if params[:after] + response = GitalyClient.call(@repository.storage, :commit_service, :list_commits, request, timeout: GitalyClient.medium_timeout) consume_commits_response(response) end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index bea2ef2c9c4..769e0c90d4f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -43942,9 +43942,6 @@ msgstr "" msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system." msgstr "" -msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it." -msgstr "" - msgid "Vulnerability|Links" msgstr "" diff --git a/scripts/utils.sh b/scripts/utils.sh index 8db525abc93..10b7f856ee6 100644 --- a/scripts/utils.sh +++ b/scripts/utils.sh @@ -38,6 +38,8 @@ function bundle_install_script() { exit 1; fi; + echo -e "section_start:`date +%s`:bundle-install[collapsed=true]\r\e[0KInstalling gems" + gem --version bundle --version gem install bundler --no-document --conservative --version 2.3.15 @@ -48,7 +50,7 @@ function bundle_install_script() { echo "${BUNDLE_WITHOUT}" bundle config - run_timed_command "bundle install ${BUNDLE_INSTALL_FLAGS} ${extra_install_args} && bundle check" + run_timed_command "bundle install ${BUNDLE_INSTALL_FLAGS} ${extra_install_args}" if [[ $(bundle info pg) ]]; then # When we test multiple versions of PG in the same pipeline, we have a single `setup-test-env` @@ -56,6 +58,8 @@ function bundle_install_script() { # Uncomment the following line if multiple versions of PG are tested in the same pipeline. run_timed_command "bundle pristine pg" fi + + echo -e "section_end:`date +%s`:bundle-install\r\e[0K" } function setup_db_user_only() { diff --git a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb index 0e531dbaf4b..99e9644da66 100644 --- a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb +++ b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb @@ -48,8 +48,8 @@ RSpec.describe Profiles::PersonalAccessTokensController do end it "only includes details of the active personal access token" do - active_personal_access_tokens_detail = ::API::Entities::PersonalAccessTokenWithDetails - .represent([active_personal_access_token]) + active_personal_access_tokens_detail = + ::PersonalAccessTokenSerializer.new.represent([active_personal_access_token]) expect(assigns(:active_personal_access_tokens).to_json).to eq(active_personal_access_tokens_detail.to_json) end @@ -100,8 +100,8 @@ RSpec.describe Profiles::PersonalAccessTokensController do get :index first_token = assigns(:active_personal_access_tokens).first.as_json - expect(first_token[:name]).to eq("Token1") - expect(first_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) + expect(first_token['name']).to eq("Token1") + expect(first_token['expires_at']).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) end it "orders tokens on id in case token has same expires_at" do @@ -110,12 +110,12 @@ RSpec.describe Profiles::PersonalAccessTokensController do get :index first_token = assigns(:active_personal_access_tokens).first.as_json - expect(first_token[:name]).to eq("Token3") - expect(first_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) + expect(first_token['name']).to eq("Token3") + expect(first_token['expires_at']).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) second_token = assigns(:active_personal_access_tokens).second.as_json - expect(second_token[:name]).to eq("Token1") - expect(second_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) + expect(second_token['name']).to eq("Token1") + expect(second_token['expires_at']).to eq(expires_1_day_from_now.strftime("%Y-%m-%d")) end end diff --git a/spec/features/tags/developer_creates_tag_spec.rb b/spec/features/tags/developer_creates_tag_spec.rb index b0219cb546d..ca76a94092e 100644 --- a/spec/features/tags/developer_creates_tag_spec.rb +++ b/spec/features/tags/developer_creates_tag_spec.rb @@ -60,7 +60,7 @@ RSpec.describe 'Developer creates tag' do it 'opens dropdown for ref', :js do click_link 'New tag' - ref_row = find('.form-group:nth-of-type(2) .col-sm-10') + ref_row = find('.form-group:nth-of-type(2) .col-sm-12') page.within ref_row do ref_input = find('[name="ref"]', visible: false) expect(ref_input.value).to eq 'master' diff --git a/spec/finders/context_commits_finder_spec.rb b/spec/finders/context_commits_finder_spec.rb index 95c685aea24..c22675bc67d 100644 --- a/spec/finders/context_commits_finder_spec.rb +++ b/spec/finders/context_commits_finder_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe ContextCommitsFinder do describe "#execute" do let(:project) { create(:project, :repository) } - let(:merge_request) { create(:merge_request) } + let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') } let(:commit) { create(:commit, id: '6d394385cf567f80a8fd85055db1ab4c5295806f') } it 'filters commits by valid sha/commit message' do @@ -24,5 +24,29 @@ RSpec.describe ContextCommitsFinder do expect(commits).to be_empty end + + it 'returns commits based in author filter' do + params = { search: 'test text', author: 'Job van der Voort' } + commits = described_class.new(project, merge_request, params).execute + + expect(commits.length).to eq(1) + expect(commits[0].id).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') + end + + it 'returns commits based in before filter' do + params = { search: 'test text', committed_before: 1474828200 } + commits = described_class.new(project, merge_request, params).execute + + expect(commits.length).to eq(1) + expect(commits[0].id).to eq('498214de67004b1da3d820901307bed2a68a8ef6') + end + + it 'returns commits based in after filter' do + params = { search: 'test text', committed_after: 1474828200 } + commits = described_class.new(project, merge_request, params).execute + + expect(commits.length).to eq(1) + expect(commits[0].id).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') + end end end diff --git a/spec/finders/groups/accepting_group_transfers_finder_spec.rb b/spec/finders/groups/accepting_group_transfers_finder_spec.rb index 6c1ceb4f7ad..1a6c6f9243b 100644 --- a/spec/finders/groups/accepting_group_transfers_finder_spec.rb +++ b/spec/finders/groups/accepting_group_transfers_finder_spec.rb @@ -29,9 +29,27 @@ RSpec.describe Groups::AcceptingGroupTransfersFinder do end end + let_it_be(:shared_with_group_where_direct_owner_as_guest) { create(:group) } + let_it_be(:shared_with_group_where_direct_owner_as_owner) { create(:group) } + let_it_be(:subgroup_of_shared_with_group_where_direct_owner_as_owner) do + create(:group, parent: shared_with_group_where_direct_owner_as_owner) + end + let(:params) { {} } describe '#execute' do + before_all do + create(:group_group_link, :owner, + shared_with_group: group_where_user_has_owner_access, + shared_group: shared_with_group_where_direct_owner_as_owner + ) + + create(:group_group_link, :guest, + shared_with_group: group_where_user_has_owner_access, + shared_group: shared_with_group_where_direct_owner_as_guest + ) + end + let(:group_to_be_transferred) { parent_group } subject(:result) do @@ -69,6 +87,10 @@ RSpec.describe Groups::AcceptingGroupTransfersFinder do expect(result).not_to include(group_where_user_has_developer_access) end + it 'excludes the groups arising from group shares where the user does not have OWNER access' do + expect(result).not_to include(shared_with_group_where_direct_owner_as_guest) + end + it 'includes ancestors, except immediate parent of the group to be transferred' do expect(result).to include(great_grandparent_group) end @@ -81,6 +103,13 @@ RSpec.describe Groups::AcceptingGroupTransfersFinder do expect(result).to include(subgroup_of_group_where_user_has_owner_access) end + it 'includes the groups where the user has OWNER access through group shares' do + expect(result).to include( + shared_with_group_where_direct_owner_as_owner, + subgroup_of_shared_with_group_where_direct_owner_as_owner + ) + end + context 'on searching with a specific term' do let(:params) { { search: 'great grandparent group' } } @@ -88,6 +117,19 @@ RSpec.describe Groups::AcceptingGroupTransfersFinder do expect(result).to contain_exactly(great_grandparent_group) end end + + context 'when the feature flag `include_groups_from_group_shares_in_group_transfer_locations` is turned off' do + before do + stub_feature_flags(include_groups_from_group_shares_in_group_transfer_locations: false) + end + + it 'excludes the groups where the user has OWNER access through group shares' do + expect(result).not_to include( + shared_with_group_where_direct_owner_as_owner, + subgroup_of_shared_with_group_where_direct_owner_as_owner + ) + end + end end end end diff --git a/spec/frontend/__helpers__/shared_test_setup.js b/spec/frontend/__helpers__/shared_test_setup.js index 4d6486544ca..45a7b8e0352 100644 --- a/spec/frontend/__helpers__/shared_test_setup.js +++ b/spec/frontend/__helpers__/shared_test_setup.js @@ -48,9 +48,6 @@ testUtilsConfig.deprecationWarningHandler = (method, message) => { const ALLOWED_DEPRECATED_METHODS = [ // https://gitlab.com/gitlab-org/gitlab/-/issues/295679 'finding components with `find` or `get`', - - // https://gitlab.com/gitlab-org/gitlab/-/issues/295680 - 'finding components with `findAll`', ]; if (!ALLOWED_DEPRECATED_METHODS.includes(method)) { global.console.error(message); diff --git a/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js b/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js index 1a92b9ee536..f679576182f 100644 --- a/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js +++ b/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js @@ -46,6 +46,6 @@ describe('ReviewTabContainer', () => { it('renders all passed commits as list', () => { createWrapper({ commits: [commit] }); - expect(wrapper.findAll(CommitItem).length).toBe(1); + expect(wrapper.findAllComponents(CommitItem).length).toBe(1); }); }); diff --git a/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js index 6658db92524..9983af873c2 100644 --- a/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js +++ b/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js @@ -67,7 +67,7 @@ describe('AlertIntegrationsList', () => { }); it('renders an an edit and delete button for each integration', () => { - expect(findTableComponent().findAll(GlButton).length).toBe(4); + expect(findTableComponent().findAllComponents(GlButton).length).toBe(4); }); it('renders an highlighted row when a current integration is selected to edit', () => { diff --git a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js index b3e0d77a40f..3871fd530d8 100644 --- a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js +++ b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js @@ -83,7 +83,7 @@ describe('ProjectsDropdownFilter component', () => { const findDropdownItems = () => findDropdown() - .findAll(GlDropdownItem) + .findAllComponents(GlDropdownItem) .filter((w) => w.text() !== 'No matching results'); const findDropdownAtIndex = (index) => findDropdownItems().at(index); @@ -106,7 +106,7 @@ describe('ProjectsDropdownFilter component', () => { }; // NOTE: Selected items are now visually separated from unselected items - const findSelectedDropdownItems = () => findHighlightedItems().findAll(GlDropdownItem); + const findSelectedDropdownItems = () => findHighlightedItems().findAllComponents(GlDropdownItem); const findSelectedDropdownAtIndex = (index) => findSelectedDropdownItems().at(index); const findSelectedButtonIdentIconAtIndex = (index) => diff --git a/spec/frontend/analytics/usage_trends/components/app_spec.js b/spec/frontend/analytics/usage_trends/components/app_spec.js index 4d8107adf33..c732dc22322 100644 --- a/spec/frontend/analytics/usage_trends/components/app_spec.js +++ b/spec/frontend/analytics/usage_trends/components/app_spec.js @@ -27,7 +27,7 @@ describe('UsageTrendsApp', () => { ['Total projects & groups', 'Pipelines', 'Issues & merge requests'].forEach((usage) => { it(`displays the ${usage} chart`, () => { const chartTitles = wrapper - .findAll(UsageTrendsCountChart) + .findAllComponents(UsageTrendsCountChart) .wrappers.map((chartComponent) => chartComponent.props('chartTitle')); expect(chartTitles).toContain(usage); diff --git a/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js b/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js index beb9efd00ed..0d9196b88ed 100644 --- a/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js +++ b/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js @@ -35,7 +35,9 @@ describe('RecoveryCodes', () => { const findRecoveryCodes = () => wrapper.findByTestId('recovery-codes'); const findCopyButton = () => wrapper.findComponent(ClipboardButton); const findButtonByText = (text) => - wrapper.findAll(GlButton).wrappers.find((buttonWrapper) => buttonWrapper.text() === text); + wrapper + .findAllComponents(GlButton) + .wrappers.find((buttonWrapper) => buttonWrapper.text() === text); const findDownloadButton = () => findButtonByText('Download codes'); const findPrintButton = () => findButtonByText('Print codes'); const findProceedButton = () => findButtonByText('Proceed'); diff --git a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js index 6a5ff1af7c9..c922d6a9809 100644 --- a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js +++ b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js @@ -35,13 +35,13 @@ describe('Batch comments diff file drafts component', () => { it('renders list of draft notes', () => { factory(); - expect(vm.findAll(DraftNote).length).toEqual(2); + expect(vm.findAllComponents(DraftNote).length).toEqual(2); }); it('renders index of draft note', () => { factory(); - const elements = vm.findAll(DesignNotePin); + const elements = vm.findAllComponents(DesignNotePin); expect(elements.length).toEqual(2); diff --git a/spec/frontend/batch_comments/components/publish_dropdown_spec.js b/spec/frontend/batch_comments/components/publish_dropdown_spec.js index 7506dc49a18..d1b7160d231 100644 --- a/spec/frontend/batch_comments/components/publish_dropdown_spec.js +++ b/spec/frontend/batch_comments/components/publish_dropdown_spec.js @@ -28,7 +28,7 @@ describe('Batch comments publish dropdown component', () => { it('renders list of drafts', () => { createComponent(); - expect(wrapper.findAll(GlDropdownItem).length).toBe(2); + expect(wrapper.findAllComponents(GlDropdownItem).length).toBe(2); }); it('renders draft count in dropdown title', () => { diff --git a/spec/frontend/branches/components/divergence_graph_spec.js b/spec/frontend/branches/components/divergence_graph_spec.js index 3b565539f87..9429a6e982c 100644 --- a/spec/frontend/branches/components/divergence_graph_spec.js +++ b/spec/frontend/branches/components/divergence_graph_spec.js @@ -21,7 +21,7 @@ describe('Branch divergence graph component', () => { maxCommits: 100, }); - expect(vm.findAll(GraphBar).length).toBe(2); + expect(vm.findAllComponents(GraphBar).length).toBe(2); expect(vm.element).toMatchSnapshot(); }); @@ -45,7 +45,7 @@ describe('Branch divergence graph component', () => { maxCommits: 100, }); - expect(vm.findAll(GraphBar).length).toBe(1); + expect(vm.findAllComponents(GraphBar).length).toBe(1); expect(vm.element).toMatchSnapshot(); }); diff --git a/spec/frontend/cascading_settings/components/lock_popovers_spec.js b/spec/frontend/cascading_settings/components/lock_popovers_spec.js index ff6ce18ead8..9d3275a1ff2 100644 --- a/spec/frontend/cascading_settings/components/lock_popovers_spec.js +++ b/spec/frontend/cascading_settings/components/lock_popovers_spec.js @@ -143,7 +143,7 @@ describe('LockPopovers', () => { }); it('mounts multiple popovers', () => { - const popovers = wrapper.findAll(GlPopover).wrappers; + const popovers = wrapper.findAllComponents(GlPopover).wrappers; expectCorrectPopoverTarget(popoverMountEl1, popovers[0]); expectCorrectPopoverTarget(popoverMountEl2, popovers[1]); diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js index a8fec9b23dd..914f2d78d3a 100644 --- a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js +++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js @@ -65,7 +65,7 @@ describe('Ci variable modal', () => { const findAddorUpdateButton = () => wrapper.findByTestId('ciUpdateOrAddVariableBtn'); const deleteVariableButton = () => findModal() - .findAll(GlButton) + .findAllComponents(GlButton) .wrappers.find((button) => button.props('variant') === 'danger'); const findProtectedVariableCheckbox = () => wrapper.findByTestId('ci-variable-protected-checkbox'); diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js index d8d2cbc764f..b607232907b 100644 --- a/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js +++ b/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js @@ -45,7 +45,7 @@ describe('Ci variable modal', () => { const findAddorUpdateButton = () => findModal().find('[data-testid="ciUpdateOrAddVariableBtn"]'); const deleteVariableButton = () => findModal() - .findAll(GlButton) + .findAllComponents(GlButton) .wrappers.find((button) => button.props('variant') === 'danger'); afterEach(() => { diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js index 964dd005a27..10264d6a011 100644 --- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js +++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js @@ -65,7 +65,7 @@ describe('InstallAgentModal', () => { const findAgentInstructions = () => findModal().findComponent(AgentToken); const findButtonByVariant = (variant) => findModal() - .findAll(GlButton) + .findAllComponents(GlButton) .wrappers.find((button) => button.props('variant') === variant); const findActionButton = () => findButtonByVariant('confirm'); const findCancelButton = () => findButtonByVariant('default'); diff --git a/spec/frontend/confidential_merge_request/components/dropdown_spec.js b/spec/frontend/confidential_merge_request/components/dropdown_spec.js index bbb6d4f9a26..770f2636648 100644 --- a/spec/frontend/confidential_merge_request/components/dropdown_spec.js +++ b/spec/frontend/confidential_merge_request/components/dropdown_spec.js @@ -30,7 +30,7 @@ describe('Confidential merge request project dropdown component', () => { }, ]); - expect(vm.findAll(GlDropdownItem).length).toBe(2); + expect(vm.findAllComponents(GlDropdownItem).length).toBe(2); }); it('shows lock icon', () => { diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js index 304c8250151..567d18f8b92 100644 --- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js +++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js @@ -30,8 +30,8 @@ describe('Deploy freeze timezone dropdown', () => { wrapper.setData({ searchTerm }); }; - const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem); - const findDropdownItemByIndex = (index) => wrapper.findAll(GlDropdownItem).at(index); + const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); + const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index); afterEach(() => { wrapper.destroy(); diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index 65831b71fd4..2b1bf19471a 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -274,7 +274,7 @@ describe('diffs/components/app', () => { }); expect(wrapper.findComponent(NoChanges).exists()).toBe(false); - expect(wrapper.findAll(DiffFile).length).toBe(1); + expect(wrapper.findAllComponents(DiffFile).length).toBe(1); }); }); @@ -636,7 +636,7 @@ describe('diffs/components/app', () => { await nextTick(); - expect(wrapper.findAll(DiffFile).length).toBe(1); + expect(wrapper.findAllComponents(DiffFile).length).toBe(1); }); describe('pagination', () => { diff --git a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js index 98f88226742..09128b04caa 100644 --- a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js +++ b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js @@ -34,7 +34,7 @@ describe('CompareDropdownLayout', () => { findListItems().wrappers.map((listItem) => ({ href: listItem.find('a').attributes('href'), text: trimText(listItem.text()), - createdAt: listItem.findAll(TimeAgo).wrappers[0]?.props('time'), + createdAt: listItem.findAllComponents(TimeAgo).wrappers[0]?.props('time'), isActive: listItem.classes().includes('is-active'), })); diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js index b3945257fbd..e9a0e0745fd 100644 --- a/spec/frontend/diffs/components/diff_discussions_spec.js +++ b/spec/frontend/diffs/components/diff_discussions_spec.js @@ -34,9 +34,9 @@ describe('DiffDiscussions', () => { expect(wrapper.findComponent(NoteableDiscussion).exists()).toBe(true); expect(wrapper.findComponent(DiscussionNotes).exists()).toBe(true); - expect(wrapper.findComponent(DiscussionNotes).findAll(TimelineEntryItem).length).toBe( - discussionsMockData.notes.length, - ); + expect( + wrapper.findComponent(DiscussionNotes).findAllComponents(TimelineEntryItem).length, + ).toBe(discussionsMockData.notes.length); }); }); diff --git a/spec/frontend/diffs/components/diff_stats_spec.js b/spec/frontend/diffs/components/diff_stats_spec.js index 09fe69e97de..3a04547fa69 100644 --- a/spec/frontend/diffs/components/diff_stats_spec.js +++ b/spec/frontend/diffs/components/diff_stats_spec.js @@ -87,7 +87,7 @@ describe('diff_stats', () => { describe('files changes', () => { const findIcon = (name) => wrapper - .findAll(GlIcon) + .findAllComponents(GlIcon) .filter((c) => c.attributes('name') === name) .at(0).element.parentNode; diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js index 33b6acd5fd5..e7fa8a574cb 100644 --- a/spec/frontend/diffs/components/diff_view_spec.js +++ b/spec/frontend/diffs/components/diff_view_spec.js @@ -88,7 +88,7 @@ describe('DiffView', () => { diffLines: [{ renderCommentRow: true, ...sides }], inline: type === 'inline', }); - expect(wrapper.findAll(DiffCommentCell).length).toBe(total); + expect(wrapper.findAllComponents(DiffCommentCell).length).toBe(total); expect(wrapper.find(container).findComponent(DiffCommentCell).exists()).toBe(true); }, ); diff --git a/spec/frontend/emoji/components/category_spec.js b/spec/frontend/emoji/components/category_spec.js index b72aa659d56..90816f28d5b 100644 --- a/spec/frontend/emoji/components/category_spec.js +++ b/spec/frontend/emoji/components/category_spec.js @@ -22,7 +22,7 @@ describe('Emoji category component', () => { }); it('renders emoji groups', () => { - expect(wrapper.findAll(EmojiGroup).length).toBe(2); + expect(wrapper.findAllComponents(EmojiGroup).length).toBe(2); }); it('renders group', async () => { diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js index d210f15ea6f..c9095441d41 100644 --- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js +++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js @@ -76,7 +76,7 @@ describe('error tracking settings project dropdown', () => { it('contains a number of dropdown items', () => { expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(true); - expect(wrapper.findAll(GlDropdownItem).length).toBe(2); + expect(wrapper.findAllComponents(GlDropdownItem).length).toBe(2); }); }); diff --git a/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js b/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js index 878cf5ed43b..91457f10bf8 100644 --- a/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js +++ b/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js @@ -1,4 +1,4 @@ -import { shallowMount } from '@vue/test-utils'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content.vue'; import eventHub from '~/filtered_search/event_hub'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; @@ -6,12 +6,12 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered describe('Recent Searches Dropdown Content', () => { let wrapper; - const findLocalStorageNote = () => wrapper.findComponent({ ref: 'localStorageNote' }); - const findDropdownItems = () => wrapper.findAll({ ref: 'dropdownItem' }); - const findDropdownNote = () => wrapper.findComponent({ ref: 'dropdownNote' }); + const findLocalStorageNote = () => wrapper.findByTestId('local-storage-note'); + const findDropdownItems = () => wrapper.findAllByTestId('dropdown-item'); + const findDropdownNote = () => wrapper.findByTestId('dropdown-note'); const createComponent = (props) => { - wrapper = shallowMount(RecentSearchesDropdownContent, { + wrapper = shallowMountExtended(RecentSearchesDropdownContent, { propsData: { allowedKeys: IssuableFilteredSearchTokenKeys.getKeys(), items: [], @@ -94,7 +94,7 @@ describe('Recent Searches Dropdown Content', () => { }); it('emits requestClearRecentSearches on Clear resent searches button', () => { - wrapper.findComponent({ ref: 'clearButton' }).trigger('click'); + wrapper.findByTestId('clear-button').trigger('click'); expect(onRequestClearRecentSearchesSpy).toHaveBeenCalled(); }); diff --git a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js index 85e5e2273a5..e6673fa78ec 100644 --- a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js +++ b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js @@ -1,7 +1,7 @@ import { GlButton } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import Vuex from 'vuex'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { trimText } from 'helpers/text_helper'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue'; @@ -16,18 +16,18 @@ describe('FrequentItemsListItemComponent', () => { let trackingSpy; let store; - const findTitle = () => wrapper.findComponent({ ref: 'frequentItemsItemTitle' }); + const findTitle = () => wrapper.findByTestId('frequent-items-item-title'); const findAvatar = () => wrapper.findComponent(ProjectAvatar); - const findAllTitles = () => wrapper.findAll({ ref: 'frequentItemsItemTitle' }); - const findNamespace = () => wrapper.findComponent({ ref: 'frequentItemsItemNamespace' }); + const findAllTitles = () => wrapper.findAllByTestId('frequent-items-item-title'); + const findNamespace = () => wrapper.findByTestId('frequent-items-item-namespace'); const findAllButtons = () => wrapper.findAllComponents(GlButton); - const findAllNamespace = () => wrapper.findAll({ ref: 'frequentItemsItemNamespace' }); + const findAllNamespace = () => wrapper.findAllByTestId('frequent-items-item-namespace'); const findAllAvatars = () => wrapper.findAllComponents(ProjectAvatar); const findAllMetadataContainers = () => - wrapper.findAll({ ref: 'frequentItemsItemMetadataContainer' }); + wrapper.findAllByTestId('frequent-items-item-metadata-container'); const createComponent = (props = {}) => { - wrapper = shallowMount(frequentItemsListItemComponent, { + wrapper = shallowMountExtended(frequentItemsListItemComponent, { store, propsData: { itemId: mockProject.id, diff --git a/spec/frontend/frequent_items/components/frequent_items_list_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_spec.js index beaab1913d0..9f08a432a3d 100644 --- a/spec/frontend/frequent_items/components/frequent_items_list_spec.js +++ b/spec/frontend/frequent_items/components/frequent_items_list_spec.js @@ -1,6 +1,6 @@ -import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue'; import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue'; import { createStore } from '~/frequent_items/store'; @@ -12,7 +12,7 @@ describe('FrequentItemsListComponent', () => { let wrapper; const createComponent = (props = {}) => { - wrapper = mount(frequentItemsListComponent, { + wrapper = mountExtended(frequentItemsListComponent, { store: createStore(), propsData: { namespace: 'projects', @@ -94,8 +94,8 @@ describe('FrequentItemsListComponent', () => { await nextTick(); expect(wrapper.classes('frequent-items-list-container')).toBe(true); - expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1); - expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5); + expect(wrapper.findAllByTestId('frequent-items-list')).toHaveLength(1); + expect(wrapper.findAllComponents(frequentItemsListItemComponent)).toHaveLength(5); }); it('should render component element with empty message', async () => { @@ -105,7 +105,7 @@ describe('FrequentItemsListComponent', () => { await nextTick(); expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1); - expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0); + expect(wrapper.findAllComponents(frequentItemsListItemComponent)).toHaveLength(0); }); }); }); diff --git a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js index 8060fb9af7f..c0ae4294e3d 100644 --- a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js +++ b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js @@ -30,7 +30,7 @@ describe('ImportProjectsTable', () => { const findImportAllButton = () => wrapper - .findAll(GlButton) + .findAllComponents(GlButton) .filter((w) => w.props().variant === 'confirm') .at(0); const findImportAllModal = () => wrapper.findComponent({ ref: 'importAllModal' }); @@ -118,7 +118,7 @@ describe('ImportProjectsTable', () => { .exists(), ).toBe(true); - expect(wrapper.findAll(ProviderRepoTableRow)).toHaveLength(repositories.length); + expect(wrapper.findAllComponents(ProviderRepoTableRow)).toHaveLength(repositories.length); }); it.each` diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js index 5f71fde934f..e8d222dc2e9 100644 --- a/spec/frontend/incidents/components/incidents_list_spec.js +++ b/spec/frontend/incidents/components/incidents_list_spec.js @@ -44,12 +44,12 @@ describe('Incidents List', () => { const findTableRows = () => wrapper.findAll('table tbody tr'); const findAlert = () => wrapper.findComponent(GlAlert); const findLoader = () => wrapper.findComponent(GlLoadingIcon); - const findTimeAgo = () => wrapper.findAll(TimeAgoTooltip); + const findTimeAgo = () => wrapper.findAllComponents(TimeAgoTooltip); const findAssignees = () => wrapper.findAll('[data-testid="incident-assignees"]'); const findCreateIncidentBtn = () => wrapper.find('[data-testid="createIncidentBtn"]'); const findClosedIcon = () => wrapper.findAll("[data-testid='incident-closed']"); const findEmptyState = () => wrapper.findComponent(GlEmptyState); - const findSeverity = () => wrapper.findAll(SeverityToken); + const findSeverity = () => wrapper.findAllComponents(SeverityToken); const findEscalationStatus = () => wrapper.findAll('[data-testid="incident-escalation-status"]'); const findIncidentLink = () => wrapper.findByTestId('incident-link'); diff --git a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js index e0ebebf1c7d..394d1f12bcb 100644 --- a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js +++ b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js @@ -23,7 +23,7 @@ describe('IncidentsSettingTabs', () => { const findToggleButton = () => wrapper.findComponent({ ref: 'toggleBtn' }); const findSectionHeader = () => wrapper.findComponent({ ref: 'sectionHeader' }); - const findIntegrationTabs = () => wrapper.findAll(GlTab); + const findIntegrationTabs = () => wrapper.findAllComponents(GlTab); it('renders header text', () => { expect(findSectionHeader().text()).toBe('Incidents'); }); diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js index e13fd39999b..c329ca8522f 100644 --- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js +++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js @@ -24,7 +24,7 @@ describe('TriggerFields', () => { }); const findTriggerLabel = () => wrapper.findByTestId('trigger-fields-group').find('label'); - const findAllGlFormGroups = () => wrapper.find('#trigger-fields').findAll(GlFormGroup); + const findAllGlFormGroups = () => wrapper.find('#trigger-fields').findAllComponents(GlFormGroup); const findAllGlFormCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox); const findAllGlFormInputs = () => wrapper.findAllComponents(GlFormInput); diff --git a/spec/frontend/issuable/components/issue_assignees_spec.js b/spec/frontend/issuable/components/issue_assignees_spec.js index 713c8b1dfdd..9a33bfae240 100644 --- a/spec/frontend/issuable/components/issue_assignees_spec.js +++ b/spec/frontend/issuable/components/issue_assignees_spec.js @@ -27,7 +27,7 @@ describe('IssueAssigneesComponent', () => { }); const findTooltipText = () => wrapper.find('.js-assignee-tooltip').text(); - const findAvatars = () => wrapper.findAll(UserAvatarLink); + const findAvatars = () => wrapper.findAllComponents(UserAvatarLink); const findOverflowCounter = () => wrapper.find('.avatar-counter'); it('returns default data props', () => { diff --git a/spec/frontend/issues/new/components/title_suggestions_item_spec.js b/spec/frontend/issues/new/components/title_suggestions_item_spec.js index eee6804528f..c54a762440f 100644 --- a/spec/frontend/issues/new/components/title_suggestions_item_spec.js +++ b/spec/frontend/issues/new/components/title_suggestions_item_spec.js @@ -20,7 +20,7 @@ describe('Issue title suggestions item component', () => { } const findLink = () => wrapper.findComponent(GlLink); - const findAuthorLink = () => wrapper.findAll(GlLink).at(1); + const findAuthorLink = () => wrapper.findAllComponents(GlLink).at(1); const findIcon = () => wrapper.findComponent(GlIcon); const findTooltip = () => wrapper.findComponent(GlTooltip); const findUserAvatar = () => wrapper.findComponent(UserAvatarImage); diff --git a/spec/frontend/issues/new/components/title_suggestions_spec.js b/spec/frontend/issues/new/components/title_suggestions_spec.js index 0a64890e4ca..1cd6576967a 100644 --- a/spec/frontend/issues/new/components/title_suggestions_spec.js +++ b/spec/frontend/issues/new/components/title_suggestions_spec.js @@ -83,7 +83,7 @@ describe('Issue title suggestions component', () => { wrapper.setData(data); await nextTick(); - expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2); + expect(wrapper.findAllComponents(TitleSuggestionsItem).length).toBe(2); }); it('adds margin class to first item', async () => { diff --git a/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js b/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js index 4df04cd5257..d30a8c081cc 100644 --- a/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js +++ b/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js @@ -65,9 +65,9 @@ describe('RelatedMergeRequests', () => { describe('template', () => { it('should render related merge request items', () => { expect(wrapper.find('[data-testid="count"]').text()).toBe('2'); - expect(wrapper.findAll(RelatedIssuableItem)).toHaveLength(2); + expect(wrapper.findAllComponents(RelatedIssuableItem)).toHaveLength(2); - const props = wrapper.findAll(RelatedIssuableItem).at(1).props(); + const props = wrapper.findAllComponents(RelatedIssuableItem).at(1).props(); const data = mockData[1]; expect(props.idKey).toEqual(data.id); diff --git a/spec/frontend/issues/show/components/header_actions_spec.js b/spec/frontend/issues/show/components/header_actions_spec.js index d7fa1fa41da..dc2b3c6fc48 100644 --- a/spec/frontend/issues/show/components/header_actions_spec.js +++ b/spec/frontend/issues/show/components/header_actions_spec.js @@ -70,12 +70,12 @@ describe('HeaderActions component', () => { const findDropdownBy = (dataTestId) => wrapper.find(`[data-testid="${dataTestId}"]`); const findMobileDropdown = () => findDropdownBy('mobile-dropdown'); const findDesktopDropdown = () => findDropdownBy('desktop-dropdown'); - const findMobileDropdownItems = () => findMobileDropdown().findAll(GlDropdownItem); - const findDesktopDropdownItems = () => findDesktopDropdown().findAll(GlDropdownItem); + const findMobileDropdownItems = () => findMobileDropdown().findAllComponents(GlDropdownItem); + const findDesktopDropdownItems = () => findDesktopDropdown().findAllComponents(GlDropdownItem); const findModal = () => wrapper.findComponent(GlModal); - const findModalLinkAt = (index) => findModal().findAll(GlLink).at(index); + const findModalLinkAt = (index) => findModal().findAllComponents(GlLink).at(index); const mountComponent = ({ props = {}, diff --git a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js index 6960eb1416e..d92aeabba0f 100644 --- a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js +++ b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js @@ -61,7 +61,7 @@ describe('Incident Tabs component', () => { ); }; - const findTabs = () => wrapper.findAll(GlTab); + const findTabs = () => wrapper.findAllComponents(GlTab); const findSummaryTab = () => findTabs().at(0); const findAlertDetailsTab = () => wrapper.find('[data-testid="alert-details-tab"]'); const findAlertDetailsComponent = () => wrapper.findComponent(AlertDetailsTable); diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js index 549b819fa19..dff1c429d07 100644 --- a/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js +++ b/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js @@ -59,7 +59,7 @@ describe('IncidentTimelineEventList', () => { }; const findTimelineEventGroups = () => wrapper.findAllByTestId('timeline-group'); - const findItems = (base = wrapper) => base.findAll(IncidentTimelineEventItem); + const findItems = (base = wrapper) => base.findAllComponents(IncidentTimelineEventItem); const findFirstTimelineEventGroup = () => findTimelineEventGroups().at(0); const findSecondTimelineEventGroup = () => findTimelineEventGroups().at(1); const findDates = () => wrapper.findAllByTestId('event-date'); diff --git a/spec/frontend/issues/show/components/pinned_links_spec.js b/spec/frontend/issues/show/components/pinned_links_spec.js index aac720df6e9..208baac7124 100644 --- a/spec/frontend/issues/show/components/pinned_links_spec.js +++ b/spec/frontend/issues/show/components/pinned_links_spec.js @@ -9,7 +9,7 @@ const plainStatusUrl = 'https://status.com'; describe('PinnedLinks', () => { let wrapper; - const findButtons = () => wrapper.findAll(GlButton); + const findButtons = () => wrapper.findAllComponents(GlButton); const createComponent = (props) => { wrapper = shallowMount(PinnedLinks, { diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js index d871b1e1dcc..f1fc5e4d90b 100644 --- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js @@ -50,7 +50,7 @@ describe('GroupsList', () => { const findGlAlert = () => wrapper.findComponent(GlAlert); const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); - const findAllItems = () => wrapper.findAll(GroupsListItem); + const findAllItems = () => wrapper.findAllComponents(GroupsListItem); const findFirstItem = () => findAllItems().at(0); const findSecondItem = () => findAllItems().at(1); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); diff --git a/spec/frontend/jira_import/components/jira_import_form_spec.js b/spec/frontend/jira_import/components/jira_import_form_spec.js index 783ecec14a2..ca91ce90a02 100644 --- a/spec/frontend/jira_import/components/jira_import_form_spec.js +++ b/spec/frontend/jira_import/components/jira_import_form_spec.js @@ -288,7 +288,7 @@ describe('JiraImportForm', () => { }); it('updates the user list', () => { - expect(getUserDropdown().findAll(GlDropdownItem)).toHaveLength(1); + expect(getUserDropdown().findAllComponents(GlDropdownItem)).toHaveLength(1); expect(getUserDropdown().findComponent(GlDropdownItem).text()).toContain( 'fchopin (Frederic Chopin)', ); diff --git a/spec/frontend/milestones/components/milestone_combobox_spec.js b/spec/frontend/milestones/components/milestone_combobox_spec.js index aee13beacbb..ce5b2a1000b 100644 --- a/spec/frontend/milestones/components/milestone_combobox_spec.js +++ b/spec/frontend/milestones/components/milestone_combobox_spec.js @@ -103,12 +103,12 @@ describe('Milestone combobox component', () => { const findProjectMilestonesSection = () => wrapper.find('[data-testid="project-milestones-section"]'); const findProjectMilestonesDropdownItems = () => - findProjectMilestonesSection().findAll(GlDropdownItem); + findProjectMilestonesSection().findAllComponents(GlDropdownItem); const findFirstProjectMilestonesDropdownItem = () => findProjectMilestonesDropdownItems().at(0); const findGroupMilestonesSection = () => wrapper.find('[data-testid="group-milestones-section"]'); const findGroupMilestonesDropdownItems = () => - findGroupMilestonesSection().findAll(GlDropdownItem); + findGroupMilestonesSection().findAllComponents(GlDropdownItem); const findFirstGroupMilestonesDropdownItem = () => findGroupMilestonesDropdownItems().at(0); // diff --git a/spec/frontend/notifications/components/custom_notifications_modal_spec.js b/spec/frontend/notifications/components/custom_notifications_modal_spec.js index 02de67f788d..9bde80e930f 100644 --- a/spec/frontend/notifications/components/custom_notifications_modal_spec.js +++ b/spec/frontend/notifications/components/custom_notifications_modal_spec.js @@ -57,7 +57,7 @@ describe('CustomNotificationsModal', () => { } const findModalBodyDescription = () => wrapper.findComponent(GlSprintf); - const findAllCheckboxes = () => wrapper.findAll(GlFormCheckbox); + const findAllCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox); const findCheckboxAt = (index) => findAllCheckboxes().at(index); beforeEach(() => { diff --git a/spec/frontend/notifications/components/notifications_dropdown_spec.js b/spec/frontend/notifications/components/notifications_dropdown_spec.js index 1f950683630..8a6fd72fbeb 100644 --- a/spec/frontend/notifications/components/notifications_dropdown_spec.js +++ b/spec/frontend/notifications/components/notifications_dropdown_spec.js @@ -42,7 +42,8 @@ describe('NotificationsDropdown', () => { const findDropdown = () => wrapper.findComponent(GlDropdown); const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`); - const findAllNotificationsDropdownItems = () => wrapper.findAll(NotificationsDropdownItem); + const findAllNotificationsDropdownItems = () => + wrapper.findAllComponents(NotificationsDropdownItem); const findDropdownItemAt = (index) => findAllNotificationsDropdownItems().at(index).findComponent(GlDropdownItem); const findNotificationsModal = () => wrapper.findComponent(CustomNotificationsModal); diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js index 88979ea2b25..96c670eaad2 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js @@ -32,7 +32,7 @@ describe('tags list row', () => { const findShortRevision = () => wrapper.find('[data-testid="digest"]'); const findClipboardButton = () => wrapper.findComponent(ClipboardButton); const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip); - const findDetailsRows = () => wrapper.findAll(DetailsRow); + const findDetailsRows = () => wrapper.findAllComponents(DetailsRow); const findPublishedDateDetail = () => wrapper.find('[data-testid="published-date-detail"]'); const findManifestDetail = () => wrapper.find('[data-testid="manifest-detail"]'); const findConfigurationDetail = () => wrapper.find('[data-testid="configuration-detail"]'); diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js index e5df260a260..3f5d4c3dbf7 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js @@ -5,7 +5,7 @@ import { GlSkeletonLoader } from '../../stubs'; describe('TagsLoader component', () => { let wrapper; - const findGlSkeletonLoaders = () => wrapper.findAll(GlSkeletonLoader); + const findGlSkeletonLoaders = () => wrapper.findAllComponents(GlSkeletonLoader); const mountComponent = () => { wrapper = shallowMount(component, { diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js index 4d33f75a5fd..042b8383571 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js @@ -8,7 +8,7 @@ import { imagesListResponse, pageInfo as defaultPageInfo } from '../../mock_data describe('Image List', () => { let wrapper; - const findRow = () => wrapper.findAll(ImageListRow); + const findRow = () => wrapper.findAllComponents(ImageListRow); const findPagination = () => wrapper.findComponent(GlKeysetPagination); const mountComponent = (props) => { diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js index 304878fe5df..e7e74a0da58 100644 --- a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js +++ b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js @@ -7,7 +7,7 @@ import { harborImagesList } from '../../mock_data'; describe('Harbor List', () => { let wrapper; - const findHarborListRow = () => wrapper.findAll(HarborListRow); + const findHarborListRow = () => wrapper.findAllComponents(HarborListRow); const mountComponent = (props) => { wrapper = shallowMount(HarborList, { diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js index e2af06416b4..9268dd0b049 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js @@ -7,7 +7,7 @@ describe('packages_filter', () => { let wrapper; const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken); - const findFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findFilteredSearchSuggestions = () => wrapper.findAllComponents(GlFilteredSearchSuggestion); const mountComponent = ({ attrs, listeners } = {}) => { wrapper = shallowMount(component, { diff --git a/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js b/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js index dfa91fd8740..18084766db9 100644 --- a/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js +++ b/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js @@ -23,7 +23,7 @@ describe('cli_commands', () => { let wrapper; const findDropdownButton = () => wrapper.findComponent(GlDropdown); - const findCodeInstruction = () => wrapper.findAll(CodeInstruction); + const findCodeInstruction = () => wrapper.findAllComponents(CodeInstruction); const mountComponent = () => { wrapper = mount(QuickstartDropdown, { diff --git a/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js b/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js index b393a855a9f..b020caa3010 100644 --- a/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js +++ b/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js @@ -14,7 +14,7 @@ describe('BitbucketServerStatusTable', () => { const findReconfigureButton = () => wrapper - .findAll(GlButton) + .findAllComponents(GlButton) .filter((w) => w.props().variant === 'info') .at(0); diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js index ebb254b49c1..f221a90da61 100644 --- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js +++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js @@ -200,7 +200,7 @@ describe('ForkForm component', () => { it('displays the correct description', () => { createComponent(); - const formRadios = wrapper.findAll(GlFormRadio); + const formRadios = wrapper.findAllComponents(GlFormRadio); Object.keys(PROJECT_VISIBILITY_TYPE).forEach((visibilityType, index) => { expect(formRadios.at(index).text()).toBe(PROJECT_VISIBILITY_TYPE[visibilityType]); @@ -210,7 +210,7 @@ describe('ForkForm component', () => { it('displays all 3 visibility levels', () => { createComponent(); - expect(wrapper.findAll(GlFormRadio)).toHaveLength(3); + expect(wrapper.findAllComponents(GlFormRadio)).toHaveLength(3); }); describe('when the namespace is changed', () => { diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js index c9c0e406c46..2f2edd6b025 100644 --- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js +++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js @@ -22,7 +22,7 @@ describe('Code Coverage', () => { const findAlert = () => wrapper.findComponent(GlAlert); const findAreaChart = () => wrapper.findComponent(GlAreaChart); - const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem); + const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); const findFirstDropdownItem = () => findAllDropdownItems().at(0); const findSecondDropdownItem = () => findAllDropdownItems().at(1); const findDownloadButton = () => wrapper.find('[data-testid="download-button"]'); diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js index 7dbacad34bf..8f6f4d8cff9 100644 --- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js +++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js @@ -119,7 +119,7 @@ describe('Pipeline editor branch switcher', () => { }; const findDropdown = () => wrapper.findComponent(GlDropdown); - const findDropdownItems = () => wrapper.findAll(GlDropdownItem); + const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); const findInfiniteScroll = () => wrapper.findComponent(GlInfiniteScroll); diff --git a/spec/frontend/pipeline_editor/components/file-tree/container_spec.js b/spec/frontend/pipeline_editor/components/file-tree/container_spec.js index 04a93e8db25..f79074f1e0f 100644 --- a/spec/frontend/pipeline_editor/components/file-tree/container_spec.js +++ b/spec/frontend/pipeline_editor/components/file-tree/container_spec.js @@ -31,7 +31,7 @@ describe('Pipeline editor file nav', () => { const findTip = () => wrapper.findComponent(GlAlert); const findCurrentConfigFilename = () => wrapper.findByTestId('current-config-filename'); - const fileTreeItems = () => wrapper.findAll(PipelineEditorFileTreeItem); + const fileTreeItems = () => wrapper.findAllComponents(PipelineEditorFileTreeItem); afterEach(() => { localStorage.clear(); diff --git a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js index 3a40ce32a24..24f27e8c5fb 100644 --- a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js +++ b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js @@ -58,7 +58,7 @@ describe('~/pipeline_editor/components/ui/editor_tab.vue', () => { const findSlotComponent = () => wrapper.findComponent(MockSourceEditor); const findAlert = () => wrapper.findComponent(GlAlert); - const findBadges = () => wrapper.findAll(GlBadge); + const findBadges = () => wrapper.findAllComponents(GlBadge); beforeEach(() => { mockChildMounted = jest.fn(); diff --git a/spec/frontend/pipeline_new/components/refs_dropdown_spec.js b/spec/frontend/pipeline_new/components/refs_dropdown_spec.js index 01d4bd7786f..8cba876c688 100644 --- a/spec/frontend/pipeline_new/components/refs_dropdown_spec.js +++ b/spec/frontend/pipeline_new/components/refs_dropdown_spec.js @@ -20,7 +20,7 @@ describe('Pipeline New Form', () => { let mock; const findDropdown = () => wrapper.findComponent(GlDropdown); - const findRefsDropdownItems = () => wrapper.findAll(GlDropdownItem); + const findRefsDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); const createComponent = (props = {}, mountFn = shallowMount) => { diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js index 5cc6537e964..b0c26976c85 100644 --- a/spec/frontend/pipelines/components/dag/dag_spec.js +++ b/spec/frontend/pipelines/components/dag/dag_spec.js @@ -19,7 +19,7 @@ import { describe('Pipeline DAG graph wrapper', () => { let wrapper; const getAlert = () => wrapper.findComponent(GlAlert); - const getAllAlerts = () => wrapper.findAll(GlAlert); + const getAllAlerts = () => wrapper.findAllComponents(GlAlert); const getGraph = () => wrapper.findComponent(DagGraph); const getNotes = () => wrapper.findComponent(DagAnnotations); const getErrorText = (type) => wrapper.vm.$options.errorTexts[type]; diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js index 03eca50c460..bfb780d5d39 100644 --- a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js +++ b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stages_spec.js @@ -8,7 +8,7 @@ const mockStages = pipelines[0].details.stages; describe('Pipeline Stages', () => { let wrapper; - const findPipelineStages = () => wrapper.findAll(PipelineStage); + const findPipelineStages = () => wrapper.findAllComponents(PipelineStage); const findPipelineStagesAt = (i) => findPipelineStages().at(i); const createComponent = (props = {}) => { diff --git a/spec/frontend/pipelines/graph/graph_component_spec.js b/spec/frontend/pipelines/graph/graph_component_spec.js index 3ab58882786..2abb5f7dc58 100644 --- a/spec/frontend/pipelines/graph/graph_component_spec.js +++ b/spec/frontend/pipelines/graph/graph_component_spec.js @@ -15,9 +15,9 @@ import { describe('graph component', () => { let wrapper; - const findLinkedColumns = () => wrapper.findAll(LinkedPipelinesColumn); + const findLinkedColumns = () => wrapper.findAllComponents(LinkedPipelinesColumn); const findLinksLayer = () => wrapper.findComponent(LinksLayer); - const findStageColumns = () => wrapper.findAll(StageColumnComponent); + const findStageColumns = () => wrapper.findAllComponents(StageColumnComponent); const findStageNameInJob = () => wrapper.find('[data-testid="stage-name-in-job"]'); const defaultProps = { diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js index 50fae3ee495..63e2d8707ea 100644 --- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js +++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js @@ -38,7 +38,7 @@ describe('Linked Pipelines Column', () => { let wrapper; const findLinkedColumnTitle = () => wrapper.find('[data-testid="linked-column-title"]'); - const findLinkedPipelineElements = () => wrapper.findAll(LinkedPipeline); + const findLinkedPipelineElements = () => wrapper.findAllComponents(LinkedPipeline); const findPipelineGraph = () => wrapper.findComponent(PipelineGraph); const findExpandButton = () => wrapper.find('[data-testid="expand-pipeline-button"]'); diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js index 1b89e322d31..d9199f3b0f7 100644 --- a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js +++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js @@ -34,7 +34,7 @@ describe('pipeline graph component', () => { }; const findAlert = () => wrapper.findComponent(GlAlert); - const findAllJobPills = () => wrapper.findAll(JobPill); + const findAllJobPills = () => wrapper.findAllComponents(JobPill); const findAllStageNames = () => wrapper.findAllComponents(StageName); const findLinksLayer = () => wrapper.findComponent(LinksLayer); const findPipelineGraph = () => wrapper.find('[data-testid="graph-container"]'); diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js index ac4be04fc41..fdfced38dca 100644 --- a/spec/frontend/pipelines/pipelines_actions_spec.js +++ b/spec/frontend/pipelines/pipelines_actions_spec.js @@ -32,8 +32,8 @@ describe('Pipelines Actions dropdown', () => { }; const findDropdown = () => wrapper.findComponent(GlDropdown); - const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem); - const findAllCountdowns = () => wrapper.findAll(GlCountdown); + const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); + const findAllCountdowns = () => wrapper.findAllComponents(GlCountdown); beforeEach(() => { mock = new MockAdapter(axios); diff --git a/spec/frontend/pipelines/pipelines_artifacts_spec.js b/spec/frontend/pipelines/pipelines_artifacts_spec.js index 481d98fcba7..e3e54716a7b 100644 --- a/spec/frontend/pipelines/pipelines_artifacts_spec.js +++ b/spec/frontend/pipelines/pipelines_artifacts_spec.js @@ -31,7 +31,8 @@ describe('Pipelines Artifacts dropdown', () => { const findDropdown = () => wrapper.findComponent(GlDropdown); const findFirstGlDropdownItem = () => wrapper.findComponent(GlDropdownItem); - const findAllGlDropdownItems = () => wrapper.findComponent(GlDropdown).findAll(GlDropdownItem); + const findAllGlDropdownItems = () => + wrapper.findComponent(GlDropdown).findAllComponents(GlDropdownItem); afterEach(() => { wrapper.destroy(); diff --git a/spec/frontend/pipelines/tokens/pipeline_branch_name_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_branch_name_token_spec.js index 497d03bff51..caa66502e11 100644 --- a/spec/frontend/pipelines/tokens/pipeline_branch_name_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_branch_name_token_spec.js @@ -10,7 +10,8 @@ describe('Pipeline Branch Name Token', () => { let wrapper; const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findAllFilteredSearchSuggestions = () => + wrapper.findAllComponents(GlFilteredSearchSuggestion); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const getBranchSuggestions = () => findAllFilteredSearchSuggestions().wrappers.map((w) => w.text()); diff --git a/spec/frontend/pipelines/tokens/pipeline_source_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_source_token_spec.js index 7d60a961621..60abb63a7e0 100644 --- a/spec/frontend/pipelines/tokens/pipeline_source_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_source_token_spec.js @@ -8,7 +8,8 @@ describe('Pipeline Source Token', () => { let wrapper; const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findAllFilteredSearchSuggestions = () => + wrapper.findAllComponents(GlFilteredSearchSuggestion); const defaultProps = { config: { diff --git a/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js index 1a51d8b251d..94f9a37f707 100644 --- a/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js @@ -7,8 +7,9 @@ describe('Pipeline Status Token', () => { let wrapper; const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); - const findAllGlIcons = () => wrapper.findAll(GlIcon); + const findAllFilteredSearchSuggestions = () => + wrapper.findAllComponents(GlFilteredSearchSuggestion); + const findAllGlIcons = () => wrapper.findAllComponents(GlIcon); const defaultProps = { config: { diff --git a/spec/frontend/pipelines/tokens/pipeline_tag_name_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_tag_name_token_spec.js index 8dd79bcfb88..7311a5d2f5a 100644 --- a/spec/frontend/pipelines/tokens/pipeline_tag_name_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_tag_name_token_spec.js @@ -8,7 +8,8 @@ describe('Pipeline Branch Name Token', () => { let wrapper; const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findAllFilteredSearchSuggestions = () => + wrapper.findAllComponents(GlFilteredSearchSuggestion); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const stubs = { diff --git a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js index 39986ca7904..c763bfe1b27 100644 --- a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js @@ -9,7 +9,8 @@ describe('Pipeline Trigger Author Token', () => { let wrapper; const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findAllFilteredSearchSuggestions = () => + wrapper.findAllComponents(GlFilteredSearchSuggestion); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const defaultProps = { diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js index 0d00cb043d5..eba6b95214d 100644 --- a/spec/frontend/popovers/components/popovers_spec.js +++ b/spec/frontend/popovers/components/popovers_spec.js @@ -31,7 +31,7 @@ describe('popovers/components/popovers.vue', () => { return target; }; - const allPopovers = () => wrapper.findAll(GlPopover); + const allPopovers = () => wrapper.findAllComponents(GlPopover); afterEach(() => { wrapper.destroy(); @@ -52,7 +52,7 @@ describe('popovers/components/popovers.vue', () => { await nextTick(); - expect(wrapper.findAll(GlPopover)).toHaveLength(1); + expect(wrapper.findAllComponents(GlPopover)).toHaveLength(1); }); describe('supports HTML content', () => { diff --git a/spec/frontend/profile/preferences/components/profile_preferences_spec.js b/spec/frontend/profile/preferences/components/profile_preferences_spec.js index 4d2dcf83d3b..89ce838a383 100644 --- a/spec/frontend/profile/preferences/components/profile_preferences_spec.js +++ b/spec/frontend/profile/preferences/components/profile_preferences_spec.js @@ -90,7 +90,7 @@ describe('ProfilePreferences component', () => { it('should not render Integrations section', () => { wrapper = createComponent(); - const views = wrapper.findAll(IntegrationView); + const views = wrapper.findAllComponents(IntegrationView); const divider = findIntegrationsDivider(); const heading = findIntegrationsHeading(); @@ -103,7 +103,7 @@ describe('ProfilePreferences component', () => { wrapper = createComponent({ provide: { integrationViews } }); const divider = findIntegrationsDivider(); const heading = findIntegrationsHeading(); - const views = wrapper.findAll(IntegrationView); + const views = wrapper.findAllComponents(IntegrationView); expect(divider.exists()).toBe(true); expect(heading.exists()).toBe(true); diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js index 287bfe1c14d..907e0e226b6 100644 --- a/spec/frontend/projects/commits/components/author_select_spec.js +++ b/spec/frontend/projects/commits/components/author_select_spec.js @@ -62,7 +62,7 @@ describe('Author Select', () => { const findDropdown = () => wrapper.findComponent(GlDropdown); const findDropdownHeader = () => wrapper.findComponent(GlDropdownSectionHeader); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); - const findDropdownItems = () => wrapper.findAll(GlDropdownItem); + const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); describe('user is searching via "filter by commit message"', () => { it('disables dropdown container', async () => { diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js index a24e40b842c..2dbecf7cc61 100644 --- a/spec/frontend/projects/compare/components/app_spec.js +++ b/spec/frontend/projects/compare/components/app_spec.js @@ -58,7 +58,7 @@ describe('CompareApp component', () => { }); it('render Source and Target BranchDropdown components', () => { - const revisionCards = wrapper.findAll(RevisionCard); + const revisionCards = wrapper.findAllComponents(RevisionCard); expect(revisionCards.length).toBe(2); expect(revisionCards.at(0).props('revisionText')).toBe('Source'); diff --git a/spec/frontend/projects/compare/components/repo_dropdown_spec.js b/spec/frontend/projects/compare/components/repo_dropdown_spec.js index 8e720b40e6f..21cca857c6a 100644 --- a/spec/frontend/projects/compare/components/repo_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/repo_dropdown_spec.js @@ -73,7 +73,7 @@ describe('RepoDropdown component', () => { }); it('emits `selectProject` event when another target project is selected', async () => { - findGlDropdown().findAll(GlDropdownItem).at(0).vm.$emit('click'); + findGlDropdown().findAllComponents(GlDropdownItem).at(0).vm.$emit('click'); await nextTick(); expect(wrapper.emitted('selectProject')[0][0]).toEqual({ diff --git a/spec/frontend/projects/compare/components/revision_card_spec.js b/spec/frontend/projects/compare/components/revision_card_spec.js index a741393fcf3..b23bd91ceda 100644 --- a/spec/frontend/projects/compare/components/revision_card_spec.js +++ b/spec/frontend/projects/compare/components/revision_card_spec.js @@ -32,10 +32,10 @@ describe('RepoDropdown component', () => { }); it('renders RepoDropdown component', () => { - expect(wrapper.findAll(RepoDropdown).exists()).toBe(true); + expect(wrapper.findAllComponents(RepoDropdown).exists()).toBe(true); }); it('renders RevisionDropdown component', () => { - expect(wrapper.findAll(RevisionDropdown).exists()).toBe(true); + expect(wrapper.findAllComponents(RevisionDropdown).exists()).toBe(true); }); }); diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js index 8d4711a79ed..f64af1aa994 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js @@ -99,7 +99,7 @@ describe('RevisionDropdown component', () => { }); it('emits a "selectRevision" event when a revision is selected', async () => { - const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem); + const findGlDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); const findFirstGlDropdownItem = () => findGlDropdownItems().at(0); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js index bd8c0d2784f..35e32fd3da0 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js @@ -144,7 +144,7 @@ describe('RevisionDropdown component', () => { wrapper.vm.branches = ['some-branch']; await nextTick(); - findGlDropdown().findAll(GlDropdownItem).at(0).vm.$emit('click'); + findGlDropdown().findAllComponents(GlDropdownItem).at(0).vm.$emit('click'); expect(wrapper.emitted('selectRevision')[0][0]).toEqual({ direction: 'to', diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js index db9d7eb9a8a..e3aaf760d1e 100644 --- a/spec/frontend/projects/pipelines/charts/components/app_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js @@ -48,7 +48,7 @@ describe('ProjectsPipelinesChartsApp', () => { }); const findGlTabs = () => wrapper.findComponent(GlTabs); - const findAllGlTabs = () => wrapper.findAll(GlTab); + const findAllGlTabs = () => wrapper.findAllComponents(GlTab); const findGlTabAtIndex = (index) => findAllGlTabs().at(index); const findLeadTimeCharts = () => wrapper.findComponent(LeadTimeChartsStub); const findTimeToRestoreServiceCharts = () => diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js index dde06d40a4d..6adcfbe8157 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js @@ -53,7 +53,7 @@ describe('ServiceDeskTemplateDropdown', () => { props: { templates: TEMPLATES }, }); - const headerItems = wrapper.findAll(GlDropdownSectionHeader); + const headerItems = wrapper.findAllComponents(GlDropdownSectionHeader); expect(headerItems).toHaveLength(1); expect(headerItems.at(0).text()).toBe(TEMPLATES[0]); @@ -68,7 +68,7 @@ describe('ServiceDeskTemplateDropdown', () => { const expectedTemplates = templates[1]; - const items = wrapper.findAll(GlDropdownItem); + const items = wrapper.findAllComponents(GlDropdownItem); const dropdownList = expectedTemplates.map((_, index) => items.at(index).text()); expect(items).toHaveLength(expectedTemplates.length); diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js index 851a3fcaf33..6c5af5a2625 100644 --- a/spec/frontend/ref/components/ref_selector_spec.js +++ b/spec/frontend/ref/components/ref_selector_spec.js @@ -98,15 +98,15 @@ describe('Ref selector component', () => { const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); const findBranchesSection = () => wrapper.find('[data-testid="branches-section"]'); - const findBranchDropdownItems = () => findBranchesSection().findAll(GlDropdownItem); + const findBranchDropdownItems = () => findBranchesSection().findAllComponents(GlDropdownItem); const findFirstBranchDropdownItem = () => findBranchDropdownItems().at(0); const findTagsSection = () => wrapper.find('[data-testid="tags-section"]'); - const findTagDropdownItems = () => findTagsSection().findAll(GlDropdownItem); + const findTagDropdownItems = () => findTagsSection().findAllComponents(GlDropdownItem); const findFirstTagDropdownItem = () => findTagDropdownItems().at(0); const findCommitsSection = () => wrapper.find('[data-testid="commits-section"]'); - const findCommitDropdownItems = () => findCommitsSection().findAll(GlDropdownItem); + const findCommitDropdownItems = () => findCommitsSection().findAllComponents(GlDropdownItem); const findFirstCommitDropdownItem = () => findCommitDropdownItems().at(0); // diff --git a/spec/frontend/releases/components/release_block_milestone_info_spec.js b/spec/frontend/releases/components/release_block_milestone_info_spec.js index 89ae556f906..541d487091c 100644 --- a/spec/frontend/releases/components/release_block_milestone_info_spec.js +++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js @@ -58,7 +58,7 @@ describe('Release block milestone info', () => { expect(milestoneListContainer().text()).toMatchInterpolatedText('Milestones 12.3 • 12.4'); milestones.forEach((m, i) => { - const milestoneLink = milestoneListContainer().findAll(GlLink).at(i); + const milestoneLink = milestoneListContainer().findAllComponents(GlLink).at(i); expect(milestoneLink.text()).toBe(m.title); expect(milestoneLink.attributes('href')).toBe(m.webUrl); diff --git a/spec/frontend/reports/components/grouped_issues_list_spec.js b/spec/frontend/reports/components/grouped_issues_list_spec.js index 74c17b0b8fc..6c0275dc47d 100644 --- a/spec/frontend/reports/components/grouped_issues_list_spec.js +++ b/spec/frontend/reports/components/grouped_issues_list_spec.js @@ -67,7 +67,7 @@ describe('Grouped Issues List', () => { propsData: { [`${issueName}Issues`]: issues }, }); - expect(wrapper.findAll(ReportItem)).toHaveLength(issues.length); + expect(wrapper.findAllComponents(ReportItem)).toHaveLength(issues.length); }); it('renders a report item with the correct props', () => { diff --git a/spec/frontend/repository/components/blob_button_group_spec.js b/spec/frontend/repository/components/blob_button_group_spec.js index d5b882bd715..a00f49ec4f8 100644 --- a/spec/frontend/repository/components/blob_button_group_spec.js +++ b/spec/frontend/repository/components/blob_button_group_spec.js @@ -66,12 +66,12 @@ describe('BlobButtonGroup component', () => { }); it('renders both the replace and delete button', () => { - expect(wrapper.findAll(GlButton)).toHaveLength(2); + expect(wrapper.findAllComponents(GlButton)).toHaveLength(2); }); it('renders the buttons in the correct order', () => { - expect(wrapper.findAll(GlButton).at(0).text()).toBe('Replace'); - expect(wrapper.findAll(GlButton).at(1).text()).toBe('Delete'); + expect(wrapper.findAllComponents(GlButton).at(0).text()).toBe('Replace'); + expect(wrapper.findAllComponents(GlButton).at(1).text()).toBe('Delete'); }); it('triggers the UploadBlobModal from the replace button', () => { diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js index a1a292e9678..c2f34f79f89 100644 --- a/spec/frontend/repository/components/breadcrumbs_spec.js +++ b/spec/frontend/repository/components/breadcrumbs_spec.js @@ -55,7 +55,7 @@ describe('Repository breadcrumbs component', () => { `('renders $linkCount links for path $path', ({ path, linkCount }) => { factory(path); - expect(wrapper.findAll(RouterLinkStub).length).toEqual(linkCount); + expect(wrapper.findAllComponents(RouterLinkStub).length).toEqual(linkCount); }); it.each` @@ -68,14 +68,14 @@ describe('Repository breadcrumbs component', () => { 'links to the correct router path when routeName is $routeName', ({ routeName, path, linkTo }) => { factory(path, {}, { name: routeName }); - expect(wrapper.findAll(RouterLinkStub).at(3).props('to')).toEqual(linkTo); + expect(wrapper.findAllComponents(RouterLinkStub).at(3).props('to')).toEqual(linkTo); }, ); it('escapes hash in directory path', () => { factory('app/assets/javascripts#'); - expect(wrapper.findAll(RouterLinkStub).at(3).props('to')).toEqual( + expect(wrapper.findAllComponents(RouterLinkStub).at(3).props('to')).toEqual( '/-/tree/app/assets/javascripts%23', ); }); @@ -83,7 +83,9 @@ describe('Repository breadcrumbs component', () => { it('renders last link as active', () => { factory('app/assets'); - expect(wrapper.findAll(RouterLinkStub).at(2).attributes('aria-current')).toEqual('page'); + expect(wrapper.findAllComponents(RouterLinkStub).at(2).attributes('aria-current')).toEqual( + 'page', + ); }); it('does not render add to tree dropdown when permissions are false', async () => { diff --git a/spec/frontend/repository/components/table/index_spec.js b/spec/frontend/repository/components/table/index_spec.js index ff0371b5c07..57b481634ca 100644 --- a/spec/frontend/repository/components/table/index_spec.js +++ b/spec/frontend/repository/components/table/index_spec.js @@ -115,7 +115,7 @@ describe('Repository table component', () => { commits: MOCK_COMMITS, }); - const rows = vm.findAll(TableRow); + const rows = vm.findAllComponents(TableRow); expect(rows.length).toEqual(3); expect(rows.at(2).attributes().mode).toEqual('120000'); diff --git a/spec/frontend/runner/components/runner_type_tabs_spec.js b/spec/frontend/runner/components/runner_type_tabs_spec.js index 22d2a9e60f7..45ab8684332 100644 --- a/spec/frontend/runner/components/runner_type_tabs_spec.js +++ b/spec/frontend/runner/components/runner_type_tabs_spec.js @@ -28,7 +28,7 @@ const mockCount = (type, multiplier = 1) => { describe('RunnerTypeTabs', () => { let wrapper; - const findTabs = () => wrapper.findAll(GlTab); + const findTabs = () => wrapper.findAllComponents(GlTab); const findActiveTab = () => findTabs() .filter((tab) => tab.attributes('active') === 'true') diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js index 39d5ee581ec..c0a8259b4fe 100644 --- a/spec/frontend/search/sidebar/components/radio_filter_spec.js +++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js @@ -44,7 +44,7 @@ describe('RadioFilter', () => { }); const findGlRadioButtonGroup = () => wrapper.find(GlFormRadioGroup); - const findGlRadioButtons = () => findGlRadioButtonGroup().findAll(GlFormRadio); + const findGlRadioButtons = () => findGlRadioButtonGroup().findAllComponents(GlFormRadio); const findGlRadioButtonsText = () => findGlRadioButtons().wrappers.map((w) => w.text()); describe('template', () => { diff --git a/spec/frontend/search/sort/components/app_spec.js b/spec/frontend/search/sort/components/app_spec.js index 04520a3e704..0e8eebba3cb 100644 --- a/spec/frontend/search/sort/components/app_spec.js +++ b/spec/frontend/search/sort/components/app_spec.js @@ -46,7 +46,7 @@ describe('GlobalSearchSort', () => { const findSortButtonGroup = () => wrapper.find(GlButtonGroup); const findSortDropdown = () => wrapper.find(GlDropdown); const findSortDirectionButton = () => wrapper.find(GlButton); - const findDropdownItems = () => findSortDropdown().findAll(GlDropdownItem); + const findDropdownItems = () => findSortDropdown().findAllComponents(GlDropdownItem); const findDropdownItemsText = () => findDropdownItems().wrappers.map((w) => w.text()); describe('template', () => { diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js index 5aa8264b98c..81ff51133bf 100644 --- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js +++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js @@ -23,7 +23,7 @@ describe('CollapsedAssigneeList component', () => { const findNoUsersIcon = () => wrapper.find(GlIcon); const findAvatarCounter = () => wrapper.find('.avatar-counter'); - const findAssignees = () => wrapper.findAll(CollapsedAssignee); + const findAssignees = () => wrapper.findAllComponents(CollapsedAssignee); const getTooltipTitle = () => wrapper.attributes('title'); afterEach(() => { diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js index f7437386814..b902d7313fd 100644 --- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js +++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js @@ -42,7 +42,7 @@ describe('UncollapsedAssigneeList component', () => { }); it('only has one user', () => { - expect(wrapper.findAll(AssigneeAvatarLink).length).toBe(1); + expect(wrapper.findAllComponents(AssigneeAvatarLink).length).toBe(1); }); it('calls the AssigneeAvatarLink with the proper props', () => { @@ -79,7 +79,7 @@ describe('UncollapsedAssigneeList component', () => { }); it('shows truncated users', () => { - expect(wrapper.findAll(AssigneeAvatarLink).length).toBe(DEFAULT_RENDER_COUNT); + expect(wrapper.findAllComponents(AssigneeAvatarLink).length).toBe(DEFAULT_RENDER_COUNT); }); describe('when more button is clicked', () => { @@ -94,7 +94,9 @@ describe('UncollapsedAssigneeList component', () => { }); it('shows all users', () => { - expect(wrapper.findAll(AssigneeAvatarLink).length).toBe(DEFAULT_RENDER_COUNT + 1); + expect(wrapper.findAllComponents(AssigneeAvatarLink).length).toBe( + DEFAULT_RENDER_COUNT + 1, + ); }); }); }); diff --git a/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js b/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js index fda21e06987..a7556b9110c 100644 --- a/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js +++ b/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js @@ -5,10 +5,10 @@ import SidebarInheritDate from '~/sidebar/components/date/sidebar_inherit_date.v describe('SidebarInheritDate', () => { let wrapper; - const findFixedFormattedDate = () => wrapper.findAll(SidebarFormattedDate).at(0); - const findInheritFormattedDate = () => wrapper.findAll(SidebarFormattedDate).at(1); - const findFixedRadio = () => wrapper.findAll(GlFormRadio).at(0); - const findInheritRadio = () => wrapper.findAll(GlFormRadio).at(1); + const findFixedFormattedDate = () => wrapper.findAllComponents(SidebarFormattedDate).at(0); + const findInheritFormattedDate = () => wrapper.findAllComponents(SidebarFormattedDate).at(1); + const findFixedRadio = () => wrapper.findAllComponents(GlFormRadio).at(0); + const findInheritRadio = () => wrapper.findAllComponents(GlFormRadio).at(1); const createComponent = ({ dueDateIsFixed = false } = {}) => { wrapper = shallowMount(SidebarInheritDate, { @@ -36,8 +36,8 @@ describe('SidebarInheritDate', () => { }); it('displays formatted fixed and inherited dates with radio buttons', () => { - expect(wrapper.findAll(SidebarFormattedDate)).toHaveLength(2); - expect(wrapper.findAll(GlFormRadio)).toHaveLength(2); + expect(wrapper.findAllComponents(SidebarFormattedDate)).toHaveLength(2); + expect(wrapper.findAllComponents(GlFormRadio)).toHaveLength(2); expect(findFixedFormattedDate().props('formattedDate')).toBe('Apr 15, 2021'); expect(findInheritFormattedDate().props('formattedDate')).toBe('May 15, 2021'); expect(findFixedRadio().text()).toBe('Fixed:'); diff --git a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js index 2c24df2436a..d00c8dcb653 100644 --- a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js +++ b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js @@ -52,7 +52,7 @@ describe('UncollapsedReviewerList component', () => { }); it('only has one user', () => { - expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(1); + expect(wrapper.findAllComponents(ReviewerAvatarLink).length).toBe(1); }); it('shows one user with avatar, and author name', () => { @@ -96,7 +96,7 @@ describe('UncollapsedReviewerList component', () => { }); it('has both users', () => { - expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(2); + expect(wrapper.findAllComponents(ReviewerAvatarLink).length).toBe(2); }); it('shows both users with avatar, and author name', () => { diff --git a/spec/frontend/snippets/components/show_spec.js b/spec/frontend/snippets/components/show_spec.js index b29ed97099f..d3b5c0e69db 100644 --- a/spec/frontend/snippets/components/show_spec.js +++ b/spec/frontend/snippets/components/show_spec.js @@ -85,7 +85,7 @@ describe('Snippet view app', () => { }, }, }); - const blobs = wrapper.findAll(SnippetBlob); + const blobs = wrapper.findAllComponents(SnippetBlob); expect(blobs.length).toBe(2); expect(blobs.at(0).props('blob')).toEqual(Blob); expect(blobs.at(1).props('blob')).toEqual(BinaryBlob); diff --git a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js index df98312b498..a650353093d 100644 --- a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js +++ b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js @@ -32,7 +32,7 @@ describe('snippets/components/snippet_blob_actions_edit', () => { }; const findLabel = () => wrapper.findComponent(GlFormGroup); - const findBlobEdits = () => wrapper.findAll(SnippetBlobEdit); + const findBlobEdits = () => wrapper.findAllComponents(SnippetBlobEdit); const findBlobsData = () => findBlobEdits().wrappers.map((x) => ({ blob: x.props('blob'), diff --git a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js index 62d1ac9b476..a86ff566683 100644 --- a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js +++ b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js @@ -38,7 +38,7 @@ describe('Snippet Visibility Edit component', () => { } const findLink = () => wrapper.find('label').find(GlLink); - const findRadios = () => wrapper.find(GlFormRadioGroup).findAll(GlFormRadio); + const findRadios = () => wrapper.find(GlFormRadioGroup).findAllComponents(GlFormRadio); const findRadiosData = () => findRadios().wrappers.map((x) => { return { diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js index 16ffd2b7013..12a44452717 100644 --- a/spec/frontend/terraform/components/states_table_spec.js +++ b/spec/frontend/terraform/components/states_table_spec.js @@ -134,7 +134,7 @@ describe('StatesTable', () => { await nextTick(); }; - const findActions = () => wrapper.findAll(StateActions); + const findActions = () => wrapper.findAllComponents(StateActions); beforeEach(() => { return createComponent(); diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js index eef352a72ff..998bb2a9ea2 100644 --- a/spec/frontend/tooltips/components/tooltips_spec.js +++ b/spec/frontend/tooltips/components/tooltips_spec.js @@ -28,7 +28,7 @@ describe('tooltips/components/tooltips.vue', () => { return target; }; - const allTooltips = () => wrapper.findAll(GlTooltip); + const allTooltips = () => wrapper.findAllComponents(GlTooltip); afterEach(() => { wrapper.destroy(); @@ -68,7 +68,7 @@ describe('tooltips/components/tooltips.vue', () => { await nextTick(); - expect(wrapper.findAll(GlTooltip)).toHaveLength(1); + expect(wrapper.findAllComponents(GlTooltip)).toHaveLength(1); }); it('sets tooltip content from title attribute', async () => { diff --git a/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js b/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js index 712abfe228a..d519ad2cdb0 100644 --- a/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js @@ -39,10 +39,12 @@ describe('Artifacts List', () => { }); it('renders job url', () => { - expect(wrapper.findAll(GlLink).at(1).attributes('href')).toEqual(data.artifacts[0].job_path); + expect(wrapper.findAllComponents(GlLink).at(1).attributes('href')).toEqual( + data.artifacts[0].job_path, + ); }); it('renders job name', () => { - expect(wrapper.findAll(GlLink).at(1).text()).toEqual(data.artifacts[0].job_name); + expect(wrapper.findAllComponents(GlLink).at(1).text()).toEqual(data.artifacts[0].job_name); }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js index 663fabb761c..5d2d1fdd6f1 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js @@ -40,7 +40,7 @@ describe('Commits message dropdown component', () => { wrapper.destroy(); }); - const findDropdownElements = () => wrapper.findAll(GlDropdownItem); + const findDropdownElements = () => wrapper.findAllComponents(GlDropdownItem); const findFirstDropdownElement = () => findDropdownElements().at(0); it('should have 3 elements in dropdown list', () => { diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js index 6e89cd41559..bc3dbe8c351 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -111,7 +111,7 @@ const createComponent = ( }; const findCheckboxElement = () => wrapper.find(SquashBeforeMerge); -const findCommitEditElements = () => wrapper.findAll(CommitEdit); +const findCommitEditElements = () => wrapper.findAllComponents(CommitEdit); const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown); const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label'); const findTipLink = () => wrapper.find(GlSprintf); diff --git a/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js index 8f20d6a8fc9..7a868eb8cc9 100644 --- a/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js @@ -16,7 +16,8 @@ describe('MrWidgetTerraformConainer', () => { const propsData = { endpoint: '/path/to/terraform/report.json' }; const findHeader = () => wrapper.find('[data-testid="terraform-header-text"]'); - const findPlans = () => wrapper.findAll(TerraformPlan).wrappers.map((x) => x.props('plan')); + const findPlans = () => + wrapper.findAllComponents(TerraformPlan).wrappers.map((x) => x.props('plan')); const mockPollingApi = (response, body, header) => { mock.onGet(propsData.endpoint).reply(response, body, header); diff --git a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js index 67420e7fc2a..dca016dc317 100644 --- a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js +++ b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js @@ -74,7 +74,7 @@ describe('WorkItemsHierarchy Hierarchy', () => { }); it('renders license badges for all work items', () => { - expect(wrapper.findAll(GlBadge)).toHaveLength(items.length); + expect(wrapper.findAllComponents(GlBadge)).toHaveLength(items.length); }); it('does not render svg icon for linking', () => { diff --git a/spec/lib/api/entities/personal_access_token_with_details_spec.rb b/spec/lib/api/entities/personal_access_token_with_details_spec.rb deleted file mode 100644 index a53d6febba1..00000000000 --- a/spec/lib/api/entities/personal_access_token_with_details_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe API::Entities::PersonalAccessTokenWithDetails do - describe '#as_json' do - let_it_be(:user) { create(:user) } - let_it_be(:token) { create(:personal_access_token, user: user, expires_at: nil) } - - let(:entity) { described_class.new(token) } - - it 'returns token data' do - expect(entity.as_json).to eq({ - id: token.id, - name: token.name, - revoked: false, - created_at: token.created_at, - scopes: ['api'], - user_id: user.id, - last_used_at: nil, - active: true, - expires_at: nil, - expired: false, - expires_soon: false, - revoke_path: Gitlab::Routing.url_helpers.revoke_profile_personal_access_token_path(token) - }) - end - end -end diff --git a/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_projects_less_than_one_mb_spec.rb b/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_projects_less_than_one_mb_spec.rb new file mode 100644 index 00000000000..205350f9df4 --- /dev/null +++ b/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_projects_less_than_one_mb_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::DisableLegacyOpenSourceLicenseForProjectsLessThanOneMb, + :migration, + schema: 20220906074449 do + let(:namespaces_table) { table(:namespaces) } + let(:projects_table) { table(:projects) } + let(:project_settings_table) { table(:project_settings) } + let(:project_statistics_table) { table(:project_statistics) } + + subject(:perform_migration) do + described_class.new(start_id: project_settings_table.minimum(:project_id), + end_id: project_settings_table.maximum(:project_id), + batch_table: :project_settings, + batch_column: :project_id, + sub_batch_size: 2, + pause_ms: 0, + connection: ActiveRecord::Base.connection) + .perform + end + + it 'sets `legacy_open_source_license_available` to false only for projects less than 1 MB', + :aggregate_failures do + project_setting_1_mb = create_legacy_license_project_setting(repo_size: 1) + project_setting_2_mb = create_legacy_license_project_setting(repo_size: 2) + project_setting_quarter_mb = create_legacy_license_project_setting(repo_size: 0.25) + project_setting_half_mb = create_legacy_license_project_setting(repo_size: 0.5) + + queries = ActiveRecord::QueryRecorder.new { perform_migration } + + expect(queries.count).to eq(7) + expect(migrated_attribute(project_setting_1_mb)).to be_truthy + expect(migrated_attribute(project_setting_2_mb)).to be_truthy + expect(migrated_attribute(project_setting_quarter_mb)).to be_falsey + expect(migrated_attribute(project_setting_half_mb)).to be_falsey + end + + private + + # @param repo_size: Repo size in MB + def create_legacy_license_project_setting(repo_size:) + path = "path-for-repo-size-#{repo_size}" + namespace = namespaces_table.create!(name: "namespace-#{path}", path: "namespace-#{path}") + project_namespace = + namespaces_table.create!(name: "-project-namespace-#{path}", path: "project-namespace-#{path}", type: 'Project') + project = projects_table + .create!(name: path, path: path, namespace_id: namespace.id, project_namespace_id: project_namespace.id) + + size_in_bytes = 1.megabyte * repo_size + project_statistics_table.create!(project_id: project.id, namespace_id: namespace.id, repository_size: size_in_bytes) + project_settings_table.create!(project_id: project.id, legacy_open_source_license_available: true) + end + + def migrated_attribute(project_setting) + project_settings_table.find(project_setting.project_id).legacy_open_source_license_available + 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 ed6a87cda6f..ff3cade07c0 100644 --- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb @@ -297,6 +297,11 @@ RSpec.describe Gitlab::GitalyClient::CommitService do describe '#list_commits' do let(:revisions) { 'master' } let(:reverse) { false } + let(:author) { nil } + let(:ignore_case) { nil } + let(:commit_message_patterns) { nil } + let(:before) { nil } + let(:after) { nil } let(:pagination_params) { nil } shared_examples 'a ListCommits request' do @@ -309,13 +314,18 @@ RSpec.describe Gitlab::GitalyClient::CommitService do expected_request = gitaly_request_with_params( Array.wrap(revisions), reverse: reverse, + author: author, + ignore_case: ignore_case, + commit_message_patterns: commit_message_patterns, + before: before, + after: after, pagination_params: pagination_params ) expect(service).to receive(:list_commits).with(expected_request, kind_of(Hash)).and_return([]) end - client.list_commits(revisions, reverse: reverse, pagination_params: pagination_params) + client.list_commits(revisions, { reverse: reverse, author: author, ignore_case: ignore_case, commit_message_patterns: commit_message_patterns, before: before, after: after, pagination_params: pagination_params }) end end @@ -333,7 +343,12 @@ RSpec.describe Gitlab::GitalyClient::CommitService do it_behaves_like 'a ListCommits request' end - context 'with pagination params' do + context 'with commit message, author, before and after' do + let(:author) { "Dmitriy" } + let(:before) { 1474828200 } + let(:after) { 1474828200 } + let(:commit_message_patterns) { "Initial commit" } + let(:ignore_case) { true } let(:pagination_params) { { limit: 1, page_token: 'foo' } } it_behaves_like 'a ListCommits request' diff --git a/spec/migrations/20220906074449_schedule_disable_legacy_open_source_license_for_projects_less_than_one_mb_spec.rb b/spec/migrations/20220906074449_schedule_disable_legacy_open_source_license_for_projects_less_than_one_mb_spec.rb new file mode 100644 index 00000000000..e4ac094ab48 --- /dev/null +++ b/spec/migrations/20220906074449_schedule_disable_legacy_open_source_license_for_projects_less_than_one_mb_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe ScheduleDisableLegacyOpenSourceLicenseForProjectsLessThanOneMb do + let_it_be(:migration) { described_class.new } + let_it_be(:post_migration) { described_class::MIGRATION } + + context 'when on gitlab.com' do + before do + allow(Gitlab).to receive(:com?).and_return(true) + end + + describe '#up' do + it 'schedules background jobs for each batch of project_settings' do + migration.up + + expect(post_migration).to( + have_scheduled_batched_migration( + table_name: :project_settings, + column_name: :project_id, + interval: described_class::INTERVAL, + batch_size: described_class::BATCH_SIZE, + max_batch_size: described_class::MAX_BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + ) + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migration.down + + expect(post_migration).not_to have_scheduled_batched_migration + end + end + end + + context 'when on self-managed instance' do + before do + allow(Gitlab).to receive(:com?).and_return(false) + end + + describe '#up' do + it 'does not schedule background job' do + expect(migration).not_to receive(:queue_batched_background_migration) + + migration.up + end + end + + describe '#down' do + it 'does not delete background job' do + expect(migration).not_to receive(:delete_batched_background_migration) + + migration.down + end + end + end +end diff --git a/spec/models/ci/pipeline_artifact_spec.rb b/spec/models/ci/pipeline_artifact_spec.rb index b051f646bd4..3038cdc944b 100644 --- a/spec/models/ci/pipeline_artifact_spec.rb +++ b/spec/models/ci/pipeline_artifact_spec.rb @@ -227,6 +227,19 @@ RSpec.describe Ci::PipelineArtifact, type: :model do expect(subject.size).to eq(size) expect(subject.file_format).to eq(Ci::PipelineArtifact::REPORT_TYPES[file_type].to_s) expect(subject.expire_at).to eq(Ci::PipelineArtifact::EXPIRATION_DATE.from_now) + expect(subject.locked).to eq('unknown') + end + + it "creates a new pipeline artifact with pipeline's locked state" do + artifact = Ci::PipelineArtifact.create_or_replace_for_pipeline!( + pipeline: pipeline, + file_type: file_type, + file: file, + size: size, + locked: pipeline.locked + ) + + expect(artifact.locked).to eq(pipeline.locked) end end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 48c37713430..c475b510e62 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -4967,6 +4967,56 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end + describe '#self_and_downstreams' do + subject(:self_and_downstreams) { pipeline.self_and_downstreams } + + let(:pipeline) { create(:ci_pipeline, :created) } + + context 'when pipeline is not child nor parent' do + it 'returns just the pipeline itself' do + expect(self_and_downstreams).to contain_exactly(pipeline) + end + end + + context 'when pipeline is child' do + let(:parent) { create(:ci_pipeline) } + let!(:pipeline) { create(:ci_pipeline, child_of: parent) } + + it 'returns self and no ancestors' do + expect(self_and_downstreams).to contain_exactly(pipeline) + end + end + + context 'when pipeline is parent' do + let(:child) { create(:ci_pipeline, child_of: pipeline) } + + it 'returns self and child' do + expect(self_and_downstreams).to contain_exactly(pipeline, child) + end + end + + context 'when pipeline is a grandparent pipeline' do + let(:child) { create(:ci_pipeline, child_of: pipeline) } + let(:grandchild) { create(:ci_pipeline, child_of: child) } + + it 'returns self, child, and grandchild' do + expect(self_and_downstreams).to contain_exactly(pipeline, child, grandchild) + end + end + + context 'when pipeline is a triggered pipeline from a different project' do + let(:downstream) { create(:ci_pipeline) } + + before do + create_source_pipeline(pipeline, downstream) + end + + it 'returns self and cross-project downstream' do + expect(self_and_downstreams).to contain_exactly(pipeline, downstream) + end + end + end + describe '#self_and_project_ancestors' do subject(:self_and_project_ancestors) { pipeline.self_and_project_ancestors } @@ -5000,6 +5050,19 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end + describe '#complete_hierarchy_count' do + context 'with a combination of ancestor, descendant and sibling pipelines' do + let!(:pipeline) { create(:ci_pipeline) } + let!(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) } + let!(:sibling_pipeline) { create(:ci_pipeline, child_of: pipeline) } + let!(:grandchild_pipeline) { create(:ci_pipeline, child_of: child_pipeline) } + + it 'counts the whole tree' do + expect(sibling_pipeline.complete_hierarchy_count).to eq(4) + end + end + end + describe '#reset_source_bridge!' do let(:pipeline) { create(:ci_pipeline, :created, project: project) } diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index cb5c43a5270..7226c9db15d 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -1186,6 +1186,25 @@ RSpec.describe Ci::Runner do end end + describe '#owner_project' do + let_it_be(:project1) { create(:project) } + let_it_be(:project2) { create(:project) } + + subject(:owner_project) { project_runner.owner_project } + + context 'with project1 as first project associated with runner' do + let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project1, project2]) } + + it { is_expected.to eq project1 } + end + + context 'with project2 as first project associated with runner' do + let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project2, project1]) } + + it { is_expected.to eq project2 } + end + end + describe "belongs_to_one_project?" do it "returns false if there are two projects runner assigned to" do project1 = create(:project) diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 1de00518a13..ec6f2bda79a 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -1017,16 +1017,5 @@ RSpec.describe CommitStatus do it { is_expected.to be_nil } end - - context 'when ci_read_stage_records is disabled' do - before do - stub_feature_flags(ci_read_stage_records: false) - end - - it 'does not read from Ci::Stage', :aggregate_failures do - expect(commit_status).not_to receive(:ci_stage) - expect(stage_name).to eq('test') - end - end end end diff --git a/spec/models/group_group_link_spec.rb b/spec/models/group_group_link_spec.rb index 969987c7e64..eec8fe0ef71 100644 --- a/spec/models/group_group_link_spec.rb +++ b/spec/models/group_group_link_spec.rb @@ -44,6 +44,17 @@ RSpec.describe GroupGroupLink do end end + describe '.with_owner_access' do + let_it_be(:group_group_link_maintainer) { create :group_group_link, :maintainer } + let_it_be(:group_group_link_owner) { create :group_group_link, :owner } + let_it_be(:group_group_link_reporter) { create :group_group_link, :reporter } + let_it_be(:group_group_link_guest) { create :group_group_link, :guest } + + it 'returns all records which have OWNER access' do + expect(described_class.with_owner_access).to match_array([group_group_link_owner]) + end + end + context 'for access via group shares' do let_it_be(:shared_with_group_1) { create(:group) } let_it_be(:shared_with_group_2) { create(:group) } diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 839f862322d..4e386bf584f 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -545,6 +545,54 @@ RSpec.describe Repository do end end + describe '#list_commits_by' do + it 'returns commits with messages containing a given string' do + commit_ids = repository.list_commits_by('test text', 'master').map(&:id) + + expect(commit_ids).to include( + 'b83d6e391c22777fca1ed3012fce84f633d7fed0', + '498214de67004b1da3d820901307bed2a68a8ef6' + ) + expect(commit_ids).not_to include('c84ff944ff4529a70788a5e9003c2b7feae29047') + end + + it 'is case insensitive' do + commit_ids = repository.list_commits_by('TEST TEXT', 'master').map(&:id) + + expect(commit_ids).to include('b83d6e391c22777fca1ed3012fce84f633d7fed0') + end + + it 'returns commits based in before filter' do + commit_ids = repository.list_commits_by('test text', 'master', before: 1474828200).map(&:id) + expect(commit_ids).to include( + '498214de67004b1da3d820901307bed2a68a8ef6' + ) + expect(commit_ids).not_to include('b83d6e391c22777fca1ed3012fce84f633d7fed0') + end + + it 'returns commits based in after filter' do + commit_ids = repository.list_commits_by('test text', 'master', after: 1474828200).map(&:id) + expect(commit_ids).to include( + 'b83d6e391c22777fca1ed3012fce84f633d7fed0' + ) + expect(commit_ids).not_to include('498214de67004b1da3d820901307bed2a68a8ef6') + end + + it 'returns commits based in author filter' do + commit_ids = repository.list_commits_by('test text', 'master', author: 'Job van der Voort').map(&:id) + expect(commit_ids).to include( + 'b83d6e391c22777fca1ed3012fce84f633d7fed0' + ) + expect(commit_ids).not_to include('498214de67004b1da3d820901307bed2a68a8ef6') + end + + describe 'when storage is broken', :broken_storage do + it 'raises a storage error' do + expect_to_raise_storage_error { broken_repository.list_commits_by('s') } + end + end + end + describe '#blob_at' do context 'blank sha' do subject { repository.blob_at(Gitlab::Git::BLANK_SHA, '.gitignore') } diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 031e1a6c918..c4eae233f3b 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -2060,6 +2060,7 @@ RSpec.describe API::Groups do let_it_be(:maintainer_group) { create(:group, name: 'maintainer group', path: 'maintainer-group') } let_it_be(:owner_group_1) { create(:group, name: 'owner group', path: 'owner-group') } let_it_be(:owner_group_2) { create(:group, name: 'gitlab group', path: 'gitlab-group') } + let_it_be(:shared_with_group_where_direct_owner_as_owner) { create(:group) } before do source_group.add_owner(user) @@ -2067,6 +2068,10 @@ RSpec.describe API::Groups do maintainer_group.add_maintainer(user) owner_group_1.add_owner(user) owner_group_2.add_owner(user) + create(:group_group_link, :owner, + shared_with_group: owner_group_1, + shared_group: shared_with_group_where_direct_owner_as_owner + ) end it 'returns 200' do @@ -2079,7 +2084,11 @@ RSpec.describe API::Groups do it 'only includes groups where the user has permissions to transfer a group to' do request - expect(group_ids_from_response).to contain_exactly(owner_group_1.id, owner_group_2.id) + expect(group_ids_from_response).to contain_exactly( + owner_group_1.id, + owner_group_2.id, + shared_with_group_where_direct_owner_as_owner.id + ) end context 'with search' do diff --git a/spec/serializers/access_token_entity_base_spec.rb b/spec/serializers/access_token_entity_base_spec.rb new file mode 100644 index 00000000000..e14a07a346a --- /dev/null +++ b/spec/serializers/access_token_entity_base_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe AccessTokenEntityBase do + let_it_be(:user) { create(:user) } + let_it_be(:token) { create(:personal_access_token, user: user, expires_at: nil) } + + subject(:json) { described_class.new(token).as_json } + + it 'has the correct attributes' do + expect(json).to( + include( + id: token.id, + name: token.name, + revoked: false, + created_at: token.created_at, + scopes: token.scopes, + expires_at: nil, + expired: false, + expires_soon: false + )) + + expect(json).not_to include(:token) + end +end diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb index e2c42ab04d0..10aa839214c 100644 --- a/spec/services/ci/create_downstream_pipeline_service_spec.rb +++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb @@ -819,5 +819,19 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do end end end + + context 'when a downstream pipeline has sibling pipelines' do + it_behaves_like 'logs downstream pipeline creation' do + let(:expected_root_pipeline) { upstream_pipeline } + let(:expected_downstream_relationship) { :multi_project } + + # New downstream, plus upstream, plus two children of upstream created below + let(:expected_hierarchy_size) { 4 } + + before do + create_list(:ci_pipeline, 2, child_of: upstream_pipeline) + end + end + end end end diff --git a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb index 31548793bac..6d4dcf28108 100644 --- a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb +++ b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb @@ -51,6 +51,30 @@ RSpec.describe Ci::PipelineArtifacts::CoverageReportService do let!(:pipeline) { create(:ci_pipeline, :with_coverage_reports, project: project) } it_behaves_like 'creating or updating a pipeline coverage report' + + context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do + it "artifact has pipeline's locked status" do + subject + + artifact = Ci::PipelineArtifact.first + + expect(artifact.locked).to eq(pipeline.locked) + end + end + + context 'when ci_update_unlocked_pipeline_artifacts is disabled' do + before do + stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false) + end + + it 'artifact has unknown locked status' do + subject + + artifact = Ci::PipelineArtifact.first + + expect(artifact.locked).to eq('unknown') + end + end end context 'when pipeline has coverage report from child pipeline' do diff --git a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb index 5568052e346..75233248113 100644 --- a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb +++ b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb @@ -51,6 +51,30 @@ RSpec.describe ::Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService do end end + context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do + it "artifact has pipeline's locked status" do + subject + + artifact = Ci::PipelineArtifact.first + + expect(artifact.locked).to eq(head_pipeline.locked) + end + end + + context 'when ci_update_unlocked_pipeline_artifacts is disabled' do + before do + stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false) + end + + it 'artifact has unknown locked status' do + subject + + artifact = Ci::PipelineArtifact.first + + expect(artifact.locked).to eq('unknown') + end + end + it 'does not persist the same artifact twice' do 2.times { described_class.new(head_pipeline).execute } diff --git a/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb b/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb new file mode 100644 index 00000000000..b3fee24e09d --- /dev/null +++ b/spec/services/ci/runners/set_runner_associated_projects_service_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Ci::Runners::SetRunnerAssociatedProjectsService, '#execute' do + subject(:execute) { described_class.new(runner: runner, current_user: user, project_ids: project_ids).execute } + + let_it_be(:owner_project) { create(:project) } + let_it_be(:project2) { create(:project) } + let_it_be(:original_projects) { [owner_project, project2] } + let_it_be(:runner) { create(:ci_runner, :project, projects: original_projects) } + + context 'without user' do + let(:user) { nil } + let(:project_ids) { [project2.id] } + + it 'does not call assign_to on runner and returns error response', :aggregate_failures do + expect(runner).not_to receive(:assign_to) + + expect(execute).to be_error + expect(execute.message).to eq('user not allowed to assign runner') + end + end + + context 'with unauthorized user' do + let(:user) { build(:user) } + let(:project_ids) { [project2.id] } + + it 'does not call assign_to on runner and returns error message' do + expect(runner).not_to receive(:assign_to) + + expect(execute).to be_error + expect(execute.message).to eq('user not allowed to assign runner') + end + end + + context 'with admin user', :enable_admin_mode do + let(:user) { create_default(:user, :admin) } + let(:project_ids) { [project3.id, project4.id] } + let(:project3) { create(:project) } + let(:project4) { create(:project) } + + context 'with successful requests' do + it 'calls assign_to on runner and returns success response' do + expect(execute).to be_success + expect(runner.reload.projects.ids).to match_array([owner_project.id] + project_ids) + end + end + + context 'with failing assign_to requests' do + it 'returns error response and rolls back transaction' do + expect(runner).to receive(:assign_to).with(project4, user).once.and_return(false) + + expect(execute).to be_error + expect(runner.reload.projects).to match_array(original_projects) + end + end + + context 'with failing destroy calls' do + it 'returns error response and rolls back transaction' do + allow_next_found_instance_of(Ci::RunnerProject) do |runner_project| + allow(runner_project).to receive(:destroy).and_return(false) + end + + expect(execute).to be_error + expect(runner.reload.projects).to match_array(original_projects) + end + end + end +end diff --git a/spec/services/ci/unlock_artifacts_service_spec.rb b/spec/services/ci/unlock_artifacts_service_spec.rb index 94d39fc9f14..776019f03f8 100644 --- a/spec/services/ci/unlock_artifacts_service_spec.rb +++ b/spec/services/ci/unlock_artifacts_service_spec.rb @@ -5,11 +5,15 @@ require 'spec_helper' RSpec.describe Ci::UnlockArtifactsService do using RSpec::Parameterized::TableSyntax - where(:tag, :ci_update_unlocked_job_artifacts) do - false | false - false | true - true | false - true | true + where(:tag, :ci_update_unlocked_job_artifacts, :ci_update_unlocked_pipeline_artifacts) do + false | false | false + false | true | false + true | false | false + true | true | false + false | false | true + false | true | true + true | false | true + true | true | true end with_them do @@ -22,6 +26,7 @@ RSpec.describe Ci::UnlockArtifactsService do let!(:old_unlocked_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :unlocked) } let!(:older_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) } let!(:older_ambiguous_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: !tag, project: project, locked: :artifacts_locked) } + let!(:code_coverage_pipeline) { create(:ci_pipeline, :with_coverage_report_artifact, ref: ref, tag: tag, project: project, locked: :artifacts_locked) } let!(:pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) } let!(:child_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) } let!(:newer_pipeline) { create(:ci_pipeline, :with_persisted_artifacts, ref: ref, tag: tag, project: project, locked: :artifacts_locked) } @@ -30,7 +35,8 @@ RSpec.describe Ci::UnlockArtifactsService do before do stub_const("#{described_class}::BATCH_SIZE", 1) - stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts) + stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts, + ci_update_unlocked_pipeline_artifacts: ci_update_unlocked_pipeline_artifacts) end describe '#execute' do @@ -72,6 +78,14 @@ RSpec.describe Ci::UnlockArtifactsService do expect { execute }.to change { ::Ci::JobArtifact.artifact_unlocked.count }.from(0).to(2) end + + it 'unlocks pipeline artifact records' do + if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts + expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1) + else + expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count } + end + end end context 'when running on just the ref' do @@ -106,6 +120,14 @@ RSpec.describe Ci::UnlockArtifactsService do expect { execute }.to change { ::Ci::JobArtifact.artifact_unlocked.count }.from(0).to(8) end + + it 'unlocks pipeline artifact records' do + if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts + expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1) + else + expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count } + end + end end end |