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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/diffs/components/app.vue9
-rw-r--r--app/assets/javascripts/diffs/store/actions.js25
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js2
-rw-r--r--app/assets/javascripts/diffs/store/utils.js4
-rw-r--r--app/assets/javascripts/incidents_settings/components/alerts_form.vue4
-rw-r--r--app/controllers/admin/instance_statistics_controller.rb12
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/controllers/projects/metrics_dashboard_controller.rb19
-rw-r--r--app/controllers/projects/settings/operations_controller.rb4
-rw-r--r--app/controllers/search_controller.rb5
-rw-r--r--app/models/project.rb2
-rw-r--r--app/serializers/diff_file_entity.rb4
-rw-r--r--app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb9
-rw-r--r--app/views/admin/instance_statistics/index.html.haml4
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml5
-rw-r--r--app/views/search/results/_note.html.haml5
-rw-r--r--changelogs/unreleased/205578-add-package-count-to-usage-data.yml5
-rw-r--r--changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml5
-rw-r--r--changelogs/unreleased/225254-remove-feature-flag.yml5
-rw-r--r--changelogs/unreleased/238116-redis-hll-search-analytics.yml5
-rw-r--r--changelogs/unreleased/authored-date-on-comments-in-search.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml5
-rw-r--r--changelogs/unreleased/remove-extracts-path-optimization-flag.yml5
-rw-r--r--config/feature_flags/development/ci_matrix_job_names.yml7
-rw-r--r--config/feature_flags/development/instance_statistics.yml7
-rw-r--r--config/feature_flags/development/search_track_unique_users.yml7
-rw-r--r--config/feature_flags/development/security-on-demand-scans-site-validation.yml7
-rw-r--r--db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb21
-rw-r--r--db/schema_migrations/202008260923241
-rw-r--r--db/structure.sql2
-rw-r--r--doc/ci/variables/README.md2
-rw-r--r--lib/extracts_ref.rb1
-rw-r--r--lib/gitlab/ci/config/normalizer/matrix_strategy.rb23
-rw-r--r--lib/gitlab/ci/features.rb4
-rw-r--r--lib/gitlab/ci/status/composite.rb11
-rw-r--r--lib/gitlab/usage_data.rb30
-rw-r--r--lib/gitlab/usage_data_counters/known_events.yml12
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json2
-rw-r--r--spec/controllers/search_controller_spec.rb5
-rw-r--r--spec/features/merge_request/maintainer_edits_fork_spec.rb2
-rw-r--r--spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb1
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js12
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js6
-rw-r--r--spec/frontend/blob/components/blob_content_spec.js18
-rw-r--r--spec/frontend/blob/components/blob_edit_content_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_edit_header_spec.js2
-rw-r--r--spec/frontend/boards/components/board_content_spec.js4
-rw-r--r--spec/frontend/boards/components/issue_count_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js2
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js24
-rw-r--r--spec/frontend/clusters/components/fluentd_output_settings_spec.js2
-rw-r--r--spec/frontend/clusters_list/components/ancestor_notice_spec.js2
-rw-r--r--spec/frontend/diffs/components/app_spec.js34
-rw-r--r--spec/frontend/diffs/components/no_changes_spec.js2
-rw-r--r--spec/frontend/diffs/store/actions_spec.js158
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js4
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js2
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_search_input_spec.js4
-rw-r--r--spec/frontend/import_projects/components/bitbucket_status_table_spec.js2
-rw-r--r--spec/frontend/import_projects/components/import_projects_table_spec.js10
-rw-r--r--spec/frontend/import_projects/components/provider_repo_table_row_spec.js4
-rw-r--r--spec/frontend/incidents_settings/components/alerts_form_spec.js1
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js4
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js4
-rw-r--r--spec/frontend/issuables_list/components/issuable_list_root_app_spec.js6
-rw-r--r--spec/frontend/issuables_list/components/issuable_spec.js2
-rw-r--r--spec/frontend/issuables_list/components/issuables_list_app_spec.js2
-rw-r--r--spec/frontend/issue_show/components/app_spec.js12
-rw-r--r--spec/frontend/jira_import/components/jira_import_form_spec.js2
-rw-r--r--spec/frontend/jobs/components/log/line_header_spec.js4
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js2
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js6
-rw-r--r--spec/frontend/monitoring/alert_widget_spec.js2
-rw-r--r--spec/frontend/mr_popover/mr_popover_spec.js2
-rw-r--r--spec/frontend/packages/details/components/package_title_spec.js6
-rw-r--r--spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js6
-rw-r--r--spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js2
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js4
-rw-r--r--spec/frontend/pages/projects/graphs/code_coverage_spec.js8
-rw-r--r--spec/frontend/pipelines/pipeline_triggerer_spec.js2
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js16
-rw-r--r--spec/frontend/releases/components/release_block_assets_spec.js2
-rw-r--r--spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js12
-rw-r--r--spec/frontend/reports/components/grouped_issues_list_spec.js2
-rw-r--r--spec/frontend/sidebar/participants_spec.js10
-rw-r--r--spec/frontend/sidebar/subscriptions_spec.js2
-rw-r--r--spec/frontend/snippets/components/edit_spec.js8
-rw-r--r--spec/frontend/snippets/components/show_spec.js6
-rw-r--r--spec/frontend/snippets/components/snippet_visibility_edit_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/clone_dropdown_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/paginated_list_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/remove_member_modal_spec.js2
-rw-r--r--spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb160
-rw-r--r--spec/lib/gitlab/ci/config/normalizer_spec.rb62
-rw-r--r--spec/lib/gitlab/ci/status/composite_spec.rb51
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb66
-rw-r--r--spec/requests/projects/metrics_dashboard_spec.rb16
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml9
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml21
-rw-r--r--spec/support/shared_examples/controllers/unique_hll_events_examples.rb29
-rw-r--r--spec/support/shared_examples/path_extraction_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb10
-rw-r--r--yarn.lock8
114 files changed, 706 insertions, 535 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 9ed27edd71a..e6a411d20d5 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -229,7 +229,6 @@ export default {
projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
- useSingleDiffStyle: this.glFeatures.singleMrDiffView,
viewDiffsFileByFile: this.viewDiffsFileByFile,
});
@@ -306,14 +305,10 @@ export default {
);
},
needsReload() {
- return (
- this.glFeatures.singleMrDiffView &&
- this.diffFiles.length &&
- isSingleViewStyle(this.diffFiles[0])
- );
+ return this.diffFiles.length && isSingleViewStyle(this.diffFiles[0]);
},
needsFirstLoad() {
- return this.glFeatures.singleMrDiffView && !this.diffFiles.length;
+ return !this.diffFiles.length;
},
fetchData(toggleTree = true) {
if (this.glFeatures.diffsBatchLoad) {
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 8e26f5e9ffe..fc381adf218 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -52,7 +52,6 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
} = options;
commit(types.SET_BASE_CONFIG, {
endpoint,
@@ -62,7 +61,6 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
});
};
@@ -70,13 +68,10 @@ export const fetchDiffFiles = ({ state, commit }) => {
const worker = new TreeWorker();
const urlParams = {
w: state.showWhitespace ? '0' : '1',
+ view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
};
let returnData;
- if (state.useSingleDiffStyle) {
- urlParams.view = window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType;
- }
-
commit(types.SET_LOADING, true);
worker.addEventListener('message', ({ data }) => {
@@ -111,12 +106,9 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
const urlParams = {
per_page: DIFFS_PER_PAGE,
w: state.showWhitespace ? '0' : '1',
+ view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
};
- if (state.useSingleDiffStyle) {
- urlParams.view = window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType;
- }
-
commit(types.SET_BATCH_LOADING, true);
commit(types.SET_RETRIEVING_BATCHES, true);
@@ -175,11 +167,9 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
export const fetchDiffFilesMeta = ({ commit, state }) => {
const worker = new TreeWorker();
- const urlParams = {};
-
- if (state.useSingleDiffStyle) {
- urlParams.view = window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType;
- }
+ const urlParams = {
+ view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
+ };
commit(types.SET_LOADING, true);
@@ -240,10 +230,7 @@ export const assignDiscussionsToDiff = (
) => {
const id = window?.location?.hash;
const isNoteLink = id.indexOf('#note') === 0;
- const diffPositionByLineCode = getDiffPositionByLineCode(
- state.diffFiles,
- state.useSingleDiffStyle,
- );
+ const diffPositionByLineCode = getDiffPositionByLineCode(state.diffFiles);
const hash = getLocationHash();
discussions
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index d31a600e354..c8f6f6bb0e5 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -41,5 +41,4 @@ export default () => ({
fileFinderVisible: false,
dismissEndpoint: '',
showSuggestPopover: true,
- useSingleDiffStyle: false,
});
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 3b03cce86fd..3be73d78c42 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -25,7 +25,6 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
} = options;
Object.assign(state, {
endpoint,
@@ -35,7 +34,6 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
});
},
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 9286d7fdcb0..320b44bd537 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -495,11 +495,11 @@ export function prepareDiffData(diff, priorFiles = []) {
return deduplicateFilesList([...priorFiles, ...cleanedFiles]);
}
-export function getDiffPositionByLineCode(diffFiles, useSingleDiffStyle) {
+export function getDiffPositionByLineCode(diffFiles) {
let lines = [];
const hasInlineDiffs = diffFiles.some(file => file.highlighted_diff_lines.length > 0);
- if (!useSingleDiffStyle || hasInlineDiffs) {
+ if (hasInlineDiffs) {
// In either of these cases, we can use `highlighted_diff_lines` because
// that will include all of the parallel diff lines, too
diff --git a/app/assets/javascripts/incidents_settings/components/alerts_form.vue b/app/assets/javascripts/incidents_settings/components/alerts_form.vue
index 636d9fc4b90..85a8241789d 100644
--- a/app/assets/javascripts/incidents_settings/components/alerts_form.vue
+++ b/app/assets/javascripts/incidents_settings/components/alerts_form.vue
@@ -9,7 +9,6 @@ import {
GlNewDropdown,
GlNewDropdownItem,
} from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
I18N_ALERT_SETTINGS_FORM,
NO_ISSUE_TEMPLATE_SELECTED,
@@ -28,7 +27,6 @@ export default {
GlNewDropdown,
GlNewDropdownItem,
},
- mixins: [glFeatureFlagsMixin()],
inject: ['service', 'alertSettings'],
data() {
return {
@@ -127,7 +125,7 @@ export default {
<span>{{ $options.i18n.sendEmail.label }}</span>
</gl-form-checkbox>
</gl-form-group>
- <gl-form-group v-if="glFeatures.autoCloseIncident" class="gl-pl-0 gl-mb-5">
+ <gl-form-group class="gl-pl-0 gl-mb-5">
<gl-form-checkbox v-model="autoCloseIncident">
<span>{{ $options.i18n.autoCloseIncidents.label }}</span>
</gl-form-checkbox>
diff --git a/app/controllers/admin/instance_statistics_controller.rb b/app/controllers/admin/instance_statistics_controller.rb
new file mode 100644
index 00000000000..ad2fea5983d
--- /dev/null
+++ b/app/controllers/admin/instance_statistics_controller.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class Admin::InstanceStatisticsController < Admin::ApplicationController
+ before_action :check_feature_flag
+
+ def index
+ end
+
+ def check_feature_flag
+ render_404 unless Feature.enabled?(:instance_analytics)
+ end
+end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 43baa849007..11d15692f7b 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -27,7 +27,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action only: [:show] do
push_frontend_feature_flag(:diffs_batch_load, @project, default_enabled: true)
push_frontend_feature_flag(:deploy_from_footer, @project, default_enabled: true)
- push_frontend_feature_flag(:single_mr_diff_view, @project, default_enabled: true)
push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline)
push_frontend_feature_flag(:code_navigation, @project, default_enabled: true)
push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true)
diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb
index 51307c3665c..ae3f0a7a0c2 100644
--- a/app/controllers/projects/metrics_dashboard_controller.rb
+++ b/app/controllers/projects/metrics_dashboard_controller.rb
@@ -6,6 +6,8 @@ module Projects
# app/controllers/projects/environments_controller.rb
# See https://gitlab.com/gitlab-org/gitlab/-/issues/226002 for more details.
+ include Gitlab::Utils::StrongMemoize
+
before_action :authorize_metrics_dashboard!
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
@@ -15,6 +17,8 @@ module Projects
def show
if environment
render 'projects/environments/metrics'
+ elsif default_environment
+ redirect_to project_metrics_dashboard_path(project, environment: default_environment)
else
render 'projects/environments/empty_metrics'
end
@@ -23,12 +27,15 @@ module Projects
private
def environment
- @environment ||=
- if params[:environment]
- project.environments.find(params[:environment])
- else
- project.default_environment
- end
+ strong_memoize(:environment) do
+ project.environments.find(params[:environment]) if params[:environment]
+ end
+ end
+
+ def default_environment
+ strong_memoize(:default_environment) do
+ project.default_environment
+ end
end
end
end
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 12543e5f780..781b850ddfe 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -6,10 +6,6 @@ module Projects
before_action :authorize_admin_operations!
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
- before_action do
- push_frontend_feature_flag(:auto_close_incident)
- end
-
respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token]
helper_method :error_tracking_setting
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 56b6a5201e7..c882e1a8358 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -4,12 +4,15 @@ class SearchController < ApplicationController
include ControllerWithCrossProjectAccessCheck
include SearchHelper
include RendersCommits
+ include RedisTracking
SCOPE_PRELOAD_METHOD = {
projects: :with_web_entity_associations,
issues: :with_web_entity_associations
}.freeze
+ track_redis_hll_event :show, name: 'i_search_total', feature: :search_track_unique_users
+
around_action :allow_gitaly_ref_name_caching
skip_before_action :authenticate_user!
@@ -126,3 +129,5 @@ class SearchController < ApplicationController
payload[:metadata]['meta.search.scope'] = params[:scope]
end
end
+
+SearchController.prepend_if_ee('EE::SearchController')
diff --git a/app/models/project.rb b/app/models/project.rb
index ab687896e2e..87bb34fb9c2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -545,6 +545,8 @@ class Project < ApplicationRecord
preload(:project_feature, :route, namespace: [:route, :owner])
}
+ scope :imported_from, -> (type) { where(import_type: type) }
+
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index 26a42d2e9eb..e3fefbb46b6 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -71,15 +71,11 @@ class DiffFileEntity < DiffFileBaseEntity
private
def parallel_diff_view?(options, diff_file)
- return true unless Feature.enabled?(:single_mr_diff_view, diff_file.repository.project, default_enabled: true)
-
# If we're not rendering inline, we must be rendering parallel
!inline_diff_view?(options, diff_file)
end
def inline_diff_view?(options, diff_file)
- return true unless Feature.enabled?(:single_mr_diff_view, diff_file.repository.project, default_enabled: true)
-
# If nothing is present, inline will be the default.
options.fetch(:diff_view, :inline).to_sym == :inline
end
diff --git a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
index d0aa8b04775..aeabbb99468 100644
--- a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
+++ b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
@@ -77,15 +77,8 @@ module Ci
private
def status_for_array(statuses, dag:)
- # TODO: This is hack to support
- # the same exact behaviour for Atomic and Legacy processing
- # that DAG is blocked from executing if dependent is not "complete"
- if dag && statuses.any? { |status| Ci::HasStatus::COMPLETED_STATUSES.exclude?(status[:status]) }
- return 'pending'
- end
-
result = Gitlab::Ci::Status::Composite
- .new(statuses)
+ .new(statuses, dag: dag)
.status
result || 'success'
end
diff --git a/app/views/admin/instance_statistics/index.html.haml b/app/views/admin/instance_statistics/index.html.haml
new file mode 100644
index 00000000000..ab28a2471e6
--- /dev/null
+++ b/app/views/admin/instance_statistics/index.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _("Instance Statistics")
+- page_title _("Instance Statistics")
+
+#js-instance-statistics-app
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 08dbd71bd0c..2e915a38c46 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -69,6 +69,11 @@
= link_to admin_cohorts_path, title: _('Cohorts') do
%span
= _('Cohorts')
+ - if Feature.enabled?(:instance_statistics)
+ = nav_link(controller: :instance_statistics) do
+ = link_to admin_instance_statistics_path, title: _('Instance Statistics') do
+ %span
+ = _('Instance Statistics')
= nav_link(controller: admin_monitoring_nav_links) do
= link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' } do
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index 270223fc508..d88b7b32ed6 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -20,6 +20,11 @@
&middot;
= link_to note.noteable.title, note_url, data: {track_event: 'click_text', track_label: 'noteable_title', track_property: 'search_result'}
+ %span.note-headline-light.note-headline-meta
+ %span.system-note-separator
+ &middot;
+ %span.system-note-separator= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
+
.note-search-result
.term
= search_md_sanitize(note.note)
diff --git a/changelogs/unreleased/205578-add-package-count-to-usage-data.yml b/changelogs/unreleased/205578-add-package-count-to-usage-data.yml
new file mode 100644
index 00000000000..6e23906e70c
--- /dev/null
+++ b/changelogs/unreleased/205578-add-package-count-to-usage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Adds package count to usage data
+merge_request: 40039
+author:
+type: added
diff --git a/changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml b/changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml
new file mode 100644
index 00000000000..ed59d696c44
--- /dev/null
+++ b/changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix skipped status of DAG pipelines
+merge_request: 39205
+author:
+type: fixed
diff --git a/changelogs/unreleased/225254-remove-feature-flag.yml b/changelogs/unreleased/225254-remove-feature-flag.yml
new file mode 100644
index 00000000000..3cb326d6e5c
--- /dev/null
+++ b/changelogs/unreleased/225254-remove-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove auto close incident feature flag
+merge_request: 40612
+author:
+type: changed
diff --git a/changelogs/unreleased/238116-redis-hll-search-analytics.yml b/changelogs/unreleased/238116-redis-hll-search-analytics.yml
new file mode 100644
index 00000000000..84b7160eca2
--- /dev/null
+++ b/changelogs/unreleased/238116-redis-hll-search-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Add the unique search visits data to the usage ping
+merge_request: 40134
+author:
+type: changed
diff --git a/changelogs/unreleased/authored-date-on-comments-in-search.yml b/changelogs/unreleased/authored-date-on-comments-in-search.yml
new file mode 100644
index 00000000000..7a25554d01c
--- /dev/null
+++ b/changelogs/unreleased/authored-date-on-comments-in-search.yml
@@ -0,0 +1,5 @@
+---
+title: Show the comment authored time in comment search results
+merge_request: 40472
+author:
+type: added
diff --git a/changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml b/changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml
new file mode 100644
index 00000000000..ddfe1d8f27c
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage pings for project import using various importers (GitLab, Bitbucket, Gitea, GitHub and more)
+merge_request: 40130
+author:
+type: added
diff --git a/changelogs/unreleased/remove-extracts-path-optimization-flag.yml b/changelogs/unreleased/remove-extracts-path-optimization-flag.yml
new file mode 100644
index 00000000000..b67b3605606
--- /dev/null
+++ b/changelogs/unreleased/remove-extracts-path-optimization-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce Redis usage when viewing repositories with lots of branches and tags
+merge_request: 40615
+author:
+type: performance
diff --git a/config/feature_flags/development/ci_matrix_job_names.yml b/config/feature_flags/development/ci_matrix_job_names.yml
new file mode 100644
index 00000000000..d8f7b2a5543
--- /dev/null
+++ b/config/feature_flags/development/ci_matrix_job_names.yml
@@ -0,0 +1,7 @@
+---
+name: ci_matrix_job_names
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39985
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/239012
+group: 'group::continuous integration'
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/instance_statistics.yml b/config/feature_flags/development/instance_statistics.yml
new file mode 100644
index 00000000000..212b7b39615
--- /dev/null
+++ b/config/feature_flags/development/instance_statistics.yml
@@ -0,0 +1,7 @@
+---
+name: instance_statistics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40583
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241711
+group: group::analytics
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/search_track_unique_users.yml b/config/feature_flags/development/search_track_unique_users.yml
new file mode 100644
index 00000000000..cd190396e5a
--- /dev/null
+++ b/config/feature_flags/development/search_track_unique_users.yml
@@ -0,0 +1,7 @@
+---
+name: search_track_unique_users
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40134
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240906
+group: group::global search
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/security-on-demand-scans-site-validation.yml b/config/feature_flags/development/security-on-demand-scans-site-validation.yml
new file mode 100644
index 00000000000..381c173b1bf
--- /dev/null
+++ b/config/feature_flags/development/security-on-demand-scans-site-validation.yml
@@ -0,0 +1,7 @@
+---
+name: security-on-demand-scans-site-validation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40685
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241815
+group: group::dynamic analysis
+type: development
+default_enabled: false
diff --git a/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb b/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
new file mode 100644
index 00000000000..94d2e5cb4ab
--- /dev/null
+++ b/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddProjectsIndexOnImportTypeCreatorIdCreatedAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_imported_projects_on_import_type_creator_id_created_at'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :projects,
+ [:import_type, :creator_id, :created_at],
+ where: 'import_type IS NOT NULL',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :projects, INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20200826092324 b/db/schema_migrations/20200826092324
new file mode 100644
index 00000000000..8745b628965
--- /dev/null
+++ b/db/schema_migrations/20200826092324
@@ -0,0 +1 @@
+35c37b8dcdca08d48086dc8164c2f6a69f563366ec9bce1f60299978a94de9bc \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 119d34610a3..06b9e1fdfc5 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -19884,6 +19884,8 @@ CREATE INDEX index_import_failures_on_project_id_and_correlation_id_value ON pub
CREATE INDEX index_import_failures_on_project_id_not_null ON public.import_failures USING btree (project_id) WHERE (project_id IS NOT NULL);
+CREATE INDEX index_imported_projects_on_import_type_creator_id_created_at ON public.projects USING btree (import_type, creator_id, created_at) WHERE (import_type IS NOT NULL);
+
CREATE UNIQUE INDEX index_index_statuses_on_project_id ON public.index_statuses USING btree (project_id);
CREATE INDEX index_insights_on_namespace_id ON public.insights USING btree (namespace_id);
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 1480b8acecd..5acaf7cfcce 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -745,7 +745,7 @@ so `&&` is evaluated before `||`.
#### Parentheses
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
+> - It's deployed behind a feature flag, enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables-core-only). **(CORE ONLY)**
diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb
index 5ef2d888550..adbe93cfa3a 100644
--- a/lib/extracts_ref.rb
+++ b/lib/extracts_ref.rb
@@ -111,7 +111,6 @@ module ExtractsRef
end
def use_first_path_segment?(ref)
- return false unless ::Feature.enabled?(:extracts_path_optimization)
return false unless repository_container
return false if repository_container.repository.has_ambiguous_refs?
diff --git a/lib/gitlab/ci/config/normalizer/matrix_strategy.rb b/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
index db21274a9ed..2865b2dcdb7 100644
--- a/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
+++ b/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
@@ -48,18 +48,29 @@ module Gitlab
}
end
- def name_with_details
- vars = variables.map { |key, value| "#{key}=#{value}"}.join('; ')
+ def name
+ if Gitlab::Ci::Features.new_matrix_job_names_enabled?
+ name_with_variable_details
+ else
+ old_name
+ end
+ end
+
+ private
- "#{job_name} (#{vars})"
+ def name_with_variable_details
+ vars = variables
+ .values
+ .compact
+ .join(', ')
+
+ "#{job_name}: [#{vars}]"
end
- def name
+ def old_name
"#{job_name} #{instance}/#{total}"
end
- private
-
attr_reader :job_name, :instance, :variables, :total
end
end
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index 386788c751f..da66cec935c 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -76,6 +76,10 @@ module Gitlab
Feature.enabled?(:project_transactionless_destroy, project, default_enabled: false)
end
+ def self.new_matrix_job_names_enabled?
+ ::Feature.enabled?(:ci_matrix_job_names, default_enabled: false)
+ end
+
def self.coverage_report_view?(project)
::Feature.enabled?(:coverage_report_view, project)
end
diff --git a/lib/gitlab/ci/status/composite.rb b/lib/gitlab/ci/status/composite.rb
index 04a9fc29802..9a4f5644f7d 100644
--- a/lib/gitlab/ci/status/composite.rb
+++ b/lib/gitlab/ci/status/composite.rb
@@ -7,7 +7,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
# This class accepts an array of arrays/hashes/or objects
- def initialize(all_statuses, with_allow_failure: true)
+ def initialize(all_statuses, with_allow_failure: true, dag: false)
unless all_statuses.respond_to?(:pluck)
raise ArgumentError, "all_statuses needs to respond to `.pluck`"
end
@@ -15,6 +15,7 @@ module Gitlab
@status_set = Set.new
@status_key = 0
@allow_failure_key = 1 if with_allow_failure
+ @dag = dag
consume_all_statuses(all_statuses)
end
@@ -31,7 +32,13 @@ module Gitlab
return if none?
strong_memoize(:status) do
- if only_of?(:skipped, :ignored)
+ if @dag && any_of?(:skipped)
+ # The DAG job is skipped if one of the needs does not run at all.
+ 'skipped'
+ elsif @dag && !only_of?(:success, :failed, :canceled, :skipped, :success_with_warnings)
+ # DAG is blocked from executing if a dependent is not "complete"
+ 'pending'
+ elsif only_of?(:skipped, :ignored)
'skipped'
elsif only_of?(:success, :skipped, :success_with_warnings, :ignored)
'success'
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 1ba21d99277..ffd5b9aee2f 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -38,6 +38,7 @@ module Gitlab
.merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, last_28_days_time_period))
.merge(analytics_unique_visits_data)
.merge(compliance_unique_visits_data)
+ .merge(search_unique_visits_data)
end
end
@@ -130,6 +131,7 @@ module Gitlab
milestone_lists: count(List.milestone),
milestones: count(Milestone),
projects_with_packages: distinct_count(::Packages::Package, :project_id),
+ packages: count(::Packages::Package),
pages_domains: count(PagesDomain),
pool_repositories: count(PoolRepository),
projects: count(Project),
@@ -511,7 +513,17 @@ module Gitlab
events: distinct_count(::Event.where(time_period), :author_id),
groups: distinct_count(::GroupMember.where(time_period), :user_id),
users_created: count(::User.where(time_period), start: user_minimum_id, finish: user_maximum_id),
- omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' }
+ omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' },
+ projects_imported: {
+ gitlab_project: projects_imported_count('gitlab_project', time_period),
+ gitlab: projects_imported_count('gitlab', time_period),
+ github: projects_imported_count('github', time_period),
+ bitbucket: projects_imported_count('bitbucket', time_period),
+ bitbucket_server: projects_imported_count('bitbucket_server', time_period),
+ gitea: projects_imported_count('gitea', time_period),
+ git: projects_imported_count('git', time_period),
+ manifest: projects_imported_count('manifest', time_period)
+ }
}
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -608,6 +620,18 @@ module Gitlab
{ compliance_unique_visits: results }
end
+ def search_unique_visits_data
+ events = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('search')
+ results = events.each_with_object({}) do |event, hash|
+ hash[event] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current) }
+ end
+
+ results['search_unique_visits_for_any_target_weekly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 7.days.ago.to_date, end_date: Date.current) }
+ results['search_unique_visits_for_any_target_monthly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+
+ { search_unique_visits: results }
+ end
+
def action_monthly_active_users(time_period)
counter = Gitlab::UsageDataCounters::TrackUniqueEvents
@@ -774,6 +798,10 @@ module Gitlab
def deployment_count(relation)
count relation, start: deployment_minimum_id, finish: deployment_maximum_id
end
+
+ def projects_imported_count(from, time_period)
+ distinct_count(::Project.imported_from(from).where(time_period), :creator_id) # rubocop: disable CodeReuse/ActiveRecord
+ end
end
end
end
diff --git a/lib/gitlab/usage_data_counters/known_events.yml b/lib/gitlab/usage_data_counters/known_events.yml
index feda3aeedfe..cd4d31345d7 100644
--- a/lib/gitlab/usage_data_counters/known_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events.yml
@@ -84,3 +84,15 @@
redis_slot: edit
expiry: 29
aggregation: daily
+- name: i_search_total
+ category: search
+ redis_slot: search
+ aggregation: weekly
+- name: i_search_advanced
+ category: search
+ redis_slot: search
+ aggregation: weekly
+- name: i_search_paid
+ category: search
+ redis_slot: search
+ aggregation: weekly
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c6958960c5c..ee9bc0fa54e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13243,6 +13243,9 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
+msgid "Instance Statistics"
+msgstr ""
+
msgid "Instance administrators group already exists"
msgstr ""
diff --git a/package.json b/package.json
index 7ecd87b02ba..74d353cceef 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
"@gitlab/svgs": "1.161.0",
- "@gitlab/ui": "20.10.0",
+ "@gitlab/ui": "20.11.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-1",
"@sentry/browser": "^5.10.2",
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index a41ff28841d..d66a0246c2d 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -149,6 +149,11 @@ RSpec.describe SearchController do
expect(assigns[:search_objects].first).to eq note
end
+ it_behaves_like 'tracking unique hll events', :show do
+ let(:request_params) { { scope: 'projects', search: 'term' } }
+ let(:target_id) { 'i_search_total' }
+ end
+
context 'on restricted projects' do
context 'when signed out' do
before do
diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb
index be12f774c29..0e65cb358da 100644
--- a/spec/features/merge_request/maintainer_edits_fork_spec.rb
+++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb
@@ -20,8 +20,6 @@ RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork
end
before do
- stub_feature_flags(single_mr_diff_view: false)
-
target_project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
index 1a7baff2fb1..9a79a80abe9 100644
--- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
+++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe 'Batch diffs', :js do
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'empty-branch') }
before do
- stub_feature_flags(single_mr_diff_view: project)
stub_feature_flags(diffs_batch_load: true)
sign_in(project.owner)
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index dc5a38bbf26..bcad415eb19 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -218,7 +218,11 @@ describe('AlertManagementTable', () => {
data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
loading: false,
});
- expect(findStatusDropdown().contains('.dropdown-title')).toBe(false);
+ expect(
+ findStatusDropdown()
+ .find('.dropdown-title')
+ .exists(),
+ ).toBe(false);
});
it('shows correct severity icons', () => {
@@ -517,7 +521,11 @@ describe('AlertManagementTable', () => {
await selectFirstStatusOption();
expect(findAlertError().exists()).toBe(true);
- expect(findAlertError().contains('[data-testid="htmlError"]')).toBe(true);
+ expect(
+ findAlertError()
+ .find('[data-testid="htmlError"]')
+ .exists(),
+ ).toBe(true);
});
});
diff --git a/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js b/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
index 5bd0d3b3c17..a8fe40687e1 100644
--- a/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
+++ b/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
@@ -56,7 +56,11 @@ describe('Alert Details Sidebar Status', () => {
});
it('displays the dropdown status header', () => {
- expect(findStatusDropdown().contains('.dropdown-title')).toBe(true);
+ expect(
+ findStatusDropdown()
+ .find('.dropdown-title')
+ .exists(),
+ ).toBe(true);
});
describe('updating the alert status', () => {
diff --git a/spec/frontend/blob/components/blob_content_spec.js b/spec/frontend/blob/components/blob_content_spec.js
index 9232a709194..3db95e5ad3f 100644
--- a/spec/frontend/blob/components/blob_content_spec.js
+++ b/spec/frontend/blob/components/blob_content_spec.js
@@ -36,20 +36,20 @@ describe('Blob Content component', () => {
describe('rendering', () => {
it('renders loader if `loading: true`', () => {
createComponent({ loading: true });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
- expect(wrapper.contains(BlobContentError)).toBe(false);
- expect(wrapper.contains(RichViewer)).toBe(false);
- expect(wrapper.contains(SimpleViewer)).toBe(false);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.find(BlobContentError).exists()).toBe(false);
+ expect(wrapper.find(RichViewer).exists()).toBe(false);
+ expect(wrapper.find(SimpleViewer).exists()).toBe(false);
});
it('renders error if there is any in the viewer', () => {
const renderError = 'Oops';
const viewer = { ...SimpleViewerMock, renderError };
createComponent({}, viewer);
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(wrapper.contains(BlobContentError)).toBe(true);
- expect(wrapper.contains(RichViewer)).toBe(false);
- expect(wrapper.contains(SimpleViewer)).toBe(false);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(BlobContentError).exists()).toBe(true);
+ expect(wrapper.find(RichViewer).exists()).toBe(false);
+ expect(wrapper.find(SimpleViewer).exists()).toBe(false);
});
it.each`
@@ -60,7 +60,7 @@ describe('Blob Content component', () => {
'renders $type viewer when activeViewer is $type and no loading or error detected',
({ mock, viewer }) => {
createComponent({}, mock);
- expect(wrapper.contains(viewer)).toBe(true);
+ expect(wrapper.find(viewer).exists()).toBe(true);
},
);
diff --git a/spec/frontend/blob/components/blob_edit_content_spec.js b/spec/frontend/blob/components/blob_edit_content_spec.js
index 3cc210e972c..a01ac751a61 100644
--- a/spec/frontend/blob/components/blob_edit_content_spec.js
+++ b/spec/frontend/blob/components/blob_edit_content_spec.js
@@ -58,7 +58,7 @@ describe('Blob Header Editing', () => {
createComponent({ value: undefined });
expect(spy).not.toHaveBeenCalled();
- expect(wrapper.contains('#editor')).toBe(true);
+ expect(wrapper.find('#editor').exists()).toBe(true);
});
it('initialises Editor Lite', () => {
diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js
index c71595a79cf..4355f46db7e 100644
--- a/spec/frontend/blob/components/blob_edit_header_spec.js
+++ b/spec/frontend/blob/components/blob_edit_header_spec.js
@@ -31,7 +31,7 @@ describe('Blob Header Editing', () => {
});
it('contains a form input field', () => {
- expect(wrapper.contains(GlFormInput)).toBe(true);
+ expect(wrapper.find(GlFormInput).exists()).toBe(true);
});
it('does not show delete button', () => {
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index 26906763622..2bf16b6b950 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -62,7 +62,7 @@ describe('BoardContent', () => {
});
it('does not display EpicsSwimlanes component', () => {
- expect(wrapper.contains(EpicsSwimlanes)).toBe(false);
- expect(wrapper.contains(GlAlert)).toBe(false);
+ expect(wrapper.find(EpicsSwimlanes).exists()).toBe(false);
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
});
});
diff --git a/spec/frontend/boards/components/issue_count_spec.js b/spec/frontend/boards/components/issue_count_spec.js
index 819d878f4e2..d1ff0bdbf88 100644
--- a/spec/frontend/boards/components/issue_count_spec.js
+++ b/spec/frontend/boards/components/issue_count_spec.js
@@ -29,7 +29,7 @@ describe('IssueCount', () => {
});
it('does not contains maxIssueCount in the template', () => {
- expect(vm.contains('.js-max-issue-size')).toBe(false);
+ expect(vm.find('.js-max-issue-size').exists()).toBe(false);
});
});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
index 4e35243f484..ab32fb12058 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
@@ -49,7 +49,7 @@ describe('Ci variable modal', () => {
});
it('does not render the autocomplete dropdown', () => {
- expect(wrapper.contains(GlFormCombobox)).toBe(false);
+ expect(wrapper.find(GlFormCombobox).exists()).toBe(false);
});
});
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index 82fa7cf8d0a..0a964426c95 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -300,11 +300,11 @@ describe('Application Row', () => {
beforeEach(() => mountComponent({ updateAvailable: true }));
it('the modal is not rendered', () => {
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(false);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(false);
});
it('the correct button is rendered', () => {
- expect(wrapper.contains("[data-qa-selector='update_button']")).toBe(true);
+ expect(wrapper.find("[data-qa-selector='update_button']").exists()).toBe(true);
});
});
@@ -318,11 +318,13 @@ describe('Application Row', () => {
});
it('displays a modal', () => {
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(true);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(true);
});
it('the correct button is rendered', () => {
- expect(wrapper.contains("[data-qa-selector='update_button_with_confirmation']")).toBe(true);
+ expect(wrapper.find("[data-qa-selector='update_button_with_confirmation']").exists()).toBe(
+ true,
+ );
});
it('triggers updateApplication event', () => {
@@ -344,8 +346,10 @@ describe('Application Row', () => {
version: '1.1.2',
});
- expect(wrapper.contains("[data-qa-selector='update_button_with_confirmation']")).toBe(true);
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(true);
+ expect(wrapper.find("[data-qa-selector='update_button_with_confirmation']").exists()).toBe(
+ true,
+ );
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(true);
});
it('does not need confirmation is version is 3.0.0', () => {
@@ -355,8 +359,8 @@ describe('Application Row', () => {
version: '3.0.0',
});
- expect(wrapper.contains("[data-qa-selector='update_button']")).toBe(true);
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(false);
+ expect(wrapper.find("[data-qa-selector='update_button']").exists()).toBe(true);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(false);
});
it('does not need confirmation if version is higher than 3.0.0', () => {
@@ -366,8 +370,8 @@ describe('Application Row', () => {
version: '5.2.1',
});
- expect(wrapper.contains("[data-qa-selector='update_button']")).toBe(true);
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(false);
+ expect(wrapper.find("[data-qa-selector='update_button']").exists()).toBe(true);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/clusters/components/fluentd_output_settings_spec.js b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
index 0bc4eb73bf9..c263679a45c 100644
--- a/spec/frontend/clusters/components/fluentd_output_settings_spec.js
+++ b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
@@ -168,7 +168,7 @@ describe('FluentdOutputSettings', () => {
});
it('displays a error message', () => {
- expect(wrapper.contains(GlAlert)).toBe(true);
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/clusters_list/components/ancestor_notice_spec.js b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
index c2fa8506014..436f1e97b04 100644
--- a/spec/frontend/clusters_list/components/ancestor_notice_spec.js
+++ b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
@@ -45,7 +45,7 @@ describe('ClustersAncestorNotice', () => {
});
it('displays link', () => {
- expect(wrapper.contains(GlLink)).toBe(true);
+ expect(wrapper.find(GlLink).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 1f274456ded..dea2108b393 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -160,10 +160,6 @@ describe('diffs/components/app', () => {
});
}
- beforeEach(() => {
- wrapper.vm.glFeatures.singleMrDiffView = true;
- });
-
it('fetches diffs if it has none', done => {
wrapper.vm.isLatestVersion = () => false;
@@ -320,7 +316,7 @@ describe('diffs/components/app', () => {
state.diffs.isParallelView = false;
});
- expect(wrapper.contains('.container-limited.limit-container-width')).toBe(true);
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(true);
});
it('does not add container-limiting classes when showFileTree is false with inline diffs', () => {
@@ -329,7 +325,7 @@ describe('diffs/components/app', () => {
state.diffs.isParallelView = false;
});
- expect(wrapper.contains('.container-limited.limit-container-width')).toBe(false);
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(false);
});
it('does not add container-limiting classes when isFluidLayout', () => {
@@ -337,7 +333,7 @@ describe('diffs/components/app', () => {
state.diffs.isParallelView = false;
});
- expect(wrapper.contains('.container-limited.limit-container-width')).toBe(false);
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(false);
});
it('displays loading icon on loading', () => {
@@ -345,7 +341,7 @@ describe('diffs/components/app', () => {
state.diffs.isLoading = true;
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('displays loading icon on batch loading', () => {
@@ -353,20 +349,20 @@ describe('diffs/components/app', () => {
state.diffs.isBatchLoading = true;
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('displays diffs container when not loading', () => {
createComponent();
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(wrapper.contains('#diffs')).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find('#diffs').exists()).toBe(true);
});
it('does not show commit info', () => {
createComponent();
- expect(wrapper.contains('.blob-commit-info')).toBe(false);
+ expect(wrapper.find('.blob-commit-info').exists()).toBe(false);
});
describe('row highlighting', () => {
@@ -442,7 +438,7 @@ describe('diffs/components/app', () => {
it('renders empty state when no diff files exist', () => {
createComponent();
- expect(wrapper.contains(NoChanges)).toBe(true);
+ expect(wrapper.find(NoChanges).exists()).toBe(true);
});
it('does not render empty state when diff files exist', () => {
@@ -452,7 +448,7 @@ describe('diffs/components/app', () => {
});
});
- expect(wrapper.contains(NoChanges)).toBe(false);
+ expect(wrapper.find(NoChanges).exists()).toBe(false);
expect(wrapper.findAll(DiffFile).length).toBe(1);
});
@@ -462,7 +458,7 @@ describe('diffs/components/app', () => {
state.diffs.mergeRequestDiff = mergeRequestDiff;
});
- expect(wrapper.contains(NoChanges)).toBe(false);
+ expect(wrapper.find(NoChanges).exists()).toBe(false);
});
});
@@ -722,7 +718,7 @@ describe('diffs/components/app', () => {
state.diffs.mergeRequestDiff = mergeRequestDiff;
});
- expect(wrapper.contains(CompareVersions)).toBe(true);
+ expect(wrapper.find(CompareVersions).exists()).toBe(true);
expect(wrapper.find(CompareVersions).props()).toEqual(
expect.objectContaining({
mergeRequestDiffs: diffsMockData,
@@ -739,7 +735,7 @@ describe('diffs/components/app', () => {
state.diffs.size = 1;
});
- expect(wrapper.contains(HiddenFilesWarning)).toBe(true);
+ expect(wrapper.find(HiddenFilesWarning).exists()).toBe(true);
expect(wrapper.find(HiddenFilesWarning).props()).toEqual(
expect.objectContaining({
total: '5',
@@ -757,7 +753,7 @@ describe('diffs/components/app', () => {
};
});
- expect(wrapper.contains(CommitWidget)).toBe(true);
+ expect(wrapper.find(CommitWidget).exists()).toBe(true);
});
it('should display diff file if there are diff files', () => {
@@ -765,7 +761,7 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ sha: '123' });
});
- expect(wrapper.contains(DiffFile)).toBe(true);
+ expect(wrapper.find(DiffFile).exists()).toBe(true);
});
it('should render tree list', () => {
diff --git a/spec/frontend/diffs/components/no_changes_spec.js b/spec/frontend/diffs/components/no_changes_spec.js
index 2795c68b4ee..78805a1cddc 100644
--- a/spec/frontend/diffs/components/no_changes_spec.js
+++ b/spec/frontend/diffs/components/no_changes_spec.js
@@ -36,7 +36,7 @@ describe('Diff no changes empty state', () => {
};
});
- expect(vm.contains('script')).toBe(false);
+ expect(vm.find('script').exists()).toBe(false);
});
describe('Renders', () => {
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index 5fef35d6c5b..2a83305f29a 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -101,7 +101,6 @@ describe('DiffsStoreActions', () => {
const projectPath = '/root/project';
const dismissEndpoint = '/-/user_callouts';
const showSuggestPopover = false;
- const useSingleDiffStyle = false;
testAction(
setBaseConfig,
@@ -113,7 +112,6 @@ describe('DiffsStoreActions', () => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
},
{
endpoint: '',
@@ -123,7 +121,6 @@ describe('DiffsStoreActions', () => {
projectPath: '',
dismissEndpoint: '',
showSuggestPopover: true,
- useSingleDiffStyle: true,
},
[
{
@@ -136,7 +133,6 @@ describe('DiffsStoreActions', () => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
},
},
],
@@ -169,13 +165,6 @@ describe('DiffsStoreActions', () => {
done();
},
);
-
- fetchDiffFiles({ state: { endpoint }, commit: () => null })
- .then(data => {
- expect(data).toEqual(res);
- done();
- })
- .catch(done.fail);
});
});
@@ -223,7 +212,7 @@ describe('DiffsStoreActions', () => {
testAction(
fetchDiffFilesBatch,
{},
- { endpointBatch, useSingleDiffStyle: true, diffViewType: 'inline' },
+ { endpointBatch, diffViewType: 'inline' },
[
{ type: types.SET_BATCH_LOADING, payload: true },
{ type: types.SET_RETRIEVING_BATCHES, payload: true },
@@ -253,7 +242,6 @@ describe('DiffsStoreActions', () => {
commit: () => {},
state: {
endpointBatch: `${endpointBatch}?view=${otherView}`,
- useSingleDiffStyle: true,
diffViewType: viewStyle,
},
})
@@ -283,7 +271,7 @@ describe('DiffsStoreActions', () => {
testAction(
fetchDiffFilesMeta,
{},
- { endpointMetadata },
+ { endpointMetadata, diffViewType: 'inline' },
[
{ type: types.SET_LOADING, payload: true },
{ type: types.SET_LOADING, payload: false },
@@ -299,146 +287,6 @@ describe('DiffsStoreActions', () => {
});
});
- describe('when the single diff view feature flag is off', () => {
- describe('fetchDiffFiles', () => {
- it('should fetch diff files', done => {
- const endpoint = '/fetch/diff/files?w=1';
- const mock = new MockAdapter(axios);
- const res = { diff_files: 1, merge_request_diffs: [] };
- mock.onGet(endpoint).reply(200, res);
-
- testAction(
- fetchDiffFiles,
- {},
- {
- endpoint,
- diffFiles: [],
- showWhitespace: false,
- diffViewType: 'inline',
- useSingleDiffStyle: false,
- currentDiffFileId: null,
- },
- [
- { type: types.SET_LOADING, payload: true },
- { type: types.SET_LOADING, payload: false },
- { type: types.SET_MERGE_REQUEST_DIFFS, payload: res.merge_request_diffs },
- { type: types.SET_DIFF_DATA, payload: res },
- ],
- [],
- () => {
- mock.restore();
- done();
- },
- );
-
- fetchDiffFiles({ state: { endpoint }, commit: () => null })
- .then(data => {
- expect(data).toEqual(res);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('fetchDiffFilesBatch', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should fetch batch diff files', done => {
- const endpointBatch = '/fetch/diffs_batch';
- const res1 = { diff_files: [{ file_hash: 'test' }], pagination: { next_page: 2 } };
- const res2 = { diff_files: [{ file_hash: 'test2' }], pagination: {} };
- mock
- .onGet(mergeUrlParams({ per_page: DIFFS_PER_PAGE, w: '1', page: 1 }, endpointBatch))
- .reply(200, res1)
- .onGet(mergeUrlParams({ per_page: DIFFS_PER_PAGE, w: '1', page: 2 }, endpointBatch))
- .reply(200, res2);
-
- testAction(
- fetchDiffFilesBatch,
- {},
- { endpointBatch, useSingleDiffStyle: false, currentDiffFileId: null },
- [
- { type: types.SET_BATCH_LOADING, payload: true },
- { type: types.SET_RETRIEVING_BATCHES, payload: true },
- { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } },
- { type: types.SET_BATCH_LOADING, payload: false },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'test' },
- { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res2.diff_files } },
- { type: types.SET_BATCH_LOADING, payload: false },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'test2' },
- { type: types.SET_RETRIEVING_BATCHES, payload: false },
- ],
- [],
- done,
- );
- });
-
- it.each`
- querystrings | requestUrl
- ${'?view=parallel'} | ${'/fetch/diffs_batch?view=parallel'}
- ${'?view=inline'} | ${'/fetch/diffs_batch?view=inline'}
- ${''} | ${'/fetch/diffs_batch'}
- `(
- 'should use the endpoint $requestUrl if the endpointBatch in state includes `$querystrings` as a querystring',
- ({ querystrings, requestUrl }) => {
- const endpointBatch = '/fetch/diffs_batch';
-
- fetchDiffFilesBatch({
- commit: () => {},
- state: {
- endpointBatch: `${endpointBatch}${querystrings}`,
- diffViewType: 'inline',
- },
- })
- .then(() => {
- expect(mock.history.get[0].url).toEqual(requestUrl);
- })
- .catch(() => {});
- },
- );
- });
-
- describe('fetchDiffFilesMeta', () => {
- const endpointMetadata = '/fetch/diffs_metadata.json';
- const noFilesData = { ...diffMetadata };
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- delete noFilesData.diff_files;
-
- mock.onGet(endpointMetadata).reply(200, diffMetadata);
- });
- it('should fetch diff meta information', done => {
- testAction(
- fetchDiffFilesMeta,
- {},
- { endpointMetadata, useSingleDiffStyle: false },
- [
- { type: types.SET_LOADING, payload: true },
- { type: types.SET_LOADING, payload: false },
- { type: types.SET_MERGE_REQUEST_DIFFS, payload: diffMetadata.merge_request_diffs },
- { type: types.SET_DIFF_DATA, payload: noFilesData },
- ],
- [],
- () => {
- mock.restore();
- done();
- },
- );
- });
- });
- });
-
describe('fetchCoverageFiles', () => {
let mock;
const endpointCoverage = '/fetch';
@@ -589,7 +437,7 @@ describe('DiffsStoreActions', () => {
testAction(
assignDiscussionsToDiff,
[],
- { diffFiles: [], useSingleDiffStyle: true },
+ { diffFiles: [] },
[],
[{ type: 'setCurrentDiffFileIdFromNote', payload: '123' }],
done,
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index 70047899612..705005b809c 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -11,13 +11,11 @@ describe('DiffsStoreMutations', () => {
const state = {};
const endpoint = '/diffs/endpoint';
const projectPath = '/root/project';
- const useSingleDiffStyle = false;
- mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath, useSingleDiffStyle });
+ mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath });
expect(state.endpoint).toEqual(endpoint);
expect(state.projectPath).toEqual(projectPath);
- expect(state.useSingleDiffStyle).toEqual(useSingleDiffStyle);
});
});
diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
index bad70a31599..97e6d1781f4 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -163,7 +163,7 @@ describe('ErrorTrackingList', () => {
it('each error in the list should have an action button set', () => {
findErrorListRows().wrappers.forEach(row => {
- expect(row.contains(ErrorTrackingActions)).toBe(true);
+ expect(row.find(ErrorTrackingActions).exists()).toBe(true);
});
});
diff --git a/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js b/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js
index 204bbfb9c2f..c5155315bb9 100644
--- a/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js
@@ -69,8 +69,8 @@ describe('FrequentItemsSearchInputComponent', () => {
describe('template', () => {
it('should render component element', () => {
expect(wrapper.classes()).toContain('search-input-container');
- expect(wrapper.contains('input.form-control')).toBe(true);
- expect(wrapper.contains('.search-icon')).toBe(true);
+ expect(wrapper.find('input.form-control').exists()).toBe(true);
+ expect(wrapper.find('.search-icon').exists()).toBe(true);
expect(wrapper.find('input.form-control').attributes('placeholder')).toBe(
'Search your projects',
);
diff --git a/spec/frontend/import_projects/components/bitbucket_status_table_spec.js b/spec/frontend/import_projects/components/bitbucket_status_table_spec.js
index 132ccd0e324..b65b388fd5f 100644
--- a/spec/frontend/import_projects/components/bitbucket_status_table_spec.js
+++ b/spec/frontend/import_projects/components/bitbucket_status_table_spec.js
@@ -33,7 +33,7 @@ describe('BitbucketStatusTable', () => {
it('renders import table component', () => {
createComponent({ providerTitle: 'Test' });
- expect(wrapper.contains(ImportProjectsTable)).toBe(true);
+ expect(wrapper.find(ImportProjectsTable).exists()).toBe(true);
});
it('passes alert in incompatible-repos-warning slot', () => {
diff --git a/spec/frontend/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_projects/components/import_projects_table_spec.js
index a5810431afe..83d27635af9 100644
--- a/spec/frontend/import_projects/components/import_projects_table_spec.js
+++ b/spec/frontend/import_projects/components/import_projects_table_spec.js
@@ -77,13 +77,13 @@ describe('ImportProjectsTable', () => {
it('renders a loading icon while repos are loading', () => {
createComponent({ state: { isLoadingRepos: true } });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('renders a loading icon while namespaces are loading', () => {
createComponent({ state: { isLoadingNamespaces: true } });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('renders a table with provider repos', () => {
@@ -97,8 +97,8 @@ describe('ImportProjectsTable', () => {
state: { namespaces: [{ fullPath: 'path' }], repositories },
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(wrapper.contains('table')).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find('table').exists()).toBe(true);
expect(
wrapper
.findAll('th')
@@ -132,7 +132,7 @@ describe('ImportProjectsTable', () => {
it('renders an empty state if there are no projects available', () => {
createComponent({ state: { repositories: [] } });
- expect(wrapper.contains(ProviderRepoTableRow)).toBe(false);
+ expect(wrapper.find(ProviderRepoTableRow).exists()).toBe(false);
expect(wrapper.text()).toContain(`No ${providerTitle} repositories found`);
});
diff --git a/spec/frontend/import_projects/components/provider_repo_table_row_spec.js b/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
index 7a743b5dc04..03e30ef610e 100644
--- a/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
+++ b/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
@@ -82,7 +82,7 @@ describe('ProviderRepoTableRow', () => {
});
it('renders a select2 namespace select', () => {
- expect(wrapper.contains(Select2Select)).toBe(true);
+ expect(wrapper.find(Select2Select).exists()).toBe(true);
expect(wrapper.find(Select2Select).props().options.data).toBe(availableNamespaces);
});
@@ -133,7 +133,7 @@ describe('ProviderRepoTableRow', () => {
});
it('does not renders a namespace select', () => {
- expect(wrapper.contains(Select2Select)).toBe(false);
+ expect(wrapper.find(Select2Select).exists()).toBe(false);
});
it('does not render import button', () => {
diff --git a/spec/frontend/incidents_settings/components/alerts_form_spec.js b/spec/frontend/incidents_settings/components/alerts_form_spec.js
index 32d13b8edc0..2516e8afdfa 100644
--- a/spec/frontend/incidents_settings/components/alerts_form_spec.js
+++ b/spec/frontend/incidents_settings/components/alerts_form_spec.js
@@ -10,7 +10,6 @@ describe('Alert integration settings form', () => {
beforeEach(() => {
wrapper = shallowMount(AlertsSettingsForm, {
provide: {
- glFeatures: { autoCloseIncident: true },
service,
alertSettings: {
issueTemplateKey: 'selecte_tmpl',
diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
index f58825f6297..70ab8fa7bcf 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -57,7 +57,7 @@ describe('JiraIssuesFields', () => {
// As per https://vuejs.org/v2/guide/forms.html#Checkbox-1,
// browsers don't include unchecked boxes in form submissions.
it('includes issues_enabled as false even if unchecked', () => {
- expect(wrapper.contains('input[name="service[issues_enabled]"]')).toBe(true);
+ expect(wrapper.find('input[name="service[issues_enabled]"]').exists()).toBe(true);
});
it('disables project_key input', () => {
@@ -90,7 +90,7 @@ describe('JiraIssuesFields', () => {
it('contains link to editProjectPath', () => {
createComponent();
- expect(wrapper.contains(`a[href="${defaultProps.editProjectPath}"]`)).toBe(true);
+ expect(wrapper.find(`a[href="${defaultProps.editProjectPath}"]`).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
index f6f64dd7fbb..0f88e4d71fe 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
@@ -40,7 +40,7 @@ describe('RelatedIssuesBlock', () => {
});
it('add related issues form is hidden', () => {
- expect(wrapper.contains('.js-add-related-issues-form-area')).toBe(false);
+ expect(wrapper.find('.js-add-related-issues-form-area').exists()).toBe(false);
});
});
@@ -120,7 +120,7 @@ describe('RelatedIssuesBlock', () => {
});
it('shows add related issues form', () => {
- expect(wrapper.contains('.js-add-related-issues-form-area')).toBe(true);
+ expect(wrapper.find('.js-add-related-issues-form-area').exists()).toBe(true);
});
});
diff --git a/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js b/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js
index aee49076b5d..7aa1c290f61 100644
--- a/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js
+++ b/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js
@@ -47,7 +47,7 @@ describe('IssuableListRootApp', () => {
it('does not show an alert', () => {
wrapper = mountComponent();
- expect(wrapper.contains(GlAlert)).toBe(false);
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
});
});
@@ -103,12 +103,12 @@ describe('IssuableListRootApp', () => {
shouldShowInProgressAlert: true,
});
- expect(wrapper.contains(GlAlert)).toBe(true);
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
findAlert().vm.$emit('dismiss');
return Vue.nextTick(() => {
- expect(wrapper.contains(GlAlert)).toBe(false);
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/issuables_list/components/issuable_spec.js b/spec/frontend/issuables_list/components/issuable_spec.js
index c7b7fb2eac1..74be7d87847 100644
--- a/spec/frontend/issuables_list/components/issuable_spec.js
+++ b/spec/frontend/issuables_list/components/issuable_spec.js
@@ -97,7 +97,7 @@ describe('Issuable component', () => {
const findUnscopedLabels = () => findLabels().filter(w => !isScopedLabel({ title: w.text() }));
const findIssuableTitle = () => wrapper.find('[data-testid="issuable-title"]');
const findIssuableStatus = () => wrapper.find('[data-testid="issuable-status"]');
- const containsJiraLogo = () => wrapper.contains('[data-testid="jira-logo"]');
+ const containsJiraLogo = () => wrapper.find('[data-testid="jira-logo"]').exists();
const findHealthStatus = () => wrapper.find('.health-status');
describe('when mounted', () => {
diff --git a/spec/frontend/issuables_list/components/issuables_list_app_spec.js b/spec/frontend/issuables_list/components/issuables_list_app_spec.js
index 65b87ddf6a6..9db03c49994 100644
--- a/spec/frontend/issuables_list/components/issuables_list_app_spec.js
+++ b/spec/frontend/issuables_list/components/issuables_list_app_spec.js
@@ -169,7 +169,7 @@ describe('Issuables list component', () => {
it('does not display empty state', () => {
expect(wrapper.vm.issuables.length).toBeGreaterThan(0);
expect(wrapper.vm.emptyState).toEqual({});
- expect(wrapper.contains(GlEmptyState)).toBe(false);
+ expect(wrapper.find(GlEmptyState).exists()).toBe(false);
});
it('sets the proper page and total items', () => {
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index f76f42cb9ae..10806499d5e 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -134,7 +134,7 @@ describe('Issuable output', () => {
wrapper.vm.showForm = true;
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.contains('.markdown-selector')).toBe(true);
+ expect(wrapper.find('.markdown-selector').exists()).toBe(true);
});
});
@@ -143,7 +143,7 @@ describe('Issuable output', () => {
wrapper.setProps({ canUpdate: false });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.contains('.markdown-selector')).toBe(false);
+ expect(wrapper.find('.markdown-selector').exists()).toBe(false);
});
});
@@ -403,7 +403,7 @@ describe('Issuable output', () => {
.then(() => {
expect(wrapper.vm.formState.lockedWarningVisible).toEqual(true);
expect(wrapper.vm.formState.lock_version).toEqual(1);
- expect(wrapper.contains('.alert')).toBe(true);
+ expect(wrapper.find('.alert').exists()).toBe(true);
});
});
});
@@ -441,14 +441,14 @@ describe('Issuable output', () => {
describe('show inline edit button', () => {
it('should not render by default', () => {
- expect(wrapper.contains('.btn-edit')).toBe(true);
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
it('should render if showInlineEditButton', () => {
wrapper.setProps({ showInlineEditButton: true });
return wrapper.vm.$nextTick(() => {
- expect(wrapper.contains('.btn-edit')).toBe(true);
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
});
});
@@ -531,7 +531,7 @@ describe('Issuable output', () => {
describe('sticky header', () => {
describe('when title is in view', () => {
it('is not shown', () => {
- expect(wrapper.contains('.issue-sticky-header')).toBe(false);
+ expect(wrapper.find('.issue-sticky-header').exists()).toBe(false);
});
});
diff --git a/spec/frontend/jira_import/components/jira_import_form_spec.js b/spec/frontend/jira_import/components/jira_import_form_spec.js
index 6ef28a71f48..39cb63af2f0 100644
--- a/spec/frontend/jira_import/components/jira_import_form_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_form_spec.js
@@ -100,7 +100,7 @@ describe('JiraImportForm', () => {
it('is shown', () => {
wrapper = mountComponent();
- expect(wrapper.contains(GlFormSelect)).toBe(true);
+ expect(wrapper.find(GlFormSelect).exists()).toBe(true);
});
it('contains a list of Jira projects to select from', () => {
diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js
index 5ce69221dab..bb90949b1f4 100644
--- a/spec/frontend/jobs/components/log/line_header_spec.js
+++ b/spec/frontend/jobs/components/log/line_header_spec.js
@@ -38,7 +38,7 @@ describe('Job Log Header Line', () => {
});
it('renders the line number component', () => {
- expect(wrapper.contains(LineNumber)).toBe(true);
+ expect(wrapper.find(LineNumber).exists()).toBe(true);
});
it('renders a span the provided text', () => {
@@ -90,7 +90,7 @@ describe('Job Log Header Line', () => {
});
it('renders the duration badge', () => {
- expect(wrapper.contains(DurationBadge)).toBe(true);
+ expect(wrapper.find(DurationBadge).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js
index ec3a3968f14..c2412a807c3 100644
--- a/spec/frontend/jobs/components/log/line_spec.js
+++ b/spec/frontend/jobs/components/log/line_spec.js
@@ -35,7 +35,7 @@ describe('Job Log Line', () => {
});
it('renders the line number component', () => {
- expect(wrapper.contains(LineNumber)).toBe(true);
+ expect(wrapper.find(LineNumber).exists()).toBe(true);
});
it('renders a span the provided text', () => {
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
index a6285fe64b5..015d5e01a46 100644
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ b/spec/frontend/jobs/components/log/log_spec.js
@@ -62,7 +62,11 @@ describe('Job Log', () => {
});
it('renders an icon with the open state', () => {
- expect(findCollapsibleLine().contains('[data-testid="angle-down-icon"]')).toBe(true);
+ expect(
+ findCollapsibleLine()
+ .find('[data-testid="angle-down-icon"]')
+ .exists(),
+ ).toBe(true);
});
describe('on click header section', () => {
diff --git a/spec/frontend/monitoring/alert_widget_spec.js b/spec/frontend/monitoring/alert_widget_spec.js
index 193dbb3e63f..d004b1da0b6 100644
--- a/spec/frontend/monitoring/alert_widget_spec.js
+++ b/spec/frontend/monitoring/alert_widget_spec.js
@@ -84,7 +84,7 @@ describe('AlertWidget', () => {
},
});
};
- const hasLoadingIcon = () => wrapper.contains(GlLoadingIcon);
+ const hasLoadingIcon = () => wrapper.find(GlLoadingIcon).exists();
const findWidgetForm = () => wrapper.find({ ref: 'widgetForm' });
const findAlertErrorMessage = () => wrapper.find({ ref: 'alertErrorMessage' });
const findCurrentSettingsText = () =>
diff --git a/spec/frontend/mr_popover/mr_popover_spec.js b/spec/frontend/mr_popover/mr_popover_spec.js
index 3f62dca4a57..094d1a6472c 100644
--- a/spec/frontend/mr_popover/mr_popover_spec.js
+++ b/spec/frontend/mr_popover/mr_popover_spec.js
@@ -61,7 +61,7 @@ describe('MR Popover', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.contains(CiIcon)).toBe(false);
+ expect(wrapper.find(CiIcon).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/packages/details/components/package_title_spec.js b/spec/frontend/packages/details/components/package_title_spec.js
index a30dc4b8aba..6c15ecf656e 100644
--- a/spec/frontend/packages/details/components/package_title_spec.js
+++ b/spec/frontend/packages/details/components/package_title_spec.js
@@ -146,7 +146,11 @@ describe('PackageTitle', () => {
it('correctly shows the package ref if there is one', () => {
createComponent({ packageEntity: npmPackage });
- expect(packageRef().contains('gl-icon-stub')).toBe(true);
+ expect(
+ packageRef()
+ .find('gl-icon-stub')
+ .exists(),
+ ).toBe(true);
expect(packageRef().text()).toBe(npmPackage.pipeline.ref);
});
});
diff --git a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
index e83fb04a688..fbe2274c40d 100644
--- a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
+++ b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
@@ -38,16 +38,16 @@ describe('CustomizeHomepageBanner', () => {
});
it('should render the banner when not dismissed', () => {
- expect(wrapper.contains(GlBanner)).toBe(true);
+ expect(wrapper.find(GlBanner).exists()).toBe(true);
});
it('should close the banner when dismiss is clicked', async () => {
mockAxios.onPost(provide.calloutsPath).replyOnce(200);
- expect(wrapper.contains(GlBanner)).toBe(true);
+ expect(wrapper.find(GlBanner).exists()).toBe(true);
wrapper.find(GlBanner).vm.$emit('close');
await wrapper.vm.$nextTick();
- expect(wrapper.contains(GlBanner)).toBe(false);
+ expect(wrapper.find(GlBanner).exists()).toBe(false);
});
it('includes the body text from options', () => {
diff --git a/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js b/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js
index 0bb96ee33d4..67ace608127 100644
--- a/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js
+++ b/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js
@@ -36,7 +36,7 @@ describe('BitbucketServerStatusTable', () => {
it('renders bitbucket status table component', () => {
createComponent();
- expect(wrapper.contains(BitbucketStatusTable)).toBe(true);
+ expect(wrapper.find(BitbucketStatusTable).exists()).toBe(true);
});
it('renders Reconfigure button', async () => {
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
index 2ec608569e3..9993e4da980 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
@@ -70,7 +70,7 @@ describe('Fork groups list component', () => {
replyWith(() => new Promise(() => {}));
createWrapper();
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('displays empty text if no groups are available', async () => {
@@ -89,7 +89,7 @@ describe('Fork groups list component', () => {
await waitForPromises();
- expect(wrapper.contains(GlSearchBoxByType)).toBe(true);
+ expect(wrapper.find(GlSearchBoxByType).exists()).toBe(true);
});
it('renders list items for each available group', async () => {
diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
index 54a080fb62b..8884f7815ab 100644
--- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js
+++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
@@ -124,7 +124,7 @@ describe('Code Coverage', () => {
});
it('renders the dropdown with all custom names as options', () => {
- expect(wrapper.contains(GlDeprecatedDropdown)).toBeDefined();
+ expect(wrapper.find(GlDeprecatedDropdown).exists()).toBeDefined();
expect(findAllDropdownItems()).toHaveLength(codeCoverageMockData.length);
expect(findFirstDropdownItem().text()).toBe(codeCoverageMockData[0].group_name);
});
@@ -150,7 +150,11 @@ describe('Code Coverage', () => {
.find(GlIcon)
.exists(),
).toBe(false);
- expect(findSecondDropdownItem().contains(GlIcon)).toBe(true);
+ expect(
+ findSecondDropdownItem()
+ .find(GlIcon)
+ .exists(),
+ ).toBe(true);
});
it('updates the graph data when selecting a different option in dropdown', async () => {
diff --git a/spec/frontend/pipelines/pipeline_triggerer_spec.js b/spec/frontend/pipelines/pipeline_triggerer_spec.js
index 6fd9a143d82..ad8136890e6 100644
--- a/spec/frontend/pipelines/pipeline_triggerer_spec.js
+++ b/spec/frontend/pipelines/pipeline_triggerer_spec.js
@@ -36,7 +36,7 @@ describe('Pipelines Triggerer', () => {
});
it('should render a table cell', () => {
- expect(wrapper.contains('.table-section')).toBe(true);
+ expect(wrapper.find('.table-section').exists()).toBe(true);
});
it('should pass triggerer information when triggerer is provided', () => {
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
index 7fe310aa400..2ea0957b347 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
@@ -26,16 +26,16 @@ describe('ServiceDeskSetting', () => {
});
it('should see activation checkbox', () => {
- expect(wrapper.contains('#service-desk-checkbox')).toBe(true);
+ expect(wrapper.find('#service-desk-checkbox').exists()).toBe(true);
});
it('should see main panel with the email info', () => {
- expect(wrapper.contains('#incoming-email-describer')).toBe(true);
+ expect(wrapper.find('#incoming-email-describer').exists()).toBe(true);
});
it('should see loading spinner and not the incoming email', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.contains('.incoming-email')).toBe(false);
+ expect(wrapper.find('.incoming-email').exists()).toBe(false);
});
});
});
@@ -78,7 +78,7 @@ describe('ServiceDeskSetting', () => {
});
it('renders a copy to clipboard button', () => {
- expect(wrapper.contains('.qa-clipboard-button')).toBe(true);
+ expect(wrapper.find('.qa-clipboard-button').exists()).toBe(true);
expect(wrapper.find('.qa-clipboard-button').element.dataset.clipboardText).toBe(
incomingEmail,
);
@@ -93,7 +93,7 @@ describe('ServiceDeskSetting', () => {
},
});
- expect(wrapper.contains('#service-desk-template-select')).toBe(true);
+ expect(wrapper.find('#service-desk-template-select').exists()).toBe(true);
});
it('renders a dropdown with a default value of ""', () => {
@@ -202,15 +202,15 @@ describe('ServiceDeskSetting', () => {
});
it('does not render email panel', () => {
- expect(wrapper.contains('#incoming-email-describer')).toBe(false);
+ expect(wrapper.find('#incoming-email-describer').exists()).toBe(false);
});
it('does not render template dropdown', () => {
- expect(wrapper.contains('#service-desk-template-select')).toBe(false);
+ expect(wrapper.find('#service-desk-template-select').exists()).toBe(false);
});
it('does not render template save button', () => {
- expect(wrapper.contains('button.btn-success')).toBe(false);
+ expect(wrapper.find('button.btn-success').exists()).toBe(false);
});
it('emits an event to turn on Service Desk when the toggle is clicked', () => {
diff --git a/spec/frontend/releases/components/release_block_assets_spec.js b/spec/frontend/releases/components/release_block_assets_spec.js
index 5e84290716c..3453ecbf8ab 100644
--- a/spec/frontend/releases/components/release_block_assets_spec.js
+++ b/spec/frontend/releases/components/release_block_assets_spec.js
@@ -128,7 +128,7 @@ describe('Release block assets', () => {
describe('external vs internal links', () => {
const containsExternalSourceIndicator = () =>
- wrapper.contains('[data-testid="external-link-indicator"]');
+ wrapper.find('[data-testid="external-link-indicator"]').exists();
describe('when a link is external', () => {
beforeEach(() => {
diff --git a/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js b/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
index 533528e1dca..c9bd040aaf5 100644
--- a/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
+++ b/spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js
@@ -126,7 +126,11 @@ describe('Grouped code quality reports app', () => {
});
it('renders a help icon with more information', () => {
- expect(findWidget().contains('[data-testid="question-icon"]')).toBe(true);
+ expect(
+ findWidget()
+ .find('[data-testid="question-icon"]')
+ .exists(),
+ ).toBe(true);
});
});
@@ -140,7 +144,11 @@ describe('Grouped code quality reports app', () => {
});
it('does not render a help icon', () => {
- expect(findWidget().contains('[data-testid="question-icon"]')).toBe(false);
+ expect(
+ findWidget()
+ .find('[data-testid="question-icon"]')
+ .exists(),
+ ).toBe(false);
});
});
});
diff --git a/spec/frontend/reports/components/grouped_issues_list_spec.js b/spec/frontend/reports/components/grouped_issues_list_spec.js
index 1f8f4a0e4c1..1172e514707 100644
--- a/spec/frontend/reports/components/grouped_issues_list_spec.js
+++ b/spec/frontend/reports/components/grouped_issues_list_spec.js
@@ -42,7 +42,7 @@ describe('Grouped Issues List', () => {
});
it.each('resolved', 'unresolved')('does not render report items for %s issues', () => {
- expect(wrapper.contains(ReportItem)).toBe(false);
+ expect(wrapper.find(ReportItem).exists()).toBe(false);
});
});
diff --git a/spec/frontend/sidebar/participants_spec.js b/spec/frontend/sidebar/participants_spec.js
index ebe94582588..93c9b3b84c3 100644
--- a/spec/frontend/sidebar/participants_spec.js
+++ b/spec/frontend/sidebar/participants_spec.js
@@ -37,7 +37,7 @@ describe('Participants', () => {
loading: true,
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('does not show loading spinner not loading', () => {
@@ -45,7 +45,7 @@ describe('Participants', () => {
loading: false,
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
it('shows participant count when given', () => {
@@ -74,7 +74,7 @@ describe('Participants', () => {
loading: true,
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('when only showing visible participants, shows an avatar only for each participant under the limit', () => {
@@ -196,11 +196,11 @@ describe('Participants', () => {
});
it('does not show sidebar collapsed icon', () => {
- expect(wrapper.contains('.sidebar-collapsed-icon')).toBe(false);
+ expect(wrapper.find('.sidebar-collapsed-icon').exists()).toBe(false);
});
it('does not show participants label title', () => {
- expect(wrapper.contains('.title')).toBe(false);
+ expect(wrapper.find('.title').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js
index cce35666985..dddb9c2bba9 100644
--- a/spec/frontend/sidebar/subscriptions_spec.js
+++ b/spec/frontend/sidebar/subscriptions_spec.js
@@ -100,7 +100,7 @@ describe('Subscriptions', () => {
});
it('does not render the toggle button', () => {
- expect(wrapper.contains('.js-issuable-subscribe-button')).toBe(false);
+ expect(wrapper.find('.js-issuable-subscribe-button').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index 25cef3a8045..33152591d42 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -168,10 +168,10 @@ describe('Snippet Edit app', () => {
props => {
createComponent(props);
- expect(wrapper.contains(TitleField)).toBe(true);
- expect(wrapper.contains(SnippetDescriptionEdit)).toBe(true);
- expect(wrapper.contains(SnippetVisibilityEdit)).toBe(true);
- expect(wrapper.contains(FormFooterActions)).toBe(true);
+ expect(wrapper.find(TitleField).exists()).toBe(true);
+ expect(wrapper.find(SnippetDescriptionEdit).exists()).toBe(true);
+ expect(wrapper.find(SnippetVisibilityEdit).exists()).toBe(true);
+ expect(wrapper.find(FormFooterActions).exists()).toBe(true);
expect(findBlobActions().exists()).toBe(true);
},
);
diff --git a/spec/frontend/snippets/components/show_spec.js b/spec/frontend/snippets/components/show_spec.js
index 24c9600fb53..b5ab7def753 100644
--- a/spec/frontend/snippets/components/show_spec.js
+++ b/spec/frontend/snippets/components/show_spec.js
@@ -66,7 +66,7 @@ describe('Snippet view app', () => {
},
},
});
- expect(wrapper.contains(EmbedDropdown)).toBe(true);
+ expect(wrapper.find(EmbedDropdown).exists()).toBe(true);
});
it('renders correct snippet-blob components', () => {
@@ -97,7 +97,7 @@ describe('Snippet view app', () => {
},
},
});
- expect(wrapper.contains(EmbedDropdown)).toBe(isRendered);
+ expect(wrapper.find(EmbedDropdown).exists()).toBe(isRendered);
});
});
@@ -119,7 +119,7 @@ describe('Snippet view app', () => {
},
},
});
- expect(wrapper.contains(CloneDropdownButton)).toBe(isRendered);
+ expect(wrapper.find(CloneDropdownButton).exists()).toBe(isRendered);
},
);
});
diff --git a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
index a8df13787a5..4ba3e906fc3 100644
--- a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
@@ -96,7 +96,11 @@ describe('Snippet Visibility Edit component', () => {
it('when helpLink is not defined, does not render label help link', () => {
createComponent({ helpLink: null });
- expect(findLabel().contains(GlLink)).toBe(false);
+ expect(
+ findLabel()
+ .find(GlLink)
+ .exists(),
+ ).toBe(false);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
index 932574610c9..4e3e918f7fb 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
@@ -21,7 +21,7 @@ describe('MrWidgetContainer', () => {
factory();
expect(wrapper.classes()).toContain('mr-widget-heading');
- expect(wrapper.contains('.mr-widget-content')).toBe(true);
+ expect(wrapper.find('.mr-widget-content').exists()).toBe(true);
});
it('accepts default slot', () => {
@@ -31,7 +31,7 @@ describe('MrWidgetContainer', () => {
},
});
- expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
+ expect(wrapper.find('.mr-widget-content .test-body').exists()).toBe(true);
});
it('accepts footer slot', () => {
@@ -42,7 +42,7 @@ describe('MrWidgetContainer', () => {
},
});
- expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
- expect(wrapper.contains('.test-footer')).toBe(true);
+ expect(wrapper.find('.mr-widget-content .test-body').exists()).toBe(true);
+ expect(wrapper.find('.test-footer').exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
index 69a50899d4d..3e111cd308a 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
@@ -18,7 +18,7 @@ describe('MrWidgetExpanableSection', () => {
});
it('renders Icon', () => {
- expect(wrapper.contains(GlIcon)).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
});
it('renders header slot', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index c3a16a776a7..19f8a67d066 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -148,8 +148,8 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(vm.contains('.js-resolve-conflicts-button')).toBe(false);
- expect(vm.contains('.js-merge-locally-button')).toBe(false);
+ expect(vm.find('.js-resolve-conflicts-button').exists()).toBe(false);
+ expect(vm.find('.js-merge-locally-button').exists()).toBe(false);
});
it('should not have resolve button when no conflict resolution path', () => {
@@ -161,7 +161,7 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(vm.contains('.js-resolve-conflicts-button')).toBe(false);
+ expect(vm.find('.js-resolve-conflicts-button').exists()).toBe(false);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js b/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
index ffcf9b1477a..7dfb265c035 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
+++ b/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
@@ -49,8 +49,8 @@ describe('MrWidgetTerraformConainer', () => {
});
it('diplays loading skeleton', () => {
- expect(wrapper.contains(GlSkeletonLoading)).toBe(true);
- expect(wrapper.contains(MrWidgetExpanableSection)).toBe(false);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(true);
+ expect(wrapper.find(MrWidgetExpanableSection).exists()).toBe(false);
});
});
@@ -61,8 +61,8 @@ describe('MrWidgetTerraformConainer', () => {
});
it('displays terraform content', () => {
- expect(wrapper.contains(GlSkeletonLoading)).toBe(false);
- expect(wrapper.contains(MrWidgetExpanableSection)).toBe(true);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
+ expect(wrapper.find(MrWidgetExpanableSection).exists()).toBe(true);
expect(findPlans()).toEqual(Object.values(plans));
});
@@ -156,7 +156,7 @@ describe('MrWidgetTerraformConainer', () => {
});
it('stops loading', () => {
- expect(wrapper.contains(GlSkeletonLoading)).toBe(false);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
});
it('generates one broken plan', () => {
diff --git a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
index 5cf42ecdc1d..22643a17b2b 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
@@ -36,6 +36,6 @@ describe('Blob Rich Viewer component', () => {
});
it('is using Markdown View Field', () => {
- expect(wrapper.contains(MarkdownFieldView)).toBe(true);
+ expect(wrapper.find(MarkdownFieldView).exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/clone_dropdown_spec.js b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
index d9829874b93..1354578cc64 100644
--- a/spec/frontend/vue_shared/components/clone_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
@@ -40,7 +40,7 @@ describe('Clone Dropdown Button', () => {
createComponent();
const group = wrapper.findAll(GlFormInputGroup).at(index);
expect(group.props('value')).toBe(value);
- expect(group.contains(GlFormInputGroup)).toBe(true);
+ expect(group.find(GlFormInputGroup).exists()).toBe(true);
});
it.each`
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
index 1acd2e05464..c5917249f0a 100644
--- a/spec/frontend/vue_shared/components/file_row_spec.js
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -118,7 +118,7 @@ describe('File row component', () => {
level: 0,
});
- expect(wrapper.contains(FileHeader)).toBe(true);
+ expect(wrapper.find(FileHeader).exists()).toBe(true);
});
it('matches the current route against encoded file URL', () => {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
index 73dbecadd89..440a93eaf64 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
@@ -52,10 +52,10 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapper.vm.filterValue).toEqual([]);
expect(wrapper.vm.selectedSortOption).toBe(mockSortOptions[0].sortDirection.descending);
expect(wrapper.vm.selectedSortDirection).toBe(SortDirection.descending);
- expect(wrapper.contains(GlButtonGroup)).toBe(true);
- expect(wrapper.contains(GlButton)).toBe(true);
- expect(wrapper.contains(GlDropdown)).toBe(true);
- expect(wrapper.contains(GlDropdownItem)).toBe(true);
+ expect(wrapper.find(GlButtonGroup).exists()).toBe(true);
+ expect(wrapper.find(GlButton).exists()).toBe(true);
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
+ expect(wrapper.find(GlDropdownItem).exists()).toBe(true);
});
it('does not initialize `selectedSortOption` and `selectedSortDirection` when `sortOptions` is not applied and hides the sort dropdown', () => {
@@ -63,10 +63,10 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapperNoSort.vm.filterValue).toEqual([]);
expect(wrapperNoSort.vm.selectedSortOption).toBe(undefined);
- expect(wrapperNoSort.contains(GlButtonGroup)).toBe(false);
- expect(wrapperNoSort.contains(GlButton)).toBe(false);
- expect(wrapperNoSort.contains(GlDropdown)).toBe(false);
- expect(wrapperNoSort.contains(GlDropdownItem)).toBe(false);
+ expect(wrapperNoSort.find(GlButtonGroup).exists()).toBe(false);
+ expect(wrapperNoSort.find(GlButton).exists()).toBe(false);
+ expect(wrapperNoSort.find(GlDropdown).exists()).toBe(false);
+ expect(wrapperNoSort.find(GlDropdownItem).exists()).toBe(false);
});
});
diff --git a/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js b/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js
index 36099d108f6..bd4b6a463ab 100644
--- a/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js
+++ b/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js
@@ -19,7 +19,7 @@ describe(`TimelineEntryItem`, () => {
expect(wrapper.classes()).toContain('timeline-entry');
- expect(wrapper.contains('.timeline-entry-inner')).toBe(true);
+ expect(wrapper.find('.timeline-entry-inner').exists()).toBe(true);
});
it('accepts default slot', () => {
diff --git a/spec/frontend/vue_shared/components/paginated_list_spec.js b/spec/frontend/vue_shared/components/paginated_list_spec.js
index 46e45296c37..c0ee49f194f 100644
--- a/spec/frontend/vue_shared/components/paginated_list_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_list_spec.js
@@ -48,7 +48,7 @@ describe('Pagination links component', () => {
describe('rendering', () => {
it('it renders the gl-paginated-list', () => {
- expect(wrapper.contains('ul.list-group')).toBe(true);
+ expect(wrapper.find('ul.list-group').exists()).toBe(true);
expect(wrapper.findAll('li.list-group-item').length).toBe(2);
});
});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 385134c4a3f..d0a602cb950 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -29,7 +29,7 @@ describe('ProjectListItem component', () => {
it('does not render a check mark icon if selected === false', () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.contains('.js-selected-icon.js-unselected')).toBe(true);
+ expect(wrapper.find('.js-selected-icon.js-unselected').exists()).toBe(true);
});
it('renders a check mark icon if selected === true', () => {
@@ -37,7 +37,7 @@ describe('ProjectListItem component', () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.contains('.js-selected-icon.js-selected')).toBe(true);
+ expect(wrapper.find('.js-selected-icon.js-selected').exists()).toBe(true);
});
it(`emits a "clicked" event when clicked`, () => {
@@ -53,7 +53,7 @@ describe('ProjectListItem component', () => {
it(`renders the project avatar`, () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.contains('.js-project-avatar')).toBe(true);
+ expect(wrapper.find('.js-project-avatar').exists()).toBe(true);
});
it(`renders a simple namespace name with a trailing slash`, () => {
diff --git a/spec/frontend/vue_shared/components/remove_member_modal_spec.js b/spec/frontend/vue_shared/components/remove_member_modal_spec.js
index 2d380b25a0a..78fe6d53eee 100644
--- a/spec/frontend/vue_shared/components/remove_member_modal_spec.js
+++ b/spec/frontend/vue_shared/components/remove_member_modal_spec.js
@@ -48,7 +48,7 @@ describe('RemoveMemberModal', () => {
});
it(`${checkboxTestDescription}`, () => {
- expect(wrapper.contains(GlFormCheckbox)).toBe(checkboxExpected);
+ expect(wrapper.find(GlFormCheckbox).exists()).toBe(checkboxExpected);
});
it('submits the form when the modal is submitted', () => {
diff --git a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
index bab604c4504..81f17e0f528 100644
--- a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
describe '.applies_to?' do
@@ -39,64 +39,114 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
it { expect(subject.size).to eq(4) }
- it 'has attributes' do
- expect(subject.map(&:attributes)).to match_array(
- [
- {
- name: 'test 1/4',
- instance: 1,
- parallel: { total: 4 },
- variables: {
- 'PROVIDER' => 'aws',
- 'STACK' => 'app1'
- }
- },
- {
- name: 'test 2/4',
- instance: 2,
- parallel: { total: 4 },
- variables: {
- 'PROVIDER' => 'aws',
- 'STACK' => 'app2'
- }
- },
- {
- name: 'test 3/4',
- instance: 3,
- parallel: { total: 4 },
- variables: {
- 'PROVIDER' => 'ovh',
- 'STACK' => 'app'
- }
- },
- {
- name: 'test 4/4',
- instance: 4,
- parallel: { total: 4 },
- variables: {
- 'PROVIDER' => 'gcp',
- 'STACK' => 'app'
+ context 'with new_matrix_job_names_enabled ff disabled' do
+ before do
+ stub_feature_flags(ci_matrix_job_names: false)
+ end
+
+ it 'has attributes' do
+ expect(subject.map(&:attributes)).to match_array(
+ [
+ {
+ name: 'test 1/4',
+ instance: 1,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'aws',
+ 'STACK' => 'app1'
+ }
+ },
+ {
+ name: 'test 2/4',
+ instance: 2,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'aws',
+ 'STACK' => 'app2'
+ }
+ },
+ {
+ name: 'test 3/4',
+ instance: 3,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'ovh',
+ 'STACK' => 'app'
+ }
+ },
+ {
+ name: 'test 4/4',
+ instance: 4,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'gcp',
+ 'STACK' => 'app'
+ }
}
- }
- ]
- )
- end
+ ]
+ )
+ end
- it 'has parallelized name' do
- expect(subject.map(&:name)).to match_array(
- ['test 1/4', 'test 2/4', 'test 3/4', 'test 4/4']
- )
+ it 'has parallelized name' do
+ expect(subject.map(&:name)).to match_array(
+ ['test 1/4', 'test 2/4', 'test 3/4', 'test 4/4']
+ )
+ end
end
- it 'has details' do
- expect(subject.map(&:name_with_details)).to match_array(
- [
- 'test (PROVIDER=aws; STACK=app1)',
- 'test (PROVIDER=aws; STACK=app2)',
- 'test (PROVIDER=gcp; STACK=app)',
- 'test (PROVIDER=ovh; STACK=app)'
- ]
- )
+ context 'with new_matrix_job_names_enabled ff enabled' do
+ before do
+ stub_feature_flags(ci_matrix_job_names: true)
+ end
+
+ it 'has attributes' do
+ expect(subject.map(&:attributes)).to match_array(
+ [
+ {
+ name: 'test: [aws, app1]',
+ instance: 1,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'aws',
+ 'STACK' => 'app1'
+ }
+ },
+ {
+ name: 'test: [aws, app2]',
+ instance: 2,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'aws',
+ 'STACK' => 'app2'
+ }
+ },
+ {
+ name: 'test: [ovh, app]',
+ instance: 3,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'ovh',
+ 'STACK' => 'app'
+ }
+ },
+ {
+ name: 'test: [gcp, app]',
+ instance: 4,
+ parallel: { total: 4 },
+ variables: {
+ 'PROVIDER' => 'gcp',
+ 'STACK' => 'app'
+ }
+ }
+ ]
+ )
+ end
+
+ it 'has parallelized name' do
+ expect(subject.map(&:name)).to match_array(
+ ['test: [aws, app1]', 'test: [aws, app2]', 'test: [gcp, app]', 'test: [ovh, app]']
+ )
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/normalizer_spec.rb b/spec/lib/gitlab/ci/config/normalizer_spec.rb
index 949af8cdc4c..75e6abf68de 100644
--- a/spec/lib/gitlab/ci/config/normalizer_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Normalizer do
let(:job_name) { :rspec }
@@ -178,39 +178,28 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
{
matrix: [
{
- VAR_1: [1],
- VAR_2: [2, 3]
+ VAR_1: ['A'],
+ VAR_2: %w[B C]
}
]
}
end
- let(:expanded_job_names) do
- [
- 'rspec 1/2',
- 'rspec 2/2'
- ]
- end
-
it 'does not have original job' do
is_expected.not_to include(job_name)
end
- it 'has parallelized jobs' do
- is_expected.to include(*expanded_job_names.map(&:to_sym))
- end
-
it 'sets job instance in options' do
expect(subject.values).to all(include(:instance))
end
it 'sets job variables', :aggregate_failures do
expect(subject.values[0]).to match(
- a_hash_including(variables: { VAR_1: 1, VAR_2: 2, USER_VARIABLE: 'user value' })
+ a_hash_including(variables: { VAR_1: 'A', VAR_2: 'B', USER_VARIABLE: 'user value' })
)
expect(subject.values[1]).to match(
- a_hash_including(variables: { VAR_1: 1, VAR_2: 3, USER_VARIABLE: 'user value' })
+ a_hash_including(variables: { VAR_1: 'A', VAR_2: 'C', USER_VARIABLE: 'user value' })
)
end
@@ -226,8 +215,45 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
expect(configs).to all(match(a_hash_including(original_config)))
end
- it_behaves_like 'parallel dependencies'
- it_behaves_like 'parallel needs'
+ context 'with new_matrix_job_names_enabled ff enabled' do
+ let(:expanded_job_names) do
+ [
+ 'rspec: [A, B]',
+ 'rspec: [A, C]'
+ ]
+ end
+
+ before do
+ stub_feature_flags(ci_matrix_job_names: true)
+ end
+
+ it 'has parallelized jobs' do
+ is_expected.to include(*expanded_job_names.map(&:to_sym))
+ end
+
+ it_behaves_like 'parallel dependencies'
+ it_behaves_like 'parallel needs'
+ end
+
+ context 'with new_matrix_job_names_enabled ff disabled' do
+ let(:expanded_job_names) do
+ [
+ 'rspec 1/2',
+ 'rspec 2/2'
+ ]
+ end
+
+ before do
+ stub_feature_flags(ci_matrix_job_names: false)
+ end
+
+ it 'has parallelized jobs' do
+ is_expected.to include(*expanded_job_names.map(&:to_sym))
+ end
+
+ it_behaves_like 'parallel dependencies'
+ it_behaves_like 'parallel needs'
+ end
end
context 'when parallel config does not matches a factory' do
diff --git a/spec/lib/gitlab/ci/status/composite_spec.rb b/spec/lib/gitlab/ci/status/composite_spec.rb
index e1dcd05373f..bcfb9f19792 100644
--- a/spec/lib/gitlab/ci/status/composite_spec.rb
+++ b/spec/lib/gitlab/ci/status/composite_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Ci::Status::Composite do
shared_examples 'compares status and warnings' do
let(:composite_status) do
- described_class.new(all_statuses)
+ described_class.new(all_statuses, dag: dag)
end
it 'returns status and warnings?' do
@@ -30,21 +30,29 @@ RSpec.describe Gitlab::Ci::Status::Composite do
end
context 'allow_failure: false' do
- where(:build_statuses, :result, :has_warnings) do
- %i(skipped) | 'skipped' | false
- %i(skipped success) | 'success' | false
- %i(created) | 'created' | false
- %i(preparing) | 'preparing' | false
- %i(canceled success skipped) | 'canceled' | false
- %i(pending created skipped) | 'pending' | false
- %i(pending created skipped success) | 'running' | false
- %i(running created skipped success) | 'running' | false
- %i(success waiting_for_resource) | 'waiting_for_resource' | false
- %i(success manual) | 'manual' | false
- %i(success scheduled) | 'scheduled' | false
- %i(created preparing) | 'preparing' | false
- %i(created success pending) | 'running' | false
- %i(skipped success failed) | 'failed' | false
+ where(:build_statuses, :dag, :result, :has_warnings) do
+ %i(skipped) | false | 'skipped' | false
+ %i(skipped success) | false | 'success' | false
+ %i(skipped success) | true | 'skipped' | false
+ %i(created) | false | 'created' | false
+ %i(preparing) | false | 'preparing' | false
+ %i(canceled success skipped) | false | 'canceled' | false
+ %i(canceled success skipped) | true | 'skipped' | false
+ %i(pending created skipped) | false | 'pending' | false
+ %i(pending created skipped success) | false | 'running' | false
+ %i(running created skipped success) | false | 'running' | false
+ %i(pending created skipped) | true | 'skipped' | false
+ %i(pending created skipped success) | true | 'skipped' | false
+ %i(running created skipped success) | true | 'skipped' | false
+ %i(success waiting_for_resource) | false | 'waiting_for_resource' | false
+ %i(success manual) | false | 'manual' | false
+ %i(success scheduled) | false | 'scheduled' | false
+ %i(created preparing) | false | 'preparing' | false
+ %i(created success pending) | false | 'running' | false
+ %i(skipped success failed) | false | 'failed' | false
+ %i(skipped success failed) | true | 'skipped' | false
+ %i(success manual) | true | 'pending' | false
+ %i(success failed created) | true | 'pending' | false
end
with_them do
@@ -57,11 +65,12 @@ RSpec.describe Gitlab::Ci::Status::Composite do
end
context 'allow_failure: true' do
- where(:build_statuses, :result, :has_warnings) do
- %i(manual) | 'skipped' | false
- %i(skipped failed) | 'success' | true
- %i(created failed) | 'created' | true
- %i(preparing manual) | 'preparing' | false
+ where(:build_statuses, :dag, :result, :has_warnings) do
+ %i(manual) | false | 'skipped' | false
+ %i(skipped failed) | false | 'success' | true
+ %i(skipped failed) | true | 'skipped' | true
+ %i(created failed) | false | 'created' | true
+ %i(preparing manual) | false | 'preparing' | false
end
with_them do
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 4bbb64c8e4a..b3074f3655e 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -194,6 +194,45 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
)
end
+ it 'includes project imports usage data' do
+ for_defined_days_back do
+ user = create(:user)
+
+ %w(gitlab_project gitlab github bitbucket bitbucket_server gitea git manifest).each do |type|
+ create(:project, import_type: type, creator_id: user.id)
+ end
+ end
+
+ expect(described_class.usage_activity_by_stage_manage({})).to include(
+ {
+ projects_imported: {
+ gitlab_project: 2,
+ gitlab: 2,
+ github: 2,
+ bitbucket: 2,
+ bitbucket_server: 2,
+ gitea: 2,
+ git: 2,
+ manifest: 2
+ }
+ }
+ )
+ expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ {
+ projects_imported: {
+ gitlab_project: 1,
+ gitlab: 1,
+ github: 1,
+ bitbucket: 1,
+ bitbucket_server: 1,
+ gitea: 1,
+ git: 1,
+ manifest: 1
+ }
+ }
+ )
+ end
+
def omniauth_providers
[
OpenStruct.new(name: 'google_oauth2'),
@@ -417,6 +456,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:project_snippets]).to eq(4)
expect(count_data[:projects_with_packages]).to eq(2)
+ expect(count_data[:packages]).to eq(3)
end
it 'gathers object store usage correctly' do
@@ -1020,6 +1060,32 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
+ describe '.search_unique_visits_data' do
+ subject { described_class.search_unique_visits_data }
+
+ before do
+ described_class.clear_memoization(:unique_visit_service)
+ events = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('search')
+ events.each do |event|
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).with(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current).and_return(123)
+ end
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).with(event_names: events, start_date: 7.days.ago.to_date, end_date: Date.current).and_return(543)
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).with(event_names: events, start_date: 4.weeks.ago.to_date, end_date: Date.current).and_return(987)
+ end
+
+ it 'returns the number of unique visits to pages with search features' do
+ expect(subject).to eq({
+ search_unique_visits: {
+ 'i_search_total' => 123,
+ 'i_search_advanced' => 123,
+ 'i_search_paid' => 123,
+ 'search_unique_visits_for_any_target_weekly' => 543,
+ 'search_unique_visits_for_any_target_monthly' => 987
+ }
+ })
+ end
+ end
+
describe '.service_desk_counts' do
subject { described_class.send(:service_desk_counts) }
diff --git a/spec/requests/projects/metrics_dashboard_spec.rb b/spec/requests/projects/metrics_dashboard_spec.rb
index f571e4a4309..f35af571e79 100644
--- a/spec/requests/projects/metrics_dashboard_spec.rb
+++ b/spec/requests/projects/metrics_dashboard_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'metrics dashboard page' do
+RSpec.describe 'Projects::MetricsDashboardController' do
let_it_be(:project) { create(:project) }
let_it_be(:environment) { create(:environment, project: project) }
let_it_be(:environment2) { create(:environment, project: project) }
@@ -16,12 +16,12 @@ RSpec.describe 'metrics dashboard page' do
describe 'GET /:namespace/:project/-/metrics' do
it 'returns 200' do
send_request
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to redirect_to(dashboard_route(environment: environment))
end
- it 'assigns environment' do
+ it 'assigns default_environment' do
send_request
- expect(assigns(:environment).id).to eq(environment.id)
+ expect(assigns(:default_environment).id).to eq(environment.id)
end
context 'with anonymous user and public dashboard visibility' do
@@ -64,12 +64,12 @@ RSpec.describe 'metrics dashboard page' do
let(:dashboard_path) { '.gitlab/dashboards/dashboard_path.yml' }
it 'returns 200' do
- send_request(dashboard_path: dashboard_path)
+ send_request(dashboard_path: dashboard_path, environment: environment.id)
expect(response).to have_gitlab_http_status(:ok)
end
it 'assigns environment' do
- send_request(dashboard_path: dashboard_path)
+ send_request(dashboard_path: dashboard_path, environment: environment.id)
expect(assigns(:environment).id).to eq(environment.id)
end
end
@@ -98,14 +98,14 @@ RSpec.describe 'metrics dashboard page' do
describe 'GET :/namespace/:project/-/metrics/:page' do
it 'returns 200 with path param page' do
# send_request(page: 'panel/new') cannot be used because it encodes '/'
- get "#{dashboard_route}/panel/new"
+ get "#{dashboard_route}/panel/new?environment=#{environment.id}"
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns 200 with dashboard and path param page' do
# send_request(page: 'panel/new') cannot be used because it encodes '/'
- get "#{dashboard_route(dashboard_path: 'dashboard.yml')}/panel/new"
+ get "#{dashboard_route(dashboard_path: 'dashboard.yml')}/panel/new?environment=#{environment.id}"
expect(response).to have_gitlab_http_status(:ok)
end
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml
index a133023b12d..ef4ddff9b64 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml
@@ -47,16 +47,13 @@ transitions:
- event: drop
jobs: [build_2]
expect:
- pipeline: running
+ pipeline: failed
stages:
build: failed
test: skipped
- deploy: pending
+ deploy: skipped
jobs:
build_1: success
build_2: failed
test: skipped
- deploy: pending
-
-# TODO: should we run deploy?
-# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml
index f324525bd56..29c1562389c 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml
@@ -34,30 +34,13 @@ transitions:
- event: success
jobs: [build_1, build_2]
expect:
- pipeline: running
- stages:
- build: success
- test: skipped
- deploy: pending
- jobs:
- build_1: success
- build_2: success
- test: skipped
- deploy: pending
-
- - event: success
- jobs: [deploy]
- expect:
pipeline: success
stages:
build: success
test: skipped
- deploy: success
+ deploy: skipped
jobs:
build_1: success
build_2: success
test: skipped
- deploy: success
-
-# TODO: should we run deploy?
-# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
+ deploy: skipped
diff --git a/spec/support/shared_examples/controllers/unique_hll_events_examples.rb b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
new file mode 100644
index 00000000000..ff86d44f5e8
--- /dev/null
+++ b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'tracking unique hll events' do |method|
+ it 'tracks unique event if the format is HTML' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(instance_of(String), target_id)
+
+ get method, params: request_params, format: :html
+ end
+
+ it 'tracks unique event if DNT is not enabled' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(instance_of(String), target_id)
+ request.headers['DNT'] = '0'
+
+ get method, params: request_params, format: :html
+ end
+
+ it 'does not track unique event if DNT is enabled' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(instance_of(String), target_id)
+ request.headers['DNT'] = '1'
+
+ get method, params: request_params, format: :html
+ end
+
+ it 'does not track unique event if the format is JSON' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(instance_of(String), target_id)
+
+ get method, params: request_params, format: :json
+ end
+end
diff --git a/spec/support/shared_examples/path_extraction_shared_examples.rb b/spec/support/shared_examples/path_extraction_shared_examples.rb
index ff55bc9a490..39c7c1f2a94 100644
--- a/spec/support/shared_examples/path_extraction_shared_examples.rb
+++ b/spec/support/shared_examples/path_extraction_shared_examples.rb
@@ -146,20 +146,6 @@ RSpec.shared_examples 'extracts refs' do
expect(extract_ref('release/app/doc/README.md')).to eq(['release/app', 'doc/README.md'])
end
-
- context 'when the extracts_path_optimization feature flag is disabled' do
- before do
- stub_feature_flags(extracts_path_optimization: false)
- end
-
- it 'always fetches all ref names' do
- expect(self).to receive(:ref_names).and_call_original
- expect(container.repository).not_to receive(:branch_names_include?)
- expect(container.repository).not_to receive(:tag_names_include?)
-
- expect(extract_ref('v1.0.0/doc/README.md')).to eq(['v1.0.0', 'doc/README.md'])
- end
- end
end
context 'when the repository has ambiguous refs' do
diff --git a/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb b/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb
index 1ef08de31a9..7608f1c7f8a 100644
--- a/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb
+++ b/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb
@@ -57,16 +57,6 @@ RSpec.shared_examples 'diff file entity' do
expect(subject).to include(:highlighted_diff_lines)
end
end
-
- context 'when the `single_mr_diff_view` feature is disabled' do
- before do
- stub_feature_flags(single_mr_diff_view: false)
- end
-
- it 'contains both kinds of diffs' do
- expect(subject).to include(:highlighted_diff_lines, :parallel_diff_lines)
- end
- end
end
end
diff --git a/yarn.lock b/yarn.lock
index 93d7859acbd..50dbab0db5b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -848,10 +848,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.161.0.tgz#661e8d19862dfba0e4c558e2eb6d64b402c1453e"
integrity sha512-qsbboEICn08ZoEoAX/TuYygsFaXlzsCY+CfmdOzqvJbOdfHhVXmrJBxd2hP2qqjTZm2PkbRRmn+03+ce1jvatQ==
-"@gitlab/ui@20.10.0":
- version "20.10.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.10.0.tgz#5efdb5394d7cc8c95ce4bc5ec5b85d33e15b41d6"
- integrity sha512-A6SDIZb7Vgj+k5iYKNLMYOp61bWFhjtsab2u3Z32sgx7GkOIZo5dB9ILJHBlLvZ5oOfQ/7Ch+3FmhGxsDjRIuQ==
+"@gitlab/ui@20.11.0":
+ version "20.11.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.11.0.tgz#6570ca518195b05e14861df5ea6a319d4dbe2298"
+ integrity sha512-vFR/xFx/D7ndRDDoqHQ8GH/YU4lCE3P3eXR3mlpNIMxgak3MuS9w9tfu78z4fRT6gTWuBZEkeoZnjZBgQewqKQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"