Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
bfd344aeac
commit
37a739daec
|
|
@ -261,6 +261,66 @@ ee:decomposition-multiple-db-parallel:
|
|||
- !reference [.rules:test:qa-parallel, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::All/
|
||||
|
||||
ee:object-storage:
|
||||
extends: .qa
|
||||
variables:
|
||||
QA_SCENARIO: Test::Instance::Image
|
||||
QA_RSPEC_TAGS: --tag object_storage
|
||||
GITLAB_QA_OPTS: --omnibus-config object_storage
|
||||
rules:
|
||||
- !reference [.rules:test:qa-non-parallel, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::ObjectStorage/
|
||||
ee:object-storage-parallel:
|
||||
extends: ee:object-storage
|
||||
parallel: 2
|
||||
rules:
|
||||
- !reference [.rules:test:qa-parallel, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::ObjectStorage/
|
||||
|
||||
ee:object-storage-aws:
|
||||
extends: ee:object-storage
|
||||
variables:
|
||||
AWS_S3_ACCESS_KEY: $QA_AWS_S3_ACCESS_KEY
|
||||
AWS_S3_BUCKET_NAME: $QA_AWS_S3_BUCKET_NAME
|
||||
AWS_S3_KEY_ID: $QA_AWS_S3_KEY_ID
|
||||
AWS_S3_REGION: $QA_AWS_S3_REGION
|
||||
GITLAB_QA_OPTS: --omnibus-config object_storage_aws
|
||||
ee:object-storage-aws-parallel:
|
||||
extends: ee:object-storage-aws
|
||||
parallel: 2
|
||||
rules:
|
||||
- !reference [ee:object-storage-parallel, rules]
|
||||
|
||||
ee:object-storage-gcs:
|
||||
extends: ee:object-storage
|
||||
variables:
|
||||
GCS_BUCKET_NAME: $QA_GCS_BUCKET_NAME
|
||||
GOOGLE_PROJECT: $QA_GOOGLE_PROJECT
|
||||
GOOGLE_JSON_KEY: $QA_GOOGLE_JSON_KEY
|
||||
GOOGLE_CLIENT_EMAIL: $QA_GOOGLE_CLIENT_EMAIL
|
||||
GITLAB_QA_OPTS: --omnibus-config object_storage_gcs
|
||||
ee:object-storage-gcs-parallel:
|
||||
extends: ee:object-storage-gcs
|
||||
parallel: 2
|
||||
rules:
|
||||
- !reference [ee:object-storage-parallel, rules]
|
||||
|
||||
ee:packages:
|
||||
extends: .qa
|
||||
variables:
|
||||
QA_SCENARIO: Test::Instance::Image
|
||||
QA_RSPEC_TAGS: --tag packages
|
||||
GITLAB_QA_OPTS: --omnibus-config packages
|
||||
rules:
|
||||
- !reference [.rules:test:qa-non-parallel, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::Packages/
|
||||
ee:packages-parallel:
|
||||
extends: ee:packages
|
||||
parallel: 2
|
||||
rules:
|
||||
- !reference [.rules:test:qa-parallel, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::Packages/
|
||||
|
||||
# ------------------------------------------
|
||||
# Non parallel jobs
|
||||
# ------------------------------------------
|
||||
|
|
@ -370,9 +430,6 @@ ee:registry:
|
|||
|
||||
ee:registry-with-cdn:
|
||||
extends: .qa
|
||||
before_script:
|
||||
- unset GITLAB_QA_ADMIN_ACCESS_TOKEN
|
||||
- !reference [.gitlab-qa-install, before_script]
|
||||
variables:
|
||||
QA_SCENARIO: Test::Integration::RegistryWithCDN
|
||||
GCS_CDN_BUCKET_NAME: $QA_GCS_CDN_BUCKET_NAME
|
||||
|
|
@ -380,6 +437,9 @@ ee:registry-with-cdn:
|
|||
GOOGLE_CDN_JSON_KEY: $QA_GOOGLE_CDN_JSON_KEY
|
||||
GOOGLE_CDN_SIGNURL_KEY: $QA_GOOGLE_CDN_SIGNURL_KEY
|
||||
GOOGLE_CDN_SIGNURL_KEY_NAME: $QA_GOOGLE_CDN_SIGNURL_KEY_NAME
|
||||
before_script:
|
||||
- unset GITLAB_QA_ADMIN_ACCESS_TOKEN
|
||||
- !reference [.qa, before_script]
|
||||
rules:
|
||||
- !reference [.rules:test:qa, rules]
|
||||
- if: $QA_SUITES =~ /Test::Integration::RegistryWithCDN/
|
||||
|
|
@ -434,55 +494,17 @@ ee:metrics:
|
|||
- !reference [.rules:test:qa, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::Metrics/
|
||||
|
||||
ee:packages:
|
||||
extends: .qa
|
||||
variables:
|
||||
QA_SCENARIO: Test::Instance::Image
|
||||
QA_RSPEC_TAGS: --tag packages
|
||||
GITLAB_QA_OPTS: --omnibus-config packages
|
||||
rules:
|
||||
- !reference [.rules:test:qa, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::Packages/
|
||||
|
||||
ee:elasticsearch:
|
||||
extends: .qa
|
||||
variables:
|
||||
QA_SCENARIO: "Test::Integration::Elasticsearch"
|
||||
script:
|
||||
before_script:
|
||||
- unset ELASTIC_URL # unset url which is globally defined in .gitlab-ci.yml
|
||||
- !reference [.qa, script]
|
||||
- !reference [.qa, before_script]
|
||||
rules:
|
||||
- !reference [.rules:test:qa, rules]
|
||||
- if: $QA_SUITES =~ /Test::Integration::Elasticsearch/
|
||||
|
||||
ee:object-storage:
|
||||
extends: .qa
|
||||
variables:
|
||||
QA_SCENARIO: Test::Instance::Image
|
||||
QA_RSPEC_TAGS: --tag object_storage
|
||||
GITLAB_QA_OPTS: --omnibus-config object_storage
|
||||
rules:
|
||||
- !reference [.rules:test:qa, rules]
|
||||
- if: $QA_SUITES =~ /Test::Instance::ObjectStorage/
|
||||
|
||||
ee:object-storage-aws:
|
||||
extends: ee:object-storage
|
||||
variables:
|
||||
AWS_S3_ACCESS_KEY: $QA_AWS_S3_ACCESS_KEY
|
||||
AWS_S3_BUCKET_NAME: $QA_AWS_S3_BUCKET_NAME
|
||||
AWS_S3_KEY_ID: $QA_AWS_S3_KEY_ID
|
||||
AWS_S3_REGION: $QA_AWS_S3_REGION
|
||||
GITLAB_QA_OPTS: --omnibus-config object_storage_aws
|
||||
|
||||
ee:object-storage-gcs:
|
||||
extends: ee:object-storage
|
||||
variables:
|
||||
GCS_BUCKET_NAME: $QA_GCS_BUCKET_NAME
|
||||
GOOGLE_PROJECT: $QA_GOOGLE_PROJECT
|
||||
GOOGLE_JSON_KEY: $QA_GOOGLE_JSON_KEY
|
||||
GOOGLE_CLIENT_EMAIL: $QA_GOOGLE_CLIENT_EMAIL
|
||||
GITLAB_QA_OPTS: --omnibus-config object_storage_gcs
|
||||
|
||||
ee:registry-object-storage-tls:
|
||||
extends: ee:object-storage-aws
|
||||
variables:
|
||||
|
|
|
|||
|
|
@ -4,26 +4,6 @@ Layout/FirstArrayElementIndentation:
|
|||
Exclude:
|
||||
- 'ee/lib/ee/api/helpers/award_emoji.rb'
|
||||
- 'ee/spec/graphql/mutations/incident_management/escalation_policy/create_spec.rb'
|
||||
- 'ee/spec/graphql/resolvers/dora_metrics_resolver_spec.rb'
|
||||
- 'ee/spec/graphql/resolvers/security_orchestration/scan_execution_policy_resolver_spec.rb'
|
||||
- 'ee/spec/graphql/resolvers/timebox_report_resolver_spec.rb'
|
||||
- 'ee/spec/graphql/types/ci/pipeline_type_spec.rb'
|
||||
- 'ee/spec/graphql/types/dast_scanner_profile_type_spec.rb'
|
||||
- 'ee/spec/graphql/types/dast_site_profile_type_spec.rb'
|
||||
- 'ee/spec/helpers/paid_feature_callout_helper_spec.rb'
|
||||
- 'ee/spec/helpers/trial_status_widget_helper_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/auth/ldap/access_levels_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/checks/diff_check_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/config/security_orchestration_policies/processor_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/templates/Jobs/browser_performance_testing_gitlab_ci_yaml_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/templates/Jobs/load_performance_testing_gitlab_ci_yaml_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/yaml_processor_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/epic_node_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_links_aggregate_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/graphql/aggregations/issues/lazy_links_aggregate_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/graphql/loaders/bulk_epic_aggregate_loader_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_builds_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_ci_builds_metric_spec.rb'
|
||||
|
|
|
|||
|
|
@ -428,6 +428,7 @@ RSpec/ExpectChange:
|
|||
- 'spec/models/project_auto_devops_spec.rb'
|
||||
- 'spec/models/project_import_state_spec.rb'
|
||||
- 'spec/models/project_spec.rb'
|
||||
- 'spec/models/project_statistics_spec.rb'
|
||||
- 'spec/models/projects/build_artifacts_size_refresh_spec.rb'
|
||||
- 'spec/models/projects/ci_feature_usage_spec.rb'
|
||||
- 'spec/models/release_spec.rb'
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ RSpec/PredicateMatcher:
|
|||
- 'spec/models/concerns/awardable_spec.rb'
|
||||
- 'spec/models/concerns/chronic_duration_attribute_spec.rb'
|
||||
- 'spec/models/concerns/ci/has_deployment_name_spec.rb'
|
||||
- 'spec/models/concerns/counter_attribute_spec.rb'
|
||||
- 'spec/models/concerns/featurable_spec.rb'
|
||||
- 'spec/models/concerns/ignorable_columns_spec.rb'
|
||||
- 'spec/models/concerns/integrations/has_data_fields_spec.rb'
|
||||
|
|
|
|||
|
|
@ -23,11 +23,10 @@ class Projects::BlameController < Projects::ApplicationController
|
|||
environment_params[:find_latest] = true
|
||||
@environment = ::Environments::EnvironmentsByDeploymentsFinder.new(@project, current_user, environment_params).execute.last
|
||||
|
||||
blame_service = Projects::BlameService.new(@blob, @commit, params.permit(:page))
|
||||
blame_service = Projects::BlameService.new(@blob, @commit, params.permit(:page, :no_pagination))
|
||||
|
||||
@blame = Gitlab::View::Presenter::Factory.new(blame_service.blame, project: @project, path: @path, page: blame_service.page).fabricate!
|
||||
|
||||
render locals: { blame_pagination: blame_service.pagination }
|
||||
@blame_pagination = blame_service.pagination
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -64,20 +64,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
|
|||
|
||||
return unless stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs])
|
||||
|
||||
if diff_options_hash[:paths].blank?
|
||||
if Feature.enabled?(:remove_caching_diff_batches, @merge_request.project)
|
||||
render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options)
|
||||
else
|
||||
render_cached(
|
||||
diffs,
|
||||
with: PaginatedDiffSerializer.new(current_user: current_user),
|
||||
cache_context: -> (_) { [Digest::SHA256.hexdigest(cache_context.to_s)] },
|
||||
**options
|
||||
)
|
||||
end
|
||||
else
|
||||
render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options)
|
||||
end
|
||||
render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options)
|
||||
end
|
||||
# rubocop: enable Metrics/AbcSize
|
||||
|
||||
|
|
|
|||
|
|
@ -57,10 +57,12 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli
|
|||
end
|
||||
|
||||
if Gitlab::Utils.to_boolean(approve_params[:approve])
|
||||
success = ::MergeRequests::ApprovalService.new(project: @project, current_user: current_user, params: approve_params).execute(merge_request)
|
||||
unless merge_request.approved_by?(current_user)
|
||||
success = ::MergeRequests::ApprovalService.new(project: @project, current_user: current_user, params: approve_params).execute(merge_request)
|
||||
|
||||
unless success
|
||||
return render json: { message: _('An error occurred while approving, please try again.') }, status: :internal_server_error
|
||||
unless success
|
||||
return render json: { message: _('An error occurred while approving, please try again.') }, status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
merge_request_activity_counter.track_submit_review_approve(user: current_user)
|
||||
|
|
|
|||
|
|
@ -92,32 +92,6 @@ module BlobHelper
|
|||
end
|
||||
end
|
||||
|
||||
def replace_blob_link(project = @project, ref = @ref, path = @path, blob:)
|
||||
modify_file_button(
|
||||
project,
|
||||
ref,
|
||||
path,
|
||||
blob: blob,
|
||||
label: _("Replace"),
|
||||
action: "replace",
|
||||
btn_class: "default",
|
||||
modal_type: "upload"
|
||||
)
|
||||
end
|
||||
|
||||
def delete_blob_link(project = @project, ref = @ref, path = @path, blob:)
|
||||
modify_file_button(
|
||||
project,
|
||||
ref,
|
||||
path,
|
||||
blob: blob,
|
||||
label: _("Delete"),
|
||||
action: "delete",
|
||||
btn_class: "default",
|
||||
modal_type: "remove"
|
||||
)
|
||||
end
|
||||
|
||||
def can_modify_blob?(blob, project = @project, ref = @ref)
|
||||
!blob.stored_externally? && can_edit_tree?(project, ref)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ module CounterAttribute
|
|||
def counter_attribute_after_flush(&callback)
|
||||
after_flush_callbacks << callback
|
||||
end
|
||||
|
||||
def counter_attribute_enabled?(attribute)
|
||||
counter_attributes.include?(attribute)
|
||||
end
|
||||
end
|
||||
|
||||
# This method must only be called by FlushCounterIncrementsWorker
|
||||
|
|
@ -157,7 +161,7 @@ module CounterAttribute
|
|||
end
|
||||
|
||||
def counter_attribute_enabled?(attribute)
|
||||
self.class.counter_attributes.include?(attribute)
|
||||
self.class.counter_attribute_enabled?(attribute)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ class ProjectStatistics < ApplicationRecord
|
|||
default_value_for :snippets_size, 0
|
||||
|
||||
counter_attribute :build_artifacts_size
|
||||
counter_attribute :storage_size
|
||||
|
||||
counter_attribute_after_flush do |project_statistic|
|
||||
project_statistic.refresh_storage_size!
|
||||
|
||||
Namespaces::ScheduleAggregationWorker.perform_async(project_statistic.namespace_id)
|
||||
end
|
||||
|
||||
|
|
@ -21,7 +22,6 @@ class ProjectStatistics < ApplicationRecord
|
|||
|
||||
COLUMNS_TO_REFRESH = [:repository_size, :wiki_size, :lfs_objects_size, :commit_count, :snippets_size, :uploads_size, :container_registry_size].freeze
|
||||
INCREMENTABLE_COLUMNS = {
|
||||
build_artifacts_size: %i[storage_size],
|
||||
packages_size: %i[storage_size],
|
||||
pipeline_artifacts_size: %i[storage_size],
|
||||
snippets_size: %i[storage_size]
|
||||
|
|
@ -109,21 +109,25 @@ class ProjectStatistics < ApplicationRecord
|
|||
self.storage_size = storage_size
|
||||
end
|
||||
|
||||
# Since this incremental update method does not call update_storage_size above,
|
||||
# we have to update the storage_size here as additional column.
|
||||
# Additional columns are updated depending on key => [columns], which allows
|
||||
# to update statistics which are and also those which aren't included in storage_size
|
||||
# or any other additional summary column in the future.
|
||||
def refresh_storage_size!
|
||||
update_storage_size
|
||||
save!
|
||||
end
|
||||
|
||||
# Since this incremental update method does not call update_storage_size above through before_save,
|
||||
# we have to update the storage_size separately.
|
||||
#
|
||||
# For counter attributes, storage_size will be refreshed after the counter is flushed,
|
||||
# through counter_attribute_after_flush
|
||||
#
|
||||
# For non-counter attributes, storage_size is updated depending on key => [columns] in INCREMENTABLE_COLUMNS
|
||||
def self.increment_statistic(project, key, amount)
|
||||
raise ArgumentError, "Cannot increment attribute: #{key}" unless INCREMENTABLE_COLUMNS.key?(key)
|
||||
raise ArgumentError, "Cannot increment attribute: #{key}" unless incrementable_attribute?(key)
|
||||
return if amount == 0
|
||||
|
||||
project.statistics.try do |project_statistics|
|
||||
if project_statistics.counter_attribute_enabled?(key)
|
||||
statistics_to_increment = [key] + INCREMENTABLE_COLUMNS[key].to_a
|
||||
statistics_to_increment.each do |statistic|
|
||||
project_statistics.delayed_increment_counter(statistic, amount)
|
||||
end
|
||||
if counter_attribute_enabled?(key)
|
||||
project_statistics.delayed_increment_counter(key, amount)
|
||||
else
|
||||
legacy_increment_statistic(project, key, amount)
|
||||
end
|
||||
|
|
@ -149,6 +153,10 @@ class ProjectStatistics < ApplicationRecord
|
|||
update_all(updates.join(', '))
|
||||
end
|
||||
|
||||
def self.incrementable_attribute?(key)
|
||||
INCREMENTABLE_COLUMNS.key?(key) || counter_attribute_enabled?(key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def schedule_namespace_aggregation_worker
|
||||
|
|
|
|||
|
|
@ -7,9 +7,24 @@ module Packages
|
|||
|
||||
overrides(:read_package)
|
||||
|
||||
rule { anonymous & ~project.public_project }.prevent_all
|
||||
condition(:package_registry_access_level_feature_flag_enabled, scope: :subject) do
|
||||
::Feature.enabled?(:package_registry_access_level, @subject)
|
||||
end
|
||||
|
||||
rule { ~project.public_project & ~project.internal_access & ~project.project_allowed_for_job_token }.prevent_all
|
||||
condition(:packages_enabled_for_everyone, scope: :subject) do
|
||||
@subject.package_registry_access_level == ProjectFeature::PUBLIC
|
||||
end
|
||||
|
||||
# This rule can be removed if the `package_registry_access_level` feature flag is removed.
|
||||
# Reason: If the feature flag is globally enabled, this rule will never be executed.
|
||||
rule { anonymous & ~project.public_project & ~package_registry_access_level_feature_flag_enabled }.prevent_all
|
||||
|
||||
# This rule can be removed if the `package_registry_access_level` feature flag is removed.
|
||||
# Reason: If the feature flag is globally enabled, this rule will never be executed.
|
||||
rule do
|
||||
~project.public_project & ~project.internal_access &
|
||||
~project.project_allowed_for_job_token & ~package_registry_access_level_feature_flag_enabled
|
||||
end.prevent_all
|
||||
|
||||
rule { project.packages_disabled }.policy do
|
||||
prevent(:read_package)
|
||||
|
|
@ -30,6 +45,10 @@ module Packages
|
|||
rule { project.write_package_registry_deploy_token }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
|
||||
rule { package_registry_access_level_feature_flag_enabled & packages_enabled_for_everyone }.policy do
|
||||
enable :read_package
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module Projects
|
|||
@blob = blob
|
||||
@commit = commit
|
||||
@page = extract_page(params)
|
||||
@pagination_enabled = pagination_state(params)
|
||||
end
|
||||
|
||||
attr_reader :page
|
||||
|
|
@ -19,7 +20,7 @@ module Projects
|
|||
end
|
||||
|
||||
def pagination
|
||||
return unless pagination_enabled?
|
||||
return unless pagination_enabled
|
||||
|
||||
Kaminari.paginate_array([], total_count: blob_lines_count, limit: per_page)
|
||||
.tap { |pagination| pagination.max_paginates_per(per_page) }
|
||||
|
|
@ -28,10 +29,10 @@ module Projects
|
|||
|
||||
private
|
||||
|
||||
attr_reader :blob, :commit
|
||||
attr_reader :blob, :commit, :pagination_enabled
|
||||
|
||||
def blame_range
|
||||
return unless pagination_enabled?
|
||||
return unless pagination_enabled
|
||||
|
||||
first_line = (page - 1) * per_page + 1
|
||||
last_line = (first_line + per_page).to_i - 1
|
||||
|
|
@ -51,6 +52,12 @@ module Projects
|
|||
PER_PAGE
|
||||
end
|
||||
|
||||
def pagination_state(params)
|
||||
return false if Gitlab::Utils.to_boolean(params[:no_pagination], default: false)
|
||||
|
||||
Feature.enabled?(:blame_page_pagination, commit.project)
|
||||
end
|
||||
|
||||
def overlimit?(page)
|
||||
page * per_page >= blob_lines_count + per_page
|
||||
end
|
||||
|
|
@ -58,9 +65,5 @@ module Projects
|
|||
def blob_lines_count
|
||||
@blob_lines_count ||= blob.data.lines.count
|
||||
end
|
||||
|
||||
def pagination_enabled?
|
||||
Feature.enabled?(:blame_page_pagination, commit.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -158,14 +158,25 @@ module Projects
|
|||
priority: UserProjectAccessChangedService::LOW_PRIORITY
|
||||
)
|
||||
else
|
||||
@project.add_owner(@project.namespace.owner, current_user: current_user)
|
||||
owner_user = @project.namespace.owner
|
||||
owner_member = @project.add_owner(owner_user, current_user: current_user)
|
||||
|
||||
# There is a possibility that the sidekiq job to refresh the authorizations of the owner_user in this project
|
||||
# isn't picked up (or finished) by the time the user is redirected to the newly created project's page.
|
||||
# If that happens, the user will hit a 404. To avoid that scenario, we manually create a `project_authorizations` record for the user here.
|
||||
if owner_member.persisted?
|
||||
owner_user.project_authorizations.safe_find_or_create_by(
|
||||
project: @project,
|
||||
access_level: ProjectMember::OWNER
|
||||
)
|
||||
end
|
||||
# During the process of adding a project owner, a check on permissions is made on the user which caches
|
||||
# the max member access for that user on this project.
|
||||
# Since that is `0` before the member is created - and we are still inside the request
|
||||
# cycle when we need to do other operations that might check those permissions (e.g. write a commit)
|
||||
# we need to purge that cache so that the updated permissions is fetched instead of using the outdated cached value of 0
|
||||
# from before member creation
|
||||
@project.team.purge_member_access_cache_for_user_id(@project.namespace.owner.id)
|
||||
@project.team.purge_member_access_cache_for_user_id(owner_user.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
- page_title _("Blame"), @blob.path, @ref
|
||||
|
||||
#blob-content-holder.tree-holder
|
||||
#blob-content-holder.tree-holder{ data: { testid: 'blob-content-holder' } }
|
||||
= render "projects/blob/breadcrumb", blob: @blob, blame: true
|
||||
|
||||
.file-holder
|
||||
.file-holder.gl-overflow-hidden
|
||||
= render "projects/blob/header", blob: @blob, blame: true
|
||||
|
||||
.file-blame-legend
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
%span.legend-box.legend-box-9
|
||||
%span.right-label Older
|
||||
|
||||
.table-responsive.file-content.blame.code{ class: user_color_scheme, data: { qa_selector: 'blame_file_content' } }
|
||||
.table-responsive.file-content.blame.code{ class: "#{user_color_scheme} gl-rounded-0!", data: { qa_selector: 'blame_file_content' } }
|
||||
%table
|
||||
- current_line = @blame.first_line
|
||||
- @blame.groups.each do |blame_group|
|
||||
|
|
@ -59,5 +59,11 @@
|
|||
|
||||
- current_line += line_count
|
||||
|
||||
- if blame_pagination
|
||||
= paginate(blame_pagination, theme: "gitlab")
|
||||
- if @blame_pagination
|
||||
.gl-display-flex.gl-justify-content-center.gl-flex-direction-column.gl-align-items-center.gl-p-3.gl-bg-gray-50.gl-border-t-solid.gl-border-t-1.gl-border-gray-100
|
||||
= _('For faster browsing, not all history is shown.')
|
||||
= render Pajamas::ButtonComponent.new(href: namespace_project_blame_path(namespace_id: @project.namespace, project_id: @project, id: @id, no_pagination: true), size: :small, button_options: { class: 'gl-mt-3' }) do |c|
|
||||
= _('View entire blame')
|
||||
|
||||
- if @blame_pagination
|
||||
= paginate(@blame_pagination, theme: "gitlab")
|
||||
|
|
|
|||
|
|
@ -6,12 +6,6 @@
|
|||
.file-actions.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-md-justify-content-end<
|
||||
= render 'projects/blob/viewer_switcher', blob: blob unless blame
|
||||
= render 'shared/web_ide_button', blob: blob
|
||||
- unless blame
|
||||
.btn-group{ role: "group", class: ("gl-ml-3" if current_user) }>
|
||||
= render_if_exists 'projects/blob/header_file_locks_link'
|
||||
- if current_user
|
||||
= replace_blob_link(@project, @ref, @path, blob: blob)
|
||||
= delete_blob_link(@project, @ref, @path, blob: blob)
|
||||
.btn-group.gl-ml-3{ role: "group" }
|
||||
= copy_blob_source_button(blob) unless blame
|
||||
= open_raw_blob_button(blob)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class FlushCounterIncrementsWorker
|
|||
data_consistency :always
|
||||
|
||||
sidekiq_options retry: 3
|
||||
loggable_arguments 0, 2
|
||||
|
||||
# The increments in `ProjectStatistics` are owned by several teams depending
|
||||
# on the counter
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: remove_caching_diff_batches
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95562
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370933
|
||||
name: draft_quick_action_non_toggle
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92654
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368610
|
||||
milestone: '15.4'
|
||||
type: development
|
||||
group: group::code review
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
const vm = require('vm');
|
||||
|
||||
/**
|
||||
* This function uses Node's `vm` modules to evaluate the `module.exports` of a given source string
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```javascript
|
||||
* const { exports: moduleExports } = evaluateModuleFromSource("const foo = 7;\n module.exports.bar = 10 + foo;");
|
||||
*
|
||||
* assert(moduleExports.bar === 17);
|
||||
* ```
|
||||
*
|
||||
* @param {String} source to be evaluated using Node's `vm` modules
|
||||
* @param {{ require: Function }} options used in the context during evaluation of the Node module
|
||||
* @returns {{ exports: any }} exports added to the script's `module.exports` context
|
||||
*/
|
||||
const evaluateModuleFromSource = (source, { require } = {}) => {
|
||||
const context = {
|
||||
module: {
|
||||
exports: {},
|
||||
},
|
||||
require,
|
||||
};
|
||||
|
||||
try {
|
||||
const script = new vm.Script(source);
|
||||
script.runInNewContext(context);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return context.module;
|
||||
};
|
||||
|
||||
module.exports = { evaluateModuleFromSource };
|
||||
|
|
@ -712,9 +712,6 @@ Gitlab.ee do
|
|||
Settings.cron_jobs['ldap_sync_worker'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['ldap_sync_worker']['cron'] ||= '30 1 * * *'
|
||||
Settings.cron_jobs['ldap_sync_worker']['job_class'] = 'LdapSyncWorker'
|
||||
Settings.cron_jobs['free_user_cap_data_remediation'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['free_user_cap_data_remediation']['cron'] ||= '17 6,10,14,18 * * *'
|
||||
Settings.cron_jobs['free_user_cap_data_remediation']['job_class'] = 'Namespaces::FreeUserCap::RemediationWorker'
|
||||
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['cron'] ||= '0 12 * * *'
|
||||
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['job_class'] = 'UpdateMaxSeatsUsedForGitlabComSubscriptionsWorker'
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
/* eslint-disable no-underscore-dangle */
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const { evaluateModuleFromSource } = require('../helpers/evaluate_module_from_source');
|
||||
|
||||
const PLUGIN_NAME = 'GraphqlKnownOperationsPlugin';
|
||||
const GRAPHQL_PATH_REGEX = /(query|mutation)\.graphql$/;
|
||||
const OPERATION_NAME_SOURCE_REGEX = /^\s*module\.exports.*oneQuery.*"(\w+)"/gm;
|
||||
|
||||
/**
|
||||
* Returns whether a given webpack module is a "graphql" module
|
||||
|
|
@ -26,9 +27,19 @@ const getOperationNames = (module) => {
|
|||
return [];
|
||||
}
|
||||
|
||||
const matches = originalSource.source().toString().matchAll(OPERATION_NAME_SOURCE_REGEX);
|
||||
const { exports: moduleExports } = evaluateModuleFromSource(originalSource.source().toString(), {
|
||||
// what: stub require(...) when evaluating the graphql module
|
||||
// why: require(...) is used to fetch fragments. We only need operation metadata, so it's fine to stub these out.
|
||||
require: () => ({ definitions: [] }),
|
||||
});
|
||||
|
||||
return Array.from(matches).map((match) => match[1]);
|
||||
const names = moduleExports.definitions
|
||||
.filter((x) => ['query', 'mutation'].includes(x.operation))
|
||||
.map((x) => x.name?.value)
|
||||
// why: It's possible for operations to not have a name. That violates our eslint rule, but either way, let's ignore those here.
|
||||
.filter(Boolean);
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
const createFileContents = (knownOperations) => {
|
||||
|
|
@ -60,7 +71,7 @@ const onSucceedModule = ({ module, knownOperations }) => {
|
|||
return;
|
||||
}
|
||||
|
||||
getOperationNames(module).forEach((x) => knownOperations.add(x));
|
||||
getOperationNames(module).forEach((name) => knownOperations.add(name));
|
||||
};
|
||||
|
||||
const onCompilerEmit = ({ compilation, knownOperations, filename }) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveFreeUserCapRemediationWorker < Gitlab::Database::Migration[2.0]
|
||||
def up
|
||||
Sidekiq::Cron::Job.find('free_user_cap_data_remediation')&.destroy
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexToTodosPendingQuery < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_on_todos_user_project_target_and_state'
|
||||
COLUMNS = %i[user_id project_id target_type target_id id].freeze
|
||||
|
||||
def up
|
||||
add_concurrent_index :todos, COLUMNS, name: INDEX_NAME, where: "state = 'pending'"
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :todos, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
d5d264f90203ba371edcf0688d1227aa69cbf0018033d141257e4c88072ee7d7
|
||||
|
|
@ -0,0 +1 @@
|
|||
30d9f3352daa48f529486030e30667a1339b04e96b207be815505477ab498adb
|
||||
|
|
@ -29531,6 +29531,8 @@ CREATE INDEX index_on_projects_path ON projects USING btree (path);
|
|||
|
||||
CREATE INDEX index_on_routes_lower_path ON routes USING btree (lower((path)::text));
|
||||
|
||||
CREATE INDEX index_on_todos_user_project_target_and_state ON todos USING btree (user_id, project_id, target_type, target_id, id) WHERE ((state)::text = 'pending'::text);
|
||||
|
||||
CREATE INDEX index_on_users_lower_email ON users USING btree (lower((email)::text));
|
||||
|
||||
CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username)::text));
|
||||
|
|
|
|||
|
|
@ -329,7 +329,6 @@ GET /groups/:id/billable_members
|
|||
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `search` | string | no | A query string to search for group members by name, username, or public email. |
|
||||
| `sort` | string | no | A query string containing parameters that specify the sort attribute and order. See supported values below. |
|
||||
| `include_awaiting_members` | boolean | no | Determines if awaiting members are included. |
|
||||
|
||||
The supported values for the `sort` attribute are:
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Parameters:
|
|||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `id` | integer/string| yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user|
|
||||
| `order_by` | string | no | Return tags ordered by `name` or `updated` fields. Default is `updated` |
|
||||
| `order_by` | string | no | Return tags ordered by `name`, `updated`, or `version` (since 15.4) fields. Default is `updated` |
|
||||
| `sort` | string | no | Return tags sorted in `asc` or `desc` order. Default is `desc` |
|
||||
| `search` | string | no | Return list of tags matching the search criteria. You can use `^term` and `term$` to find tags that begin and end with `term` respectively. No other regular expressions are supported. |
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ as it can cause the pipeline to behave unexpectedly.
|
|||
| `CI_JOB_JWT` | 12.10 | all | A RS256 JSON web token to authenticate with third party systems that support JWT authentication, for example [HashiCorp's Vault](../secrets/index.md). |
|
||||
| `CI_JOB_JWT_V1` | 14.6 | all | The same value as `CI_JOB_JWT`. |
|
||||
| `CI_JOB_JWT_V2` | 14.6 | all | [**alpha:**](../../policy/alpha-beta-support.md#alpha-features) A newly formatted RS256 JSON web token to increase compatibility. Similar to `CI_JOB_JWT`, except the issuer (`iss`) claim is changed from `gitlab.com` to `https://gitlab.com`, `sub` has changed from `job_id` to a string that contains the project path, and an `aud` claim is added. Format is subject to change. Be aware, the `aud` field is a constant value. Trusting JWTs in multiple relying parties can lead to [one RP sending a JWT to another one and acting maliciously as a job](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72555#note_769112331). |
|
||||
| `CI_JOB_MANUAL` | 8.12 | all | `true` if a job was started manually. |
|
||||
| `CI_JOB_MANUAL` | 8.12 | all | Only available if the job was started manually. `true` when available. |
|
||||
| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job. |
|
||||
| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the job's stage. |
|
||||
| `CI_JOB_STATUS` | all | 13.5 | The status of the job as each runner stage is executed. Use with [`after_script`](../yaml/index.md#after_script). Can be `success`, `failed`, or `canceled`. |
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ The generated service account has the following roles:
|
|||
- `roles/cloudbuild.builds.builder`
|
||||
- `roles/run.admin`
|
||||
- `roles/storage.admin`
|
||||
- `roles/cloudsql.admin`
|
||||
- `roles/cloudsql.client`
|
||||
- `roles/browser`
|
||||
|
||||
You can enhance security by storing CI variables in secret managers. Learn more about [secret management with GitLab](../ci/secrets/index.md).
|
||||
|
|
|
|||
|
|
@ -20,6 +20,17 @@ See also [guidelines for reusing abstractions](../reusing_abstractions.md).
|
|||
|
||||
Everything listed here can be [reopened for discussion](https://about.gitlab.com/handbook/values/#disagree-commit-and-disagree).
|
||||
|
||||
## String literals quoting
|
||||
|
||||
Due to the sheer amount of work to rectify, we do not care whether string
|
||||
literals are single, or double quoted.
|
||||
|
||||
Previous discussions include:
|
||||
|
||||
- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44234>
|
||||
- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/36076>
|
||||
- <https://gitlab.com/gitlab-org/gitlab/-/issues/198046>
|
||||
|
||||
## Instance variable access using `attr_reader`
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52351) in GitLab 14.1.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ the **Merge** button until you remove the **Draft** flag:
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32692) in GitLab 13.2, Work-In-Progress (WIP) merge requests were renamed to **Draft**.
|
||||
> - [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/228685) all support for using **WIP** in GitLab 14.8.
|
||||
> - **Mark as draft** and **Mark as ready** buttons [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227421) in GitLab 13.5.
|
||||
> `/draft` quick action as a toggle [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92654) in GitLab 15.3.
|
||||
|
||||
There are several ways to flag a merge request as a draft:
|
||||
|
||||
|
|
@ -29,8 +30,7 @@ There are several ways to flag a merge request as a draft:
|
|||
below the **Title** field.
|
||||
- **Commenting in an existing merge request**: Add the `/draft`
|
||||
[quick action](../quick_actions.md#issues-merge-requests-and-epics)
|
||||
in a comment. This quick action is a toggle, and can be repeated to change the status
|
||||
back to Ready.
|
||||
in a comment. GitLab 15.4 [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92654) the toggle behavior of `/draft`. To mark a merge request as ready, use `/ready`.
|
||||
- **Creating a commit**: Add `draft:`, `Draft:`, `fixup!`, or `Fixup!` to the
|
||||
beginning of a commit message targeting the merge request's source branch. This
|
||||
is not a toggle, and adding this text again in a later commit doesn't mark the
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ threads. Some quick actions might not be available to all subscription tiers.
|
|||
| `/copy_metadata <#issue>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Copy labels and milestone from another issue in the project. |
|
||||
| `/create_merge_request <branch name>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Create a new merge request starting from the current issue. |
|
||||
| `/done` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Mark to do as done. |
|
||||
| `/draft` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Toggle the [draft status](merge_requests/drafts.md). |
|
||||
| `/draft` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Set the [draft status](merge_requests/drafts.md). Use for toggling the draft status ([deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92654) in GitLab 15.4.) |
|
||||
| `/due <date>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set due date. Examples of valid `<date>` include `in 2 days`, `this Friday` and `December 31st`. |
|
||||
| `/duplicate <#issue>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Close this issue and mark as a duplicate of another issue. Also, mark both as related. |
|
||||
| `/epic <epic>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add to epic `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic. |
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ module API
|
|||
params do
|
||||
optional :sort, type: String, values: %w[asc desc], default: 'desc',
|
||||
desc: 'Return tags sorted in updated by `asc` or `desc` order.'
|
||||
optional :order_by, type: String, values: %w[name updated], default: 'updated',
|
||||
desc: 'Return tags ordered by `name` or `updated` fields.'
|
||||
optional :order_by, type: String, values: %w[name updated version], default: 'updated',
|
||||
desc: 'Return tags ordered by `name`, `updated`, `version` fields.'
|
||||
optional :search, type: String, desc: 'Return list of tags matching the search criteria'
|
||||
optional :page_token, type: String, desc: 'Name of tag to start the paginaition from'
|
||||
use :pagination
|
||||
|
|
|
|||
|
|
@ -88,33 +88,21 @@ module Gitlab
|
|||
@execution_message[:rebase] = _('Scheduled a rebase of branch %{branch}.') % { branch: branch }
|
||||
end
|
||||
|
||||
desc { _('Toggle the Draft status') }
|
||||
desc { _('Set the Draft status') }
|
||||
explanation do
|
||||
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
|
||||
if quick_action_target.draft?
|
||||
_("Marks this %{noun} as ready.")
|
||||
else
|
||||
_("Marks this %{noun} as a draft.")
|
||||
end % { noun: noun }
|
||||
draft_action_message(_("Marks"))
|
||||
end
|
||||
execution_message do
|
||||
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
|
||||
if quick_action_target.draft?
|
||||
_("Marked this %{noun} as ready.")
|
||||
else
|
||||
_("Marked this %{noun} as a draft.")
|
||||
end % { noun: noun }
|
||||
draft_action_message(_("Marked"))
|
||||
end
|
||||
|
||||
types MergeRequest
|
||||
condition do
|
||||
quick_action_target.respond_to?(:draft?) &&
|
||||
# Allow it to mark as draft on MR creation page or through MR notes
|
||||
#
|
||||
(quick_action_target.new_record? || current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target))
|
||||
end
|
||||
command :draft do
|
||||
@updates[:wip_event] = quick_action_target.draft? ? 'ready' : 'draft'
|
||||
@updates[:wip_event] = draft_action_command
|
||||
end
|
||||
|
||||
desc { _('Set the Ready status') }
|
||||
|
|
@ -317,6 +305,25 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def draft_action_message(verb)
|
||||
noun = quick_action_target.to_ability_name.humanize(capitalize: false)
|
||||
if !quick_action_target.draft?
|
||||
_("%{verb} this %{noun} as a draft.")
|
||||
elsif Feature.disabled?(:draft_quick_action_non_toggle, quick_action_target.project)
|
||||
_("%{verb} this %{noun} as ready.")
|
||||
else
|
||||
_("No change to this %{noun}'s draft status.")
|
||||
end % { verb: verb, noun: noun }
|
||||
end
|
||||
|
||||
def draft_action_command
|
||||
if Feature.disabled?(:draft_quick_action_non_toggle, quick_action_target.project)
|
||||
quick_action_target.draft? ? 'ready' : 'draft'
|
||||
else
|
||||
'draft'
|
||||
end
|
||||
end
|
||||
|
||||
def merge_orchestration_service
|
||||
@merge_orchestration_service ||= ::MergeRequests::MergeOrchestrationService.new(project, current_user)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ module GoogleApi
|
|||
"https://www.googleapis.com/auth/logging.write",
|
||||
"https://www.googleapis.com/auth/monitoring"
|
||||
].freeze
|
||||
ROLES_LIST = %w[roles/iam.serviceAccountUser roles/artifactregistry.admin roles/cloudbuild.builds.builder roles/run.admin roles/storage.admin roles/cloudsql.admin roles/browser].freeze
|
||||
ROLES_LIST = %w[roles/iam.serviceAccountUser roles/artifactregistry.admin roles/cloudbuild.builds.builder roles/run.admin roles/storage.admin roles/cloudsql.client roles/browser].freeze
|
||||
REVOKE_URL = 'https://oauth2.googleapis.com/revoke'
|
||||
|
||||
class << self
|
||||
|
|
|
|||
|
|
@ -1180,6 +1180,12 @@ msgstr ""
|
|||
msgid "%{verb} %{time_spent_value} spent time."
|
||||
msgstr ""
|
||||
|
||||
msgid "%{verb} this %{noun} as a draft."
|
||||
msgstr ""
|
||||
|
||||
msgid "%{verb} this %{noun} as ready."
|
||||
msgstr ""
|
||||
|
||||
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -16781,6 +16787,9 @@ msgstr ""
|
|||
msgid "For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
|
||||
msgstr ""
|
||||
|
||||
msgid "For faster browsing, not all history is shown."
|
||||
msgstr ""
|
||||
|
||||
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -24281,6 +24290,9 @@ msgstr ""
|
|||
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Marked"
|
||||
msgstr ""
|
||||
|
||||
msgid "Marked For Deletion At - %{deletion_time}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -24290,9 +24302,6 @@ msgstr ""
|
|||
msgid "Marked as ready. Merging is now allowed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Marked this %{noun} as a draft."
|
||||
msgstr ""
|
||||
|
||||
msgid "Marked this %{noun} as ready."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -24305,7 +24314,7 @@ msgstr ""
|
|||
msgid "Marked to do as done."
|
||||
msgstr ""
|
||||
|
||||
msgid "Marks this %{noun} as a draft."
|
||||
msgid "Marks"
|
||||
msgstr ""
|
||||
|
||||
msgid "Marks this %{noun} as ready."
|
||||
|
|
@ -36334,6 +36343,9 @@ msgstr ""
|
|||
msgid "Set target branch to %{branch_name}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set the Draft status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set the Ready status"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -41420,9 +41432,6 @@ msgstr ""
|
|||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle the Draft status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle the Performance Bar"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -43485,6 +43494,9 @@ msgstr ""
|
|||
msgid "View eligible approvers"
|
||||
msgstr ""
|
||||
|
||||
msgid "View entire blame"
|
||||
msgstr ""
|
||||
|
||||
msgid "View epics list"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46047,6 +46059,9 @@ msgstr ""
|
|||
msgid "added %{emails}"
|
||||
msgstr ""
|
||||
|
||||
msgid "added a %{link_type} link"
|
||||
msgstr ""
|
||||
|
||||
msgid "added a Zoom call to this issue"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -47701,6 +47716,9 @@ msgstr ""
|
|||
msgid "removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed a %{link_type} link"
|
||||
msgstr ""
|
||||
|
||||
msgid "removed a Zoom call from this issue"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,6 @@ module QA
|
|||
element :lock_button
|
||||
end
|
||||
|
||||
view 'app/helpers/blob_helper.rb' do
|
||||
element :edit_button, "_('Edit')" # rubocop:disable QA/ElementWithPattern
|
||||
element :delete_button, '_("Delete")' # rubocop:disable QA/ElementWithPattern
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/vue_shared/components/web_ide_link.vue' do
|
||||
element :edit_button
|
||||
end
|
||||
|
|
|
|||
|
|
@ -471,6 +471,21 @@ RSpec.describe Projects::MergeRequests::DraftsController do
|
|||
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
|
||||
.to have_received(:track_submit_review_approve).with(user: user)
|
||||
end
|
||||
|
||||
context 'when merge request is already approved by user' do
|
||||
before do
|
||||
create(:approval, merge_request: merge_request, user: user)
|
||||
end
|
||||
|
||||
it 'does return 200' do
|
||||
post :publish, params: params.merge!(approve: true)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
|
||||
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
|
||||
.to have_received(:track_submit_review_approve).with(user: user)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ RSpec.describe 'File blame', :js do
|
|||
it 'displays the blame page without pagination' do
|
||||
visit_blob_blame(path)
|
||||
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).not_to have_css('.gl-pagination')
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).not_to have_css('.gl-pagination')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when blob length is over the blame range limit' do
|
||||
|
|
@ -47,12 +49,15 @@ RSpec.describe 'File blame', :js do
|
|||
it 'displays two first lines of the file with pagination' do
|
||||
visit_blob_blame(path)
|
||||
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).to have_css('.gl-pagination')
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).to have_css('.gl-pagination')
|
||||
expect(page).to have_link _('View entire blame')
|
||||
|
||||
expect(page).to have_css('#L1')
|
||||
expect(page).not_to have_css('#L3')
|
||||
expect(find('.page-link.active')).to have_text('1')
|
||||
expect(page).to have_css('#L1')
|
||||
expect(page).not_to have_css('#L3')
|
||||
expect(find('.page-link.active')).to have_text('1')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user clicks on the next button' do
|
||||
|
|
@ -63,15 +68,35 @@ RSpec.describe 'File blame', :js do
|
|||
end
|
||||
|
||||
it 'displays next two lines of the file with pagination' do
|
||||
expect(page).not_to have_css('#L1')
|
||||
expect(page).to have_css('#L3')
|
||||
expect(find('.page-link.active')).to have_text('2')
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
expect(page).not_to have_css('#L1')
|
||||
expect(page).to have_css('#L3')
|
||||
expect(find('.page-link.active')).to have_text('2')
|
||||
end
|
||||
end
|
||||
|
||||
it 'correctly redirects to the prior blame page' do
|
||||
find('.version-link').click
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
find('.version-link').click
|
||||
|
||||
expect(find('.page-link.active')).to have_text('2')
|
||||
expect(find('.page-link.active')).to have_text('2')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user clicks on View entire blame button' do
|
||||
before do
|
||||
visit_blob_blame(path)
|
||||
end
|
||||
|
||||
it 'displays the blame page without pagination' do
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
click_link _('View entire blame')
|
||||
|
||||
expect(page).to have_css('#L1')
|
||||
expect(page).to have_css('#L3')
|
||||
expect(page).not_to have_css('.gl-pagination')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -83,8 +108,11 @@ RSpec.describe 'File blame', :js do
|
|||
it 'displays the blame page without pagination' do
|
||||
visit_blob_blame(path)
|
||||
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).not_to have_css('.gl-pagination')
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).not_to have_css('.gl-pagination')
|
||||
expect(page).not_to have_link _('View entire blame')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -99,25 +127,29 @@ RSpec.describe 'File blame', :js do
|
|||
it 'displays two hundred lines of the file with pagination' do
|
||||
visit_blob_blame(path)
|
||||
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).to have_css('.gl-pagination')
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
expect(page).to have_css('.blame-commit')
|
||||
expect(page).to have_css('.gl-pagination')
|
||||
|
||||
expect(page).to have_css('#L1')
|
||||
expect(page).not_to have_css('#L201')
|
||||
expect(find('.page-link.active')).to have_text('1')
|
||||
expect(page).to have_css('#L1')
|
||||
expect(page).not_to have_css('#L201')
|
||||
expect(find('.page-link.active')).to have_text('1')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user clicks on the next button' do
|
||||
before do
|
||||
visit_blob_blame(path)
|
||||
|
||||
find('.js-next-button').click
|
||||
end
|
||||
|
||||
it 'displays next two hundred lines of the file with pagination' do
|
||||
expect(page).not_to have_css('#L1')
|
||||
expect(page).to have_css('#L201')
|
||||
expect(find('.page-link.active')).to have_text('2')
|
||||
within '[data-testid="blob-content-holder"]' do
|
||||
find('.js-next-button').click
|
||||
|
||||
expect(page).not_to have_css('#L1')
|
||||
expect(page).to have_css('#L201')
|
||||
expect(find('.page-link.active')).to have_text('2')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@ describe('keepAlive', () => {
|
|||
});
|
||||
|
||||
it('converts a component to a keep-alive component', async () => {
|
||||
const { element } = wrapper.find(component);
|
||||
const { element } = wrapper.findComponent(component);
|
||||
|
||||
await wrapper.vm.deactivate();
|
||||
expect(wrapper.find(component).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(component).exists()).toBe(false);
|
||||
|
||||
await wrapper.vm.activate();
|
||||
|
||||
// assert that when the component is destroyed and re-rendered, the
|
||||
// newly rendered component has the reference to the old component
|
||||
// (i.e. the old component was deactivated and activated)
|
||||
expect(wrapper.find(component).element).toBe(element);
|
||||
expect(wrapper.findComponent(component).element).toBe(element);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@ describe('~/access_tokens/components/new_access_token_app', () => {
|
|||
};
|
||||
|
||||
const triggerSuccess = async (newToken = 'new token') => {
|
||||
wrapper.find(DomElementListener).vm.$emit(EVENT_SUCCESS, { detail: [{ new_token: newToken }] });
|
||||
wrapper
|
||||
.findComponent(DomElementListener)
|
||||
.vm.$emit(EVENT_SUCCESS, { detail: [{ new_token: newToken }] });
|
||||
await nextTick();
|
||||
};
|
||||
|
||||
const triggerError = async (errors = ['1', '2']) => {
|
||||
wrapper.find(DomElementListener).vm.$emit(EVENT_ERROR, { detail: [{ errors }] });
|
||||
wrapper.findComponent(DomElementListener).vm.$emit(EVENT_ERROR, { detail: [{ errors }] });
|
||||
await nextTick();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ describe('AddContextCommitsModal', () => {
|
|||
return wrapper;
|
||||
};
|
||||
|
||||
const findModal = () => wrapper.find(GlModal);
|
||||
const findSearch = () => wrapper.find(GlSearchBoxByType);
|
||||
const findModal = () => wrapper.findComponent(GlModal);
|
||||
const findSearch = () => wrapper.findComponent(GlSearchBoxByType);
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createWrapper();
|
||||
|
|
@ -107,7 +107,7 @@ describe('AddContextCommitsModal', () => {
|
|||
|
||||
it('a disabled ok button in first tab, when row is selected in second tab', () => {
|
||||
createWrapper({ selectedContextCommits: [commit] });
|
||||
expect(wrapper.find(GlModal).attributes('ok-disabled')).toBe('true');
|
||||
expect(wrapper.findComponent(GlModal).attributes('ok-disabled')).toBe('true');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ describe('ReviewTabContainer', () => {
|
|||
|
||||
it('shows loading icon when commits are being loaded', () => {
|
||||
createWrapper({ isLoading: true });
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('shows loading error text when API call fails', () => {
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ describe('TopicSelect', () => {
|
|||
|
||||
const dropdownItems = findAllDropdownItems();
|
||||
|
||||
expect(dropdownItems.at(0).find(GlAvatarLabeled).props('label')).toBe('Topic 1');
|
||||
expect(dropdownItems.at(1).find(GlAvatarLabeled).props('label')).toBe('GitLab');
|
||||
expect(dropdownItems.at(0).findComponent(GlAvatarLabeled).props('label')).toBe('Topic 1');
|
||||
expect(dropdownItems.at(1).findComponent(GlAvatarLabeled).props('label')).toBe('GitLab');
|
||||
});
|
||||
|
||||
it('emits `click` event when topic selected', () => {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ describe('AlertManagementEmptyState', () => {
|
|||
}
|
||||
});
|
||||
|
||||
const EmptyState = () => wrapper.find(GlEmptyState);
|
||||
const EmptyState = () => wrapper.findComponent(GlEmptyState);
|
||||
|
||||
describe('Empty state', () => {
|
||||
it('shows empty state', () => {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ describe('AlertManagementList', () => {
|
|||
|
||||
describe('Alert List Wrapper', () => {
|
||||
it('should show the empty state when alerts are not enabled', () => {
|
||||
expect(wrapper.find(AlertManagementEmptyState).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertManagementTable).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(AlertManagementEmptyState).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(AlertManagementTable).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should show the alerts table when alerts are enabled', () => {
|
||||
|
|
@ -39,8 +39,8 @@ describe('AlertManagementList', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find(AlertManagementEmptyState).exists()).toBe(false);
|
||||
expect(wrapper.find(AlertManagementTable).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(AlertManagementEmptyState).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(AlertManagementTable).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -172,8 +172,8 @@ describe('AlertManagementTable', () => {
|
|||
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.find(GlTable).exists()).toBe(true);
|
||||
expect(findAlertsTable().find(GlIcon).classes('icon-critical')).toBe(true);
|
||||
expect(wrapper.findComponent(GlTable).exists()).toBe(true);
|
||||
expect(findAlertsTable().findComponent(GlIcon).classes('icon-critical')).toBe(true);
|
||||
});
|
||||
|
||||
it('renders severity text', () => {
|
||||
|
|
@ -200,7 +200,7 @@ describe('AlertManagementTable', () => {
|
|||
loading: false,
|
||||
});
|
||||
|
||||
const avatar = findAssignees().at(1).find(GlAvatar);
|
||||
const avatar = findAssignees().at(1).findComponent(GlAvatar);
|
||||
const { src, label } = avatar.attributes();
|
||||
const { name, avatarUrl } = mockAlerts[1].assignees.nodes[0];
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ describe('AlertMappingBuilder', () => {
|
|||
expect(findColumnInRow(0, 2).text()).toContain(i18n.columns.payloadKeyTitle);
|
||||
expect(findColumnInRow(0, 3).text()).toContain(i18n.columns.fallbackKeyTitle);
|
||||
|
||||
const fallbackColumnIcon = findColumnInRow(0, 3).find(GlIcon);
|
||||
const fallbackColumnIcon = findColumnInRow(0, 3).findComponent(GlIcon);
|
||||
expect(fallbackColumnIcon.exists()).toBe(true);
|
||||
expect(fallbackColumnIcon.attributes('name')).toBe('question');
|
||||
expect(fallbackColumnIcon.attributes('title')).toBe(i18n.fallbackTooltip);
|
||||
|
|
@ -55,7 +55,7 @@ describe('AlertMappingBuilder', () => {
|
|||
|
||||
it('renders disabled form input for each mapped field', () => {
|
||||
alertFields.forEach((field, index) => {
|
||||
const input = findColumnInRow(index + 1, 0).find(GlFormInput);
|
||||
const input = findColumnInRow(index + 1, 0).findComponent(GlFormInput);
|
||||
const types = field.types.map((t) => capitalizeFirstCharacter(t.toLowerCase())).join(' or ');
|
||||
expect(input.attributes('value')).toBe(`${field.label} (${types})`);
|
||||
expect(input.attributes('disabled')).toBe('');
|
||||
|
|
@ -71,7 +71,7 @@ describe('AlertMappingBuilder', () => {
|
|||
|
||||
it('renders mapping dropdown for each field', () => {
|
||||
alertFields.forEach(({ types }, index) => {
|
||||
const dropdown = findColumnInRow(index + 1, 2).find(GlDropdown);
|
||||
const dropdown = findColumnInRow(index + 1, 2).findComponent(GlDropdown);
|
||||
const { searchBox, dropdownItems, mappingOptions } = getDropdownContent(dropdown, types);
|
||||
|
||||
expect(dropdown.exists()).toBe(true);
|
||||
|
|
@ -82,7 +82,7 @@ describe('AlertMappingBuilder', () => {
|
|||
|
||||
it('renders fallback dropdown only for the fields that have fallback', () => {
|
||||
alertFields.forEach(({ types, numberOfFallbacks }, index) => {
|
||||
const dropdown = findColumnInRow(index + 1, 3).find(GlDropdown);
|
||||
const dropdown = findColumnInRow(index + 1, 3).findComponent(GlDropdown);
|
||||
expect(dropdown.exists()).toBe(Boolean(numberOfFallbacks));
|
||||
|
||||
if (numberOfFallbacks) {
|
||||
|
|
@ -96,8 +96,8 @@ describe('AlertMappingBuilder', () => {
|
|||
it('emits event with selected mapping', () => {
|
||||
const mappingToSave = { fieldName: 'TITLE', mapping: 'PARSED_TITLE' };
|
||||
jest.spyOn(transformationUtils, 'transformForSave').mockReturnValue(mappingToSave);
|
||||
const dropdown = findColumnInRow(1, 2).find(GlDropdown);
|
||||
const option = dropdown.find(GlDropdownItem);
|
||||
const dropdown = findColumnInRow(1, 2).findComponent(GlDropdown);
|
||||
const option = dropdown.findComponent(GlDropdownItem);
|
||||
option.vm.$emit('click');
|
||||
expect(wrapper.emitted('onMappingUpdate')[0]).toEqual([mappingToSave]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ describe('Alert integration settings form', () => {
|
|||
let wrapper;
|
||||
const service = { updateSettings: jest.fn().mockResolvedValue() };
|
||||
|
||||
const findForm = () => wrapper.find({ ref: 'settingsForm' });
|
||||
const findForm = () => wrapper.findComponent({ ref: 'settingsForm' });
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallowMount(AlertsSettingsForm, {
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ describe('AlertIntegrationsList', () => {
|
|||
mountComponent();
|
||||
});
|
||||
|
||||
const findTableComponent = () => wrapper.find(GlTable);
|
||||
const findTableComponentRows = () => wrapper.find(GlTable).findAll('table tbody tr');
|
||||
const findTableComponent = () => wrapper.findComponent(GlTable);
|
||||
const findTableComponentRows = () => wrapper.findComponent(GlTable).findAll('table tbody tr');
|
||||
const finsStatusCell = () => wrapper.findAll('[data-testid="integration-activated-status"]');
|
||||
|
||||
it('renders a table', () => {
|
||||
|
|
@ -78,7 +78,7 @@ describe('AlertIntegrationsList', () => {
|
|||
describe('integration status', () => {
|
||||
it('enabled', () => {
|
||||
const cell = finsStatusCell().at(0);
|
||||
const activatedIcon = cell.find(GlIcon);
|
||||
const activatedIcon = cell.findComponent(GlIcon);
|
||||
expect(cell.text()).toBe(i18n.status.enabled.name);
|
||||
expect(activatedIcon.attributes('name')).toBe('check');
|
||||
expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
|
||||
|
|
@ -86,7 +86,7 @@ describe('AlertIntegrationsList', () => {
|
|||
|
||||
it('disabled', () => {
|
||||
const cell = finsStatusCell().at(1);
|
||||
const notActivatedIcon = cell.find(GlIcon);
|
||||
const notActivatedIcon = cell.findComponent(GlIcon);
|
||||
expect(cell.text()).toBe(i18n.status.disabled.name);
|
||||
expect(notActivatedIcon.attributes('name')).toBe('warning-solid');
|
||||
expect(notActivatedIcon.attributes('title')).toBe(i18n.status.disabled.tooltip);
|
||||
|
|
|
|||
|
|
@ -325,9 +325,9 @@ describe('AlertsSettingsForm', () => {
|
|||
});
|
||||
|
||||
await nextTick();
|
||||
expect(findSamplePayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(
|
||||
disabled,
|
||||
);
|
||||
expect(
|
||||
findSamplePayloadSection().findComponent(GlFormTextarea).attributes('disabled'),
|
||||
).toBe(disabled);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -63,14 +63,14 @@ describe('AlertsSettingsWrapper', () => {
|
|||
|
||||
const findLoader = () => wrapper.findComponent(IntegrationsList).findComponent(GlLoadingIcon);
|
||||
const findIntegrationsList = () => wrapper.findComponent(IntegrationsList);
|
||||
const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr');
|
||||
const findIntegrations = () => wrapper.findComponent(IntegrationsList).findAll('table tbody tr');
|
||||
const findAddIntegrationBtn = () => wrapper.findByTestId('add-integration-btn');
|
||||
const findAlertsSettingsForm = () => wrapper.findComponent(AlertsSettingsForm);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
|
||||
function destroyHttpIntegration(localWrapper) {
|
||||
localWrapper
|
||||
.find(IntegrationsList)
|
||||
.findComponent(IntegrationsList)
|
||||
.vm.$emit('delete-integration', { id: integrationToDestroy.id });
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ describe('AlertsSettingsWrapper', () => {
|
|||
data: { integrations: [] },
|
||||
loading: true,
|
||||
});
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(IntegrationsList).exists()).toBe(true);
|
||||
expect(findLoader().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ describe('Activity Chart Bundle', () => {
|
|||
wrapper = null;
|
||||
});
|
||||
|
||||
const findChart = () => wrapper.find(GlColumnChart);
|
||||
const findChart = () => wrapper.findComponent(GlColumnChart);
|
||||
const findNoData = () => wrapper.find('[data-testid="noActivityChartData"]');
|
||||
|
||||
describe('Activity Chart', () => {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ describe('MetricPopover', () => {
|
|||
const findAllMetricLinks = () => wrapper.findAll('[data-testid="metric-link"]');
|
||||
const findMetricDescription = () => wrapper.findByTestId('metric-description');
|
||||
const findMetricDocsLink = () => wrapper.findByTestId('metric-docs-link');
|
||||
const findMetricDocsLinkIcon = () => findMetricDocsLink().find(GlIcon);
|
||||
const findMetricDocsLinkIcon = () => findMetricDocsLink().findComponent(GlIcon);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
|
|
@ -83,7 +83,9 @@ describe('MetricPopover', () => {
|
|||
const allLinkContainers = findAllMetricLinks();
|
||||
|
||||
expect(allLinkContainers.at(idx).text()).toContain(link.name);
|
||||
expect(allLinkContainers.at(idx).find(GlLink).attributes('href')).toBe(link.url);
|
||||
expect(allLinkContainers.at(idx).findComponent(GlLink).attributes('href')).toBe(
|
||||
link.url,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ describe('ProjectsDropdownFilter component', () => {
|
|||
const findClearAllButton = () => wrapper.findByText('Clear all');
|
||||
const findSelectedProjectsLabel = () => wrapper.findComponent(GlTruncate);
|
||||
|
||||
const findDropdown = () => wrapper.find(GlDropdown);
|
||||
const findDropdown = () => wrapper.findComponent(GlDropdown);
|
||||
|
||||
const findDropdownItems = () =>
|
||||
findDropdown()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ describe('UsageTrendsApp', () => {
|
|||
});
|
||||
|
||||
it('displays the usage counts component', () => {
|
||||
expect(wrapper.find(UsageCounts).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(UsageCounts).exists()).toBe(true);
|
||||
});
|
||||
|
||||
['Total projects & groups', 'Pipelines', 'Issues & merge requests'].forEach((usage) => {
|
||||
|
|
@ -35,6 +35,6 @@ describe('UsageTrendsApp', () => {
|
|||
});
|
||||
|
||||
it('displays the users chart component', () => {
|
||||
expect(wrapper.find(UsersChart).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(UsersChart).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ describe('UsageTrendsCountChart', () => {
|
|||
wrapper = null;
|
||||
});
|
||||
|
||||
const findLoader = () => wrapper.find(ChartSkeletonLoader);
|
||||
const findChart = () => wrapper.find(GlLineChart);
|
||||
const findAlert = () => wrapper.find(GlAlert);
|
||||
const findLoader = () => wrapper.findComponent(ChartSkeletonLoader);
|
||||
const findChart = () => wrapper.findComponent(GlLineChart);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
|
||||
describe('while loading', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ describe('UsersChart', () => {
|
|||
wrapper = null;
|
||||
});
|
||||
|
||||
const findLoader = () => wrapper.find(ChartSkeletonLoader);
|
||||
const findAlert = () => wrapper.find(GlAlert);
|
||||
const findChart = () => wrapper.find(GlAreaChart);
|
||||
const findLoader = () => wrapper.findComponent(ChartSkeletonLoader);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findChart = () => wrapper.findComponent(GlAreaChart);
|
||||
|
||||
describe('while loading', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ describe('Keep latest artifact checkbox', () => {
|
|||
const fullPath = 'gitlab-org/gitlab';
|
||||
const helpPagePath = '/help/ci/pipelines/job_artifacts';
|
||||
|
||||
const findCheckbox = () => wrapper.find(GlFormCheckbox);
|
||||
const findHelpLink = () => wrapper.find(GlLink);
|
||||
const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
|
||||
const findHelpLink = () => wrapper.findComponent(GlLink);
|
||||
|
||||
const createComponent = (handlers) => {
|
||||
requestHandlers = {
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ describe('RecoveryCodes', () => {
|
|||
};
|
||||
|
||||
const queryByText = (text, options) => within(wrapper.element).queryByText(text, options);
|
||||
const findAlert = () => wrapper.find(GlAlert);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findRecoveryCodes = () => wrapper.findByTestId('recovery-codes');
|
||||
const findCopyButton = () => wrapper.find(ClipboardButton);
|
||||
const findCopyButton = () => wrapper.findComponent(ClipboardButton);
|
||||
const findButtonByText = (text) =>
|
||||
wrapper.findAll(GlButton).wrappers.find((buttonWrapper) => buttonWrapper.text() === text);
|
||||
const findDownloadButton = () => findButtonByText('Download codes');
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ describe('initRecoveryCodes', () => {
|
|||
let el;
|
||||
let wrapper;
|
||||
|
||||
const findRecoveryCodesComponent = () => wrapper.find(RecoveryCodes);
|
||||
const findRecoveryCodesComponent = () => wrapper.findComponent(RecoveryCodes);
|
||||
|
||||
beforeEach(() => {
|
||||
el = document.createElement('div');
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ describe('BadgeSettings component', () => {
|
|||
button.vm.$emit('click');
|
||||
await nextTick();
|
||||
|
||||
const modal = wrapper.find(GlModal);
|
||||
const modal = wrapper.findComponent(GlModal);
|
||||
expect(modal.isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ describe('BadgeSettings component', () => {
|
|||
});
|
||||
|
||||
it('displays badge list', () => {
|
||||
expect(wrapper.find(BadgeList).isVisible()).toBe(true);
|
||||
expect(wrapper.findComponent(BadgeList).isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
describe('when editing', () => {
|
||||
|
|
@ -64,7 +64,7 @@ describe('BadgeSettings component', () => {
|
|||
});
|
||||
|
||||
it('displays no badge list', () => {
|
||||
expect(wrapper.find(BadgeList).isVisible()).toBe(false);
|
||||
expect(wrapper.findComponent(BadgeList).isVisible()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ describe('Batch comments draft note component', () => {
|
|||
createComponent();
|
||||
expect(wrapper.findComponent(GlBadge).exists()).toBe(true);
|
||||
|
||||
const note = wrapper.find(NoteableNote);
|
||||
const note = wrapper.findComponent(NoteableNote);
|
||||
|
||||
expect(note.exists()).toBe(true);
|
||||
expect(note.props().note).toEqual(draft);
|
||||
|
|
@ -122,7 +122,7 @@ describe('Batch comments draft note component', () => {
|
|||
describe('update', () => {
|
||||
it('dispatches updateDraft', async () => {
|
||||
createComponent();
|
||||
const note = wrapper.find(NoteableNote);
|
||||
const note = wrapper.findComponent(NoteableNote);
|
||||
|
||||
note.vm.$emit('handleEdit');
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ describe('Batch comments draft note component', () => {
|
|||
createComponent();
|
||||
jest.spyOn(window, 'confirm').mockImplementation(() => true);
|
||||
|
||||
const note = wrapper.find(NoteableNote);
|
||||
const note = wrapper.findComponent(NoteableNote);
|
||||
|
||||
note.vm.$emit('handleDeleteNote', draft);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,6 @@ describe('Batch comments publish dropdown component', () => {
|
|||
it('renders draft count in dropdown title', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(GlDropdown).props('headerText')).toEqual('2 pending comments');
|
||||
expect(wrapper.findComponent(GlDropdown).props('headerText')).toEqual('2 pending comments');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ describe('Captcha Modal', () => {
|
|||
});
|
||||
|
||||
const findGlModal = () => {
|
||||
const glModal = wrapper.find(GlModal);
|
||||
const glModal = wrapper.findComponent(GlModal);
|
||||
|
||||
jest.spyOn(glModal.vm, 'show').mockImplementation(() => glModal.vm.$emit('shown'));
|
||||
jest
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ describe('LockPopovers', () => {
|
|||
wrapper = mountExtended(LockPopovers);
|
||||
};
|
||||
|
||||
const findPopover = () => extendedWrapper(wrapper.find(GlPopover));
|
||||
const findPopover = () => extendedWrapper(wrapper.findComponent(GlPopover));
|
||||
const findByTextInPopover = (text, options) =>
|
||||
findPopover().findByText((_, element) => element.textContent === text, options);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ describe('CI Lint', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findEditor = () => wrapper.find(SourceEditor);
|
||||
const findAlert = () => wrapper.find(GlAlert);
|
||||
const findCiLintResults = () => wrapper.find(CiLintResults);
|
||||
const findEditor = () => wrapper.findComponent(SourceEditor);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findCiLintResults = () => wrapper.findComponent(CiLintResults);
|
||||
const findValidateBtn = () => wrapper.find('[data-testid="ci-lint-validate"]');
|
||||
const findClearBtn = () => wrapper.find('[data-testid="ci-lint-clear"]');
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ describe('SecureFilesList', () => {
|
|||
const [secureFile] = secureFiles;
|
||||
|
||||
expect(findCell(0, 0).text()).toBe(secureFile.name);
|
||||
expect(findCell(0, 1).find(TimeAgoTooltip).props('time')).toBe(secureFile.created_at);
|
||||
expect(findCell(0, 1).findComponent(TimeAgoTooltip).props('time')).toBe(
|
||||
secureFile.created_at,
|
||||
);
|
||||
});
|
||||
|
||||
describe('event tracking', () => {
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ describe('TriggersList', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findTable = () => wrapper.find(GlTable);
|
||||
const findTable = () => wrapper.findComponent(GlTable);
|
||||
const findHeaderAt = (i) => wrapper.findAll('thead th').at(i);
|
||||
const findRows = () => wrapper.findAll('tbody tr');
|
||||
const findRowAt = (i) => findRows().at(i);
|
||||
const findCell = (i, col) => findRowAt(i).findAll('td').at(col);
|
||||
const findClipboardBtn = (i) => findCell(i, 0).find(ClipboardButton);
|
||||
const findInvalidBadge = (i) => findCell(i, 0).find(GlBadge);
|
||||
const findClipboardBtn = (i) => findCell(i, 0).findComponent(ClipboardButton);
|
||||
const findInvalidBadge = (i) => findCell(i, 0).findComponent(GlBadge);
|
||||
const findEditBtn = (i) => findRowAt(i).find('[data-testid="edit-btn"]');
|
||||
const findRevokeBtn = (i) => findRowAt(i).find('[data-testid="trigger_revoke_button"]');
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ describe('TriggersList', () => {
|
|||
it('displays a time ago label when last used', () => {
|
||||
expect(findCell(0, 3).text()).toBe('Never');
|
||||
|
||||
expect(findCell(1, 3).find(TimeAgoTooltip).props('time')).toBe(triggers[1].lastUsed);
|
||||
expect(findCell(1, 3).findComponent(TimeAgoTooltip).props('time')).toBe(triggers[1].lastUsed);
|
||||
});
|
||||
|
||||
it('displays actions in a rows', () => {
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ describe('Ci variable modal', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findCiEnvironmentsDropdown = () => wrapper.find(CiEnvironmentsDropdown);
|
||||
const findCiEnvironmentsDropdown = () => wrapper.findComponent(CiEnvironmentsDropdown);
|
||||
const findReferenceWarning = () => wrapper.findByTestId('contains-variable-reference');
|
||||
const findModal = () => wrapper.find(ModalStub);
|
||||
const findModal = () => wrapper.findComponent(ModalStub);
|
||||
const findAWSTip = () => wrapper.findByTestId('aws-guidance-tip');
|
||||
const findAddorUpdateButton = () => wrapper.findByTestId('ciUpdateOrAddVariableBtn');
|
||||
const deleteVariableButton = () =>
|
||||
|
|
@ -72,7 +72,8 @@ describe('Ci variable modal', () => {
|
|||
const findMaskedVariableCheckbox = () => wrapper.findByTestId('ci-variable-masked-checkbox');
|
||||
const findValueField = () => wrapper.find('#ci-variable-value');
|
||||
const findEnvScopeLink = () => wrapper.findByTestId('environment-scope-link');
|
||||
const findEnvScopeInput = () => wrapper.findByTestId('environment-scope').find(GlFormInput);
|
||||
const findEnvScopeInput = () =>
|
||||
wrapper.findByTestId('environment-scope').findComponent(GlFormInput);
|
||||
const findVariableTypeDropdown = () => wrapper.find('#ci-variable-type');
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ describe('Ci Variable Popover', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findButton = () => wrapper.find(GlButton);
|
||||
const findButton = () => wrapper.findComponent(GlButton);
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ describe('Ci variable modal', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findCiEnvironmentsDropdown = () => wrapper.find(CiEnvironmentsDropdown);
|
||||
const findModal = () => wrapper.find(ModalStub);
|
||||
const findCiEnvironmentsDropdown = () => wrapper.findComponent(CiEnvironmentsDropdown);
|
||||
const findModal = () => wrapper.findComponent(ModalStub);
|
||||
const findAddorUpdateButton = () => findModal().find('[data-testid="ciUpdateOrAddVariableBtn"]');
|
||||
const deleteVariableButton = () =>
|
||||
findModal()
|
||||
|
|
@ -213,7 +213,7 @@ describe('Ci variable modal', () => {
|
|||
|
||||
const environmentScopeInput = wrapper
|
||||
.find('[data-testid="environment-scope"]')
|
||||
.find(GlFormInput);
|
||||
.findComponent(GlFormInput);
|
||||
expect(findCiEnvironmentsDropdown().exists()).toBe(false);
|
||||
expect(environmentScopeInput.attributes('readonly')).toBe('readonly');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ describe('AgentTable', () => {
|
|||
|
||||
const findAgentLink = (at) => wrapper.findAllByTestId('cluster-agent-name-link').at(at);
|
||||
const findStatusText = (at) => wrapper.findAllByTestId('cluster-agent-connection-status').at(at);
|
||||
const findStatusIcon = (at) => findStatusText(at).find(GlIcon);
|
||||
const findStatusIcon = (at) => findStatusText(at).findComponent(GlIcon);
|
||||
const findLastContactText = (at) => wrapper.findAllByTestId('cluster-agent-last-contact').at(at);
|
||||
const findVersionText = (at) => wrapper.findAllByTestId('cluster-agent-version').at(at);
|
||||
const findConfiguration = (at) =>
|
||||
|
|
@ -113,7 +113,7 @@ describe('AgentTable', () => {
|
|||
texts,
|
||||
lineNumber,
|
||||
}) => {
|
||||
const findIcon = () => findVersionText(lineNumber).find(GlIcon);
|
||||
const findIcon = () => findVersionText(lineNumber).findComponent(GlIcon);
|
||||
const findPopover = () => wrapper.findByTestId(`popover-${agent}`);
|
||||
const versionWarning = versionMismatch || versionOutdated;
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ describe('AgentTable', () => {
|
|||
`(
|
||||
'displays config file path as "$agentPath" at line $lineNumber',
|
||||
({ agentConfig, link, lineNumber }) => {
|
||||
const findLink = findConfiguration(lineNumber).find(GlLink);
|
||||
const findLink = findConfiguration(lineNumber).findComponent(GlLink);
|
||||
|
||||
expect(findLink.attributes('href')).toBe(link);
|
||||
expect(findConfiguration(lineNumber).text()).toBe(agentConfig);
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ describe('Agents', () => {
|
|||
});
|
||||
|
||||
it('displays a loading icon', () => {
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ describe('ClustersAncestorNotice', () => {
|
|||
});
|
||||
|
||||
it('displays link', () => {
|
||||
expect(wrapper.find(GlLink).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLink).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ describe('Clusters', () => {
|
|||
({ lineNumber, result }) => {
|
||||
const statuses = findStatuses();
|
||||
const status = statuses.at(lineNumber);
|
||||
expect(status.find(GlLoadingIcon).exists()).toBe(result);
|
||||
expect(status.findComponent(GlLoadingIcon).exists()).toBe(result);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ describe('NodeErrorHelpText', () => {
|
|||
await nextTick();
|
||||
};
|
||||
|
||||
const findPopover = () => wrapper.find(GlPopover);
|
||||
const findPopover = () => wrapper.findComponent(GlPopover);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ describe('Code navigation app component', () => {
|
|||
it('hides popover when no definition set', () => {
|
||||
factory();
|
||||
|
||||
expect(wrapper.find(Popover).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(Popover).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders popover when definition set', () => {
|
||||
|
|
@ -73,7 +73,7 @@ describe('Code navigation app component', () => {
|
|||
currentBlobPath: 'index.js',
|
||||
});
|
||||
|
||||
expect(wrapper.find(Popover).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(Popover).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('calls showDefinition when clicking blob viewer', () => {
|
||||
|
|
|
|||
|
|
@ -115,8 +115,8 @@ describe('Code navigation popover component', () => {
|
|||
definitionPathPrefix: DEFINITION_PATH_PREFIX,
|
||||
});
|
||||
|
||||
expect(wrapper.find({ ref: 'code-output' }).exists()).toBe(true);
|
||||
expect(wrapper.find({ ref: 'doc-output' }).exists()).toBe(false);
|
||||
expect(wrapper.findComponent({ ref: 'code-output' }).exists()).toBe(true);
|
||||
expect(wrapper.findComponent({ ref: 'doc-output' }).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -128,8 +128,8 @@ describe('Code navigation popover component', () => {
|
|||
definitionPathPrefix: DEFINITION_PATH_PREFIX,
|
||||
});
|
||||
|
||||
expect(wrapper.find({ ref: 'code-output' }).exists()).toBe(false);
|
||||
expect(wrapper.find({ ref: 'doc-output' }).exists()).toBe(true);
|
||||
expect(wrapper.findComponent({ ref: 'code-output' }).exists()).toBe(false);
|
||||
expect(wrapper.findComponent({ ref: 'doc-output' }).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ describe('Commit pipeline status component', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findLoader = () => wrapper.find(GlLoadingIcon);
|
||||
const findLoader = () => wrapper.findComponent(GlLoadingIcon);
|
||||
const findLink = () => wrapper.find('a');
|
||||
const findCiIcon = () => findLink().find(CiIcon);
|
||||
const findCiIcon = () => findLink().findComponent(CiIcon);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ describe('Confidential merge request project dropdown component', () => {
|
|||
it('shows lock icon', () => {
|
||||
factory();
|
||||
|
||||
expect(vm.find(GlDropdown).props('icon')).toBe('lock');
|
||||
expect(vm.findComponent(GlDropdown).props('icon')).toBe('lock');
|
||||
});
|
||||
|
||||
it('has dropdown text', () => {
|
||||
factory();
|
||||
|
||||
expect(vm.find(GlDropdown).props('text')).toBe('Select private project');
|
||||
expect(vm.findComponent(GlDropdown).props('text')).toBe('Select private project');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ describe.each`
|
|||
};
|
||||
|
||||
const selectFile = async (file) => {
|
||||
const input = wrapper.find({ ref: 'fileSelector' });
|
||||
const input = wrapper.findComponent({ ref: 'fileSelector' });
|
||||
|
||||
// override the property definition because `input.files` isn't directly modifyable
|
||||
Object.defineProperty(input.element, 'files', { value: [file], writable: true });
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ describe('content_editor/components/toolbar_image_button', () => {
|
|||
const findDropdown = () => wrapper.findComponent(GlDropdown);
|
||||
|
||||
const selectFile = async (file) => {
|
||||
const input = wrapper.find({ ref: 'fileSelector' });
|
||||
const input = wrapper.findComponent({ ref: 'fileSelector' });
|
||||
|
||||
// override the property definition because `input.files` isn't directly modifyable
|
||||
Object.defineProperty(input.element, 'files', { value: [file], writable: true });
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ describe('content_editor/components/toolbar_link_button', () => {
|
|||
const findRemoveLinkButton = () => wrapper.findByText('Remove link');
|
||||
|
||||
const selectFile = async (file) => {
|
||||
const input = wrapper.find({ ref: 'fileSelector' });
|
||||
const input = wrapper.findComponent({ ref: 'fileSelector' });
|
||||
|
||||
// override the property definition because `input.files` isn't directly modifyable
|
||||
Object.defineProperty(input.element, 'files', { value: [file], writable: true });
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ describe('content/components/wrappers/code_block', () => {
|
|||
it('does not render a preview if showPreview: false', async () => {
|
||||
createWrapper({ language: 'plantuml', isDiagram: true, showPreview: false });
|
||||
|
||||
expect(wrapper.find({ ref: 'diagramContainer' }).exists()).toBe(false);
|
||||
expect(wrapper.findComponent({ ref: 'diagramContainer' }).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('does not update preview when diagram is not active', async () => {
|
||||
|
|
@ -134,7 +134,7 @@ describe('content/components/wrappers/code_block', () => {
|
|||
await nextTick();
|
||||
|
||||
expect(wrapper.find('img').attributes('src')).toBe('url/to/some/diagram');
|
||||
expect(wrapper.find(SandboxedMermaid).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(SandboxedMermaid).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders an iframe with preview for a mermaid diagram', async () => {
|
||||
|
|
@ -143,7 +143,7 @@ describe('content/components/wrappers/code_block', () => {
|
|||
await emitEditorEvent({ event: 'transaction', tiptapEditor });
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.find(SandboxedMermaid).props('source')).toBe('');
|
||||
expect(wrapper.findComponent(SandboxedMermaid).props('source')).toBe('');
|
||||
expect(wrapper.find('img').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ describe('Reusable form component', () => {
|
|||
`(
|
||||
'should render the correct component for #$id with the value "$value"',
|
||||
({ index, id, component, value }) => {
|
||||
const findFormElement = () => findFormGroup(index).find(component);
|
||||
const findFormElement = () => findFormGroup(index).findComponent(component);
|
||||
|
||||
expect(findFormElement().attributes('id')).toBe(id);
|
||||
expect(findFormElement().attributes('value')).toBe(value);
|
||||
|
|
@ -307,7 +307,8 @@ describe('Reusable form component', () => {
|
|||
|
||||
it('should render a checked GlFormCheckbox for #active', () => {
|
||||
const activeCheckboxIndex = 6;
|
||||
const findFormElement = () => findFormGroup(activeCheckboxIndex).find(GlFormCheckbox);
|
||||
const findFormElement = () =>
|
||||
findFormGroup(activeCheckboxIndex).findComponent(GlFormCheckbox);
|
||||
|
||||
expect(findFormElement().attributes('id')).toBe('active');
|
||||
expect(findFormElement().attributes('checked')).toBe('true');
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ describe('Value stream analytics component', () => {
|
|||
it('renders the stage table with a loading icon', () => {
|
||||
const tableWrapper = findStageTable();
|
||||
expect(tableWrapper.exists()).toBe(true);
|
||||
expect(tableWrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(tableWrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders the path navigation loading state', () => {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,9 @@ describe('Project PathNavigation', () => {
|
|||
|
||||
describe('displays correctly', () => {
|
||||
it('has the correct props', () => {
|
||||
expect(wrapper.find(GlPath).props('items')).toMatchObject(transformedProjectStagePathData);
|
||||
expect(wrapper.findComponent(GlPath).props('items')).toMatchObject(
|
||||
transformedProjectStagePathData,
|
||||
);
|
||||
});
|
||||
|
||||
it('contains all the expected stages', () => {
|
||||
|
|
@ -69,11 +71,11 @@ describe('Project PathNavigation', () => {
|
|||
describe('loading', () => {
|
||||
describe('is false', () => {
|
||||
it('displays the gl-path component', () => {
|
||||
expect(wrapper.find(GlPath).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlPath).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('hides the gl-skeleton-loading component', () => {
|
||||
expect(wrapper.find(GlSkeletonLoader).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders each stage', () => {
|
||||
|
|
@ -112,11 +114,11 @@ describe('Project PathNavigation', () => {
|
|||
});
|
||||
|
||||
it('hides the gl-path component', () => {
|
||||
expect(wrapper.find(GlPath).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(GlPath).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('displays the gl-skeleton-loading component', () => {
|
||||
expect(wrapper.find(GlSkeletonLoader).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ describe('Deploy freeze modal', () => {
|
|||
|
||||
wrapper.find('#deploy-freeze-start').trigger('input');
|
||||
wrapper.find('#deploy-freeze-end').trigger('input');
|
||||
wrapper.find(TimezoneDropdown).trigger('input');
|
||||
wrapper.findComponent(TimezoneDropdown).trigger('input');
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ describe('Deploy freeze settings', () => {
|
|||
|
||||
describe('Deploy freeze table contains components', () => {
|
||||
it('contains deploy freeze table', () => {
|
||||
expect(wrapper.find(DeployFreezeTable).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DeployFreezeTable).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('contains deploy freeze modal', () => {
|
||||
expect(wrapper.find(DeployFreezeModal).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DeployFreezeModal).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ describe('Deploy freeze timezone dropdown', () => {
|
|||
});
|
||||
|
||||
it('renders selected time zone as dropdown label', () => {
|
||||
expect(wrapper.find(GlDropdown).vm.text).toBe('Alaska');
|
||||
expect(wrapper.findComponent(GlDropdown).vm.text).toBe('Alaska');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const UPDATED_COMMIT_URL = `${TEST_HOST}/COMMIT/NEW`;
|
|||
Vue.use(Vuex);
|
||||
|
||||
function getCollapsedFilesWarning(wrapper) {
|
||||
return wrapper.find(CollapsedFilesWarning);
|
||||
return wrapper.findComponent(CollapsedFilesWarning);
|
||||
}
|
||||
|
||||
describe('diffs/components/app', () => {
|
||||
|
|
@ -167,7 +167,7 @@ describe('diffs/components/app', () => {
|
|||
state.diffs.isLoading = true;
|
||||
});
|
||||
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('displays loading icon on batch loading', () => {
|
||||
|
|
@ -175,13 +175,13 @@ describe('diffs/components/app', () => {
|
|||
state.diffs.batchLoadingState = 'loading';
|
||||
});
|
||||
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('displays diffs container when not loading', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
|
||||
expect(wrapper.find('#diffs').exists()).toBe(true);
|
||||
});
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ describe('diffs/components/app', () => {
|
|||
it('renders empty state when no diff files exist', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(NoChanges).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(NoChanges).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render empty state when diff files exist', () => {
|
||||
|
|
@ -273,7 +273,7 @@ describe('diffs/components/app', () => {
|
|||
});
|
||||
});
|
||||
|
||||
expect(wrapper.find(NoChanges).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(NoChanges).exists()).toBe(false);
|
||||
expect(wrapper.findAll(DiffFile).length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -487,8 +487,8 @@ describe('diffs/components/app', () => {
|
|||
state.diffs.mergeRequestDiff = mergeRequestDiff;
|
||||
});
|
||||
|
||||
expect(wrapper.find(CompareVersions).exists()).toBe(true);
|
||||
expect(wrapper.find(CompareVersions).props()).toEqual(
|
||||
expect(wrapper.findComponent(CompareVersions).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(CompareVersions).props()).toEqual(
|
||||
expect.objectContaining({
|
||||
diffFilesCountText: null,
|
||||
}),
|
||||
|
|
@ -506,8 +506,8 @@ describe('diffs/components/app', () => {
|
|||
state.diffs.size = 1;
|
||||
});
|
||||
|
||||
expect(wrapper.find(HiddenFilesWarning).exists()).toBe(true);
|
||||
expect(wrapper.find(HiddenFilesWarning).props()).toEqual(
|
||||
expect(wrapper.findComponent(HiddenFilesWarning).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(HiddenFilesWarning).props()).toEqual(
|
||||
expect.objectContaining({
|
||||
total: '5',
|
||||
plainDiffPath: 'plain diff path',
|
||||
|
|
@ -547,7 +547,7 @@ describe('diffs/components/app', () => {
|
|||
};
|
||||
});
|
||||
|
||||
expect(wrapper.find(CommitWidget).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(CommitWidget).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should display diff file if there are diff files', () => {
|
||||
|
|
@ -555,13 +555,13 @@ describe('diffs/components/app', () => {
|
|||
state.diffs.diffFiles.push({ sha: '123' });
|
||||
});
|
||||
|
||||
expect(wrapper.find(DiffFile).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DiffFile).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("doesn't render tree list when no changes exist", () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(TreeList).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(TreeList).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should render tree list', () => {
|
||||
|
|
@ -569,7 +569,7 @@ describe('diffs/components/app', () => {
|
|||
state.diffs.diffFiles = [{ file_hash: '111', file_path: '111.js' }];
|
||||
});
|
||||
|
||||
expect(wrapper.find(TreeList).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(TreeList).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -641,7 +641,7 @@ describe('diffs/components/app', () => {
|
|||
|
||||
describe('pagination', () => {
|
||||
const fileByFileNav = () => wrapper.find('[data-testid="file-by-file-navigation"]');
|
||||
const paginator = () => fileByFileNav().find(GlPagination);
|
||||
const paginator = () => fileByFileNav().findComponent(GlPagination);
|
||||
|
||||
it('sets previous button as disabled', async () => {
|
||||
createComponent({ fileByFileUserPreference: true }, ({ state }) => {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ describe('CollapsedFilesWarning', () => {
|
|||
Vue.use(Vuex);
|
||||
|
||||
const getAlertActionButton = () =>
|
||||
wrapper.find(CollapsedFilesWarning).find('button.gl-alert-action:first-child');
|
||||
const getAlertCloseButton = () => wrapper.find(CollapsedFilesWarning).find('button');
|
||||
wrapper.findComponent(CollapsedFilesWarning).find('button.gl-alert-action:first-child');
|
||||
const getAlertCloseButton = () => wrapper.findComponent(CollapsedFilesWarning).find('button');
|
||||
|
||||
const createComponent = (props = {}, { full } = { full: false }) => {
|
||||
const mounter = full ? mount : shallowMount;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ describe('diffs/components/commit_item', () => {
|
|||
const getAvatarElement = () => wrapper.find('.user-avatar-link');
|
||||
const getCommitterElement = () => wrapper.find('.committer');
|
||||
const getCommitActionsElement = () => wrapper.find('.commit-actions');
|
||||
const getCommitPipelineStatus = () => wrapper.find(CommitPipelineStatus);
|
||||
const getCommitPipelineStatus = () => wrapper.findComponent(CommitPipelineStatus);
|
||||
|
||||
const mountComponent = (propsData) => {
|
||||
wrapper = mount(Component, {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ describe('diffs/components/commit_widget', () => {
|
|||
});
|
||||
|
||||
it('renders commit item', () => {
|
||||
const commitElement = wrapper.find(CommitItem);
|
||||
const commitElement = wrapper.findComponent(CommitItem);
|
||||
|
||||
expect(commitElement.exists()).toBe(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,24 +20,24 @@ describe('DiffCommentCell', () => {
|
|||
it('renders discussions if line has discussions', () => {
|
||||
const wrapper = createWrapper({ renderDiscussion: true });
|
||||
|
||||
expect(wrapper.find(DiffDiscussions).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DiffDiscussions).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render discussions if line has no discussions', () => {
|
||||
const wrapper = createWrapper();
|
||||
|
||||
expect(wrapper.find(DiffDiscussions).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(DiffDiscussions).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders discussion reply if line has no draft', () => {
|
||||
const wrapper = createWrapper();
|
||||
|
||||
expect(wrapper.find(DiffDiscussionReply).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DiffDiscussionReply).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render discussion reply if line has draft', () => {
|
||||
const wrapper = createWrapper({ hasDraft: true });
|
||||
|
||||
expect(wrapper.find(DiffDiscussionReply).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(DiffDiscussionReply).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -110,13 +110,13 @@ describe('DiffContent', () => {
|
|||
props: { diffFile: textDiffFile },
|
||||
});
|
||||
|
||||
expect(wrapper.find(DiffView).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DiffView).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders rendering more lines loading icon', () => {
|
||||
createComponent({ props: { diffFile: { ...textDiffFile, renderingLines: true } } });
|
||||
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ describe('DiffContent', () => {
|
|||
props: { diffFile: { ...emptyDiffFile, viewer: { name: diffViewerModes.no_preview } } },
|
||||
});
|
||||
|
||||
expect(wrapper.find(NoPreviewViewer).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(NoPreviewViewer).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should render not diffable view if viewer set to non_diffable', () => {
|
||||
|
|
@ -141,7 +141,7 @@ describe('DiffContent', () => {
|
|||
props: { diffFile: { ...emptyDiffFile, viewer: { name: diffViewerModes.not_diffable } } },
|
||||
});
|
||||
|
||||
expect(wrapper.find(NotDiffableViewer).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(NotDiffableViewer).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ describe('DiffContent', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find(DiffDiscussions).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DiffDiscussions).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('emits saveDiffDiscussion when note-form emits `handleFormUpdate`', () => {
|
||||
|
|
@ -169,7 +169,7 @@ describe('DiffContent', () => {
|
|||
},
|
||||
});
|
||||
|
||||
wrapper.find(NoteForm).vm.$emit('handleFormUpdate', noteStub);
|
||||
wrapper.findComponent(NoteForm).vm.$emit('handleFormUpdate', noteStub);
|
||||
expect(saveDiffDiscussionMock).toHaveBeenCalledWith(expect.any(Object), {
|
||||
note: noteStub,
|
||||
formData: {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ describe('DiffDiscussionReply', () => {
|
|||
hasForm: false,
|
||||
});
|
||||
|
||||
expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(ReplyPlaceholder).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -83,6 +83,6 @@ describe('DiffDiscussionReply', () => {
|
|||
hasForm: false,
|
||||
});
|
||||
|
||||
expect(wrapper.find(NoteSignedOutWidget).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(NoteSignedOutWidget).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ describe('DiffDiscussions', () => {
|
|||
it('should have notes list', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(NoteableDiscussion).exists()).toBe(true);
|
||||
expect(wrapper.find(DiscussionNotes).exists()).toBe(true);
|
||||
expect(wrapper.find(DiscussionNotes).findAll(TimelineEntryItem).length).toBe(
|
||||
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,
|
||||
);
|
||||
});
|
||||
|
|
@ -48,7 +48,7 @@ describe('DiffDiscussions', () => {
|
|||
const diffNotesToggle = findDiffNotesToggle();
|
||||
|
||||
expect(diffNotesToggle.exists()).toBe(true);
|
||||
expect(diffNotesToggle.find(GlIcon).exists()).toBe(true);
|
||||
expect(diffNotesToggle.findComponent(GlIcon).exists()).toBe(true);
|
||||
expect(diffNotesToggle.classes('diff-notes-collapse')).toBe(true);
|
||||
});
|
||||
|
||||
|
|
@ -80,12 +80,12 @@ describe('DiffDiscussions', () => {
|
|||
discussions[0].expanded = false;
|
||||
createComponent({ discussions, shouldCollapseDiscussions: true });
|
||||
|
||||
expect(wrapper.find(NoteableDiscussion).isVisible()).toBe(false);
|
||||
expect(wrapper.findComponent(NoteableDiscussion).isVisible()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders badge on avatar', () => {
|
||||
createComponent({ renderAvatarBadge: true });
|
||||
const noteableDiscussion = wrapper.find(NoteableDiscussion);
|
||||
const noteableDiscussion = wrapper.findComponent(NoteableDiscussion);
|
||||
|
||||
expect(noteableDiscussion.find('.design-note-pin').exists()).toBe(true);
|
||||
expect(noteableDiscussion.find('.design-note-pin').text().trim()).toBe('1');
|
||||
|
|
|
|||
|
|
@ -76,18 +76,19 @@ describe('DiffFileHeader component', () => {
|
|||
wrapper.destroy();
|
||||
});
|
||||
|
||||
const findHeader = () => wrapper.find({ ref: 'header' });
|
||||
const findTitleLink = () => wrapper.find({ ref: 'titleWrapper' });
|
||||
const findExpandButton = () => wrapper.find({ ref: 'expandDiffToFullFileButton' });
|
||||
const findHeader = () => wrapper.findComponent({ ref: 'header' });
|
||||
const findTitleLink = () => wrapper.findComponent({ ref: 'titleWrapper' });
|
||||
const findExpandButton = () => wrapper.findComponent({ ref: 'expandDiffToFullFileButton' });
|
||||
const findFileActions = () => wrapper.find('.file-actions');
|
||||
const findModeChangedLine = () => wrapper.find({ ref: 'fileMode' });
|
||||
const findModeChangedLine = () => wrapper.findComponent({ ref: 'fileMode' });
|
||||
const findLfsLabel = () => wrapper.find('[data-testid="label-lfs"]');
|
||||
const findToggleDiscussionsButton = () => wrapper.find({ ref: 'toggleDiscussionsButton' });
|
||||
const findExternalLink = () => wrapper.find({ ref: 'externalLink' });
|
||||
const findReplacedFileButton = () => wrapper.find({ ref: 'replacedFileButton' });
|
||||
const findViewFileButton = () => wrapper.find({ ref: 'viewButton' });
|
||||
const findCollapseIcon = () => wrapper.find({ ref: 'collapseIcon' });
|
||||
const findEditButton = () => wrapper.find({ ref: 'editButton' });
|
||||
const findToggleDiscussionsButton = () =>
|
||||
wrapper.findComponent({ ref: 'toggleDiscussionsButton' });
|
||||
const findExternalLink = () => wrapper.findComponent({ ref: 'externalLink' });
|
||||
const findReplacedFileButton = () => wrapper.findComponent({ ref: 'replacedFileButton' });
|
||||
const findViewFileButton = () => wrapper.findComponent({ ref: 'viewButton' });
|
||||
const findCollapseIcon = () => wrapper.findComponent({ ref: 'collapseIcon' });
|
||||
const findEditButton = () => wrapper.findComponent({ ref: 'editButton' });
|
||||
const findReviewFileCheckbox = () => wrapper.find("[data-testid='fileReviewCheckbox']");
|
||||
|
||||
const createComponent = ({ props, options = {} } = {}) => {
|
||||
|
|
@ -153,7 +154,7 @@ describe('DiffFileHeader component', () => {
|
|||
});
|
||||
|
||||
it('displays a copy to clipboard button', () => {
|
||||
expect(wrapper.find(ClipboardButton).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(ClipboardButton).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('triggers the copy to clipboard tracking event', () => {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue