Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4bb797f255
commit
774f6e6e98
|
|
@ -3,104 +3,6 @@
|
|||
Style/PercentLiteralDelimiters:
|
||||
Exclude:
|
||||
- 'metrics_server/metrics_server.rb'
|
||||
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/receiver_spec.rb'
|
||||
- 'spec/lib/gitlab/encoding_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/endpoint_attributes_spec.rb'
|
||||
- 'spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb'
|
||||
- 'spec/lib/gitlab/external_authorization/client_spec.rb'
|
||||
- 'spec/lib/gitlab/favicon_spec.rb'
|
||||
- 'spec/lib/gitlab/feature_categories_spec.rb'
|
||||
- 'spec/lib/gitlab/file_detector_spec.rb'
|
||||
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
|
||||
- 'spec/lib/gitlab/git/merge_base_spec.rb'
|
||||
- 'spec/lib/gitlab/git/repository_spec.rb'
|
||||
- 'spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/operation_service_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/ref_service_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/note_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/graphql/known_operations_spec.rb'
|
||||
- 'spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb'
|
||||
- 'spec/lib/gitlab/hashed_path_spec.rb'
|
||||
- 'spec/lib/gitlab/highlight_spec.rb'
|
||||
- 'spec/lib/gitlab/i18n/translation_entry_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/attribute_cleaner_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/attributes_permitter_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/lfs_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/tree_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_sources_spec.rb'
|
||||
- 'spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb'
|
||||
- 'spec/lib/gitlab/issues/rebalancing/state_spec.rb'
|
||||
- 'spec/lib/gitlab/jira_import/handle_labels_service_spec.rb'
|
||||
- 'spec/lib/gitlab/jira_import/issue_serializer_spec.rb'
|
||||
- 'spec/lib/gitlab/jira_import/labels_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/kubernetes/kubectl_cmd_spec.rb'
|
||||
- 'spec/lib/gitlab/kubernetes/role_spec.rb'
|
||||
- 'spec/lib/gitlab/language_data_spec.rb'
|
||||
- 'spec/lib/gitlab/markup_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/rails_slis_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/go_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/multipart_spec.rb'
|
||||
- 'spec/lib/gitlab/omniauth_initializer_spec.rb'
|
||||
- 'spec/lib/gitlab/pagination/keyset/order_spec.rb'
|
||||
- 'spec/lib/gitlab/pagination/offset_header_builder_spec.rb'
|
||||
- 'spec/lib/gitlab/path_regex_spec.rb'
|
||||
- 'spec/lib/gitlab/popen_spec.rb'
|
||||
- 'spec/lib/gitlab/process_management_spec.rb'
|
||||
- 'spec/lib/gitlab/process_supervisor_spec.rb'
|
||||
- 'spec/lib/gitlab/quick_actions/extractor_spec.rb'
|
||||
- 'spec/lib/gitlab/reference_extractor_spec.rb'
|
||||
- 'spec/lib/gitlab/repository_cache_adapter_spec.rb'
|
||||
- 'spec/lib/gitlab/repository_hash_cache_spec.rb'
|
||||
- 'spec/lib/gitlab/repository_set_cache_spec.rb'
|
||||
- 'spec/lib/gitlab/search/abuse_detection_spec.rb'
|
||||
- 'spec/lib/gitlab/search_results_spec.rb'
|
||||
- 'spec/lib/gitlab/security/scan_configuration_spec.rb'
|
||||
- 'spec/lib/gitlab/shard_health_cache_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_config/worker_matcher_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_status_spec.rb'
|
||||
- 'spec/lib/gitlab/ssh_public_key_spec.rb'
|
||||
- 'spec/lib/gitlab/string_range_marker_spec.rb'
|
||||
- 'spec/lib/gitlab/string_regex_marker_spec.rb'
|
||||
- 'spec/lib/gitlab/suggestions/suggestion_set_spec.rb'
|
||||
- 'spec/lib/gitlab/task_helpers_spec.rb'
|
||||
- 'spec/lib/gitlab/tracking/event_definition_spec.rb'
|
||||
- 'spec/lib/gitlab/url_sanitizer_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/metric_definition_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/metric_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/service_ping/instrumented_payload_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_spec.rb'
|
||||
- 'spec/lib/gitlab/utils/log_limited_array_spec.rb'
|
||||
- 'spec/lib/gitlab/webpack/graphql_known_operations_spec.rb'
|
||||
- 'spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb'
|
||||
- 'spec/lib/object_storage/config_spec.rb'
|
||||
- 'spec/lib/object_storage/direct_upload_spec.rb'
|
||||
- 'spec/lib/rouge/formatters/html_gitlab_spec.rb'
|
||||
- 'spec/lib/safe_zip/entry_spec.rb'
|
||||
- 'spec/lib/safe_zip/extract_params_spec.rb'
|
||||
- 'spec/lib/safe_zip/extract_spec.rb'
|
||||
- 'spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb'
|
||||
- 'spec/lib/security/ci_configuration/sast_build_action_spec.rb'
|
||||
- 'spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb'
|
||||
- 'spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb'
|
||||
- 'spec/lib/sidebars/menu_spec.rb'
|
||||
- 'spec/lib/system_check/orphans/namespace_check_spec.rb'
|
||||
- 'spec/lib/system_check/orphans/repository_check_spec.rb'
|
||||
- 'spec/lib/system_check/sidekiq_check_spec.rb'
|
||||
- 'spec/lib/unnested_in_filters/dsl_spec.rb'
|
||||
- 'spec/lib/unnested_in_filters/rewriter_spec.rb'
|
||||
- 'spec/metrics_server/metrics_server_spec.rb'
|
||||
- 'spec/models/alert_management/http_integration_spec.rb'
|
||||
- 'spec/models/appearance_spec.rb'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#import "./crm_organization_fields.fragment.graphql"
|
||||
|
||||
mutation updateOrganization($input: CustomerRelationsOrganizationUpdateInput!) {
|
||||
mutation updateCustomerRelationsOrganization($input: CustomerRelationsOrganizationUpdateInput!) {
|
||||
customerRelationsOrganizationUpdate(input: $input) {
|
||||
organization {
|
||||
...OrganizationFragment
|
||||
|
|
@ -5,7 +5,7 @@ import { TYPENAME_CRM_ORGANIZATION, TYPENAME_GROUP } from '~/graphql_shared/cons
|
|||
import CrmForm from '../../components/crm_form.vue';
|
||||
import getGroupOrganizationsQuery from './graphql/get_group_organizations.query.graphql';
|
||||
import createCustomerRelationsOrganizationMutation from './graphql/create_customer_relations_organization.mutation.graphql';
|
||||
import updateOrganizationMutation from './graphql/update_organization.mutation.graphql';
|
||||
import updateCustomerRelationsOrganizationMutation from './graphql/update_customer_relations_organization.mutation.graphql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -29,7 +29,7 @@ export default {
|
|||
return convertToGraphQLId(TYPENAME_GROUP, this.groupId);
|
||||
},
|
||||
mutation() {
|
||||
if (this.isEditMode) return updateOrganizationMutation;
|
||||
if (this.isEditMode) return updateCustomerRelationsOrganizationMutation;
|
||||
|
||||
return createCustomerRelationsOrganizationMutation;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -228,6 +228,24 @@ async function fetchOperations(operationsUrl, serviceName) {
|
|||
}
|
||||
}
|
||||
|
||||
async function fetchMetrics() {
|
||||
// TODO replace mocks with API calls https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2469
|
||||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
return {
|
||||
metrics: [
|
||||
{ name: 'metric A', description: 'a counter metric called A', type: 'COUNTER' },
|
||||
{ name: 'metric B', description: 'a gauge metric called B', type: 'GAUGE' },
|
||||
{ name: 'metric C', description: 'a histogram metric called C', type: 'HISTOGRAM' },
|
||||
{
|
||||
name: 'metric D',
|
||||
description: 'a exp histogram metric called D',
|
||||
type: 'EXPONENTIAL HISTOGRAM',
|
||||
},
|
||||
],
|
||||
};
|
||||
/* eslint-enable @gitlab/require-i18n-strings */
|
||||
}
|
||||
|
||||
export function buildClient({ provisioningUrl, tracingUrl, servicesUrl, operationsUrl } = {}) {
|
||||
if (!provisioningUrl || !tracingUrl || !servicesUrl || !operationsUrl) {
|
||||
throw new Error(
|
||||
|
|
@ -241,5 +259,6 @@ export function buildClient({ provisioningUrl, tracingUrl, servicesUrl, operatio
|
|||
fetchTrace: (traceId) => fetchTrace(tracingUrl, traceId),
|
||||
fetchServices: () => fetchServices(servicesUrl),
|
||||
fetchOperations: (serviceName) => fetchOperations(operationsUrl, serviceName),
|
||||
fetchMetrics: () => fetchMetrics(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,3 +288,11 @@ export const createOrganizationResponse = {
|
|||
},
|
||||
errors: [],
|
||||
};
|
||||
|
||||
export const updateOrganizationResponse = {
|
||||
organization: {
|
||||
id: 'gid://gitlab/Organizations/1',
|
||||
name: 'Default updated',
|
||||
},
|
||||
errors: [],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<script>
|
||||
import OrganizationSettings from './organization_settings.vue';
|
||||
|
||||
export default {
|
||||
name: 'OrganizationSettingsGeneralApp',
|
||||
components: { OrganizationSettings },
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<organization-settings />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<script>
|
||||
import { s__, __ } from '~/locale';
|
||||
import { createAlert, VARIANT_INFO } from '~/alert';
|
||||
import NewEditForm from '~/organizations/shared/components/new_edit_form.vue';
|
||||
import { FORM_FIELD_NAME, FORM_FIELD_ID } from '~/organizations/shared/constants';
|
||||
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
|
||||
import updateOrganizationMutation from '../graphql/mutations/update_organization.mutation.graphql';
|
||||
|
||||
export default {
|
||||
name: 'OrganizationSettings',
|
||||
components: { NewEditForm, SettingsBlock },
|
||||
inject: ['organization'],
|
||||
i18n: {
|
||||
submitButtonText: __('Save changes'),
|
||||
settingsBlock: {
|
||||
title: s__('Organization|Organization settings'),
|
||||
description: s__('Organization|Update your organization name, description, and avatar.'),
|
||||
},
|
||||
errorMessage: s__(
|
||||
'Organization|An error occurred updating your organization. Please try again.',
|
||||
),
|
||||
successMessage: s__('Organization|Organization was successfully updated.'),
|
||||
},
|
||||
fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async onSubmit(formValues) {
|
||||
this.loading = true;
|
||||
try {
|
||||
const {
|
||||
data: {
|
||||
updateOrganization: { errors },
|
||||
},
|
||||
} = await this.$apollo.mutate({
|
||||
mutation: updateOrganizationMutation,
|
||||
variables: {
|
||||
id: this.organization.id,
|
||||
name: formValues.name,
|
||||
},
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
// TODO: handle errors when using real API after https://gitlab.com/gitlab-org/gitlab/-/issues/419608 is complete.
|
||||
return;
|
||||
}
|
||||
|
||||
createAlert({ message: this.$options.i18n.successMessage, variant: VARIANT_INFO });
|
||||
} catch (error) {
|
||||
createAlert({ message: this.$options.i18n.errorMessage, error, captureError: true });
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<settings-block default-expanded slide-animated>
|
||||
<template #title>{{ $options.i18n.settingsBlock.title }}</template>
|
||||
<template #description>{{ $options.i18n.settingsBlock.description }}</template>
|
||||
<template #default>
|
||||
<new-edit-form
|
||||
:loading="loading"
|
||||
:initial-form-values="organization"
|
||||
:fields-to-render="$options.fieldsToRender"
|
||||
:submit-button-text="$options.i18n.submitButtonText"
|
||||
:show-cancel-button="false"
|
||||
@submit="onSubmit"
|
||||
/>
|
||||
</template>
|
||||
</settings-block>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
mutation updateOrganization($input: LocalUpdateOrganizationInput!) {
|
||||
updateOrganization(input: $input) @client {
|
||||
organization {
|
||||
id
|
||||
name
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# TODO: Use real input type when https://gitlab.com/gitlab-org/gitlab/-/issues/419608 is complete.
|
||||
input LocalUpdateOrganizationInput {
|
||||
id: ID!
|
||||
name: String
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
|
||||
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import resolvers from '../../shared/graphql/resolvers';
|
||||
import App from './components/app.vue';
|
||||
|
||||
export const initOrganizationsSettingsGeneral = () => {
|
||||
const el = document.getElementById('js-organizations-settings-general');
|
||||
|
||||
if (!el) return false;
|
||||
|
||||
const {
|
||||
dataset: { appData },
|
||||
} = el;
|
||||
const { organization, organizationsPath, rootUrl } = convertObjectPropsToCamelCase(
|
||||
JSON.parse(appData),
|
||||
);
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: createDefaultClient(resolvers),
|
||||
});
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'OrganizationSettingsGeneralRoot',
|
||||
apolloProvider,
|
||||
provide: {
|
||||
organization,
|
||||
organizationsPath,
|
||||
rootUrl,
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement(App);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -12,6 +12,7 @@ import { formValidators } from '@gitlab/ui/dist/utils';
|
|||
import { s__, __ } from '~/locale';
|
||||
import { slugify } from '~/lib/utils/text_utility';
|
||||
import { joinPaths } from '~/lib/utils/url_utility';
|
||||
import { FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_PATH } from '../constants';
|
||||
|
||||
export default {
|
||||
name: 'NewEditForm',
|
||||
|
|
@ -25,43 +26,47 @@ export default {
|
|||
GlTruncate,
|
||||
},
|
||||
i18n: {
|
||||
createOrganization: s__('Organization|Create organization'),
|
||||
cancel: __('Cancel'),
|
||||
pathPlaceholder: s__('Organization|my-organization'),
|
||||
},
|
||||
formId: 'new-organization-form',
|
||||
fields: {
|
||||
name: {
|
||||
label: s__('Organization|Organization name'),
|
||||
validators: [formValidators.required(s__('Organization|Organization name is required.'))],
|
||||
groupAttrs: {
|
||||
description: s__(
|
||||
'Organization|Must start with a letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.',
|
||||
),
|
||||
},
|
||||
inputAttrs: {
|
||||
class: 'gl-md-form-input-lg',
|
||||
placeholder: s__('Organization|My organization'),
|
||||
},
|
||||
},
|
||||
path: {
|
||||
label: s__('Organization|Organization URL'),
|
||||
validators: [formValidators.required(s__('Organization|Organization URL is required.'))],
|
||||
},
|
||||
},
|
||||
inject: ['organizationsPath', 'rootUrl'],
|
||||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
initialFormValues: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default() {
|
||||
return {
|
||||
[FORM_FIELD_NAME]: '',
|
||||
[FORM_FIELD_PATH]: '',
|
||||
};
|
||||
},
|
||||
},
|
||||
fieldsToRender: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default() {
|
||||
return [FORM_FIELD_NAME, FORM_FIELD_PATH];
|
||||
},
|
||||
},
|
||||
submitButtonText: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: s__('Organization|Create organization'),
|
||||
},
|
||||
showCancelButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formValues: {
|
||||
name: '',
|
||||
path: '',
|
||||
},
|
||||
formValues: this.initialFormValues,
|
||||
hasPathBeenManuallySet: false,
|
||||
};
|
||||
},
|
||||
|
|
@ -69,10 +74,57 @@ export default {
|
|||
baseUrl() {
|
||||
return joinPaths(this.rootUrl, this.organizationsPath, '/');
|
||||
},
|
||||
fields() {
|
||||
const fields = {
|
||||
[FORM_FIELD_NAME]: {
|
||||
label: s__('Organization|Organization name'),
|
||||
validators: [formValidators.required(s__('Organization|Organization name is required.'))],
|
||||
groupAttrs: {
|
||||
class: this.fieldsToRender.includes(FORM_FIELD_ID)
|
||||
? 'gl-flex-grow-1 gl-md-form-input-lg'
|
||||
: 'gl-flex-grow-1',
|
||||
description: s__(
|
||||
'Organization|Must start with a letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.',
|
||||
),
|
||||
},
|
||||
inputAttrs: {
|
||||
class: !this.fieldsToRender.includes(FORM_FIELD_ID) ? 'gl-md-form-input-lg' : null,
|
||||
placeholder: s__('Organization|My organization'),
|
||||
},
|
||||
},
|
||||
[FORM_FIELD_ID]: {
|
||||
label: s__('Organization|Organization ID'),
|
||||
groupAttrs: {
|
||||
class: 'gl-md-form-input-lg gl-flex-grow-1',
|
||||
},
|
||||
inputAttrs: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
[FORM_FIELD_PATH]: {
|
||||
label: s__('Organization|Organization URL'),
|
||||
validators: [formValidators.required(s__('Organization|Organization URL is required.'))],
|
||||
groupAttrs: {
|
||||
class: 'gl-w-full',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return Object.entries(fields).reduce((accumulator, [fieldKey, fieldDefinition]) => {
|
||||
if (!this.fieldsToRender.includes(fieldKey)) {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
return {
|
||||
...accumulator,
|
||||
[fieldKey]: fieldDefinition,
|
||||
};
|
||||
}, {});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'formValues.name': function watchName(value) {
|
||||
if (this.hasPathBeenManuallySet) {
|
||||
if (this.hasPathBeenManuallySet || !this.fieldsToRender.includes(FORM_FIELD_PATH)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +145,8 @@ export default {
|
|||
<gl-form-fields
|
||||
v-model="formValues"
|
||||
:form-id="$options.formId"
|
||||
:fields="$options.fields"
|
||||
:fields="fields"
|
||||
class="gl-display-flex gl-column-gap-5 gl-flex-wrap"
|
||||
@submit="$emit('submit', formValues)"
|
||||
>
|
||||
<template #input(path)="{ id, value, validation, input, blur }">
|
||||
|
|
@ -117,9 +170,11 @@ export default {
|
|||
</gl-form-fields>
|
||||
<div class="gl-display-flex gl-gap-3">
|
||||
<gl-button type="submit" variant="confirm" class="js-no-auto-disable" :loading="loading">{{
|
||||
$options.i18n.createOrganization
|
||||
submitButtonText
|
||||
}}</gl-button>
|
||||
<gl-button v-if="showCancelButton" :href="organizationsPath">{{
|
||||
$options.i18n.cancel
|
||||
}}</gl-button>
|
||||
<gl-button :href="organizationsPath">{{ $options.i18n.cancel }}</gl-button>
|
||||
</div>
|
||||
</gl-form>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export const FORM_FIELD_NAME = 'name';
|
||||
export const FORM_FIELD_ID = 'id';
|
||||
export const FORM_FIELD_PATH = 'path';
|
||||
|
|
@ -3,6 +3,7 @@ import {
|
|||
organizationProjects,
|
||||
organizationGroups,
|
||||
createOrganizationResponse,
|
||||
updateOrganizationResponse,
|
||||
} from '../../mock_data';
|
||||
|
||||
const simulateLoading = () => {
|
||||
|
|
@ -40,5 +41,11 @@ export default {
|
|||
|
||||
return createOrganizationResponse;
|
||||
},
|
||||
updateOrganization: async () => {
|
||||
// Simulate API loading
|
||||
await simulateLoading();
|
||||
|
||||
return updateOrganizationResponse;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import { initOrganizationsSettingsGeneral } from '~/organizations/settings/general';
|
||||
|
||||
initOrganizationsSettingsGeneral();
|
||||
|
|
@ -105,7 +105,7 @@ export default {
|
|||
};
|
||||
},
|
||||
update(data) {
|
||||
return data.workspace.workItems.nodes[0];
|
||||
return data.workspace.workItems.nodes[0] ?? {};
|
||||
},
|
||||
skip() {
|
||||
return !this.workItemIid;
|
||||
|
|
@ -150,13 +150,13 @@ export default {
|
|||
};
|
||||
},
|
||||
isProjectArchived() {
|
||||
return this.workItem?.project?.archived;
|
||||
return this.workItem.archived;
|
||||
},
|
||||
canCreateNote() {
|
||||
return this.workItem?.userPermissions?.createNote;
|
||||
return this.workItem.userPermissions?.createNote;
|
||||
},
|
||||
workItemState() {
|
||||
return this.workItem?.state;
|
||||
return this.workItem.state;
|
||||
},
|
||||
commentButtonText() {
|
||||
return this.isNewDiscussion ? __('Comment') : __('Reply');
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
isEditing: false,
|
||||
workItem: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -163,13 +164,13 @@ export default {
|
|||
return this.authorId === this.currentUserId;
|
||||
},
|
||||
isWorkItemAuthor() {
|
||||
return getIdFromGraphQLId(this.workItem?.author?.id) === this.authorId;
|
||||
return getIdFromGraphQLId(this.workItem.author?.id) === this.authorId;
|
||||
},
|
||||
projectName() {
|
||||
return this.workItem?.project?.name;
|
||||
return this.workItem.namespace?.name;
|
||||
},
|
||||
isWorkItemConfidential() {
|
||||
return this.workItem?.confidential;
|
||||
return this.workItem.confidential;
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
|
|
@ -184,7 +185,7 @@ export default {
|
|||
};
|
||||
},
|
||||
update(data) {
|
||||
return data.workspace?.workItems?.nodes[0];
|
||||
return data.workspace?.workItems?.nodes[0] ?? {};
|
||||
},
|
||||
skip() {
|
||||
return !this.workItemIid;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlLabel, GlLink, GlIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import { GlLabel, GlLink, GlIcon, GlTooltipDirective, GlButton } from '@gitlab/ui';
|
||||
import { __, s__ } from '~/locale';
|
||||
import { isScopedLabel } from '~/lib/utils/common_utils';
|
||||
import RichTimestampTooltip from '~/vue_shared/components/rich_timestamp_tooltip.vue';
|
||||
import WorkItemLinkChildMetadata from 'ee_else_ce/work_items/components/shared/work_item_link_child_metadata.vue';
|
||||
|
|
@ -15,21 +15,21 @@ import {
|
|||
WIDGET_TYPE_LABELS,
|
||||
WORK_ITEM_NAME_TO_ICON_MAP,
|
||||
} from '../../constants';
|
||||
import WorkItemLinksMenu from './work_item_links_menu.vue';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
confidential: __('Confidential'),
|
||||
created: __('Created'),
|
||||
closed: __('Closed'),
|
||||
remove: s__('WorkItem|Remove'),
|
||||
},
|
||||
components: {
|
||||
GlLabel,
|
||||
GlLink,
|
||||
GlIcon,
|
||||
GlButton,
|
||||
RichTimestampTooltip,
|
||||
WorkItemLinkChildMetadata,
|
||||
WorkItemLinksMenu,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
@ -53,6 +53,11 @@ export default {
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isFocused: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
labels() {
|
||||
return this.metadataWidgets[WIDGET_TYPE_LABELS]?.labels?.nodes || [];
|
||||
|
|
@ -106,6 +111,9 @@ export default {
|
|||
}
|
||||
return false;
|
||||
},
|
||||
showRemove() {
|
||||
return this.canUpdate && this.isFocused;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showScopedLabel(label) {
|
||||
|
|
@ -117,8 +125,12 @@ export default {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="item-body work-item-link-child gl-relative gl-display-flex gl-flex-grow-1 gl-overflow-break-word gl-min-w-0 gl-pl-3 gl-pr-2 gl-py-2 gl-mx-n2 gl-rounded-base"
|
||||
class="item-body work-item-link-child gl-relative gl-display-flex gl-flex-grow-1 gl-overflow-break-word gl-min-w-0 gl-pl-3 gl-pr-2 gl-py-2 gl-mx-n2 gl-rounded-base gl-gap-3"
|
||||
data-testid="links-child"
|
||||
@mouseover="isFocused = true"
|
||||
@mouseleave="isFocused = false"
|
||||
@focusin="isFocused = true"
|
||||
@focusout="isFocused = false"
|
||||
>
|
||||
<div class="item-contents gl-display-flex gl-flex-grow-1 gl-flex-wrap gl-min-w-0">
|
||||
<div
|
||||
|
|
@ -181,10 +193,16 @@ export default {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="canUpdate" class="gl-ml-0 gl-sm-ml-auto! gl-display-inline-flex">
|
||||
<work-item-links-menu
|
||||
data-testid="links-menu"
|
||||
@removeChild="$emit('removeChild', childItem)"
|
||||
<div v-if="canUpdate">
|
||||
<gl-button
|
||||
:class="{ 'gl-visibility-visible': showRemove }"
|
||||
class="gl-visibility-hidden"
|
||||
category="tertiary"
|
||||
size="small"
|
||||
icon="close"
|
||||
:aria-label="$options.i18n.remove"
|
||||
data-testid="remove-work-item-link"
|
||||
@click="$emit('removeChild', childItem)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<script>
|
||||
import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlDisclosureDropdownItem,
|
||||
GlDisclosureDropdown,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gl-ml-5">
|
||||
<gl-disclosure-dropdown
|
||||
category="tertiary"
|
||||
toggle-class="btn-icon btn-sm"
|
||||
icon="ellipsis_v"
|
||||
data-testid="work_items_links_menu"
|
||||
:aria-label="__(`More actions`)"
|
||||
text-sr-only
|
||||
no-caret
|
||||
>
|
||||
<gl-disclosure-dropdown-item @action="$emit('removeChild')">
|
||||
<template #list-item>{{ s__('WorkItem|Remove') }}</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
</gl-disclosure-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -146,9 +146,9 @@ export default {
|
|||
if (isEmpty(this.workItem)) {
|
||||
this.setEmptyState();
|
||||
}
|
||||
if (!this.isModal && this.workItem.project) {
|
||||
const path = this.workItem.project?.fullPath
|
||||
? ` · ${this.workItem.project.fullPath}`
|
||||
if (!this.isModal && this.workItem.namespace) {
|
||||
const path = this.workItem.namespace.fullPath
|
||||
? ` · ${this.workItem.namespace.fullPath}`
|
||||
: '';
|
||||
|
||||
document.title = `${this.workItem.title} · ${this.workItem?.workItemType?.name}${path}`;
|
||||
|
|
@ -181,19 +181,19 @@ export default {
|
|||
return this.workItemType ? `#${this.workItem.iid}` : '';
|
||||
},
|
||||
canUpdate() {
|
||||
return this.workItem?.userPermissions?.updateWorkItem;
|
||||
return this.workItem.userPermissions?.updateWorkItem;
|
||||
},
|
||||
canDelete() {
|
||||
return this.workItem?.userPermissions?.deleteWorkItem;
|
||||
return this.workItem.userPermissions?.deleteWorkItem;
|
||||
},
|
||||
canSetWorkItemMetadata() {
|
||||
return this.workItem?.userPermissions?.setWorkItemMetadata;
|
||||
return this.workItem.userPermissions?.setWorkItemMetadata;
|
||||
},
|
||||
canAssignUnassignUser() {
|
||||
return this.workItemAssignees && this.canSetWorkItemMetadata;
|
||||
},
|
||||
projectFullPath() {
|
||||
return this.workItem?.project?.fullPath;
|
||||
return this.workItem.namespace?.fullPath;
|
||||
},
|
||||
workItemsMvc2Enabled() {
|
||||
return this.glFeatures.workItemsMvc2;
|
||||
|
|
@ -222,7 +222,7 @@ export default {
|
|||
return this.parentWorkItem?.webUrl;
|
||||
},
|
||||
workItemIconName() {
|
||||
return this.workItem?.workItemType?.iconName;
|
||||
return this.workItem.workItemType?.iconName;
|
||||
},
|
||||
noAccessSvgPath() {
|
||||
return `data:image/svg+xml;utf8,${encodeURIComponent(noAccessSvg)}`;
|
||||
|
|
@ -285,7 +285,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
isWidgetPresent(type) {
|
||||
return this.workItem?.widgets?.find((widget) => widget.type === type);
|
||||
return this.workItem.widgets?.find((widget) => widget.type === type);
|
||||
},
|
||||
toggleConfidentiality(confidentialStatus) {
|
||||
this.updateInProgress = true;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
fragment WorkItem on WorkItem {
|
||||
id
|
||||
iid
|
||||
archived
|
||||
title
|
||||
state
|
||||
description
|
||||
|
|
@ -13,10 +14,9 @@ fragment WorkItem on WorkItem {
|
|||
closedAt
|
||||
reference(full: true)
|
||||
createNoteEmail
|
||||
project {
|
||||
namespace {
|
||||
id
|
||||
fullPath
|
||||
archived
|
||||
name
|
||||
}
|
||||
author {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export default {
|
|||
data: {
|
||||
workspace: {
|
||||
__typename: TYPENAME_PROJECT,
|
||||
id: workItem.project.id,
|
||||
id: workItem.namespace.id,
|
||||
workItems: {
|
||||
__typename: 'WorkItemConnection',
|
||||
nodes: [workItem],
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
# last_activity_before: datetime
|
||||
# repository_storage: string
|
||||
# not_aimed_for_deletion: boolean
|
||||
# full_paths: string[]
|
||||
#
|
||||
class ProjectsFinder < UnionFinder
|
||||
include CustomAttributesFilter
|
||||
|
|
@ -78,6 +79,7 @@ class ProjectsFinder < UnionFinder
|
|||
def filter_projects(collection)
|
||||
collection = collection.without_deleted
|
||||
collection = by_ids(collection)
|
||||
collection = by_full_paths(collection)
|
||||
collection = by_personal(collection)
|
||||
collection = by_starred(collection)
|
||||
collection = by_trending(collection)
|
||||
|
|
@ -162,6 +164,10 @@ class ProjectsFinder < UnionFinder
|
|||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def by_full_paths(items)
|
||||
params[:full_paths].present? ? items.where_full_path_in(params[:full_paths], use_includes: false) : items
|
||||
end
|
||||
|
||||
def union(items)
|
||||
find_union(items, Project).with_route
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
module Resolvers
|
||||
class ProjectsResolver < BaseResolver
|
||||
include ProjectSearchArguments
|
||||
include LooksAhead
|
||||
|
||||
type Types::ProjectType.connection_type, null: true
|
||||
|
||||
|
|
@ -10,6 +11,10 @@ module Resolvers
|
|||
required: false,
|
||||
description: 'Filter projects by IDs.'
|
||||
|
||||
argument :full_paths, [GraphQL::Types::String],
|
||||
required: false,
|
||||
description: 'Filter projects by full paths. You cannot provide more than 50 full paths.'
|
||||
|
||||
argument :sort, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
|
||||
|
|
@ -23,19 +28,48 @@ module Resolvers
|
|||
required: false,
|
||||
description: "Return only projects with merge requests enabled."
|
||||
|
||||
def resolve(**args)
|
||||
ProjectsFinder
|
||||
def resolve_with_lookahead(**args)
|
||||
validate_args!(args)
|
||||
|
||||
projects = ProjectsFinder
|
||||
.new(current_user: current_user, params: finder_params(args), project_ids_relation: parse_gids(args[:ids]))
|
||||
.execute
|
||||
|
||||
apply_lookahead(projects)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_args!(args)
|
||||
return unless args[:full_paths].present? && args[:full_paths].length > 50
|
||||
|
||||
raise Gitlab::Graphql::Errors::ArgumentError, 'You cannot provide more than 50 full_paths'
|
||||
end
|
||||
|
||||
def unconditional_includes
|
||||
[:creator, :group, :invited_groups, :project_setting]
|
||||
end
|
||||
|
||||
def preloads
|
||||
{
|
||||
full_path: [:route],
|
||||
topics: [:topics],
|
||||
import_status: [:import_state],
|
||||
service_desk_address: [:project_feature, :service_desk_setting],
|
||||
jira_import_status: [:jira_imports],
|
||||
container_repositories: [:container_repositories],
|
||||
container_repositories_count: [:container_repositories],
|
||||
web_url: { namespace: [:route] },
|
||||
is_catalog_resource: [:catalog_resource]
|
||||
}
|
||||
end
|
||||
|
||||
def finder_params(args)
|
||||
{
|
||||
**project_finder_params(args),
|
||||
with_issues_enabled: args[:with_issues_enabled],
|
||||
with_merge_requests_enabled: args[:with_merge_requests_enabled]
|
||||
with_merge_requests_enabled: args[:with_merge_requests_enabled],
|
||||
full_paths: args[:full_paths]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -44,3 +78,5 @@ module Resolvers
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Resolvers::ProjectsResolver.prepend_mod_with('Resolvers::ProjectsResolver')
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@ module Organizations
|
|||
}.to_json
|
||||
end
|
||||
|
||||
def organization_settings_general_app_data(organization)
|
||||
{
|
||||
organization: organization.slice(:id, :name, :path),
|
||||
organizations_path: organizations_path,
|
||||
root_url: root_url
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def organization_groups_and_projects_app_data
|
||||
shared_groups_and_projects_app_data.to_json
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ module Ml
|
|||
presence: true,
|
||||
length: { maximum: 255 }
|
||||
|
||||
validates :description,
|
||||
length: { maximum: 500 }
|
||||
|
||||
validate :valid_model?, :valid_package?
|
||||
|
||||
belongs_to :model, class_name: 'Ml::Model'
|
||||
|
|
@ -24,8 +27,9 @@ module Ml
|
|||
scope :latest_by_model, -> { order_by_model_id_id_desc.select('DISTINCT ON (model_id) *') }
|
||||
|
||||
class << self
|
||||
def find_or_create!(model, version, package)
|
||||
create_with(package: package).find_or_create_by!(project: model.project, model: model, version: version)
|
||||
def find_or_create!(model, version, package, description)
|
||||
create_with(package: package, description: description)
|
||||
.find_or_create_by!(project: model.project, model: model, version: version)
|
||||
end
|
||||
|
||||
def by_project_id_and_id(project_id, id)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ module Ml
|
|||
@name = params[:model_name]
|
||||
@version = params[:version]
|
||||
@package = params[:package]
|
||||
@description = params[:description]
|
||||
end
|
||||
|
||||
def execute
|
||||
model = Ml::FindOrCreateModelService.new(project, name).execute
|
||||
Ml::ModelVersion.find_or_create!(model, version, package)
|
||||
Ml::ModelVersion.find_or_create!(model, version, package, description)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :version, :name, :project, :package
|
||||
attr_reader :version, :name, :project, :package, :description
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
- if Gitlab.ee? && ::Gitlab::Llm::TanukiBot.show_breadcrumbs_entry_point_for?(user: current_user)
|
||||
- label = s_('TanukiBot|GitLab Duo Chat')
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm,
|
||||
= render Pajamas::ButtonComponent.new(variant: :default,
|
||||
category: :secondary,
|
||||
icon: 'tanuki-ai',
|
||||
size: 'small',
|
||||
size: 'medium',
|
||||
button_options: { class: 'js-tanuki-bot-chat-toggle gl-ml-3 gl-display-none gl-md-display-inline', data: { track_action: 'click_button', track_label: 'tanuki_bot_breadcrumbs_button' }, aria: { label: label }}) do
|
||||
= label
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm,
|
||||
= render Pajamas::ButtonComponent.new(variant: :default,
|
||||
category: :secondary,
|
||||
icon: 'tanuki-ai',
|
||||
size: 'small',
|
||||
size: 'medium',
|
||||
button_options: { class: 'js-tanuki-bot-chat-toggle has-tooltip gl-ml-3 gl-md-display-none', title: label, data: { track_action: 'click_button', track_label: 'tanuki_bot_breadcrumbs_button', placement: 'left' }, aria: { label: label }})
|
||||
|
|
|
|||
|
|
@ -1 +1,4 @@
|
|||
- page_title _("General settings")
|
||||
- add_page_specific_style 'page_bundles/settings'
|
||||
|
||||
#js-organizations-settings-general{ data: { app_data: organization_settings_general_app_data(@organization) } }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDescriptionToMlModelVersions < Gitlab::Database::Migration[2.1]
|
||||
def change
|
||||
# rubocop:disable Migration/AddLimitToTextColumns -- limit being added on 20231023122508
|
||||
add_column :ml_model_versions, :description, :text
|
||||
# rubocop:enable Migration/AddLimitToTextColumns
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddTextLimitToDescriptionsOnMlModelVersions < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_text_limit :ml_model_versions, :description, 500
|
||||
end
|
||||
|
||||
def down
|
||||
remove_text_limit :ml_model_versions, :description
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
912289edbed417e2e552e8d0c6d44d37b1066531d3dd28a6960fce47a8fcbe52
|
||||
|
|
@ -0,0 +1 @@
|
|||
b4850d28d0000d9dd7f81df26a5b9f4b5a38c2f0d33a48037ab5c097789345d8
|
||||
|
|
@ -18905,7 +18905,9 @@ CREATE TABLE ml_model_versions (
|
|||
model_id bigint NOT NULL,
|
||||
package_id bigint,
|
||||
version text NOT NULL,
|
||||
CONSTRAINT check_28b2d892c8 CHECK ((char_length(version) <= 255))
|
||||
description text,
|
||||
CONSTRAINT check_28b2d892c8 CHECK ((char_length(version) <= 255)),
|
||||
CONSTRAINT check_caff7d000b CHECK ((char_length(description) <= 500))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ml_model_versions_id_seq
|
||||
|
|
|
|||
|
|
@ -627,6 +627,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="queryprojectsfullpaths"></a>`fullPaths` | [`[String!]`](#string) | Filter projects by full paths. You cannot provide more than 50 full paths. |
|
||||
| <a id="queryprojectsids"></a>`ids` | [`[ID!]`](#id) | Filter projects by IDs. |
|
||||
| <a id="queryprojectsmembership"></a>`membership` | [`Boolean`](#boolean) | Return only projects that the current user is a member of. |
|
||||
| <a id="queryprojectssearch"></a>`search` | [`String`](#string) | Search query, which can be for the project name, a path, or a description. |
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ module Gitlab
|
|||
.sort
|
||||
.each do |counter|
|
||||
object_type = counter.split('/').last
|
||||
result[operation][object_type] = CACHING.read_integer(counter) || 0
|
||||
result[operation][object_type] = CACHING.read_integer(counter, timeout: IMPORT_CACHING_TIMEOUT) || 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29979,6 +29979,9 @@ msgstr ""
|
|||
msgid "Metrics:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Check again"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Create metric"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -29988,9 +29991,15 @@ msgstr ""
|
|||
msgid "Metrics|Delete metric?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Description"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Edit metric"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Failed to load metrics."
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|For grouping similar metrics"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -30000,12 +30009,21 @@ msgstr ""
|
|||
msgid "Metrics|Legend label (optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Metrics"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Must be a valid PromQL query."
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|New metric"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|No metrics to display."
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|PromQL query is valid"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -30015,6 +30033,9 @@ msgstr ""
|
|||
msgid "Metrics|There was an error trying to validate your query"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Type"
|
||||
msgstr ""
|
||||
|
||||
msgid "Metrics|Unit label"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33201,6 +33222,9 @@ msgstr ""
|
|||
msgid "Organization|An error occurred loading user organizations. Please refresh the page to try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|An error occurred updating your organization. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Copy organization ID"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33234,6 +33258,9 @@ msgstr ""
|
|||
msgid "Organization|Org ID"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Organization ID"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Organization URL"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33252,9 +33279,15 @@ msgstr ""
|
|||
msgid "Organization|Organization overview"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Organization settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Organization successfully created."
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Organization was successfully updated."
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Organizations"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33264,6 +33297,9 @@ msgstr ""
|
|||
msgid "Organization|Search or filter list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|Update your organization name, description, and avatar."
|
||||
msgstr ""
|
||||
|
||||
msgid "Organization|View all"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@
|
|||
"remark-rehype": "^10.1.0",
|
||||
"scrollparent": "^2.0.1",
|
||||
"semver": "^7.3.4",
|
||||
"sentrybrowser": "npm:@sentry/browser@7.73.0",
|
||||
"sentrybrowser": "npm:@sentry/browser@7.74.1",
|
||||
"sentrybrowser5": "npm:@sentry/browser@5.30.0",
|
||||
"sortablejs": "^1.10.2",
|
||||
"string-hash": "1.1.3",
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ RSpec.describe 'Work item linked items', :js, feature_category: :team_planning d
|
|||
|
||||
expect(find('.work-items-list')).to have_content('Task 1')
|
||||
|
||||
find_by_testid('links-menu').click
|
||||
click_button 'Remove'
|
||||
find_by_testid('links-child').hover
|
||||
find_by_testid('remove-work-item-link').click
|
||||
|
||||
wait_for_all_requests
|
||||
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ RSpec.describe 'Work item children', :js, feature_category: :team_planning do
|
|||
expect(find('[data-testid="links-child"]')).to have_content('Task 1')
|
||||
expect(find('[data-testid="children-count"]')).to have_content('1')
|
||||
|
||||
find('[data-testid="links-menu"]').click
|
||||
click_button 'Remove'
|
||||
find_by_testid('links-child').hover
|
||||
find_by_testid('remove-work-item-link').click
|
||||
|
||||
wait_for_all_requests
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,18 @@ RSpec.describe ProjectsFinder, feature_category: :groups_and_projects do
|
|||
it { is_expected.to eq([internal_project]) }
|
||||
end
|
||||
|
||||
describe 'with full_paths' do
|
||||
let_it_be(:second_public_project) do
|
||||
create(:project, :public, :merge_requests_enabled, :issues_disabled, group: group, name: 'second-public', path: 'second-public')
|
||||
end
|
||||
|
||||
context 'only returns projects matching the provided full paths' do
|
||||
let(:params) { { full_paths: [public_project.full_path, second_public_project.full_path] } }
|
||||
|
||||
it { is_expected.to match_array([public_project, second_public_project]) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with id_after' do
|
||||
context 'only returns projects with a project id greater than given' do
|
||||
let(:params) { { id_after: internal_project.id } }
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
|||
import OrganizationFormWrapper from '~/crm/organizations/components/organization_form_wrapper.vue';
|
||||
import CrmForm from '~/crm/components/crm_form.vue';
|
||||
import getGroupOrganizationsQuery from '~/crm/organizations/components/graphql/get_group_organizations.query.graphql';
|
||||
import createOrganizationMutation from '~/crm/organizations/components/graphql/create_customer_relations_organization.mutation.graphql';
|
||||
import updateOrganizationMutation from '~/crm/organizations/components/graphql/update_organization.mutation.graphql';
|
||||
import createCustomerRelationsOrganizationMutation from '~/crm/organizations/components/graphql/create_customer_relations_organization.mutation.graphql';
|
||||
import updateCustomerRelationsOrganizationMutation from '~/crm/organizations/components/graphql/update_customer_relations_organization.mutation.graphql';
|
||||
|
||||
describe('Customer relations organization form wrapper', () => {
|
||||
let wrapper;
|
||||
|
|
@ -48,7 +48,7 @@ describe('Customer relations organization form wrapper', () => {
|
|||
expect(organizationForm.props('fields')).toHaveLength(4);
|
||||
expect(organizationForm.props('title')).toBe('Edit organization');
|
||||
expect(organizationForm.props('successMessage')).toBe('Organization has been updated.');
|
||||
expect(organizationForm.props('mutation')).toBe(updateOrganizationMutation);
|
||||
expect(organizationForm.props('mutation')).toBe(updateCustomerRelationsOrganizationMutation);
|
||||
expect(organizationForm.props('getQuery')).toMatchObject({
|
||||
query: getGroupOrganizationsQuery,
|
||||
variables: { groupFullPath: 'flightjs' },
|
||||
|
|
@ -69,7 +69,7 @@ describe('Customer relations organization form wrapper', () => {
|
|||
expect(organizationForm.props('fields')).toHaveLength(3);
|
||||
expect(organizationForm.props('title')).toBe('New organization');
|
||||
expect(organizationForm.props('successMessage')).toBe('Organization has been added.');
|
||||
expect(organizationForm.props('mutation')).toBe(createOrganizationMutation);
|
||||
expect(organizationForm.props('mutation')).toBe(createCustomerRelationsOrganizationMutation);
|
||||
expect(organizationForm.props('getQuery')).toMatchObject({
|
||||
query: getGroupOrganizationsQuery,
|
||||
variables: { groupFullPath: 'flightjs' },
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import OrganizationSettings from '~/organizations/settings/general/components/organization_settings.vue';
|
||||
import App from '~/organizations/settings/general/components/app.vue';
|
||||
|
||||
describe('OrganizationSettings', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = () => {
|
||||
wrapper = shallowMountExtended(App);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders `Organization settings` section', () => {
|
||||
expect(wrapper.findComponent(OrganizationSettings).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
import VueApollo from 'vue-apollo';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import OrganizationSettings from '~/organizations/settings/general/components/organization_settings.vue';
|
||||
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
|
||||
import NewEditForm from '~/organizations/shared/components/new_edit_form.vue';
|
||||
import { FORM_FIELD_NAME, FORM_FIELD_ID } from '~/organizations/shared/constants';
|
||||
import resolvers from '~/organizations/shared/graphql/resolvers';
|
||||
import { createAlert, VARIANT_INFO } from '~/alert';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
jest.useFakeTimers();
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('OrganizationSettings', () => {
|
||||
let wrapper;
|
||||
let mockApollo;
|
||||
|
||||
const defaultProvide = {
|
||||
organization: {
|
||||
id: 1,
|
||||
name: 'GitLab',
|
||||
},
|
||||
};
|
||||
|
||||
const createComponent = ({ mockResolvers = resolvers } = {}) => {
|
||||
mockApollo = createMockApollo([], mockResolvers);
|
||||
|
||||
wrapper = shallowMountExtended(OrganizationSettings, {
|
||||
provide: defaultProvide,
|
||||
apolloProvider: mockApollo,
|
||||
});
|
||||
};
|
||||
|
||||
const findForm = () => wrapper.findComponent(NewEditForm);
|
||||
const submitForm = async () => {
|
||||
findForm().vm.$emit('submit', { name: 'Foo bar', path: 'foo-bar' });
|
||||
await nextTick();
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockApollo = null;
|
||||
});
|
||||
|
||||
it('renders settings block', () => {
|
||||
expect(wrapper.findComponent(SettingsBlock).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders form with correct props', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findForm().props()).toMatchObject({
|
||||
loading: false,
|
||||
initialFormValues: defaultProvide.organization,
|
||||
fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID],
|
||||
});
|
||||
});
|
||||
|
||||
describe('when form is submitted', () => {
|
||||
describe('when API is loading', () => {
|
||||
beforeEach(async () => {
|
||||
const mockResolvers = {
|
||||
Mutation: {
|
||||
updateOrganization: jest.fn().mockReturnValueOnce(new Promise(() => {})),
|
||||
},
|
||||
};
|
||||
|
||||
createComponent({ mockResolvers });
|
||||
|
||||
await submitForm();
|
||||
});
|
||||
|
||||
it('sets form `loading` prop to `true`', () => {
|
||||
expect(findForm().props('loading')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when API request is successful', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent();
|
||||
await submitForm();
|
||||
jest.runAllTimers();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('displays info alert', () => {
|
||||
expect(createAlert).toHaveBeenCalledWith({
|
||||
message: 'Organization was successfully updated.',
|
||||
variant: VARIANT_INFO,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when API request is not successful', () => {
|
||||
const error = new Error();
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockResolvers = {
|
||||
Mutation: {
|
||||
updateOrganization: jest.fn().mockRejectedValueOnce(error),
|
||||
},
|
||||
};
|
||||
|
||||
createComponent({ mockResolvers });
|
||||
await submitForm();
|
||||
jest.runAllTimers();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('displays error alert', () => {
|
||||
expect(createAlert).toHaveBeenCalledWith({
|
||||
message: 'An error occurred updating your organization. Please try again.',
|
||||
error,
|
||||
captureError: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { GlButton, GlInputGroupText, GlTruncate } from '@gitlab/ui';
|
||||
|
||||
import NewEditForm from '~/organizations/shared/components/new_edit_form.vue';
|
||||
import { FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_PATH } from '~/organizations/shared/constants';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
|
||||
describe('NewEditForm', () => {
|
||||
|
|
@ -27,6 +28,7 @@ describe('NewEditForm', () => {
|
|||
};
|
||||
|
||||
const findNameField = () => wrapper.findByLabelText('Organization name');
|
||||
const findIdField = () => wrapper.findByLabelText('Organization ID');
|
||||
const findUrlField = () => wrapper.findByLabelText('Organization URL');
|
||||
const submitForm = async () => {
|
||||
await wrapper.findByRole('button', { name: 'Create organization' }).trigger('click');
|
||||
|
|
@ -47,6 +49,45 @@ describe('NewEditForm', () => {
|
|||
expect(findUrlField().exists()).toBe(true);
|
||||
});
|
||||
|
||||
describe('when `fieldsToRender` prop is set', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ propsData: { fieldsToRender: [FORM_FIELD_ID] } });
|
||||
});
|
||||
|
||||
it('only renders provided fields', () => {
|
||||
expect(findNameField().exists()).toBe(false);
|
||||
expect(findIdField().exists()).toBe(true);
|
||||
expect(findUrlField().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `initialFormValues` prop is set', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
propsData: {
|
||||
fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_PATH],
|
||||
initialFormValues: {
|
||||
[FORM_FIELD_NAME]: 'Foo bar',
|
||||
[FORM_FIELD_ID]: 1,
|
||||
[FORM_FIELD_PATH]: 'foo-bar',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sets initial values for fields', () => {
|
||||
expect(findNameField().element.value).toBe('Foo bar');
|
||||
expect(findIdField().element.value).toBe('1');
|
||||
expect(findUrlField().element.value).toBe('foo-bar');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders `Organization ID` field as disabled', () => {
|
||||
createComponent({ propsData: { fieldsToRender: [FORM_FIELD_ID] } });
|
||||
|
||||
expect(findIdField().attributes('disabled')).toBe('disabled');
|
||||
});
|
||||
|
||||
describe('when form is submitted without filling in required fields', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent();
|
||||
|
|
@ -100,6 +141,30 @@ describe('NewEditForm', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when `Organization URL` field is not rendered', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
propsData: {
|
||||
fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID],
|
||||
initialFormValues: {
|
||||
[FORM_FIELD_NAME]: 'Foo bar',
|
||||
[FORM_FIELD_ID]: 1,
|
||||
[FORM_FIELD_PATH]: 'foo-bar',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await findNameField().setValue('Foo bar baz');
|
||||
await submitForm();
|
||||
});
|
||||
|
||||
it('does not modify `Organization URL` when typing in `Organization name`', () => {
|
||||
expect(wrapper.emitted('submit')).toEqual([
|
||||
[{ name: 'Foo bar baz', id: 1, path: 'foo-bar' }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `loading` prop is `true`', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ propsData: { loading: true } });
|
||||
|
|
@ -109,4 +174,46 @@ describe('NewEditForm', () => {
|
|||
expect(wrapper.findComponent(GlButton).props('loading')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `showCancelButton` prop is `false`', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ propsData: { showCancelButton: false } });
|
||||
});
|
||||
|
||||
it('does not show cancel button', () => {
|
||||
expect(wrapper.findByRole('link', { name: 'Cancel' }).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `showCancelButton` prop is `true`', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('shows cancel button', () => {
|
||||
expect(wrapper.findByRole('link', { name: 'Cancel' }).attributes('href')).toBe(
|
||||
defaultProvide.organizationsPath,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `submitButtonText` prop is not set', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('defaults to `Create organization`', () => {
|
||||
expect(wrapper.findByRole('button', { name: 'Create organization' }).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `submitButtonText` prop is set', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ propsData: { submitButtonText: 'Save changes' } });
|
||||
});
|
||||
|
||||
it('uses it for submit button', () => {
|
||||
expect(wrapper.findByRole('button', { name: 'Save changes' }).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { GlLabel, GlIcon, GlLink } from '@gitlab/ui';
|
||||
import { GlLabel, GlIcon, GlLink, GlButton } from '@gitlab/ui';
|
||||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
|
|
@ -9,7 +9,6 @@ import { createAlert } from '~/alert';
|
|||
import RichTimestampTooltip from '~/vue_shared/components/rich_timestamp_tooltip.vue';
|
||||
|
||||
import WorkItemLinkChildContents from '~/work_items/components/shared/work_item_link_child_contents.vue';
|
||||
import WorkItemLinksMenu from '~/work_items/components/shared/work_item_links_menu.vue';
|
||||
import { WORK_ITEM_TYPE_VALUE_OBJECTIVE } from '~/work_items/constants';
|
||||
|
||||
import {
|
||||
|
|
@ -39,7 +38,7 @@ describe('WorkItemLinkChildContents', () => {
|
|||
const findAllLabels = () => wrapper.findAllComponents(GlLabel);
|
||||
const findRegularLabel = () => findAllLabels().at(0);
|
||||
const findScopedLabel = () => findAllLabels().at(1);
|
||||
const findLinksMenuComponent = () => wrapper.findComponent(WorkItemLinksMenu);
|
||||
const findRemoveButton = () => wrapper.findComponent(GlButton);
|
||||
|
||||
const createComponent = ({ canUpdate = true, childItem = workItemTask } = {}) => {
|
||||
wrapper = shallowMountExtended(WorkItemLinkChildContents, {
|
||||
|
|
@ -149,18 +148,18 @@ describe('WorkItemLinkChildContents', () => {
|
|||
createComponent();
|
||||
});
|
||||
|
||||
it('renders work-item-links-menu', () => {
|
||||
expect(findLinksMenuComponent().exists()).toBe(true);
|
||||
it('renders remove button', () => {
|
||||
expect(findRemoveButton().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render work-item-links-menu when canUpdate is false', () => {
|
||||
createComponent({ canUpdate: false });
|
||||
|
||||
expect(findLinksMenuComponent().exists()).toBe(false);
|
||||
expect(findRemoveButton().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('removeChild event on menu triggers `click-remove-child` event', () => {
|
||||
findLinksMenuComponent().vm.$emit('removeChild');
|
||||
findRemoveButton().vm.$emit('click');
|
||||
|
||||
expect(wrapper.emitted('removeChild')).toEqual([[workItemTask]]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui';
|
||||
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import WorkItemLinksMenu from '~/work_items/components/shared/work_item_links_menu.vue';
|
||||
|
||||
describe('WorkItemLinksMenu', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = () => {
|
||||
wrapper = shallowMountExtended(WorkItemLinksMenu);
|
||||
};
|
||||
|
||||
const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
|
||||
const findRemoveDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem);
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders dropdown and dropdown items', () => {
|
||||
expect(findDropdown().exists()).toBe(true);
|
||||
expect(findRemoveDropdownItem().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('emits removeChild event on click Remove', () => {
|
||||
findRemoveDropdownItem().vm.$emit('action');
|
||||
|
||||
expect(wrapper.emitted('removeChild')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -92,7 +92,7 @@ describe('WorkItemDescription', () => {
|
|||
it('passes correct autocompletion data and preview markdown sources and enables quick actions', async () => {
|
||||
const {
|
||||
iid,
|
||||
project: { fullPath },
|
||||
namespace: { fullPath },
|
||||
} = workItemQueryResponse.data.workItem;
|
||||
|
||||
await createComponent({ isEditing: true });
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ describe('WorkItemTodo component', () => {
|
|||
const workItemQueryResponse = workItemResponseFactory({ canUpdate: true });
|
||||
const mockWorkItemId = workItemQueryResponse.data.workItem.id;
|
||||
const mockWorkItemIid = workItemQueryResponse.data.workItem.iid;
|
||||
const mockWorkItemFullpath = workItemQueryResponse.data.workItem.project.fullPath;
|
||||
const mockWorkItemFullpath = workItemQueryResponse.data.workItem.namespace.fullPath;
|
||||
|
||||
const createTodoSuccessHandler = jest
|
||||
.fn()
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ export const workItemQueryResponse = {
|
|||
__typename: 'WorkItem',
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
title: 'Test',
|
||||
state: 'OPEN',
|
||||
description: 'description',
|
||||
|
|
@ -127,11 +128,10 @@ export const workItemQueryResponse = {
|
|||
webUrl: 'http://127.0.0.1:3000/root',
|
||||
__typename: 'UserCore',
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
workItemType: {
|
||||
|
|
@ -224,6 +224,7 @@ export const updateWorkItemMutationResponse = {
|
|||
__typename: 'WorkItem',
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
title: 'Updated title',
|
||||
state: 'OPEN',
|
||||
description: 'description',
|
||||
|
|
@ -234,11 +235,10 @@ export const updateWorkItemMutationResponse = {
|
|||
author: {
|
||||
...mockAssignees[0],
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
workItemType: {
|
||||
|
|
@ -335,6 +335,7 @@ export const convertWorkItemMutationResponse = {
|
|||
__typename: 'WorkItem',
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
title: 'Updated title',
|
||||
state: 'OPEN',
|
||||
description: 'description',
|
||||
|
|
@ -345,11 +346,10 @@ export const convertWorkItemMutationResponse = {
|
|||
author: {
|
||||
...mockAssignees[0],
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
workItemType: {
|
||||
|
|
@ -626,6 +626,7 @@ export const workItemResponseFactory = ({
|
|||
__typename: 'WorkItem',
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid,
|
||||
archived: false,
|
||||
title: 'Updated title',
|
||||
state,
|
||||
description: 'description',
|
||||
|
|
@ -634,11 +635,10 @@ export const workItemResponseFactory = ({
|
|||
updatedAt,
|
||||
closedAt: null,
|
||||
author,
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
workItemType,
|
||||
|
|
@ -901,6 +901,7 @@ export const createWorkItemMutationResponse = {
|
|||
__typename: 'WorkItem',
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
title: 'Updated title',
|
||||
state: 'OPEN',
|
||||
description: 'description',
|
||||
|
|
@ -911,11 +912,10 @@ export const createWorkItemMutationResponse = {
|
|||
author: {
|
||||
...mockAssignees[0],
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
workItemType: {
|
||||
|
|
@ -987,6 +987,7 @@ export const workItemHierarchyEmptyResponse = {
|
|||
{
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
state: 'OPEN',
|
||||
workItemType: {
|
||||
id: 'gid://gitlab/WorkItems::Type/1',
|
||||
|
|
@ -1000,11 +1001,10 @@ export const workItemHierarchyEmptyResponse = {
|
|||
updatedAt: null,
|
||||
closedAt: null,
|
||||
author: mockAssignees[0],
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
userPermissions: {
|
||||
|
|
@ -1045,6 +1045,7 @@ export const workItemHierarchyNoUpdatePermissionResponse = {
|
|||
workItem: {
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
state: 'OPEN',
|
||||
workItemType: {
|
||||
id: 'gid://gitlab/WorkItems::Type/6',
|
||||
|
|
@ -1067,11 +1068,10 @@ export const workItemHierarchyNoUpdatePermissionResponse = {
|
|||
adminWorkItemLink: true,
|
||||
__typename: 'WorkItemPermissions',
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
confidential: false,
|
||||
|
|
@ -1207,6 +1207,7 @@ export const workItemHierarchyResponse = {
|
|||
{
|
||||
id: 'gid://gitlab/WorkItem/1',
|
||||
iid: '1',
|
||||
archived: false,
|
||||
workItemType: {
|
||||
id: 'gid://gitlab/WorkItems::Type/1',
|
||||
name: 'Issue',
|
||||
|
|
@ -1227,11 +1228,10 @@ export const workItemHierarchyResponse = {
|
|||
...mockAssignees[0],
|
||||
},
|
||||
confidential: false,
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
description: 'Issue description',
|
||||
|
|
@ -1303,17 +1303,17 @@ export const workItemObjectiveMetadataWidgets = {
|
|||
export const workItemObjectiveWithChild = {
|
||||
id: 'gid://gitlab/WorkItem/12',
|
||||
iid: '12',
|
||||
archived: false,
|
||||
workItemType: {
|
||||
id: 'gid://gitlab/WorkItems::Type/2411',
|
||||
name: 'Objective',
|
||||
iconName: 'issue-type-objective',
|
||||
__typename: 'WorkItemType',
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
userPermissions: {
|
||||
|
|
@ -1381,6 +1381,7 @@ export const workItemHierarchyTreeResponse = {
|
|||
workItem: {
|
||||
id: 'gid://gitlab/WorkItem/2',
|
||||
iid: '2',
|
||||
archived: false,
|
||||
workItemType: {
|
||||
id: 'gid://gitlab/WorkItems::Type/2411',
|
||||
name: 'Objective',
|
||||
|
|
@ -1398,11 +1399,10 @@ export const workItemHierarchyTreeResponse = {
|
|||
__typename: 'WorkItemPermissions',
|
||||
},
|
||||
confidential: false,
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
widgets: [
|
||||
|
|
@ -1483,6 +1483,7 @@ export const changeIndirectWorkItemParentMutationResponse = {
|
|||
description: null,
|
||||
id: 'gid://gitlab/WorkItem/13',
|
||||
iid: '13',
|
||||
archived: false,
|
||||
state: 'OPEN',
|
||||
title: 'Objective 2',
|
||||
confidential: false,
|
||||
|
|
@ -1492,11 +1493,10 @@ export const changeIndirectWorkItemParentMutationResponse = {
|
|||
author: {
|
||||
...mockAssignees[0],
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
reference: 'test-project-path#13',
|
||||
|
|
@ -1552,6 +1552,7 @@ export const changeWorkItemParentMutationResponse = {
|
|||
description: null,
|
||||
id: 'gid://gitlab/WorkItem/2',
|
||||
iid: '2',
|
||||
archived: false,
|
||||
state: 'OPEN',
|
||||
title: 'Foo',
|
||||
confidential: false,
|
||||
|
|
@ -1561,11 +1562,10 @@ export const changeWorkItemParentMutationResponse = {
|
|||
author: {
|
||||
...mockAssignees[0],
|
||||
},
|
||||
project: {
|
||||
namespace: {
|
||||
__typename: 'Project',
|
||||
id: '1',
|
||||
fullPath: 'test-project-path',
|
||||
archived: false,
|
||||
name: 'Project name',
|
||||
},
|
||||
reference: 'test-project-path#2',
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Resolvers::ProjectsResolver do
|
||||
RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
describe '#resolve' do
|
||||
|
|
|
|||
|
|
@ -91,4 +91,20 @@ RSpec.describe Organizations::OrganizationHelper, feature_category: :cell do
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#organization_settings_general_app_data' do
|
||||
it 'returns expected json' do
|
||||
expect(Gitlab::Json.parse(helper.organization_settings_general_app_data(organization))).to eq(
|
||||
{
|
||||
'organization' => {
|
||||
'id' => organization.id,
|
||||
'name' => organization.name,
|
||||
'path' => organization.path
|
||||
},
|
||||
'organizations_path' => organizations_path,
|
||||
'root_url' => root_url
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe UsersHelper do
|
||||
RSpec.describe UsersHelper, feature_category: :user_management do
|
||||
include TermsHelper
|
||||
|
||||
let_it_be(:user) { create(:user, timezone: ActiveSupport::TimeZone::MAPPING['UTC']) }
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler, feature_category: :se
|
|||
shared_examples 'does not add CC address' do
|
||||
it 'creates a new issue and adds issue_email_participant from From header' do
|
||||
expect { receiver.execute }.to change { Issue.count }.by(1)
|
||||
expect(Issue.last.issue_email_participants.map(&:email)).to match_array(%w(from@example.com))
|
||||
expect(Issue.last.issue_email_participants.map(&:email)).to match_array(%w[from@example.com])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler, feature_category: :se
|
|||
# 1 from issue creation
|
||||
# 1 from new note reply
|
||||
expect(Issue.last.issue_email_participants.map(&:email))
|
||||
.to match_array(%w(alan@adventuretime.ooo jake@adventuretime.ooo))
|
||||
.to match_array(%w[alan@adventuretime.ooo jake@adventuretime.ooo])
|
||||
end
|
||||
|
||||
context 'when issue_email_participants FF is disabled' do
|
||||
|
|
@ -228,7 +228,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler, feature_category: :se
|
|||
subject
|
||||
|
||||
expect(Issue.last.issue_email_participants.map(&:email))
|
||||
.to match_array(%w(jake@adventuretime.ooo))
|
||||
.to match_array(%w[jake@adventuretime.ooo])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -256,7 +256,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler, feature_category: :se
|
|||
subject
|
||||
|
||||
expect(Issue.last.issue_email_participants.map(&:email))
|
||||
.to match_array(%w(alan@adventuretime.ooo))
|
||||
.to match_array(%w[alan@adventuretime.ooo])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ RSpec.describe Gitlab::Email::Handler do
|
|||
|
||||
describe 'regexps are set properly' do
|
||||
let(:addresses) do
|
||||
%W(sent_notification_key#{Gitlab::Email::Common::UNSUBSCRIBE_SUFFIX} sent_notification_key#{Gitlab::Email::Common::UNSUBSCRIBE_SUFFIX_LEGACY}) +
|
||||
%w(sent_notification_key path-to-project-123-user_email_token-merge-request) +
|
||||
%w(path-to-project-123-user_email_token-issue path-to-project-123-user_email_token-issue-123) +
|
||||
%w(path/to/project+user_email_token path/to/project+merge-request+user_email_token some/project)
|
||||
%W[sent_notification_key#{Gitlab::Email::Common::UNSUBSCRIBE_SUFFIX} sent_notification_key#{Gitlab::Email::Common::UNSUBSCRIBE_SUFFIX_LEGACY}] +
|
||||
%w[sent_notification_key path-to-project-123-user_email_token-merge-request] +
|
||||
%w[path-to-project-123-user_email_token-issue path-to-project-123-user_email_token-issue-123] +
|
||||
%w[path/to/project+user_email_token path/to/project+merge-request+user_email_token some/project]
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ RSpec.describe Gitlab::Email::Receiver do
|
|||
|
||||
metadata = receiver.mail_metadata
|
||||
|
||||
expect(metadata.keys).to match_array(%i(mail_uid from_address to_address mail_key references delivered_to envelope_to x_envelope_to meta received_recipients cc_address))
|
||||
expect(metadata.keys).to match_array(%i[mail_uid from_address to_address mail_key references delivered_to envelope_to x_envelope_to meta received_recipients cc_address])
|
||||
expect(metadata[:meta]).to include(client_id: client_id, project: project.full_path)
|
||||
expect(metadata[meta_key]).to eq(meta_value)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ RSpec.describe Gitlab::EncodingHelper, feature_category: :shared do
|
|||
[nil, ""],
|
||||
["", ""],
|
||||
[" ", " "],
|
||||
%w(a1 a1),
|
||||
%w[a1 a1],
|
||||
["编码", "\xE7\xBC\x96\xE7\xA0\x81".b]
|
||||
].each do |input, result|
|
||||
it "encodes #{input.inspect} to #{result.inspect}" do
|
||||
|
|
|
|||
|
|
@ -11,19 +11,19 @@ RSpec.describe Gitlab::EndpointAttributes, feature_category: :api do
|
|||
|
||||
let(:controller) do
|
||||
Class.new(base_controller) do
|
||||
feature_category :foo, %w(update edit)
|
||||
feature_category :bar, %w(index show)
|
||||
feature_category :quux, %w(destroy)
|
||||
feature_category :foo, %w[update edit]
|
||||
feature_category :bar, %w[index show]
|
||||
feature_category :quux, %w[destroy]
|
||||
|
||||
urgency :high, %w(do_a)
|
||||
urgency :low, %w(do_b do_c)
|
||||
urgency :high, %w[do_a]
|
||||
urgency :low, %w[do_b do_c]
|
||||
end
|
||||
end
|
||||
|
||||
let(:subclass) do
|
||||
Class.new(controller) do
|
||||
feature_category :baz, %w(subclass_index)
|
||||
urgency :high, %w(superclass_do_something)
|
||||
feature_category :baz, %w[subclass_index]
|
||||
urgency :high, %w[superclass_do_something]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ RSpec.describe Gitlab::ErrorTracking::StackTraceHighlightDecorator do
|
|||
[11, '<span id="LC1" class="line" lang="ruby"><span class="k">class</span> <span class="nc">HelloWorld</span></span>'],
|
||||
[12, '<span id="LC1" class="line" lang="ruby"> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">message</span></span>'],
|
||||
[13, '<span id="LC1" class="line" lang="ruby"> <span class="vi">@name</span> <span class="o">=</span> <span class="s1">\'World\'</span></span>'],
|
||||
[14, %[<span id="LC1" class="line" lang="ruby"> <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">\#{</span><span class="vi">@name</span><span class="si">}</span><span class="s2">"</span></span>]],
|
||||
[14, %(<span id="LC1" class="line" lang="ruby"> <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">\#{</span><span class="vi">@name</span><span class="si">}</span><span class="s2">"</span></span>)],
|
||||
[15, '<span id="LC1" class="line" lang="ruby"> <span class="k">end</span></span>'],
|
||||
[16, '<span id="LC1" class="line" lang="ruby"><span class="k">end</span></span>']
|
||||
]
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Client do
|
|||
|
||||
describe 'for non-ldap users with identities' do
|
||||
before do
|
||||
%w(twitter facebook).each do |provider|
|
||||
%w[twitter facebook].each do |provider|
|
||||
create(:identity, provider: provider, extern_uid: "#{provider}_external_id", user: user)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ RSpec.describe Gitlab::Favicon, :request_store do
|
|||
subject { described_class.available_status_names }
|
||||
|
||||
it 'returns the available status names' do
|
||||
expect(subject).to eq %w(
|
||||
expect(subject).to eq %w[
|
||||
favicon_status_canceled
|
||||
favicon_status_created
|
||||
favicon_status_failed
|
||||
|
|
@ -73,7 +73,7 @@ RSpec.describe Gitlab::Favicon, :request_store do
|
|||
favicon_status_skipped
|
||||
favicon_status_success
|
||||
favicon_status_warning
|
||||
)
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::FeatureCategories do
|
||||
let(:fake_categories) { %w(foo bar) }
|
||||
let(:fake_categories) { %w[foo bar] }
|
||||
|
||||
subject(:feature_categories) { described_class.new(fake_categories) }
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ require 'spec_helper'
|
|||
RSpec.describe Gitlab::FileDetector do
|
||||
describe '.types_in_paths' do
|
||||
it 'returns the file types for the given paths' do
|
||||
expect(described_class.types_in_paths(%w(README.md CHANGELOG VERSION VERSION)))
|
||||
.to eq(%i{readme changelog version})
|
||||
expect(described_class.types_in_paths(%w[README.md CHANGELOG VERSION VERSION]))
|
||||
.to eq(%i[readme changelog version])
|
||||
end
|
||||
|
||||
it 'does not include unrecognized file paths' do
|
||||
expect(described_class.types_in_paths(%w(README.md foo.txt)))
|
||||
.to eq(%i{readme})
|
||||
expect(described_class.types_in_paths(%w[README.md foo.txt]))
|
||||
.to eq(%i[readme])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ RSpec.describe Gitlab::FileDetector do
|
|||
extensions = ['txt', *Gitlab::MarkupHelper::EXTENSIONS]
|
||||
|
||||
extensions.each do |ext|
|
||||
%w(index readme).each do |file|
|
||||
%w[index readme].each do |file|
|
||||
expect(described_class.type_of("#{file}.#{ext}")).to eq(:readme)
|
||||
end
|
||||
end
|
||||
|
|
@ -45,13 +45,13 @@ RSpec.describe Gitlab::FileDetector do
|
|||
end
|
||||
|
||||
it 'returns the type of a changelog file' do
|
||||
%w(CHANGELOG HISTORY CHANGES NEWS).each do |file|
|
||||
%w[CHANGELOG HISTORY CHANGES NEWS].each do |file|
|
||||
expect(described_class.type_of(file)).to eq(:changelog)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the type of a license file' do
|
||||
%w(LICENSE LICENCE COPYING UNLICENSE UNLICENCE).each do |file|
|
||||
%w[LICENSE LICENCE COPYING UNLICENSE UNLICENCE].each do |file|
|
||||
expect(described_class.type_of(file)).to eq(:license)
|
||||
end
|
||||
end
|
||||
|
|
@ -73,7 +73,7 @@ RSpec.describe Gitlab::FileDetector do
|
|||
end
|
||||
|
||||
it 'returns the type of an avatar' do
|
||||
%w(logo.gif logo.png logo.jpg).each do |file|
|
||||
%w[logo.gif logo.png logo.jpg].each do |file|
|
||||
expect(described_class.type_of(file)).to eq(:avatar)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -78,13 +78,13 @@ RSpec.describe Gitlab::Gfm::ReferenceRewriter do
|
|||
context 'label referenced by id' do
|
||||
let(:text) { '#1 and ~123' }
|
||||
|
||||
it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~123} }
|
||||
it { is_expected.to eq %(#{old_project_ref}#1 and #{old_project_ref}~123) }
|
||||
end
|
||||
|
||||
context 'label referenced by text' do
|
||||
let(:text) { '#1 and ~"test"' }
|
||||
|
||||
it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~123} }
|
||||
it { is_expected.to eq %(#{old_project_ref}#1 and #{old_project_ref}~123) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -99,13 +99,13 @@ RSpec.describe Gitlab::Gfm::ReferenceRewriter do
|
|||
context 'label referenced by id' do
|
||||
let(:text) { '#1 and ~321' }
|
||||
|
||||
it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~321} }
|
||||
it { is_expected.to eq %(#{old_project_ref}#1 and #{old_project_ref}~321) }
|
||||
end
|
||||
|
||||
context 'label referenced by text' do
|
||||
let(:text) { '#1 and ~"group label"' }
|
||||
|
||||
it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~321} }
|
||||
it { is_expected.to eq %(#{old_project_ref}#1 and #{old_project_ref}~321) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -149,7 +149,7 @@ RSpec.describe Gitlab::Gfm::ReferenceRewriter do
|
|||
|
||||
let(:text) { 'milestone: %"9.0"' }
|
||||
|
||||
it { is_expected.to eq %[milestone: #{old_project_ref}%"9.0"] }
|
||||
it { is_expected.to eq %(milestone: #{old_project_ref}%"9.0") }
|
||||
end
|
||||
|
||||
context 'when referring to group milestone' do
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ RSpec.describe Gitlab::Git::MergeBase do
|
|||
|
||||
shared_context 'existing refs with a merge base', :existing_refs do
|
||||
let(:refs) do
|
||||
%w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209)
|
||||
%w[304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209]
|
||||
end
|
||||
end
|
||||
|
||||
shared_context 'when passing a missing ref', :missing_ref do
|
||||
let(:refs) do
|
||||
%w(304d257dcb821665ab5110318fc58a007bd104ed aaaa)
|
||||
%w[304d257dcb821665ab5110318fc58a007bd104ed aaaa]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -51,13 +51,13 @@ RSpec.describe Gitlab::Git::MergeBase do
|
|||
end
|
||||
|
||||
it 'returns a merge base when passing 2 branch names' do
|
||||
merge_base = described_class.new(repository, %w(master feature))
|
||||
merge_base = described_class.new(repository, %w[master feature])
|
||||
|
||||
expect(merge_base.sha).to be_present
|
||||
end
|
||||
|
||||
it 'returns a merge base when passing a tag name' do
|
||||
merge_base = described_class.new(repository, %w(master v1.0.0))
|
||||
merge_base = described_class.new(repository, %w[master v1.0.0])
|
||||
|
||||
expect(merge_base.sha).to be_present
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2435,7 +2435,7 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
|
|||
end
|
||||
|
||||
it 'deletes all refs except those with the specified prefixes' do
|
||||
repository.delete_all_refs_except(%w(refs/keep refs/also-keep refs/heads))
|
||||
repository.delete_all_refs_except(%w[refs/keep refs/also-keep refs/heads])
|
||||
expect(repository.ref_exists?("refs/delete/a")).to be(false)
|
||||
expect(repository.ref_exists?("refs/also-delete/b")).to be(false)
|
||||
expect(repository.ref_exists?("refs/keep/c")).to be(true)
|
||||
|
|
@ -2722,15 +2722,15 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
|
|||
|
||||
describe '#check_objects_exist' do
|
||||
it 'returns hash specifying which object exists in repo' do
|
||||
refs_exist = %w(
|
||||
refs_exist = %w[
|
||||
b83d6e391c22777fca1ed3012fce84f633d7fed0
|
||||
498214de67004b1da3d820901307bed2a68a8ef6
|
||||
1b12f15a11fc6e62177bef08f47bc7b5ce50b141
|
||||
)
|
||||
refs_dont_exist = %w(
|
||||
]
|
||||
refs_dont_exist = %w[
|
||||
1111111111111111111111111111111111111111
|
||||
2222222222222222222222222222222222222222
|
||||
)
|
||||
]
|
||||
object_existence_map = repository.check_objects_exist(refs_exist + refs_dont_exist)
|
||||
expect(object_existence_map).to eq({
|
||||
'b83d6e391c22777fca1ed3012fce84f633d7fed0' => true,
|
||||
|
|
|
|||
|
|
@ -957,7 +957,7 @@ RSpec.describe Gitlab::GitAccess, :aggregate_failures, feature_category: :system
|
|||
}
|
||||
}
|
||||
|
||||
[%w(feature exact), ['feat*', 'wildcard']].each do |protected_branch_name, protected_branch_type|
|
||||
[%w[feature exact], ['feat*', 'wildcard']].each do |protected_branch_name, protected_branch_type|
|
||||
context do
|
||||
let(:who_can_action) { :maintainers_can_push }
|
||||
let(:protected_branch) { create(:protected_branch, who_can_action, name: protected_branch_name, project: project) }
|
||||
|
|
|
|||
|
|
@ -1184,7 +1184,7 @@ RSpec.describe Gitlab::GitalyClient::OperationService, feature_category: :source
|
|||
patch_names.map { |name| File.read(File.join(patches_folder, name)) }.join("\n")
|
||||
end
|
||||
|
||||
let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) }
|
||||
let(:patch_names) { %w[0001-This-does-not-apply-to-the-feature-branch.patch] }
|
||||
let(:branch_name) { 'branch-with-patches' }
|
||||
|
||||
subject(:commit_patches) do
|
||||
|
|
@ -1203,7 +1203,7 @@ RSpec.describe Gitlab::GitalyClient::OperationService, feature_category: :source
|
|||
end
|
||||
|
||||
context 'when the patch could not be applied' do
|
||||
let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) }
|
||||
let(:patch_names) { %w[0001-This-does-not-apply-to-the-feature-branch.patch] }
|
||||
let(:branch_name) { 'feature' }
|
||||
|
||||
it 'raises the correct error' do
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ RSpec.describe Gitlab::GitalyClient::RefService, feature_category: :gitaly do
|
|||
.with(gitaly_request_with_params(merged_only: true, merged_branches: ['test']), kind_of(Hash))
|
||||
.and_return([])
|
||||
|
||||
client.merged_branches(%w(test))
|
||||
client.merged_branches(%w[test])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -425,7 +425,7 @@ RSpec.describe Gitlab::GitalyClient::RefService, feature_category: :gitaly do
|
|||
end
|
||||
|
||||
describe '#delete_refs' do
|
||||
let(:prefixes) { %w(refs/heads refs/keep-around) }
|
||||
let(:prefixes) { %w[refs/heads refs/keep-around] }
|
||||
|
||||
subject(:delete_refs) { client.delete_refs(except_with_prefixes: prefixes) }
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter, feature_category: :
|
|||
end
|
||||
|
||||
context 'when the note have invalid chars' do
|
||||
let(:note_body) { %{There were an invalid char "\u0000" <= right here} }
|
||||
let(:note_body) { %(There were an invalid char "\u0000" <= right here) }
|
||||
|
||||
it 'removes invalid chars' do
|
||||
expect(importer.user_finder)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,16 @@ RSpec.describe Gitlab::GithubImport::ObjectCounter, :clean_gitlab_redis_cache, f
|
|||
'imported' => { 'issue' => 8 }
|
||||
)
|
||||
end
|
||||
|
||||
it 'uses the same TTL as when incrementing' do
|
||||
expect(Gitlab::Cache::Import::Caching)
|
||||
.to receive(:read_integer)
|
||||
.with(anything, timeout: described_class::IMPORT_CACHING_TIMEOUT)
|
||||
.twice
|
||||
.and_call_original
|
||||
|
||||
described_class.summary(project)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when import is in progress but cache expired' do
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ RSpec.describe Gitlab::Graphql::KnownOperations do
|
|||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
# Include duplicated operation names to test that we are unique-ifying them
|
||||
let(:fake_operations) { %w(foo foo bar bar) }
|
||||
let(:fake_operations) { %w[foo foo bar bar] }
|
||||
let(:fake_schema) do
|
||||
Class.new(GraphQL::Schema) do
|
||||
query Graphql::FakeQueryType
|
||||
|
|
@ -34,7 +34,7 @@ RSpec.describe Gitlab::Graphql::KnownOperations do
|
|||
|
||||
describe "#operations" do
|
||||
it "returns array of known operations" do
|
||||
expect(subject.operations.map(&:name)).to match_array(%w(unknown foo bar))
|
||||
expect(subject.operations.map(&:name)).to match_array(%w[unknown foo bar])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ require 'rspec-parameterized'
|
|||
RSpec.describe Gitlab::Graphql::Tracers::MetricsTracer do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:default_known_operations) { ::Gitlab::Graphql::KnownOperations.new(%w(lorem foo bar)) }
|
||||
let(:default_known_operations) { ::Gitlab::Graphql::KnownOperations.new(%w[lorem foo bar]) }
|
||||
|
||||
let(:fake_schema) do
|
||||
Class.new(GraphQL::Schema) do
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ RSpec.describe Gitlab::HashedPath do
|
|||
end
|
||||
|
||||
context 'when path contains multiple values' do
|
||||
let(:path) { %w(path1 path2) }
|
||||
let(:path) { %w[path1 path2] }
|
||||
|
||||
it 'returns the disk path' do
|
||||
expect(subject).to match(%r[\h{2}/\h{2}/\h{64}/path1/path2])
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ RSpec.describe Gitlab::Highlight do
|
|||
it 'returns plain version for unknown lexer context' do
|
||||
result = described_class.highlight(plain_text_file_name, plain_text_content)
|
||||
|
||||
expect(result).to eq(%[<span id="LC1" class="line" lang="plaintext">plain text contents</span>])
|
||||
expect(result).to eq(%(<span id="LC1" class="line" lang="plaintext">plain text contents</span>))
|
||||
end
|
||||
|
||||
context 'when content is too long to be highlighted' do
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ RSpec.describe Gitlab::I18n::TranslationEntry do
|
|||
|
||||
describe '#msgid_contains_newlines' do
|
||||
it 'is true when the msgid is an array' do
|
||||
data = { msgid: %w(hello world) }
|
||||
data = { msgid: %w[hello world] }
|
||||
entry = described_class.new(entry_data: data, nplurals: 2)
|
||||
|
||||
expect(entry.msgid_has_multiple_lines?).to be_truthy
|
||||
|
|
@ -117,7 +117,7 @@ RSpec.describe Gitlab::I18n::TranslationEntry do
|
|||
|
||||
describe '#plural_id_contains_newlines' do
|
||||
it 'is true when the msgid is an array' do
|
||||
data = { msgid_plural: %w(hello world) }
|
||||
data = { msgid_plural: %w[hello world] }
|
||||
entry = described_class.new(entry_data: data, nplurals: 2)
|
||||
|
||||
expect(entry.plural_id_has_multiple_lines?).to be_truthy
|
||||
|
|
@ -126,7 +126,7 @@ RSpec.describe Gitlab::I18n::TranslationEntry do
|
|||
|
||||
describe '#translations_contain_newlines' do
|
||||
it 'is true when the msgid is an array' do
|
||||
data = { msgstr: %w(hello world) }
|
||||
data = { msgstr: %w[hello world] }
|
||||
entry = described_class.new(entry_data: data, nplurals: 2)
|
||||
|
||||
expect(entry.translations_have_multiple_lines?).to be_truthy
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::BaseAfterExportStrat
|
|||
|
||||
describe '#log_validation_errors' do
|
||||
it 'add the message to the shared context' do
|
||||
errors = %w(test_message test_message2)
|
||||
errors = %w[test_message test_message2]
|
||||
|
||||
allow(service).to receive(:invalid?).and_return(true)
|
||||
allow(service.errors).to receive(:full_messages).and_return(errors)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
|
|||
|
||||
describe 'validations' do
|
||||
it 'only POST and PUT method allowed' do
|
||||
%w(POST post PUT put).each do |method|
|
||||
%w[POST post PUT put].each do |method|
|
||||
expect(subject.new(url: example_url, http_method: method)).to be_valid
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ RSpec.describe Gitlab::ImportExport::AttributeCleaner do
|
|||
'note_ids' => [1, 2, 3],
|
||||
'remote_attachment_url' => 'http://something.dodgy',
|
||||
'remote_attachment_request_header' => 'bad value',
|
||||
'remote_attachment_urls' => %w(http://something.dodgy http://something.okay),
|
||||
'remote_attachment_urls' => %w[http://something.dodgy http://something.okay],
|
||||
'attributes' => {
|
||||
'issue_ids' => [1, 2, 3],
|
||||
'merge_request_ids' => [1, 2, 3],
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter, feature_category: :imp
|
|||
EOF
|
||||
end
|
||||
|
||||
let(:file) { Tempfile.new(%w(import_export .yml)) }
|
||||
let(:file) { Tempfile.new(%w[import_export .yml]) }
|
||||
let(:config_hash) { Gitlab::ImportExport::Config.new(config: file.path).to_h }
|
||||
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer, :with_license, feature_
|
|||
it 'has project and group labels' do
|
||||
label_types = subject['issues'].first['label_links'].map { |link| link['label']['type'] }
|
||||
|
||||
expect(label_types).to match_array(%w(ProjectLabel GroupLabel))
|
||||
expect(label_types).to match_array(%w[ProjectLabel GroupLabel])
|
||||
end
|
||||
|
||||
it 'has priorities associated to labels' do
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ RSpec.describe Gitlab::ImportExport::Json::NdjsonWriter, feature_category: :impo
|
|||
describe "#write_relation_array" do
|
||||
it "writes json in correct files" do
|
||||
values = [{ "key" => "value_1", "key_1" => "value_1" }, { "key" => "value_2", "key_1" => "value_2" }]
|
||||
relations = %w(relation1 relation2)
|
||||
relations = %w[relation1 relation2]
|
||||
relations.each do |relation|
|
||||
subject.write_relation_array(exportable_path, relation, values.to_enum)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ RSpec.describe Gitlab::ImportExport::LfsRestorer do
|
|||
|
||||
# Use the LfsSaver to save data to be restored
|
||||
def save_lfs_data
|
||||
%w(project wiki).each do |repository_type|
|
||||
%w[project wiki].each do |repository_type|
|
||||
create(
|
||||
:lfs_objects_project,
|
||||
project: project,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ RSpec.describe Gitlab::ImportExport::LfsSaver do
|
|||
describe 'saving a json file' do
|
||||
before do
|
||||
# Create two more LfsObjectProject records with different `repository_type`s
|
||||
%w(wiki design).each do |repository_type|
|
||||
%w[wiki design].each do |repository_type|
|
||||
create(
|
||||
:lfs_objects_project,
|
||||
project: project,
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver, :with_license, feature_
|
|||
it 'has project and group labels' do
|
||||
label_types = subject.first['label_links'].map { |link| link['label']['type'] }
|
||||
|
||||
expect(label_types).to match_array(%w(ProjectLabel GroupLabel))
|
||||
expect(label_types).to match_array(%w[ProjectLabel GroupLabel])
|
||||
end
|
||||
|
||||
it 'has priorities associated to labels' do
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ RSpec.describe Gitlab::ImportExport::Saver do
|
|||
subject.save # rubocop:disable Rails/SaveBang
|
||||
|
||||
expect(ImportExportUpload.find_by(project: project).export_file.url)
|
||||
.to match(%r[/uploads/-/system/import_export_upload/export_file.*])
|
||||
.to match(%r{/uploads/-/system/import_export_upload/export_file.*})
|
||||
end
|
||||
|
||||
it 'logs metrics after saving' do
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ RSpec.describe Gitlab::ImportExport::SnippetRepoRestorer do
|
|||
expect(restorer.restore).to be_truthy
|
||||
end.to change { SnippetRepository.count }.by(1)
|
||||
|
||||
snippet.repository.expire_method_caches(%i(exists?))
|
||||
snippet.repository.expire_method_caches(%i[exists?])
|
||||
expect(snippet.repository_exists?).to be_truthy
|
||||
|
||||
blob = snippet.repository.blob_at(snippet.default_branch, snippet.file_name)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ RSpec.describe Gitlab::ImportSources, feature_category: :importers do
|
|||
describe '.values' do
|
||||
it 'returns an array' do
|
||||
expected =
|
||||
%w(
|
||||
%w[
|
||||
github
|
||||
bitbucket
|
||||
bitbucket_server
|
||||
|
|
@ -33,7 +33,7 @@ RSpec.describe Gitlab::ImportSources, feature_category: :importers do
|
|||
gitlab_project
|
||||
gitea
|
||||
manifest
|
||||
)
|
||||
]
|
||||
|
||||
expect(described_class.values).to eq(expected)
|
||||
end
|
||||
|
|
@ -42,14 +42,14 @@ RSpec.describe Gitlab::ImportSources, feature_category: :importers do
|
|||
describe '.importer_names' do
|
||||
it 'returns an array of importer names' do
|
||||
expected =
|
||||
%w(
|
||||
%w[
|
||||
github
|
||||
bitbucket
|
||||
bitbucket_server
|
||||
fogbugz
|
||||
gitlab_project
|
||||
gitea
|
||||
)
|
||||
]
|
||||
|
||||
expect(described_class.importer_names).to eq(expected)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,25 +11,25 @@ RSpec.describe Gitlab::Instrumentation::RedisClusterValidator, feature_category:
|
|||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:command, :arguments, :keys, :is_valid) do
|
||||
:rename | %w(foo bar) | 2 | false
|
||||
:RENAME | %w(foo bar) | 2 | false
|
||||
'rename' | %w(foo bar) | 2 | false
|
||||
'RENAME' | %w(foo bar) | 2 | false
|
||||
:rename | %w(iaa ahy) | 2 | true # 'iaa' and 'ahy' hash to the same slot
|
||||
:rename | %w({foo}:1 {foo}:2) | 2 | true
|
||||
:rename | %w(foo foo bar) | 2 | true # This is not a valid command but should not raise here
|
||||
:mget | %w(foo bar) | 2 | false
|
||||
:mget | %w(foo foo bar) | 3 | false
|
||||
:mget | %w(foo foo) | 2 | true
|
||||
:blpop | %w(foo bar 1) | 2 | false
|
||||
:blpop | %w(foo foo 1) | 2 | true
|
||||
:mset | %w(foo a bar a) | 2 | false
|
||||
:mset | %w(foo a foo a) | 2 | true
|
||||
:del | %w(foo bar) | 2 | false
|
||||
:del | [%w(foo bar)] | 2 | false # Arguments can be a nested array
|
||||
:del | %w(foo foo) | 2 | true
|
||||
:hset | %w(foo bar) | 1 | nil # Single key write
|
||||
:get | %w(foo) | 1 | nil # Single key read
|
||||
:rename | %w[foo bar] | 2 | false
|
||||
:RENAME | %w[foo bar] | 2 | false
|
||||
'rename' | %w[foo bar] | 2 | false
|
||||
'RENAME' | %w[foo bar] | 2 | false
|
||||
:rename | %w[iaa ahy] | 2 | true # 'iaa' and 'ahy' hash to the same slot
|
||||
:rename | %w[{foo}:1 {foo}:2] | 2 | true
|
||||
:rename | %w[foo foo bar] | 2 | true # This is not a valid command but should not raise here
|
||||
:mget | %w[foo bar] | 2 | false
|
||||
:mget | %w[foo foo bar] | 3 | false
|
||||
:mget | %w[foo foo] | 2 | true
|
||||
:blpop | %w[foo bar 1] | 2 | false
|
||||
:blpop | %w[foo foo 1] | 2 | true
|
||||
:mset | %w[foo a bar a] | 2 | false
|
||||
:mset | %w[foo a foo a] | 2 | true
|
||||
:del | %w[foo bar] | 2 | false
|
||||
:del | [%w[foo bar]] | 2 | false # Arguments can be a nested array
|
||||
:del | %w[foo foo] | 2 | true
|
||||
:hset | %w[foo bar] | 1 | nil # Single key write
|
||||
:get | %w[foo] | 1 | nil # Single key read
|
||||
:mget | [] | 0 | true # This is invalid, but not because it's a cross-slot command
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
|
|||
end
|
||||
|
||||
it 'returns array of issue ids' do
|
||||
expect(rebalance_caching.get_cached_issue_ids(0, 100)).to eq(%w(1 2 3))
|
||||
expect(rebalance_caching.get_cached_issue_ids(0, 100)).to eq(%w[1 2 3])
|
||||
end
|
||||
|
||||
it 'limits returned values' do
|
||||
expect(rebalance_caching.get_cached_issue_ids(0, 2)).to eq(%w(1 2))
|
||||
expect(rebalance_caching.get_cached_issue_ids(0, 2)).to eq(%w[1 2])
|
||||
end
|
||||
|
||||
context 'when caching duplicate issue_ids' do
|
||||
|
|
@ -84,7 +84,7 @@ RSpec.describe Gitlab::Issues::Rebalancing::State, :clean_gitlab_redis_shared_st
|
|||
end
|
||||
|
||||
it 'returns cached issues with latest scores' do
|
||||
expect(rebalance_caching.get_cached_issue_ids(0, 100)).to eq(%w(3 2 1))
|
||||
expect(rebalance_caching.get_cached_issue_ids(0, 100)).to eq(%w[3 2 1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ RSpec.describe Gitlab::JiraImport::HandleLabelsService do
|
|||
let_it_be(:other_project_label) { create(:label, title: 'feature') }
|
||||
let_it_be(:group_label) { create(:group_label, group: group, title: 'dev') }
|
||||
|
||||
let(:jira_labels) { %w(bug feature dev group::new) }
|
||||
let(:jira_labels) { %w[bug feature dev group::new] }
|
||||
|
||||
subject { described_class.new(project, jira_labels).execute }
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ RSpec.describe Gitlab::JiraImport::HandleLabelsService do
|
|||
it 'creates the missing labels on the project level' do
|
||||
expect { subject }.to change { Label.count }.from(3).to(5)
|
||||
|
||||
expect(created_labels.map(&:title)).to match_array(%w(feature group::new))
|
||||
expect(created_labels.map(&:title)).to match_array(%w[feature group::new])
|
||||
end
|
||||
|
||||
it 'returns the id of all labels matching the title' do
|
||||
|
|
@ -32,7 +32,7 @@ RSpec.describe Gitlab::JiraImport::HandleLabelsService do
|
|||
end
|
||||
|
||||
context 'when no provided jira labels are missing' do
|
||||
let(:jira_labels) { %w(bug dev) }
|
||||
let(:jira_labels) { %w[bug dev] }
|
||||
|
||||
it 'does not create any new labels' do
|
||||
expect { subject }.not_to change { Label.count }.from(3)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ RSpec.describe Gitlab::JiraImport::IssueSerializer do
|
|||
end
|
||||
|
||||
let(:priority_field) { { 'name' => 'Medium' } }
|
||||
let(:labels_field) { %w(bug dev backend frontend) }
|
||||
let(:labels_field) { %w[bug dev backend frontend] }
|
||||
|
||||
let(:fields) do
|
||||
{
|
||||
|
|
@ -101,7 +101,7 @@ RSpec.describe Gitlab::JiraImport::IssueSerializer do
|
|||
end
|
||||
|
||||
context 'when there are no new labels' do
|
||||
let(:labels_field) { %w(bug dev) }
|
||||
let(:labels_field) { %w[bug dev] }
|
||||
|
||||
it 'assigns the labels to the Issue hash' do
|
||||
expect(subject[:label_ids]).to match_array([project_label.id, group_label.id])
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ RSpec.describe Gitlab::JiraImport::LabelsImporter do
|
|||
let_it_be(:jira_import_with_label) { create(:jira_import_state, label: label, project: project) }
|
||||
let_it_be(:issue_label) { create(:label, project: project, title: 'bug') }
|
||||
|
||||
let(:jira_labels_1) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "isLast" => false, "values" => %w(backend bug) } }
|
||||
let(:jira_labels_2) { { "maxResults" => 2, "startAt" => 2, "total" => 3, "isLast" => true, "values" => %w(feature) } }
|
||||
let(:jira_labels_1) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "isLast" => false, "values" => %w[backend bug] } }
|
||||
let(:jira_labels_2) { { "maxResults" => 2, "startAt" => 2, "total" => 3, "isLast" => true, "values" => %w[feature] } }
|
||||
|
||||
context 'when labels are returned from jira' do
|
||||
before do
|
||||
|
|
@ -55,8 +55,8 @@ RSpec.describe Gitlab::JiraImport::LabelsImporter do
|
|||
end
|
||||
|
||||
it 'calls Gitlab::JiraImport::HandleLabelsService' do
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).to receive(:new).with(project, %w(backend bug)).and_return(double(execute: [1, 2]))
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).to receive(:new).with(project, %w(feature)).and_return(double(execute: [3]))
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).to receive(:new).with(project, %w[backend bug]).and_return(double(execute: [1, 2]))
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).to receive(:new).with(project, %w[feature]).and_return(double(execute: [3]))
|
||||
|
||||
subject
|
||||
end
|
||||
|
|
@ -92,7 +92,7 @@ RSpec.describe Gitlab::JiraImport::LabelsImporter do
|
|||
end
|
||||
|
||||
context 'when the isLast argument is missing' do
|
||||
let(:jira_labels) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "values" => %w(bug dev) } }
|
||||
let(:jira_labels) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "values" => %w[bug dev] } }
|
||||
|
||||
it_behaves_like 'no labels handling'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ require_relative '../../../../lib/gitlab/kubernetes/pod_cmd'
|
|||
RSpec.describe Gitlab::Kubernetes::KubectlCmd do
|
||||
describe '.delete' do
|
||||
it 'constructs string properly' do
|
||||
args = %w(resource_type type --flag-1 --flag-2)
|
||||
args = %w[resource_type type --flag-1 --flag-2]
|
||||
|
||||
expected_command = 'kubectl delete resource_type type --flag-1 --flag-2'
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ RSpec.describe Gitlab::Kubernetes::KubectlCmd do
|
|||
|
||||
context 'with optional args' do
|
||||
it 'constructs command properly with many args' do
|
||||
args = %w(arg-1 --flag-0-1 arg-2 --flag-0-2)
|
||||
args = %w[arg-1 --flag-0-1 arg-2 --flag-0-2]
|
||||
|
||||
expected_command = 'kubectl apply -f filename arg-1 --flag-0-1 arg-2 --flag-0-2'
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ RSpec.describe Gitlab::Kubernetes::Role do
|
|||
|
||||
let(:rules) do
|
||||
[{
|
||||
apiGroups: %w(hello.world),
|
||||
resources: %w(oil diamonds coffee),
|
||||
verbs: %w(say do walk run)
|
||||
apiGroups: %w[hello.world],
|
||||
resources: %w[oil diamonds coffee],
|
||||
verbs: %w[say do walk run]
|
||||
}]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ RSpec.describe Gitlab::LanguageData do
|
|||
expect(described_class.extensions).to be_a(Set)
|
||||
expect(described_class.extensions.count).to be > 0
|
||||
# Sanity check for known extensions
|
||||
expect(described_class.extensions).to include(*%w(.rb .yml .json))
|
||||
expect(described_class.extensions).to include(*%w[.rb .yml .json])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ require 'fast_spec_helper'
|
|||
|
||||
RSpec.describe Gitlab::MarkupHelper do
|
||||
describe '#markup?' do
|
||||
%w(textile rdoc org creole wiki
|
||||
mediawiki rst adoc ad asciidoc mdown md markdown).each do |type|
|
||||
%w[textile rdoc org creole wiki
|
||||
mediawiki rst adoc ad asciidoc mdown md markdown].each do |type|
|
||||
it "returns true for #{type} files" do
|
||||
expect(described_class.markup?("README.#{type}")).to be_truthy
|
||||
end
|
||||
|
|
@ -17,7 +17,7 @@ RSpec.describe Gitlab::MarkupHelper do
|
|||
end
|
||||
|
||||
describe '#gitlab_markdown?' do
|
||||
%w(mdown mkd mkdn md markdown).each do |type|
|
||||
%w[mdown mkd mkdn md markdown].each do |type|
|
||||
it "returns true for #{type} files" do
|
||||
expect(described_class.gitlab_markdown?("README.#{type}")).to be_truthy
|
||||
end
|
||||
|
|
@ -29,7 +29,7 @@ RSpec.describe Gitlab::MarkupHelper do
|
|||
end
|
||||
|
||||
describe '#asciidoc?' do
|
||||
%w(adoc ad asciidoc ADOC).each do |type|
|
||||
%w[adoc ad asciidoc ADOC].each do |type|
|
||||
it "returns true for #{type} files" do
|
||||
expect(described_class.asciidoc?("README.#{type}")).to be_truthy
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Gitlab::Metrics::RailsSlis, feature_category: :error_budgets do
|
||||
before do
|
||||
allow(Gitlab::Graphql::KnownOperations).to receive(:default).and_return(Gitlab::Graphql::KnownOperations.new(%w(foo bar)))
|
||||
allow(Gitlab::Graphql::KnownOperations).to receive(:default).and_return(Gitlab::Graphql::KnownOperations.new(%w[foo bar]))
|
||||
end
|
||||
|
||||
describe '.initialize_request_slis!' do
|
||||
|
|
|
|||
|
|
@ -40,11 +40,11 @@ RSpec.describe Gitlab::Metrics::Samplers::ThreadsSampler do
|
|||
context 'thread names', :aggregate_failures do
|
||||
where(:thread_names, :expected_names) do
|
||||
[
|
||||
[[nil], %w(unnamed)],
|
||||
[[nil], %w[unnamed]],
|
||||
[['puma threadpool 1', 'puma threadpool 001', 'puma threadpool 002'], ['puma threadpool']],
|
||||
[%w(sidekiq_worker_thread), %w(sidekiq_worker_thread)],
|
||||
[%w(some_sampler some_exporter), %w(some_sampler some_exporter)],
|
||||
[%w(unknown thing), %w(unrecognized)]
|
||||
[%w[sidekiq_worker_thread], %w[sidekiq_worker_thread]],
|
||||
[%w[some_sampler some_exporter], %w[some_sampler some_exporter]],
|
||||
[%w[unknown thing], %w[unrecognized]]
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
|
||||
expect(response[0]).to eq(404)
|
||||
expect(response[1]['Content-Type']).to eq('text/html')
|
||||
expected_body = %{<html><body>go get #{Gitlab.config.gitlab.url}/#{project.full_path}</body></html>}
|
||||
expected_body = %(<html><body>go get #{Gitlab.config.gitlab.url}/#{project.full_path}</body></html>)
|
||||
expect(response[2]).to eq([expected_body])
|
||||
end
|
||||
end
|
||||
|
|
@ -278,7 +278,7 @@ RSpec.describe Gitlab::Middleware::Go, feature_category: :source_code_management
|
|||
project_url = "http://#{Gitlab.config.gitlab.host}/#{path}"
|
||||
expect(response[0]).to eq(200)
|
||||
expect(response[1]['Content-Type']).to eq('text/html')
|
||||
expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}"><meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/-/tree/#{branch}{/dir} #{project_url}/-/blob/#{branch}{/dir}/{file}#L{line}"></head><body>go get #{Gitlab.config.gitlab.url}/#{path}</body></html>}
|
||||
expected_body = %(<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}"><meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/-/tree/#{branch}{/dir} #{project_url}/-/blob/#{branch}{/dir}/{file}#L{line}"></head><body>go get #{Gitlab.config.gitlab.url}/#{path}</body></html>)
|
||||
expect(response[2]).to eq([expected_body])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ RSpec.describe Gitlab::Middleware::Multipart do
|
|||
let(:params) { upload_parameters_for(key: 'file', mode: mode, filename: filename, remote_id: remote_id).merge('file.path' => '/should/not/be/read') }
|
||||
|
||||
it 'builds an UploadedFile' do
|
||||
expect_uploaded_files(original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file))
|
||||
expect_uploaded_files(original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w[file])
|
||||
|
||||
subject
|
||||
end
|
||||
|
|
@ -61,7 +61,7 @@ RSpec.describe Gitlab::Middleware::Multipart do
|
|||
let(:params) { upload_parameters_for(filepath: uploaded_filepath, key: 'file', mode: mode, filename: filename) }
|
||||
|
||||
it 'builds an UploadedFile' do
|
||||
expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, size: uploaded_file.size, params_path: %w(file))
|
||||
expect_uploaded_files(filepath: uploaded_filepath, original_filename: filename, size: uploaded_file.size, params_path: %w[file])
|
||||
|
||||
subject
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue