Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f52c68bbac
commit
bb6a3bf05e
|
|
@ -1653,7 +1653,6 @@ RSpec/MissingFeatureCategory:
|
|||
- 'ee/spec/services/arkose/blocked_users_report_service_spec.rb'
|
||||
- 'ee/spec/services/arkose/record_user_data_service_spec.rb'
|
||||
- 'ee/spec/services/arkose/token_verification_service_spec.rb'
|
||||
- 'ee/spec/services/audit_event_service_spec.rb'
|
||||
- 'ee/spec/services/audit_events/build_service_spec.rb'
|
||||
- 'ee/spec/services/audit_events/custom_audit_event_service_spec.rb'
|
||||
- 'ee/spec/services/audit_events/impersonation_audit_event_service_spec.rb'
|
||||
|
|
@ -1676,7 +1675,6 @@ RSpec/MissingFeatureCategory:
|
|||
- 'ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
|
||||
- 'ee/spec/services/award_emojis/add_service_spec.rb'
|
||||
- 'ee/spec/services/award_emojis/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/base_count_service_spec.rb'
|
||||
- 'ee/spec/services/billable_members/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/boards/create_service_spec.rb'
|
||||
- 'ee/spec/services/boards/epic_boards/create_service_spec.rb'
|
||||
|
|
@ -1695,28 +1693,11 @@ RSpec/MissingFeatureCategory:
|
|||
- 'ee/spec/services/boards/update_service_spec.rb'
|
||||
- 'ee/spec/services/boards/user_preferences/update_service_spec.rb'
|
||||
- 'ee/spec/services/branches/delete_service_spec.rb'
|
||||
- 'ee/spec/services/ee/auto_merge_service_spec.rb'
|
||||
- 'ee/spec/services/ee/event_create_service_spec.rb'
|
||||
- 'ee/spec/services/ee/merge_request_metrics_service_spec.rb'
|
||||
- 'ee/spec/services/ee/notes/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/ee/notes/post_process_service_spec.rb'
|
||||
- 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
|
||||
- 'ee/spec/services/ee/notes/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/null_notification_service_spec.rb'
|
||||
- 'ee/spec/services/ee/post_receive_service_spec.rb'
|
||||
- 'ee/spec/services/ee/preview_markdown_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/approve_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/authorized_build_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/block_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/build_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/create_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/migrate_records_to_ghost_user_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/reject_service_spec.rb'
|
||||
- 'ee/spec/services/ee/users/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/vulnerability_feedback_module/update_service_spec.rb'
|
||||
- 'ee/spec/services/external_status_checks/create_service_spec.rb'
|
||||
- 'ee/spec/services/ldap_group_reset_service_spec.rb'
|
||||
- 'ee/spec/services/projects/after_rename_service_spec.rb'
|
||||
- 'ee/spec/services/projects/alerting/notify_service_spec.rb'
|
||||
- 'ee/spec/services/projects/cleanup_service_spec.rb'
|
||||
|
|
@ -1756,33 +1737,7 @@ RSpec/MissingFeatureCategory:
|
|||
- 'ee/spec/services/requirements_management/process_test_reports_service_spec.rb'
|
||||
- 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
|
||||
- 'ee/spec/services/resource_access_tokens/revoke_service_spec.rb'
|
||||
- 'ee/spec/services/start_pull_mirroring_service_spec.rb'
|
||||
- 'ee/spec/services/system_note_service_spec.rb'
|
||||
- 'ee/spec/services/timebox_report_service_spec.rb'
|
||||
- 'ee/spec/services/todo_service_spec.rb'
|
||||
- 'ee/spec/services/users/abuse/namespace_bans/create_service_spec.rb'
|
||||
- 'ee/spec/services/users/abuse/namespace_bans/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/users/abuse/projects_download_ban_check_service_spec.rb'
|
||||
- 'ee/spec/services/users/captcha_challenge_service_spec.rb'
|
||||
- 'ee/spec/services/users/update_highest_member_role_service_spec.rb'
|
||||
- 'ee/spec/services/users_ops_dashboard_projects/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_exports/create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_external_issue_links/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_feedback/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_issue_links/create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_issue_links/delete_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_merge_request_links/create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_scanners/list_service_spec.rb'
|
||||
- 'ee/spec/services/web_hook_service_spec.rb'
|
||||
- 'ee/spec/services/wiki_pages/create_service_spec.rb'
|
||||
- 'ee/spec/services/wiki_pages/destroy_service_spec.rb'
|
||||
- 'ee/spec/services/wiki_pages/update_service_spec.rb'
|
||||
- 'ee/spec/services/wikis/create_attachment_service_spec.rb'
|
||||
- 'ee/spec/services/work_items/update_service_spec.rb'
|
||||
- 'ee/spec/services/work_items/widgets/status_service/update_service_spec.rb'
|
||||
- 'ee/spec/services/work_items/widgets/weight_service/update_service_spec.rb'
|
||||
- 'ee/spec/tasks/geo/git_rake_spec.rb'
|
||||
- 'ee/spec/tasks/gitlab/license_rake_spec.rb'
|
||||
- 'ee/spec/tasks/gitlab/spdx_rake_spec.rb'
|
||||
|
|
@ -6096,120 +6051,10 @@ RSpec/MissingFeatureCategory:
|
|||
- 'spec/serializers/user_serializer_spec.rb'
|
||||
- 'spec/serializers/web_ide_terminal_entity_spec.rb'
|
||||
- 'spec/serializers/web_ide_terminal_serializer_spec.rb'
|
||||
- 'spec/services/access_token_validation_service_spec.rb'
|
||||
- 'spec/services/application_settings/update_service_spec.rb'
|
||||
- 'spec/services/applications/create_service_spec.rb'
|
||||
- 'spec/services/audit_event_service_spec.rb'
|
||||
- 'spec/services/auto_merge_service_spec.rb'
|
||||
- 'spec/services/base_container_service_spec.rb'
|
||||
- 'spec/services/base_count_service_spec.rb'
|
||||
- 'spec/services/bulk_create_integration_service_spec.rb'
|
||||
- 'spec/services/bulk_push_event_payload_service_spec.rb'
|
||||
- 'spec/services/bulk_update_integration_service_spec.rb'
|
||||
- 'spec/services/cohorts_service_spec.rb'
|
||||
- 'spec/services/compare_service_spec.rb'
|
||||
- 'spec/services/event_create_service_spec.rb'
|
||||
- 'spec/services/gpg_keys/destroy_service_spec.rb'
|
||||
- 'spec/services/gravatar_service_spec.rb'
|
||||
- 'spec/services/import_export_clean_up_service_spec.rb'
|
||||
- 'spec/services/markdown_content_rewriter_service_spec.rb'
|
||||
- 'spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb'
|
||||
- 'spec/services/note_summary_spec.rb'
|
||||
- 'spec/services/post_receive_service_spec.rb'
|
||||
- 'spec/services/preview_markdown_service_spec.rb'
|
||||
- 'spec/services/push_event_payload_service_spec.rb'
|
||||
- 'spec/services/repository_archive_clean_up_service_spec.rb'
|
||||
- 'spec/services/reset_project_cache_service_spec.rb'
|
||||
- 'spec/services/service_response_spec.rb'
|
||||
- 'spec/services/system_hooks_service_spec.rb'
|
||||
- 'spec/services/task_list_toggle_service_spec.rb'
|
||||
- 'spec/services/tasks_to_be_done/base_service_spec.rb'
|
||||
- 'spec/services/terraform/remote_state_handler_spec.rb'
|
||||
- 'spec/services/terraform/states/destroy_service_spec.rb'
|
||||
- 'spec/services/terraform/states/trigger_destroy_service_spec.rb'
|
||||
- 'spec/services/test_hooks/project_service_spec.rb'
|
||||
- 'spec/services/test_hooks/system_service_spec.rb'
|
||||
- 'spec/services/timelogs/delete_service_spec.rb'
|
||||
- 'spec/services/todo_service_spec.rb'
|
||||
- 'spec/services/todos/allowed_target_filter_service_spec.rb'
|
||||
- 'spec/services/todos/destroy/confidential_issue_service_spec.rb'
|
||||
- 'spec/services/todos/destroy/design_service_spec.rb'
|
||||
- 'spec/services/todos/destroy/destroyed_issuable_service_spec.rb'
|
||||
- 'spec/services/todos/destroy/project_private_service_spec.rb'
|
||||
- 'spec/services/todos/destroy/unauthorized_features_service_spec.rb'
|
||||
- 'spec/services/topics/merge_service_spec.rb'
|
||||
- 'spec/services/two_factor/destroy_service_spec.rb'
|
||||
- 'spec/services/update_container_registry_info_service_spec.rb'
|
||||
- 'spec/services/update_merge_request_metrics_service_spec.rb'
|
||||
- 'spec/services/upload_service_spec.rb'
|
||||
- 'spec/services/uploads/destroy_service_spec.rb'
|
||||
- 'spec/services/user_preferences/update_service_spec.rb'
|
||||
- 'spec/services/users/activity_service_spec.rb'
|
||||
- 'spec/services/users/approve_service_spec.rb'
|
||||
- 'spec/services/users/authorized_build_service_spec.rb'
|
||||
- 'spec/services/users/ban_service_spec.rb'
|
||||
- 'spec/services/users/banned_user_base_service_spec.rb'
|
||||
- 'spec/services/users/batch_status_cleaner_service_spec.rb'
|
||||
- 'spec/services/users/block_service_spec.rb'
|
||||
- 'spec/services/users/build_service_spec.rb'
|
||||
- 'spec/services/users/create_service_spec.rb'
|
||||
- 'spec/services/users/destroy_service_spec.rb'
|
||||
- 'spec/services/users/dismiss_callout_service_spec.rb'
|
||||
- 'spec/services/users/dismiss_group_callout_service_spec.rb'
|
||||
- 'spec/services/users/dismiss_project_callout_service_spec.rb'
|
||||
- 'spec/services/users/email_verification/generate_token_service_spec.rb'
|
||||
- 'spec/services/users/email_verification/validate_token_service_spec.rb'
|
||||
- 'spec/services/users/in_product_marketing_email_records_spec.rb'
|
||||
- 'spec/services/users/keys_count_service_spec.rb'
|
||||
- 'spec/services/users/last_push_event_service_spec.rb'
|
||||
- 'spec/services/users/migrate_records_to_ghost_user_in_batches_service_spec.rb'
|
||||
- 'spec/services/users/migrate_records_to_ghost_user_service_spec.rb'
|
||||
- 'spec/services/users/refresh_authorized_projects_service_spec.rb'
|
||||
- 'spec/services/users/registrations_build_service_spec.rb'
|
||||
- 'spec/services/users/reject_service_spec.rb'
|
||||
- 'spec/services/users/repair_ldap_blocked_service_spec.rb'
|
||||
- 'spec/services/users/respond_to_terms_service_spec.rb'
|
||||
- 'spec/services/users/saved_replies/create_service_spec.rb'
|
||||
- 'spec/services/users/saved_replies/destroy_service_spec.rb'
|
||||
- 'spec/services/users/saved_replies/update_service_spec.rb'
|
||||
- 'spec/services/users/set_status_service_spec.rb'
|
||||
- 'spec/services/users/signup_service_spec.rb'
|
||||
- 'spec/services/users/unban_service_spec.rb'
|
||||
- 'spec/services/users/unblock_service_spec.rb'
|
||||
- 'spec/services/users/update_canonical_email_service_spec.rb'
|
||||
- 'spec/services/users/update_highest_member_role_service_spec.rb'
|
||||
- 'spec/services/users/update_service_spec.rb'
|
||||
- 'spec/services/users/update_todo_count_cache_service_spec.rb'
|
||||
- 'spec/services/users/upsert_credit_card_validation_service_spec.rb'
|
||||
- 'spec/services/users/validate_manual_otp_service_spec.rb'
|
||||
- 'spec/services/users/validate_push_otp_service_spec.rb'
|
||||
- 'spec/services/verify_pages_domain_service_spec.rb'
|
||||
- 'spec/services/web_hooks/destroy_service_spec.rb'
|
||||
- 'spec/services/web_hooks/log_destroy_service_spec.rb'
|
||||
- 'spec/services/web_hooks/log_execution_service_spec.rb'
|
||||
- 'spec/services/webauthn/authenticate_service_spec.rb'
|
||||
- 'spec/services/webauthn/register_service_spec.rb'
|
||||
- 'spec/services/wiki_pages/base_service_spec.rb'
|
||||
- 'spec/services/wiki_pages/create_service_spec.rb'
|
||||
- 'spec/services/wiki_pages/destroy_service_spec.rb'
|
||||
- 'spec/services/wiki_pages/event_create_service_spec.rb'
|
||||
- 'spec/services/wiki_pages/update_service_spec.rb'
|
||||
- 'spec/services/wikis/create_attachment_service_spec.rb'
|
||||
- 'spec/services/work_items/build_service_spec.rb'
|
||||
- 'spec/services/work_items/create_from_task_service_spec.rb'
|
||||
- 'spec/services/work_items/create_service_spec.rb'
|
||||
- 'spec/services/work_items/delete_service_spec.rb'
|
||||
- 'spec/services/work_items/delete_task_service_spec.rb'
|
||||
- 'spec/services/work_items/parent_links/destroy_service_spec.rb'
|
||||
- 'spec/services/work_items/task_list_reference_removal_service_spec.rb'
|
||||
- 'spec/services/work_items/task_list_reference_replacement_service_spec.rb'
|
||||
- 'spec/services/work_items/update_service_spec.rb'
|
||||
- 'spec/services/work_items/widgets/assignees_service/update_service_spec.rb'
|
||||
- 'spec/services/work_items/widgets/description_service/update_service_spec.rb'
|
||||
- 'spec/services/work_items/widgets/milestone_service/create_service_spec.rb'
|
||||
- 'spec/services/work_items/widgets/milestone_service/update_service_spec.rb'
|
||||
- 'spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb'
|
||||
- 'spec/services/x509_certificate_revoke_service_spec.rb'
|
||||
- 'spec/sidekiq/cron/job_gem_dependency_spec.rb'
|
||||
- 'spec/sidekiq_cluster/sidekiq_cluster_spec.rb'
|
||||
- 'spec/spam/concerns/has_spam_action_response_fields_spec.rb'
|
||||
|
|
|
|||
|
|
@ -1,25 +1,19 @@
|
|||
import Vue from 'vue';
|
||||
import { darkModeEnabled } from '~/lib/utils/color_utils';
|
||||
import { setUrlParams } from '~/lib/utils/url_utility';
|
||||
|
||||
export function getFrameSrc(url) {
|
||||
return `${setUrlParams({ theme: darkModeEnabled() ? 'dark' : 'light' }, url)}&kiosk=inline-embed`;
|
||||
}
|
||||
import ObservabilityApp from '~/observability/components/observability_app.vue';
|
||||
import { SKELETON_VARIANT_EMBED, INLINE_EMBED_DIMENSIONS } from '~/observability/constants';
|
||||
|
||||
const mountVueComponent = (element) => {
|
||||
const url = [element.dataset.frameUrl];
|
||||
|
||||
const url = element.dataset.frameUrl;
|
||||
return new Vue({
|
||||
el: element,
|
||||
render(h) {
|
||||
return h('iframe', {
|
||||
style: {
|
||||
height: '366px',
|
||||
width: '768px',
|
||||
},
|
||||
attrs: {
|
||||
src: getFrameSrc(url),
|
||||
frameBorder: '0',
|
||||
return h(ObservabilityApp, {
|
||||
props: {
|
||||
observabilityIframeSrc: url,
|
||||
inlineEmbed: true,
|
||||
skeletonVariant: SKELETON_VARIANT_EMBED,
|
||||
height: INLINE_EMBED_DIMENSIONS.HEIGHT,
|
||||
width: INLINE_EMBED_DIMENSIONS.WIDTH,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
@ -27,7 +21,5 @@ const mountVueComponent = (element) => {
|
|||
};
|
||||
|
||||
export default function renderObservability(elements) {
|
||||
elements.forEach((element) => {
|
||||
mountVueComponent(element);
|
||||
});
|
||||
return elements.map(mountVueComponent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,10 +102,10 @@ export default {
|
|||
'issuable-info-container': !canReorder,
|
||||
'card-body': canReorder,
|
||||
}"
|
||||
class="item-body gl-display-flex gl-align-items-center gl-gap-3 gl-px-3 gl-py-2 py-xl-0 gl-mx-n2"
|
||||
class="item-body gl-display-flex gl-align-items-center gl-gap-3 gl-mx-n2"
|
||||
>
|
||||
<div
|
||||
class="item-contents gl-display-flex gl-align-items-center gl-flex-wrap gl-flex-grow-1 gl-gap-2 flex-xl-nowrap gl-min-h-7"
|
||||
class="item-contents gl-display-flex gl-align-items-center gl-flex-wrap gl-flex-grow-1 gl-gap-2 gl-px-3 gl-py-2 py-xl-0 flex-xl-nowrap gl-min-h-7"
|
||||
>
|
||||
<!-- Title area: Status icon (XL) and title -->
|
||||
<div class="item-title gl-display-flex gl-gap-3 gl-min-w-0">
|
||||
|
|
|
|||
|
|
@ -96,8 +96,12 @@ export default {
|
|||
label="Fetching related merge requests"
|
||||
class="gl-py-4"
|
||||
/>
|
||||
<ul v-else class="content-list related-items-list">
|
||||
<li v-for="mr in mergeRequests" :key="mr.id" class="list-item gl-m-0! gl-px-4! gl-py-3!">
|
||||
<ul v-else class="content-list related-items-list gl-px-4! gl-py-3!">
|
||||
<li
|
||||
v-for="mr in mergeRequests"
|
||||
:key="mr.id"
|
||||
class="list-item gl-m-0! gl-p-0! gl-border-b-0!"
|
||||
>
|
||||
<related-issuable-item
|
||||
:id-key="mr.id"
|
||||
:display-reference="mr.reference"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { darkModeEnabled } from '~/lib/utils/color_utils';
|
||||
import { setUrlParams } from '~/lib/utils/url_utility';
|
||||
|
||||
import { MESSAGE_EVENT_TYPE, SKELETON_VARIANTS_BY_ROUTE } from '../constants';
|
||||
import { MESSAGE_EVENT_TYPE, FULL_APP_DIMENSIONS } from '../constants';
|
||||
import ObservabilitySkeleton from './skeleton/index.vue';
|
||||
|
||||
export default {
|
||||
|
|
@ -14,25 +14,33 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
inlineEmbed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
skeletonVariant: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'dashboards',
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: FULL_APP_DIMENSIONS.HEIGHT,
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: FULL_APP_DIMENSIONS.WIDTH,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
iframeSrcWithParams() {
|
||||
return setUrlParams(
|
||||
return `${setUrlParams(
|
||||
{ theme: darkModeEnabled() ? 'dark' : 'light', username: gon?.current_username },
|
||||
this.observabilityIframeSrc,
|
||||
);
|
||||
},
|
||||
getSkeletonVariant() {
|
||||
const [, variant] =
|
||||
Object.entries(SKELETON_VARIANTS_BY_ROUTE).find(([path]) =>
|
||||
this.$route.path.endsWith(path),
|
||||
) || [];
|
||||
|
||||
const DEFAULT_SKELETON = 'dashboards';
|
||||
|
||||
if (!variant) return DEFAULT_SKELETON;
|
||||
|
||||
return variant;
|
||||
)}${this.inlineEmbed ? '&kiosk=inline-embed' : ''}`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -54,38 +62,24 @@ export default {
|
|||
this.$refs.observabilitySkeleton.onContentLoaded();
|
||||
break;
|
||||
case MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE:
|
||||
this.routeUpdateHandler(payload);
|
||||
this.$emit('route-update', payload);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
routeUpdateHandler(payload) {
|
||||
const isNewObservabilityPath = this.$route?.query?.observability_path !== payload?.url;
|
||||
|
||||
const shouldNotHandleMessage = !payload.url || !isNewObservabilityPath;
|
||||
|
||||
if (shouldNotHandleMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this will update the `observability_path` query param on each route change inside Observability UI
|
||||
this.$router.replace({
|
||||
name: this.$route.pathname,
|
||||
query: { ...this.$route.query, observability_path: payload.url },
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<observability-skeleton ref="observabilitySkeleton" :variant="getSkeletonVariant">
|
||||
<observability-skeleton ref="observabilitySkeleton" :variant="skeletonVariant">
|
||||
<iframe
|
||||
id="observability-ui-iframe"
|
||||
data-testid="observability-ui-iframe"
|
||||
frameborder="0"
|
||||
height="100%"
|
||||
:width="width"
|
||||
:height="height"
|
||||
:src="iframeSrcWithParams"
|
||||
sandbox="allow-same-origin allow-forms allow-scripts"
|
||||
></iframe>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<script>
|
||||
import { GlSkeletonLoader } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlSkeletonLoader,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-skeleton-loader>
|
||||
<rect y="5" width="400" height="30" rx="2" ry="2" />
|
||||
<rect y="50" width="400" height="80" rx="2" ry="2" />
|
||||
</gl-skeleton-loader>
|
||||
</template>
|
||||
|
|
@ -8,10 +8,12 @@ import {
|
|||
OBSERVABILITY_ROUTES,
|
||||
TIMEOUT_ERROR_LABEL,
|
||||
TIMEOUT_ERROR_MESSAGE,
|
||||
SKELETON_VARIANT_EMBED,
|
||||
} from '../../constants';
|
||||
import DashboardsSkeleton from './dashboards.vue';
|
||||
import ExploreSkeleton from './explore.vue';
|
||||
import ManageSkeleton from './manage.vue';
|
||||
import EmbedSkeleton from './embed.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -19,11 +21,13 @@ export default {
|
|||
DashboardsSkeleton,
|
||||
ExploreSkeleton,
|
||||
ManageSkeleton,
|
||||
EmbedSkeleton,
|
||||
GlAlert,
|
||||
},
|
||||
SKELETON_VARIANTS_BY_ROUTE,
|
||||
SKELETON_STATE,
|
||||
OBSERVABILITY_ROUTES,
|
||||
SKELETON_VARIANT_EMBED,
|
||||
i18n: {
|
||||
TIMEOUT_ERROR_LABEL,
|
||||
TIMEOUT_ERROR_MESSAGE,
|
||||
|
|
@ -102,6 +106,7 @@ export default {
|
|||
<dashboards-skeleton v-if="isSkeletonShown($options.OBSERVABILITY_ROUTES.DASHBOARDS)" />
|
||||
<explore-skeleton v-else-if="isSkeletonShown($options.OBSERVABILITY_ROUTES.EXPLORE)" />
|
||||
<manage-skeleton v-else-if="isSkeletonShown($options.OBSERVABILITY_ROUTES.MANAGE)" />
|
||||
<embed-skeleton v-else-if="variant === $options.SKELETON_VARIANT_EMBED" />
|
||||
|
||||
<gl-skeleton-loader v-else>
|
||||
<rect y="2" width="10" height="8" />
|
||||
|
|
@ -122,12 +127,14 @@ export default {
|
|||
{{ $options.i18n.TIMEOUT_ERROR_MESSAGE }}
|
||||
</gl-alert>
|
||||
|
||||
<div
|
||||
v-show="state === $options.SKELETON_STATE.HIDDEN"
|
||||
data-testid="observability-wrapper"
|
||||
class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-flex-align-items-stretch"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<transition>
|
||||
<div
|
||||
v-show="state === $options.SKELETON_STATE.HIDDEN"
|
||||
data-testid="observability-wrapper"
|
||||
class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-flex-align-items-stretch"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ export const SKELETON_VARIANTS_BY_ROUTE = Object.freeze({
|
|||
[OBSERVABILITY_ROUTES.MANAGE]: 'manage',
|
||||
});
|
||||
|
||||
export const SKELETON_VARIANT_EMBED = 'embed';
|
||||
|
||||
export const SKELETON_STATE = Object.freeze({
|
||||
ERROR: 'error',
|
||||
VISIBLE: 'visible',
|
||||
|
|
@ -30,3 +32,13 @@ export const DEFAULT_TIMERS = Object.freeze({
|
|||
|
||||
export const TIMEOUT_ERROR_LABEL = __('Unable to load the page');
|
||||
export const TIMEOUT_ERROR_MESSAGE = __('Reload the page to try again.');
|
||||
|
||||
export const INLINE_EMBED_DIMENSIONS = Object.freeze({
|
||||
HEIGHT: '366px',
|
||||
WIDTH: '768px',
|
||||
});
|
||||
|
||||
export const FULL_APP_DIMENSIONS = Object.freeze({
|
||||
HEIGHT: '100%',
|
||||
WIDTH: '100%',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import Vue from 'vue';
|
|||
import VueRouter from 'vue-router';
|
||||
|
||||
import ObservabilityApp from './components/observability_app.vue';
|
||||
import { SKELETON_VARIANTS_BY_ROUTE } from './constants';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
|
|
@ -17,10 +18,41 @@ export default () => {
|
|||
return new Vue({
|
||||
el,
|
||||
router,
|
||||
computed: {
|
||||
skeletonVariant() {
|
||||
const [, variant] =
|
||||
Object.entries(SKELETON_VARIANTS_BY_ROUTE).find(([path]) =>
|
||||
this.$route.path.endsWith(path),
|
||||
) || [];
|
||||
|
||||
return variant;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
routeUpdateHandler(payload) {
|
||||
const isNewObservabilityPath = this.$route?.query?.observability_path !== payload?.url;
|
||||
|
||||
const shouldNotHandleMessage = !payload.url || !isNewObservabilityPath;
|
||||
|
||||
if (shouldNotHandleMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this will update the `observability_path` query param on each route change inside Observability UI
|
||||
this.$router.replace({
|
||||
name: this.$route?.pathname,
|
||||
query: { ...this.$route.query, observability_path: payload.url },
|
||||
});
|
||||
},
|
||||
},
|
||||
render(h) {
|
||||
return h(ObservabilityApp, {
|
||||
props: {
|
||||
observabilityIframeSrc: el.dataset.observabilityIframeSrc,
|
||||
skeletonVariant: this.skeletonVariant,
|
||||
},
|
||||
on: {
|
||||
'route-update': (payload) => this.routeUpdateHandler(payload),
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -159,6 +159,11 @@ $item-remove-button-space: 42px;
|
|||
|
||||
.mr-ci-status {
|
||||
line-height: 0;
|
||||
|
||||
a:focus {
|
||||
@include gl-rounded-full;
|
||||
@include gl-focus;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xs) {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ module Types
|
|||
description 'Values for sorting projects'
|
||||
|
||||
value 'SIMILARITY', 'Most similar to the search query.', value: :similarity
|
||||
value 'STORAGE', 'Sort by storage size.', value: :storage
|
||||
value 'ACTIVITY_DESC', 'Sort by latest activity, in descending order.', value: :latest_activity_desc
|
||||
value 'ACTIVITY_DESC', 'Sort by latest activity, descending order.', value: :latest_activity_desc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Types::Projects::NamespaceProjectSortEnum.prepend_mod
|
||||
|
|
|
|||
|
|
@ -13,4 +13,5 @@
|
|||
help_text: '%{help_text} %{learn_more_link}'.html_safe % { help_text: help_text, learn_more_link: learn_more_link },
|
||||
checkbox_options: { checked: group.auto_devops_enabled? }
|
||||
|
||||
= f.submit _('Save changes'), class: 'gl-mt-5', pajamas_button: true
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, button_options: { class: 'gl-mt-5' }) do
|
||||
= _('Save changes')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
table_name: bulk_import_batch_trackers
|
||||
classes: []
|
||||
classes:
|
||||
- BulkImports::BatchTracker
|
||||
feature_categories:
|
||||
- importers
|
||||
description: Used to store and track the import status of a batch of relations for the migration
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
table_name: bulk_import_export_batches
|
||||
classes: []
|
||||
classes:
|
||||
- BulkImports::ExportBatch
|
||||
feature_categories:
|
||||
- importers
|
||||
description: Used to track the generation status of export batch files for groups
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ classes:
|
|||
- Integrations::Shimo
|
||||
- Integrations::Slack
|
||||
- Integrations::SlackSlashCommands
|
||||
- Integrations::SquashTm
|
||||
- Integrations::Teamcity
|
||||
- Integrations::UnifyCircuit
|
||||
- Integrations::WebexTeams
|
||||
|
|
|
|||
|
|
@ -23781,9 +23781,11 @@ Values for sorting projects.
|
|||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="namespaceprojectsortactivity_desc"></a>`ACTIVITY_DESC` | Sort by latest activity, in descending order. |
|
||||
| <a id="namespaceprojectsortactivity_desc"></a>`ACTIVITY_DESC` | Sort by latest activity, descending order. |
|
||||
| <a id="namespaceprojectsortsimilarity"></a>`SIMILARITY` | Most similar to the search query. |
|
||||
| <a id="namespaceprojectsortstorage"></a>`STORAGE` | Sort by storage size. |
|
||||
| <a id="namespaceprojectsortstorage"></a>`STORAGE` | Sort by excess repository storage size, descending order. |
|
||||
| <a id="namespaceprojectsortstorage_size_asc"></a>`STORAGE_SIZE_ASC` | Sort by total storage size, ascending order. |
|
||||
| <a id="namespaceprojectsortstorage_size_desc"></a>`STORAGE_SIZE_DESC` | Sort by total storage size, descending order. |
|
||||
|
||||
### `NegatedIterationWildcardId`
|
||||
|
||||
|
|
|
|||
|
|
@ -630,6 +630,7 @@ The following variables allow configuration of global dependency scanning settin
|
|||
| `DS_EXCLUDED_ANALYZERS` | Specify the analyzers (by name) to exclude from Dependency Scanning. For more information, see [Dependency Scanning Analyzers](analyzers.md). |
|
||||
| `DS_EXCLUDED_PATHS` | Exclude files and directories from the scan based on the paths. A comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. |
|
||||
| `DS_IMAGE_SUFFIX` | Suffix added to the image name. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/354796) in GitLab 14.10.) Automatically set to `"-fips"` when FIPS mode is enabled. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/357922) in GitLab 15.0.) |
|
||||
| `DS_MAX_DEPTH` | Defines how many directory levels deep that the analyzer should search for supported files to scan. A value of `-1` scans all directories regardless of depth. Default: `2`. |
|
||||
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
|
||||
| `SECURE_LOG_LEVEL` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. Default: `info`. |
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
You can use scan result policies to take action based on scan results. For example, one type of scan
|
||||
result policy is a security approval policy that allows approval to be required based on the
|
||||
findings of one or more security scan jobs. Scan result policies are evaluated after a CI scanning
|
||||
job is fully executed. The following video gives you an overview of GitLab scan result policies:
|
||||
findings of one or more security scan jobs. Scan result policies are evaluated after a CI scanning job is fully executed.
|
||||
|
||||
NOTE:
|
||||
Scan result policies are applicable only to [protected](../../project/protected_branches.md) target branches.
|
||||
|
||||
The following video gives you an overview of GitLab scan result policies:
|
||||
|
||||
<div class="video-fallback">
|
||||
See the video: <a href="https://youtu.be/w5I9gcUgr9U">Overview of GitLab Scan Result Policies</a>.
|
||||
|
|
|
|||
|
|
@ -170,11 +170,7 @@ passing in an optional value to the `commit_sha` query parameter.
|
|||
|
||||
## Compliance frameworks report
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387910) in GitLab 15.10 with a flag named `compliance_frameworks_report`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `compliance_frameworks_report`.
|
||||
On GitLab.com, this feature is available.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387910) in GitLab 15.10.
|
||||
|
||||
With compliance frameworks report, you can see the compliance frameworks that are applied to projects in a group. Each row of the report shows:
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8092) in GitLab 15.9 [with a flag](../../administration/feature_flags.md) named `license_scanning_policies`. Disabled by default.
|
||||
|
||||
License Approval Policies allow you to specify multiple types of criteria that define when approval is required before a merge request can be merged in. The following video provides an overview of these policies.
|
||||
License Approval Policies allow you to specify multiple types of criteria that define when approval is required before a merge request can be merged in.
|
||||
|
||||
NOTE:
|
||||
License Approval Policies are applicable only to [protected](../project/protected_branches.md) target branches.
|
||||
|
||||
The following video provides an overview of these policies.
|
||||
|
||||
<div class="video-fallback">
|
||||
See the video: <a href="https://www.youtube.com/watch?v=34qBQ9t8qO8">Overview of GitLab License Approval Policies</a>.
|
||||
|
|
|
|||
|
|
@ -56,15 +56,15 @@ dependency_scanning:
|
|||
|
||||
.gemnasium-shared-rule:
|
||||
exists:
|
||||
- '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
|
||||
- '{composer.lock,*/composer.lock,*/*/composer.lock}'
|
||||
- '{gems.locked,*/gems.locked,*/*/gems.locked}'
|
||||
- '{go.sum,*/go.sum,*/*/go.sum}'
|
||||
- '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
|
||||
- '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
|
||||
- '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
|
||||
- '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
|
||||
- '{conan.lock,*/conan.lock,*/*/conan.lock}'
|
||||
- '**/Gemfile.lock'
|
||||
- '**/composer.lock'
|
||||
- '**/gems.locked'
|
||||
- '**/go.sum'
|
||||
- '**/npm-shrinkwrap.json'
|
||||
- '**/package-lock.json'
|
||||
- '**/yarn.lock'
|
||||
- '**/packages.lock.json'
|
||||
- '**/conan.lock'
|
||||
|
||||
gemnasium-dependency_scanning:
|
||||
extends:
|
||||
|
|
@ -91,10 +91,10 @@ gemnasium-dependency_scanning:
|
|||
|
||||
.gemnasium-maven-shared-rule:
|
||||
exists:
|
||||
- '{build.gradle,*/build.gradle,*/*/build.gradle}'
|
||||
- '{build.gradle.kts,*/build.gradle.kts,*/*/build.gradle.kts}'
|
||||
- '{build.sbt,*/build.sbt,*/*/build.sbt}'
|
||||
- '{pom.xml,*/pom.xml,*/*/pom.xml}'
|
||||
- '**/build.gradle'
|
||||
- '**/build.gradle.kts'
|
||||
- '**/build.sbt'
|
||||
- '**/pom.xml'
|
||||
|
||||
gemnasium-maven-dependency_scanning:
|
||||
extends:
|
||||
|
|
@ -119,12 +119,12 @@ gemnasium-maven-dependency_scanning:
|
|||
|
||||
.gemnasium-python-shared-rule:
|
||||
exists:
|
||||
- '{requirements.txt,*/requirements.txt,*/*/requirements.txt}'
|
||||
- '{requirements.pip,*/requirements.pip,*/*/requirements.pip}'
|
||||
- '{Pipfile,*/Pipfile,*/*/Pipfile}'
|
||||
- '{requires.txt,*/requires.txt,*/*/requires.txt}'
|
||||
- '{setup.py,*/setup.py,*/*/setup.py}'
|
||||
- '{poetry.lock,*/poetry.lock,*/*/poetry.lock}'
|
||||
- '**/requirements.txt'
|
||||
- '**/requirements.pip'
|
||||
- '**/Pipfile'
|
||||
- '**/requires.txt'
|
||||
- '**/setup.py'
|
||||
- '**/poetry.lock'
|
||||
|
||||
gemnasium-python-dependency_scanning:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -56,15 +56,15 @@ dependency_scanning:
|
|||
|
||||
.gemnasium-shared-rule:
|
||||
exists:
|
||||
- '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
|
||||
- '{composer.lock,*/composer.lock,*/*/composer.lock}'
|
||||
- '{gems.locked,*/gems.locked,*/*/gems.locked}'
|
||||
- '{go.sum,*/go.sum,*/*/go.sum}'
|
||||
- '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
|
||||
- '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
|
||||
- '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
|
||||
- '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
|
||||
- '{conan.lock,*/conan.lock,*/*/conan.lock}'
|
||||
- '**/Gemfile.lock'
|
||||
- '**/composer.lock'
|
||||
- '**/gems.locked'
|
||||
- '**/go.sum'
|
||||
- '**/npm-shrinkwrap.json'
|
||||
- '**/package-lock.json'
|
||||
- '**/yarn.lock'
|
||||
- '**/packages.lock.json'
|
||||
- '**/conan.lock'
|
||||
|
||||
gemnasium-dependency_scanning:
|
||||
extends:
|
||||
|
|
@ -109,10 +109,10 @@ gemnasium-dependency_scanning:
|
|||
|
||||
.gemnasium-maven-shared-rule:
|
||||
exists:
|
||||
- '{build.gradle,*/build.gradle,*/*/build.gradle}'
|
||||
- '{build.gradle.kts,*/build.gradle.kts,*/*/build.gradle.kts}'
|
||||
- '{build.sbt,*/build.sbt,*/*/build.sbt}'
|
||||
- '{pom.xml,*/pom.xml,*/*/pom.xml}'
|
||||
- '**/build.gradle'
|
||||
- '**/build.gradle.kts'
|
||||
- '**/build.sbt'
|
||||
- '**/pom.xml'
|
||||
|
||||
gemnasium-maven-dependency_scanning:
|
||||
extends:
|
||||
|
|
@ -155,12 +155,12 @@ gemnasium-maven-dependency_scanning:
|
|||
|
||||
.gemnasium-python-shared-rule:
|
||||
exists:
|
||||
- '{requirements.txt,*/requirements.txt,*/*/requirements.txt}'
|
||||
- '{requirements.pip,*/requirements.pip,*/*/requirements.pip}'
|
||||
- '{Pipfile,*/Pipfile,*/*/Pipfile}'
|
||||
- '{requires.txt,*/requires.txt,*/*/requires.txt}'
|
||||
- '{setup.py,*/setup.py,*/*/setup.py}'
|
||||
- '{poetry.lock,*/poetry.lock,*/*/poetry.lock}'
|
||||
- '**/requirements.txt'
|
||||
- '**/requirements.pip'
|
||||
- '**/Pipfile'
|
||||
- '**/requires.txt'
|
||||
- '**/setup.py'
|
||||
- '**/poetry.lock'
|
||||
|
||||
gemnasium-python-dependency_scanning:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_security do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_security, quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/396855',
|
||||
type: :flaky
|
||||
} do
|
||||
describe "Unlocking job artifacts across parent-child pipelines" do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
|
||||
|
|
|
|||
|
|
@ -147,14 +147,14 @@ RSpec.describe 'Edit group settings', feature_category: :subgroups do
|
|||
selected_group.add_owner(user)
|
||||
end
|
||||
|
||||
it 'can successfully transfer the group', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/384966' do
|
||||
it 'can successfully transfer the group' do
|
||||
visit edit_group_path(selected_group)
|
||||
|
||||
page.within('[data-testid="transfer-locations-dropdown"]') do
|
||||
click_button _('Select parent group')
|
||||
fill_in _('Search'), with: target_group_name
|
||||
wait_for_requests
|
||||
click_button target_group_name
|
||||
click_button(target_group_name || 'No parent group')
|
||||
end
|
||||
|
||||
click_button s_('GroupSettings|Transfer group')
|
||||
|
|
@ -166,7 +166,10 @@ RSpec.describe 'Edit group settings', feature_category: :subgroups do
|
|||
click_button 'Confirm'
|
||||
end
|
||||
|
||||
expect(page).to have_text "Group '#{selected_group.name}' was successfully transferred."
|
||||
within('[data-testid="breadcrumb-links"]') do
|
||||
expect(page).to have_content(target_group_name) if target_group_name
|
||||
expect(page).to have_content(selected_group.name)
|
||||
end
|
||||
expect(current_url).to include(selected_group.reload.full_path)
|
||||
end
|
||||
end
|
||||
|
|
@ -175,7 +178,7 @@ RSpec.describe 'Edit group settings', feature_category: :subgroups do
|
|||
let(:selected_group) { create(:group, path: 'foo-subgroup', parent: group) }
|
||||
|
||||
context 'when transfering to no parent group' do
|
||||
let(:target_group_name) { 'No parent group' }
|
||||
let(:target_group_name) { nil }
|
||||
|
||||
it_behaves_like 'can transfer the group'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,9 +8,6 @@ RSpec.describe 'Observability rendering', :js, feature_category: :metrics do
|
|||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:observable_url) { "https://www.gitlab.com/groups/#{group.path}/-/observability/explore?observability_path=/explore?foo=bar" }
|
||||
let_it_be(:expected_observable_url) { "https://observe.gitlab.com/-/#{group.id}/explore?foo=bar" }
|
||||
let_it_be(:expected) do
|
||||
%(<iframe src="#{expected_observable_url}&theme=light&kiosk=inline-embed" frameborder="0")
|
||||
end
|
||||
|
||||
before do
|
||||
stub_config_setting(url: "https://www.gitlab.com")
|
||||
|
|
|
|||
|
|
@ -1,40 +1,43 @@
|
|||
import Vue from 'vue';
|
||||
import { createWrapper } from '@vue/test-utils';
|
||||
import renderObservability from '~/behaviors/markdown/render_observability';
|
||||
import * as ColorUtils from '~/lib/utils/color_utils';
|
||||
import { INLINE_EMBED_DIMENSIONS, SKELETON_VARIANT_EMBED } from '~/observability/constants';
|
||||
import ObservabilityApp from '~/observability/components/observability_app.vue';
|
||||
|
||||
describe('Observability iframe renderer', () => {
|
||||
const findObservabilityIframes = (theme = 'light') =>
|
||||
document.querySelectorAll(
|
||||
`iframe[src="https://observe.gitlab.com/?theme=${theme}&kiosk=inline-embed"]`,
|
||||
);
|
||||
|
||||
const renderEmbeddedObservability = () => {
|
||||
renderObservability([...document.querySelectorAll('.js-render-observability')]);
|
||||
jest.runAllTimers();
|
||||
};
|
||||
describe('renderObservability', () => {
|
||||
let subject;
|
||||
|
||||
beforeEach(() => {
|
||||
document.body.dataset.page = '';
|
||||
document.body.innerHTML = '';
|
||||
subject = document.createElement('div');
|
||||
subject.classList.add('js-render-observability');
|
||||
subject.dataset.frameUrl = 'https://observe.gitlab.com/';
|
||||
document.body.appendChild(subject);
|
||||
});
|
||||
|
||||
it('renders an observability iframe', () => {
|
||||
document.body.innerHTML = `<div class="js-render-observability" data-frame-url="https://observe.gitlab.com/"></div>`;
|
||||
|
||||
expect(findObservabilityIframes()).toHaveLength(0);
|
||||
|
||||
renderEmbeddedObservability();
|
||||
|
||||
expect(findObservabilityIframes()).toHaveLength(1);
|
||||
afterEach(() => {
|
||||
subject.remove();
|
||||
});
|
||||
|
||||
it('renders iframe with dark param when GL has dark theme', () => {
|
||||
document.body.innerHTML = `<div class="js-render-observability" data-frame-url="https://observe.gitlab.com/"></div>`;
|
||||
jest.spyOn(ColorUtils, 'darkModeEnabled').mockImplementation(() => true);
|
||||
it('should return an array of Vue instances', () => {
|
||||
const vueInstances = renderObservability([
|
||||
...document.querySelectorAll('.js-render-observability'),
|
||||
]);
|
||||
expect(vueInstances).toEqual([expect.any(Vue)]);
|
||||
});
|
||||
|
||||
expect(findObservabilityIframes('dark')).toHaveLength(0);
|
||||
it('should correctly pass props to the ObservabilityApp component', () => {
|
||||
const vueInstances = renderObservability([
|
||||
...document.querySelectorAll('.js-render-observability'),
|
||||
]);
|
||||
|
||||
renderEmbeddedObservability();
|
||||
const wrapper = createWrapper(vueInstances[0]);
|
||||
|
||||
expect(findObservabilityIframes('dark')).toHaveLength(1);
|
||||
expect(wrapper.findComponent(ObservabilityApp).props()).toMatchObject({
|
||||
observabilityIframeSrc: 'https://observe.gitlab.com/',
|
||||
skeletonVariant: SKELETON_VARIANT_EMBED,
|
||||
inlineEmbed: true,
|
||||
height: INLINE_EMBED_DIMENSIONS.HEIGHT,
|
||||
width: INLINE_EMBED_DIMENSIONS.WIDTH,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import { createWrapper } from '@vue/test-utils';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import renderObservability from '~/observability/index';
|
||||
import ObservabilityApp from '~/observability/components/observability_app.vue';
|
||||
import { SKELETON_VARIANTS_BY_ROUTE } from '~/observability/constants';
|
||||
|
||||
describe('renderObservability', () => {
|
||||
let element;
|
||||
let vueInstance;
|
||||
let component;
|
||||
|
||||
const OBSERVABILITY_ROUTES = Object.keys(SKELETON_VARIANTS_BY_ROUTE);
|
||||
const SKELETON_VARIANTS = Object.values(SKELETON_VARIANTS_BY_ROUTE);
|
||||
|
||||
beforeEach(() => {
|
||||
element = document.createElement('div');
|
||||
element.setAttribute('id', 'js-observability-app');
|
||||
element.dataset.observabilityIframeSrc = 'https://observe.gitlab.com/';
|
||||
document.body.appendChild(element);
|
||||
|
||||
vueInstance = renderObservability();
|
||||
component = createWrapper(vueInstance).findComponent(ObservabilityApp);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
element.remove();
|
||||
});
|
||||
|
||||
it('should return a Vue instance', () => {
|
||||
expect(vueInstance).toEqual(expect.any(Vue));
|
||||
});
|
||||
|
||||
it('should render the ObservabilityApp component', () => {
|
||||
expect(component.props('observabilityIframeSrc')).toBe('https://observe.gitlab.com/');
|
||||
});
|
||||
|
||||
describe('skeleton variant', () => {
|
||||
it.each`
|
||||
pathDescription | path | variant
|
||||
${'dashboards'} | ${OBSERVABILITY_ROUTES[0]} | ${SKELETON_VARIANTS[0]}
|
||||
${'explore'} | ${OBSERVABILITY_ROUTES[1]} | ${SKELETON_VARIANTS[1]}
|
||||
${'manage dashboards'} | ${OBSERVABILITY_ROUTES[2]} | ${SKELETON_VARIANTS[2]}
|
||||
${'any other'} | ${'unknown/route'} | ${SKELETON_VARIANTS[0]}
|
||||
`(
|
||||
'renders the $variant skeleton variant for $pathDescription path',
|
||||
async ({ path, variant }) => {
|
||||
component.vm.$router.push(path);
|
||||
await nextTick();
|
||||
|
||||
expect(component.props('skeletonVariant')).toBe(variant);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('handle route-update events', async () => {
|
||||
component.vm.$router.push('/something?foo=bar');
|
||||
component.vm.$emit('route-update', { url: '/some_path' });
|
||||
expect(component.vm.$router.currentRoute.path).toBe('/something');
|
||||
expect(component.vm.$router.currentRoute.query).toEqual({
|
||||
foo: 'bar',
|
||||
observability_path: '/some_path',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import ObservabilityApp from '~/observability/components/observability_app.vue';
|
||||
import ObservabilitySkeleton from '~/observability/components/skeleton/index.vue';
|
||||
|
||||
import { MESSAGE_EVENT_TYPE, SKELETON_VARIANTS_BY_ROUTE } from '~/observability/constants';
|
||||
import {
|
||||
MESSAGE_EVENT_TYPE,
|
||||
INLINE_EMBED_DIMENSIONS,
|
||||
FULL_APP_DIMENSIONS,
|
||||
SKELETON_VARIANT_EMBED,
|
||||
} from '~/observability/constants';
|
||||
|
||||
import { darkModeEnabled } from '~/lib/utils/color_utils';
|
||||
|
||||
jest.mock('~/lib/utils/color_utils');
|
||||
|
||||
describe('Observability root app', () => {
|
||||
describe('ObservabilityApp', () => {
|
||||
let wrapper;
|
||||
const replace = jest.fn();
|
||||
const $router = {
|
||||
replace,
|
||||
};
|
||||
|
||||
const $route = {
|
||||
pathname: 'https://gitlab.com/gitlab-org/',
|
||||
path: 'https://gitlab.com/gitlab-org/-/observability/dashboards',
|
||||
|
|
@ -26,21 +27,19 @@ describe('Observability root app', () => {
|
|||
|
||||
const TEST_IFRAME_SRC = 'https://observe.gitlab.com/9970/?groupId=14485840';
|
||||
|
||||
const OBSERVABILITY_ROUTES = Object.keys(SKELETON_VARIANTS_BY_ROUTE);
|
||||
const TEST_USERNAME = 'test-user';
|
||||
|
||||
const SKELETON_VARIANTS = Object.values(SKELETON_VARIANTS_BY_ROUTE);
|
||||
|
||||
const mountComponent = (route = $route) => {
|
||||
const mountComponent = (props) => {
|
||||
wrapper = shallowMountExtended(ObservabilityApp, {
|
||||
propsData: {
|
||||
observabilityIframeSrc: TEST_IFRAME_SRC,
|
||||
...props,
|
||||
},
|
||||
stubs: {
|
||||
'observability-skeleton': ObservabilitySkeleton,
|
||||
},
|
||||
mocks: {
|
||||
$router,
|
||||
$route: route,
|
||||
$route,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -48,13 +47,11 @@ describe('Observability root app', () => {
|
|||
const dispatchMessageEvent = (message) =>
|
||||
window.dispatchEvent(new MessageEvent('message', message));
|
||||
|
||||
beforeEach(() => {
|
||||
gon.current_username = TEST_USERNAME;
|
||||
});
|
||||
|
||||
describe('iframe src', () => {
|
||||
const TEST_USERNAME = 'test-user';
|
||||
|
||||
beforeEach(() => {
|
||||
gon.current_username = TEST_USERNAME;
|
||||
});
|
||||
|
||||
it('should render an iframe with observabilityIframeSrc, decorated with light theme and username', () => {
|
||||
darkModeEnabled.mockReturnValueOnce(false);
|
||||
mountComponent();
|
||||
|
|
@ -88,48 +85,70 @@ describe('Observability root app', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('on GOUI_ROUTE_UPDATE', () => {
|
||||
it('should not call replace method from vue router if message event does not have url', () => {
|
||||
mountComponent();
|
||||
dispatchMessageEvent({
|
||||
type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE,
|
||||
payload: { data: 'some other data' },
|
||||
describe('iframe kiosk query param', () => {
|
||||
it('when inlineEmbed, it should set the proper kiosk query parameter', () => {
|
||||
mountComponent({
|
||||
inlineEmbed: true,
|
||||
});
|
||||
expect(replace).not.toHaveBeenCalled();
|
||||
|
||||
const iframe = findIframe();
|
||||
|
||||
expect(iframe.attributes('src')).toBe(
|
||||
`${TEST_IFRAME_SRC}&theme=light&username=${TEST_USERNAME}&kiosk=inline-embed`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('iframe size', () => {
|
||||
it('should set the specified size', () => {
|
||||
mountComponent({
|
||||
height: INLINE_EMBED_DIMENSIONS.HEIGHT,
|
||||
width: INLINE_EMBED_DIMENSIONS.WIDTH,
|
||||
});
|
||||
|
||||
const iframe = findIframe();
|
||||
|
||||
expect(iframe.attributes('width')).toBe(INLINE_EMBED_DIMENSIONS.WIDTH);
|
||||
expect(iframe.attributes('height')).toBe(INLINE_EMBED_DIMENSIONS.HEIGHT);
|
||||
});
|
||||
|
||||
it.each`
|
||||
condition | origin | observability_path | url
|
||||
${'message origin is different from iframe source origin'} | ${'https://example.com'} | ${'/'} | ${'/explore'}
|
||||
${'path is same as before (observability_path)'} | ${'https://observe.gitlab.com'} | ${'/foo?bar=test'} | ${'/foo?bar=test'}
|
||||
`(
|
||||
'should not call replace method from vue router if $condition',
|
||||
async ({ origin, observability_path, url }) => {
|
||||
mountComponent({ ...$route, query: { observability_path } });
|
||||
dispatchMessageEvent({
|
||||
data: { type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE, payload: { url } },
|
||||
origin,
|
||||
});
|
||||
expect(replace).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
it('should fallback to default size', () => {
|
||||
mountComponent({});
|
||||
|
||||
it('should call replace method from vue router on message event callback', () => {
|
||||
const iframe = findIframe();
|
||||
|
||||
expect(iframe.attributes('width')).toBe(FULL_APP_DIMENSIONS.WIDTH);
|
||||
expect(iframe.attributes('height')).toBe(FULL_APP_DIMENSIONS.HEIGHT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('skeleton variant', () => {
|
||||
it('sets the specified skeleton variant', () => {
|
||||
mountComponent({ skeletonVariant: SKELETON_VARIANT_EMBED });
|
||||
const props = wrapper.findComponent(ObservabilitySkeleton).props();
|
||||
|
||||
expect(props.variant).toBe(SKELETON_VARIANT_EMBED);
|
||||
});
|
||||
|
||||
it('should have a default skeleton variant', () => {
|
||||
mountComponent();
|
||||
const props = wrapper.findComponent(ObservabilitySkeleton).props();
|
||||
|
||||
expect(props.variant).toBe('dashboards');
|
||||
});
|
||||
});
|
||||
|
||||
describe('on GOUI_ROUTE_UPDATE', () => {
|
||||
it('should emit a route-update event', () => {
|
||||
mountComponent();
|
||||
|
||||
const payload = { url: '/explore' };
|
||||
dispatchMessageEvent({
|
||||
data: { type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE, payload: { url: '/explore' } },
|
||||
data: { type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE, payload },
|
||||
origin: 'https://observe.gitlab.com',
|
||||
});
|
||||
|
||||
expect(replace).toHaveBeenCalled();
|
||||
expect(replace).toHaveBeenCalledWith({
|
||||
name: 'https://gitlab.com/gitlab-org/',
|
||||
query: {
|
||||
otherQuery: 100,
|
||||
observability_path: '/explore',
|
||||
},
|
||||
});
|
||||
expect(wrapper.emitted('route-update')[0]).toEqual([payload]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -163,34 +182,17 @@ describe('Observability root app', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('skeleton variant', () => {
|
||||
it.each`
|
||||
pathDescription | path | variant
|
||||
${'dashboards'} | ${OBSERVABILITY_ROUTES[0]} | ${SKELETON_VARIANTS[0]}
|
||||
${'explore'} | ${OBSERVABILITY_ROUTES[1]} | ${SKELETON_VARIANTS[1]}
|
||||
${'manage dashboards'} | ${OBSERVABILITY_ROUTES[2]} | ${SKELETON_VARIANTS[2]}
|
||||
${'any other'} | ${'unknown/route'} | ${SKELETON_VARIANTS[0]}
|
||||
`('renders the $variant skeleton variant for $pathDescription path', ({ path, variant }) => {
|
||||
mountComponent({ ...$route, path });
|
||||
const props = wrapper.findComponent(ObservabilitySkeleton).props();
|
||||
|
||||
expect(props.variant).toBe(variant);
|
||||
});
|
||||
});
|
||||
|
||||
describe('on observability ui unmount', () => {
|
||||
it('should remove message event and should not call replace method from vue router', () => {
|
||||
describe('on unmount', () => {
|
||||
it('should not emit any even on route update', () => {
|
||||
mountComponent();
|
||||
wrapper.destroy();
|
||||
|
||||
// testing event cleanup logic, should not call on messege event after component is destroyed
|
||||
|
||||
dispatchMessageEvent({
|
||||
data: { type: MESSAGE_EVENT_TYPE.GOUI_ROUTE_UPDATE, payload: { url: '/explore' } },
|
||||
origin: 'https://observe.gitlab.com',
|
||||
});
|
||||
|
||||
expect(replace).not.toHaveBeenCalled();
|
||||
expect(wrapper.emitted('route-update')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,8 +6,13 @@ import Skeleton from '~/observability/components/skeleton/index.vue';
|
|||
import DashboardsSkeleton from '~/observability/components/skeleton/dashboards.vue';
|
||||
import ExploreSkeleton from '~/observability/components/skeleton/explore.vue';
|
||||
import ManageSkeleton from '~/observability/components/skeleton/manage.vue';
|
||||
import EmbedSkeleton from '~/observability/components/skeleton/embed.vue';
|
||||
|
||||
import { SKELETON_VARIANTS_BY_ROUTE, DEFAULT_TIMERS } from '~/observability/constants';
|
||||
import {
|
||||
SKELETON_VARIANTS_BY_ROUTE,
|
||||
DEFAULT_TIMERS,
|
||||
SKELETON_VARIANT_EMBED,
|
||||
} from '~/observability/constants';
|
||||
|
||||
describe('Skeleton component', () => {
|
||||
let wrapper;
|
||||
|
|
@ -22,6 +27,8 @@ describe('Skeleton component', () => {
|
|||
|
||||
const findManageSkeleton = () => wrapper.findComponent(ManageSkeleton);
|
||||
|
||||
const findEmbedSkeleton = () => wrapper.findComponent(EmbedSkeleton);
|
||||
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
|
||||
const mountComponent = ({ ...props } = {}) => {
|
||||
|
|
@ -97,16 +104,20 @@ describe('Skeleton component', () => {
|
|||
${'dashboards'} | ${'variant is dashboards'} | ${SKELETON_VARIANTS[0]}
|
||||
${'explore'} | ${'variant is explore'} | ${SKELETON_VARIANTS[1]}
|
||||
${'manage'} | ${'variant is manage'} | ${SKELETON_VARIANTS[2]}
|
||||
${'embed'} | ${'variant is embed'} | ${SKELETON_VARIANT_EMBED}
|
||||
${'default'} | ${'variant is not manage, dashboards or explore'} | ${'unknown'}
|
||||
`('should render $skeletonType skeleton if $condition', async ({ skeletonType, variant }) => {
|
||||
mountComponent({ variant });
|
||||
jest.advanceTimersByTime(DEFAULT_TIMERS.CONTENT_WAIT_MS);
|
||||
await nextTick();
|
||||
const showsDefaultSkeleton = !SKELETON_VARIANTS.includes(variant);
|
||||
const showsDefaultSkeleton = ![...SKELETON_VARIANTS, SKELETON_VARIANT_EMBED].includes(
|
||||
variant,
|
||||
);
|
||||
|
||||
expect(findDashboardsSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANTS[0]);
|
||||
expect(findExploreSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANTS[1]);
|
||||
expect(findManageSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANTS[2]);
|
||||
expect(findEmbedSkeleton().exists()).toBe(skeletonType === SKELETON_VARIANT_EMBED);
|
||||
|
||||
expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(showsDefaultSkeleton);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AccessTokenValidationService do
|
||||
RSpec.describe AccessTokenValidationService, feature_category: :system_access do
|
||||
describe ".include_any_scope?" do
|
||||
let(:request) { double("request") }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AuditEventService, :with_license do
|
||||
RSpec.describe AuditEventService, :with_license, feature_category: :audit_events do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:user) { create(:user, :with_sign_ins) }
|
||||
let_it_be(:project_member) { create(:project_member, user: user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AutoMergeService do
|
||||
RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BaseContainerService do
|
||||
RSpec.describe BaseContainerService, feature_category: :container_registry do
|
||||
let(:project) { Project.new }
|
||||
let(:user) { User.new }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BaseCountService, :use_clean_rails_memory_store_caching do
|
||||
RSpec.describe BaseCountService, :use_clean_rails_memory_store_caching, feature_category: :shared do
|
||||
let(:service) { described_class.new }
|
||||
|
||||
describe '#relation_for_count' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BulkCreateIntegrationService do
|
||||
RSpec.describe BulkCreateIntegrationService, feature_category: :integrations do
|
||||
include JiraIntegrationHelpers
|
||||
|
||||
before_all do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BulkPushEventPayloadService do
|
||||
RSpec.describe BulkPushEventPayloadService, feature_category: :source_code_management do
|
||||
let(:event) { create(:push_event) }
|
||||
|
||||
let(:push_data) do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BulkUpdateIntegrationService do
|
||||
RSpec.describe BulkUpdateIntegrationService, feature_category: :integrations do
|
||||
include JiraIntegrationHelpers
|
||||
|
||||
before_all do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe CohortsService do
|
||||
RSpec.describe CohortsService, feature_category: :shared do
|
||||
describe '#execute' do
|
||||
def month_start(months_ago)
|
||||
months_ago.months.ago.beginning_of_month.to_date
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe CompareService do
|
||||
RSpec.describe CompareService, feature_category: :source_code_management do
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:user) { create(:user) }
|
||||
let(:service) { described_class.new(project, 'feature') }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redis_shared_state do
|
||||
RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redis_shared_state, feature_category: :service_ping do
|
||||
include SnowplowHelpers
|
||||
|
||||
let(:service) { described_class.new }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GravatarService do
|
||||
RSpec.describe GravatarService, feature_category: :user_profile do
|
||||
describe '#execute' do
|
||||
let(:url) { 'http://example.com/avatar?hash=%{hash}&size=%{size}&email=%{email}&username=%{username}' }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ImportExportCleanUpService do
|
||||
RSpec.describe ImportExportCleanUpService, feature_category: :importers do
|
||||
describe '#execute' do
|
||||
let(:service) { described_class.new }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe MarkdownContentRewriterService do
|
||||
RSpec.describe MarkdownContentRewriterService, feature_category: :team_planning do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:source_parent) { create(:project, :public) }
|
||||
let_it_be(:target_parent) { create(:project, :public) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe NoteSummary do
|
||||
RSpec.describe NoteSummary, feature_category: :code_review_workflow do
|
||||
let(:project) { build(:project) }
|
||||
let(:noteable) { build(:issue) }
|
||||
let(:user) { build(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PostReceiveService do
|
||||
RSpec.describe PostReceiveService, feature_category: :team_planning do
|
||||
include GitlabShellHelpers
|
||||
include Gitlab::Routing
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PreviewMarkdownService do
|
||||
RSpec.describe PreviewMarkdownService, feature_category: :team_planning do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PushEventPayloadService do
|
||||
RSpec.describe PushEventPayloadService, feature_category: :source_code_management do
|
||||
let(:event) { create(:push_event) }
|
||||
|
||||
describe '#execute' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe RepositoryArchiveCleanUpService do
|
||||
RSpec.describe RepositoryArchiveCleanUpService, feature_category: :source_code_management do
|
||||
subject(:service) { described_class.new }
|
||||
|
||||
describe '#execute (new archive locations)' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ResetProjectCacheService do
|
||||
RSpec.describe ResetProjectCacheService, feature_category: :projects do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ require 're2'
|
|||
require_relative '../../app/services/service_response'
|
||||
require_relative '../../lib/gitlab/error_tracking'
|
||||
|
||||
RSpec.describe ServiceResponse do
|
||||
RSpec.describe ServiceResponse, feature_category: :shared do
|
||||
describe '.success' do
|
||||
it 'creates a successful response without a message' do
|
||||
expect(described_class.success).to be_success
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe SystemHooksService do
|
||||
RSpec.describe SystemHooksService, feature_category: :webhooks do
|
||||
describe '#execute_hooks_for' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TaskListToggleService do
|
||||
RSpec.describe TaskListToggleService, feature_category: :team_planning do
|
||||
let(:markdown) do
|
||||
<<-EOT.strip_heredoc
|
||||
* [ ] Task 1
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TasksToBeDone::BaseService do
|
||||
RSpec.describe TasksToBeDone::BaseService, feature_category: :team_planning do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:assignee_one) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Terraform::RemoteStateHandler do
|
||||
RSpec.describe Terraform::RemoteStateHandler, feature_category: :infrastructure_as_code do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:developer) { create(:user, developer_projects: [project]) }
|
||||
let_it_be(:maintainer) { create(:user, maintainer_projects: [project]) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Terraform::States::DestroyService do
|
||||
RSpec.describe Terraform::States::DestroyService, feature_category: :infrastructure_as_code do
|
||||
let_it_be(:state) { create(:terraform_state, :with_version, :deletion_in_progress) }
|
||||
|
||||
let(:file) { instance_double(Terraform::StateUploader, relative_path: 'path') }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Terraform::States::TriggerDestroyService do
|
||||
RSpec.describe Terraform::States::TriggerDestroyService, feature_category: :infrastructure_as_code do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:user) { create(:user, maintainer_projects: [project]) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TestHooks::ProjectService do
|
||||
RSpec.describe TestHooks::ProjectService, feature_category: :code_testing do
|
||||
include AfterNextHelpers
|
||||
|
||||
let(:current_user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TestHooks::SystemService do
|
||||
RSpec.describe TestHooks::SystemService, feature_category: :code_testing do
|
||||
include AfterNextHelpers
|
||||
|
||||
describe '#execute' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Timelogs::DeleteService do
|
||||
RSpec.describe Timelogs::DeleteService, feature_category: :team_planning do
|
||||
let_it_be(:author) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TodoService do
|
||||
RSpec.describe TodoService, feature_category: :team_planning do
|
||||
include AfterNextHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Todos::AllowedTargetFilterService do
|
||||
RSpec.describe Todos::AllowedTargetFilterService, feature_category: :team_planning do
|
||||
include DesignManagementTestHelpers
|
||||
|
||||
let_it_be(:authorized_group) { create(:group, :private) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Todos::Destroy::ConfidentialIssueService do
|
||||
RSpec.describe Todos::Destroy::ConfidentialIssueService, feature_category: :team_planning do
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:user) { create(:user) }
|
||||
let(:author) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Todos::Destroy::DesignService do
|
||||
RSpec.describe Todos::Destroy::DesignService, feature_category: :design_management do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:user_2) { create(:user) }
|
||||
let_it_be(:design) { create(:design) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Todos::Destroy::DestroyedIssuableService do
|
||||
RSpec.describe Todos::Destroy::DestroyedIssuableService, feature_category: :team_planning do
|
||||
describe '#execute' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Todos::Destroy::ProjectPrivateService do
|
||||
RSpec.describe Todos::Destroy::ProjectPrivateService, feature_category: :team_planning do
|
||||
let(:group) { create(:group, :public) }
|
||||
let(:project) { create(:project, :public, group: group) }
|
||||
let(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Todos::Destroy::UnauthorizedFeaturesService do
|
||||
RSpec.describe Todos::Destroy::UnauthorizedFeaturesService, feature_category: :team_planning do
|
||||
let_it_be(:project, reload: true) { create(:project, :public, :repository) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
let_it_be(:mr) { create(:merge_request, source_project: project) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Topics::MergeService do
|
||||
RSpec.describe Topics::MergeService, feature_category: :shared do
|
||||
let_it_be(:source_topic) { create(:topic, name: 'source_topic') }
|
||||
let_it_be(:target_topic) { create(:topic, name: 'target_topic') }
|
||||
let_it_be(:project_1) { create(:project, :public, topic_list: source_topic.name) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe TwoFactor::DestroyService do
|
||||
RSpec.describe TwoFactor::DestroyService, feature_category: :system_access do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
subject { described_class.new(current_user, user: user).execute }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe UpdateContainerRegistryInfoService do
|
||||
RSpec.describe UpdateContainerRegistryInfoService, feature_category: :container_registry do
|
||||
let_it_be(:application_settings) { Gitlab::CurrentSettings }
|
||||
let_it_be(:api_url) { 'http://registry.gitlab' }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe MergeRequestMetricsService do
|
||||
RSpec.describe MergeRequestMetricsService, feature_category: :code_review_workflow do
|
||||
let(:metrics) { create(:merge_request).metrics }
|
||||
|
||||
describe '#merge' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe UploadService do
|
||||
RSpec.describe UploadService, feature_category: :shared do
|
||||
describe 'File service' do
|
||||
before do
|
||||
@user = create(:user)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Uploads::DestroyService do
|
||||
RSpec.describe Uploads::DestroyService, feature_category: :shared do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be_with_reload(:upload) { create(:upload, :issuable_upload, model: project) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe UserPreferences::UpdateService do
|
||||
RSpec.describe UserPreferences::UpdateService, feature_category: :user_profile do
|
||||
let(:user) { create(:user) }
|
||||
let(:params) { { view_diffs_file_by_file: false } }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::ActivityService do
|
||||
RSpec.describe Users::ActivityService, feature_category: :user_profile do
|
||||
include ExclusiveLeaseHelpers
|
||||
|
||||
let(:user) { create(:user, last_activity_on: last_activity_on) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::ApproveService do
|
||||
RSpec.describe Users::ApproveService, feature_category: :user_management do
|
||||
let_it_be(:current_user) { create(:admin) }
|
||||
|
||||
let(:user) { create(:user, :blocked_pending_approval) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::AuthorizedBuildService do
|
||||
RSpec.describe Users::AuthorizedBuildService, feature_category: :user_management do
|
||||
describe '#execute' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::BanService do
|
||||
RSpec.describe Users::BanService, feature_category: :user_management do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
let_it_be(:current_user) { create(:admin) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::BannedUserBaseService do
|
||||
RSpec.describe Users::BannedUserBaseService, feature_category: :user_management do
|
||||
let(:admin) { create(:admin) }
|
||||
let(:base_service) { described_class.new(admin) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::BatchStatusCleanerService do
|
||||
RSpec.describe Users::BatchStatusCleanerService, feature_category: :user_management do
|
||||
let_it_be(:user_status_1) { create(:user_status, emoji: 'coffee', message: 'msg1', clear_status_at: 1.year.ago) }
|
||||
let_it_be(:user_status_2) { create(:user_status, emoji: 'coffee', message: 'msg1', clear_status_at: 1.year.from_now) }
|
||||
let_it_be(:user_status_3) { create(:user_status, emoji: 'coffee', message: 'msg1', clear_status_at: 2.years.ago) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::BlockService do
|
||||
RSpec.describe Users::BlockService, feature_category: :user_management do
|
||||
let_it_be(:current_user) { create(:admin) }
|
||||
|
||||
subject(:service) { described_class.new(current_user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::BuildService do
|
||||
RSpec.describe Users::BuildService, feature_category: :user_management do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
describe '#execute' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::CreateService do
|
||||
RSpec.describe Users::CreateService, feature_category: :user_management do
|
||||
describe '#execute' do
|
||||
let(:password) { User.random_password }
|
||||
let(:admin_user) { create(:admin) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::DestroyService do
|
||||
RSpec.describe Users::DestroyService, feature_category: :user_management do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:admin) { create(:admin) }
|
||||
let!(:namespace) { user.namespace }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::DismissCalloutService do
|
||||
RSpec.describe Users::DismissCalloutService, feature_category: :user_management do
|
||||
describe '#execute' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::DismissGroupCalloutService do
|
||||
RSpec.describe Users::DismissGroupCalloutService, feature_category: :user_management do
|
||||
describe '#execute' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::DismissProjectCalloutService do
|
||||
RSpec.describe Users::DismissProjectCalloutService, feature_category: :user_management do
|
||||
describe '#execute' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::EmailVerification::GenerateTokenService do
|
||||
RSpec.describe Users::EmailVerification::GenerateTokenService, feature_category: :system_access do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:service) { described_class.new(attr: attr) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::EmailVerification::ValidateTokenService, :clean_gitlab_redis_rate_limiting do
|
||||
RSpec.describe Users::EmailVerification::ValidateTokenService, :clean_gitlab_redis_rate_limiting, feature_category: :system_access do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:service) { described_class.new(attr: attr, user: user, token: token) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::InProductMarketingEmailRecords do
|
||||
RSpec.describe Users::InProductMarketingEmailRecords, feature_category: :onboarding do
|
||||
let_it_be(:user) { create :user }
|
||||
|
||||
subject(:records) { described_class.new }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::KeysCountService, :use_clean_rails_memory_store_caching do
|
||||
RSpec.describe Users::KeysCountService, :use_clean_rails_memory_store_caching, feature_category: :system_access do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject { described_class.new(user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::LastPushEventService do
|
||||
RSpec.describe Users::LastPushEventService, feature_category: :source_code_management do
|
||||
let(:user) { build(:user, id: 1) }
|
||||
let(:project) { build(:project, id: 2) }
|
||||
let(:event) { build(:push_event, id: 3, author: user, project: project) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::MigrateRecordsToGhostUserInBatchesService do
|
||||
RSpec.describe Users::MigrateRecordsToGhostUserInBatchesService, feature_category: :user_management do
|
||||
let(:service) { described_class.new }
|
||||
|
||||
let_it_be(:ghost_user_migration) { create(:ghost_user_migration) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::MigrateRecordsToGhostUserService do
|
||||
RSpec.describe Users::MigrateRecordsToGhostUserService, feature_category: :user_management do
|
||||
include BatchDestroyDependentAssociationsHelper
|
||||
|
||||
let!(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::RefreshAuthorizedProjectsService do
|
||||
RSpec.describe Users::RefreshAuthorizedProjectsService, feature_category: :user_management do
|
||||
include ExclusiveLeaseHelpers
|
||||
|
||||
# We're using let! here so that any expectations for the service class are not
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::RegistrationsBuildService do
|
||||
RSpec.describe Users::RegistrationsBuildService, feature_category: :system_access do
|
||||
describe '#execute' do
|
||||
let(:base_params) { build_stubbed(:user).slice(:first_name, :last_name, :username, :email, :password) }
|
||||
let(:skip_param) { {} }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::RejectService do
|
||||
RSpec.describe Users::RejectService, feature_category: :user_management do
|
||||
let_it_be(:current_user) { create(:admin) }
|
||||
|
||||
let(:user) { create(:user, :blocked_pending_approval) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::RepairLdapBlockedService do
|
||||
RSpec.describe Users::RepairLdapBlockedService, feature_category: :system_access do
|
||||
let(:user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') }
|
||||
let(:identity) { user.ldap_identity }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::RespondToTermsService do
|
||||
RSpec.describe Users::RespondToTermsService, feature_category: :user_profile do
|
||||
let(:user) { create(:user) }
|
||||
let(:term) { create(:term) }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::SavedReplies::CreateService do
|
||||
RSpec.describe Users::SavedReplies::CreateService, feature_category: :team_planning do
|
||||
describe '#execute' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:saved_reply) { create(:saved_reply, user: current_user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::SavedReplies::DestroyService do
|
||||
RSpec.describe Users::SavedReplies::DestroyService, feature_category: :team_planning do
|
||||
describe '#execute' do
|
||||
let!(:saved_reply) { create(:saved_reply) }
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue